//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//
/***
*handler.cpp - defines C++ setHandler routine
*
*Purpose:
*       Defines C++ setHandler routine.
*
*******************************************************************************/

#include <stddef.h>
#include <corecrt.h>
#include <new.h>

/* pointer to old-style C++ new handler */
_PNH _pnhHeap;
#define _mlock(l)
#define _munlock(l)
/***
*_PNH _set_new_handler(_PNH pnh) - set the new handler
*
*Purpose:
*       _set_new_handler is different from the ANSI C++ working standard definition
*       of set_new_handler.  Therefore it has a leading underscore in its name.
*
*Entry:
*       Pointer to the new handler to be installed.
*
*Return:
*       Previous new handler
*
*******************************************************************************/
_PNH __cdecl _set_new_handler( 
        _PNH pnh 
        )
{
        _PNH pnhOld;

        /* lock the heap */
        _mlock(_HEAP_LOCK);

        pnhOld = _pnhHeap;
        _pnhHeap = pnh;

        /* unlock the heap */
        _munlock(_HEAP_LOCK);

        return(pnhOld);
}


/***
*_PNH _query_new_handler(void) - query value of new handler
*
*Purpose:
*       Obtain current new handler value.
*
*Entry:
*       None
*
*       WARNING: This function is OBSOLETE. Use _query_new_ansi_handler instead.
*
*Return:
*       Currently installed new handler
*
*******************************************************************************/
_PNH __cdecl _query_new_handler ( 
        void 
        )
{
        return _pnhHeap;
}


/***
*int _callnewh - call the appropriate new handler
*
*Purpose:
*       Call the appropriate new handler.
*
*Entry:
*       None
*
*Return:
*       1 for success
*       0 for failure
*       may throw bad_alloc
*
*******************************************************************************/
extern "C" int __cdecl _callnewh(size_t size)
{
//ANSI_NEW_HANDLER should not be defined for backwards compatibility reasons!
#ifdef ANSI_NEW_HANDLER
        /*
         * if ANSI C++ new handler is activated but not installed, throw exception
         */
#ifdef  _MT
        _ptiddata ptd;

        ptd = _getptd();
        if (ptd->_newh == NULL)
            throw bad_alloc();
#else
        if (_defnewh == NULL)
            throw bad_alloc();
#endif
 
        /* 
         * if ANSI C++ new handler activated and installed, call it
         * if it returns, the new handler was successful, retry allocation
         */
#ifdef  _MT
        if (ptd->_newh != _NO_ANSI_NEW_HANDLER)
            (*(ptd->_newh))();
#else
        if (_defnewh != _NO_ANSI_NEW_HANDLER)
            (*_defnewh)();
#endif

        /* ANSI C++ new handler is inactivated, call old handler if installed */
        else 
#endif /* ANSI_NEW_HANDLER */
        {
            _PNH pnh = _pnhHeap;

            if ( (pnh == NULL) || ((*pnh)(size) == 0) )
                return 0;
        }
        return 1;
}
