/**@@@+++@@@@******************************************************************
**
** Microsoft Windows Media
** Copyright (C) Microsoft Corporation. All rights reserved.
**
***@@@---@@@@******************************************************************
*/

#include <drmcommon.h>
#include <drmstkalloc.h>

/*
** Push the stack to allocate the requested size of buffer 
*/
DRM_RESULT DRM_API DRM_STK_Alloc(
    IN  DRM_STACK_ALLOCATOR_CONTEXT *pContext,
    IN  DRM_DWORD                    cbSize,
    OUT DRM_VOID                   **ppbBuffer)
{
    DRM_RESULT dr = DRM_E_LOGICERR;
    DRM_DWORD  dwSize = cbSize;

    ChkArg( pContext && ppbBuffer && cbSize );
    
    *ppbBuffer = NULL;
    /* allocate buffer from top of stack */
    if ( ( dwSize % SIZEOF(DRM_DWORD_PTR) )!=0 )
    {
        /* adjust cbSize for alignment of DRM_DWORD_PTR */
        dwSize += SIZEOF(DRM_DWORD_PTR) - ( dwSize % SIZEOF(DRM_DWORD_PTR) );
    }

    if ( (pContext->nStackTop+dwSize+SIZEOF(DRM_DWORD) ) >= pContext->cbStack )
    {
        dr = DRM_E_OUTOFMEMORY;
        goto ErrorExit;
    }

    DRM_BYT_CopyBytes((DRM_BYTE*)pContext->pbStack, pContext->nStackTop, (DRM_BYTE*)&dwSize, 0, SIZEOF(DRM_DWORD));
    *ppbBuffer = pContext->pbStack + ((pContext->nStackTop + SIZEOF(DRM_DWORD))/CB_NATIVE_BYTE);

    pContext->nStackTop += (DRM_DWORD)(dwSize+SIZEOF(DRM_DWORD));
    /*
    TRACE(("Alloc: top=0x%08X  pb=0x%08X  cb=%d\n", pContext->nStackTop, *ppbBuffer, dwSize));
    */
#if DBG
    MEMSET((DRM_BYTE*)*ppbBuffer, 0xa, dwSize);
#endif
    dr = DRM_SUCCESS;

ErrorExit:    
    return dr;
}


/*
** Pop the stack to free the allocated buffer
*/
DRM_RESULT DRM_API DRM_STK_Free(
    IN DRM_STACK_ALLOCATOR_CONTEXT *pContext,
    IN DRM_VOID                    *pbBuffer)
{
    DRM_RESULT dr = DRM_E_LOGICERR;
    DRM_DWORD  dwSize = 0;
    
    if ( pbBuffer == NULL )
    {
        /* pbBuffer is NULL, simply return */
        goto ErrorExit;
    }

    ChkArg( pContext );

    /* verify the buffer with the stack */
    MEMCPY((DRM_BYTE*)&dwSize,(DRM_BYTE*)pbBuffer - sizeof(DRM_DWORD),SIZEOF(DRM_DWORD) );    
    /*
    TRACE((" Free: top=0x%08X  pb=0x%08X  cb=%d\n", pContext->nStackTop, pbBuffer, dwSize));
    */
    if ( ((DRM_BYTE*)pbBuffer+(dwSize/CB_NATIVE_BYTE)) != &pContext->pbStack[(pContext->nStackTop/CB_NATIVE_BYTE)])
    {
        TRACE(("\n\n***  DRM_STK_Free(): heap corrupted ***\n\n"));
        DRMASSERT( FALSE );
        dr = DRM_E_STACK_CORRUPT; /* internal stack corrupted */
        goto ErrorExit;
    }

#if DBG
    /* clear the buffer */
    MEMSET((DRM_BYTE*)pbBuffer-sizeof(DRM_DWORD), 0xb, dwSize+SIZEOF(DRM_DWORD));
#endif

    pContext->nStackTop -= (DRM_DWORD)(dwSize+SIZEOF(DRM_DWORD));
    dr = DRM_SUCCESS;
ErrorExit:    
    return dr;
}
