/**@@@+++@@@@******************************************************************
**
** Microsoft Windows Media
** Copyright (C) Microsoft Corporation. All rights reserved.
**
***@@@---@@@@******************************************************************
*/
//#include <stdlib.h>
// #include <stdarg.h>
// #include <stdio.h>
#include <drmcommon.h>
#include <drmcrt.h>
#include <oemimpl.h>
#ifdef DX_CC5_SEP_PLAT
#include "CRYS_RND.h"
#endif


fncdrmassert g_OEMAssertCallback = NULL;
/**********************************************************************
** Function:		_trace
**
** Synopsis:		Trace function that prints information to a file.  
**
** Arguments:	[szFmt] -- Format string of the variable arguments to follow.
**
** Returns:		None
**
** Notes:			
**
***********************************************************************/


/**********************************************************************
**
***********************************************************************
*/
DRM_VOID DRM_API
_oem_trace (
    IN DRM_CHAR * szFmt, ...)
{
	return;
}


/**********************************************************************
** Memory allocation functions 
***********************************************************************
*/
DRM_VOID* DRM_API 
OEM_malloc(
    DRM_DWORD size)
{
	return DX_VOS_MemMalloc( size );
}


DRM_VOID DRM_API 
OEM_free( 
    DRM_VOID* pv )
{
    DX_VOS_MemFree( pv );
}


DRM_VOID* DRM_API 
OEM_realloc(
    DRM_VOID*pv, 
    DRM_DWORD size)
{
    if( pv )
    {
        return DX_VOS_MemRealloc( pv, size );
    }
    
    return DX_VOS_MemMalloc( size );
}


/**********************************************************************
** Random number generation functions 
***********************************************************************
*/
#ifndef DX_CC5_SEP_PLAT
static       DRM_UINT64 random_seed       =  DRM_UI64LITERAL(0x25B946EB, 0xC0B36173);
static const DRM_UINT64 random_multiplier =  DRM_UI64LITERAL(0x2B992DDF, 0xA23249D5); /* odd */
#endif
/*
Set the random number seed.
*/
void DRM_API set_random_seed(
    const DRM_UINT64 new_seed)
{
#ifndef DX_CC5_SEP_PLAT
    random_seed = DRM_UI64Mul(DRM_UI64(14142135), new_seed);
#endif
    return;
}



#define PACKED_CHAR_BIT (CHAR_BIT/CB_NATIVE_BYTE)
/*
Return pseudorandom array of bytes.

CAVEAT: This generator has not been designed to be fast,
nor to have good cryptographic or statistical properties.
It is not designed for multitasking.
*/
DRM_RESULT DRM_API OEM_GenRandomBytes( 
       OUT DRM_BYTE* pbData, 
    IN     DRM_DWORD cbData )
{
#ifndef DX_CC5_SEP_PLAT
    DRM_RESULT dr = DRM_SUCCESS;
    static DRM_BOOL fFirst=TRUE;
    size_t nbyte_left = cbData;
    DRM_DWORD ib = 0;

    ChkArg( pbData != NULL );

    /* set random seed the first time */
    if ( fFirst )
    {
        DRMFILETIME ft;
        DRM_UINT64 u64;
        
        OEM_GetDeviceTime (&ft);
        FILETIME_TO_UI64( ft, u64 );
        
        set_random_seed(u64);
        fFirst = FALSE;
    }

    while (nbyte_left != 0)
    {
        size_t nbyte_now = min(nbyte_left, SIZEOF(DRM_DWORD));
        DRM_DWORD value_now;
        const DRM_INT shift_count = PACKED_CHAR_BIT*(SIZEOF(random_seed) - SIZEOF(value_now));

        nbyte_left -= nbyte_now;
        random_seed = DRM_UI64Add( DRM_UI64Mul(random_seed,random_multiplier), DRM_UI64(1));
        value_now = DRM_I64ToUI32(DRM_UI2I64(DRM_UI64ShR(random_seed, shift_count)));
        do 
        {
            /* Should never overflow like this, but PREfast complains so better to be safe */
            if( ib >= cbData )
            {
                break;
            }
            PUT_BYTE(pbData, ib, (DRM_BYTE)(value_now & UCHAR_MAX) );
            ib++;
            value_now >>= PACKED_CHAR_BIT;
            nbyte_now--;
        } while (nbyte_now != 0);
    }
    
ErrorExit:
#else
    DRM_RESULT dr = DRM_SUCCESS;
	
	dr = CRYS_RND_GenerateVector(cbData,pbData);
#endif
    return dr;
} /* OEM_GenRandomBytes */
 
#if DRM_SUPPORT_SST_REDUNANCY
#include <drmtoken.h>
DRM_RESULT DRM_API VariableSSTRedundancyGetorSet(const DRM_CONST_STRING* pdstrToken, TOKEN* pNewValue, TOKEN* pResult, DRM_VOID* pvOpaqueData, DRM_BOOL fSet)
{
    return DRM_E_NOTIMPL;
}
#endif


DRM_RESULT DRM_API OEM_GetSetDataStoreRedundancy(
    IN     DRM_VOID  *f_pvOpaqueData,
    IN OUT DRM_BYTE  *f_pbKey,
    IN     DRM_DWORD  f_cbKey,
    IN     DRM_BOOL   f_fGet) 
{
    return DRM_E_NOTIMPL;
}

DRM_RESULT OEM_StringCchCopyN( 
    DRM_WCHAR       *pwszDest,
    DRM_DWORD        cchDest,
    const DRM_WCHAR *pwszSrc,
    DRM_DWORD        cchSrc )
{
    DRM_RESULT  dr = DRM_SUCCESS;

    if( cchDest > INT_MAX
     || cchSrc  > INT_MAX )
    {
        dr = DRM_E_INVALIDARG;
    }
    else
    {
        if (cchDest == 0)
        {
            // can not null terminate a zero-byte dest buffer
            dr = DRM_E_INVALIDARG;
        }
        else
        {
            while( cchDest  > 0
                && cchSrc   > 0 
                && *pwszSrc != g_wchNull )
            {
                *pwszDest = *pwszSrc;
		++pwszSrc;
		++pwszDest;
                cchDest--;
                cchSrc--;
            }

            if( cchDest == 0 )
            {
                // we are going to truncate pszDest
                pwszDest--;
                dr = DRM_E_BUFFERTOOSMALL;
            }
            *pwszDest = g_wchNull;
        }
    }

    return dr;
}

