/**@@@+++@@@@******************************************************************
**
** Microsoft Windows Media
** Copyright (C) Microsoft Corporation. All rights reserved.
**
***@@@---@@@@******************************************************************
*/
#include "DX_VOS_File.h"
#include "DX_VOS_String.h"
#include "DX_VOS_config.h"

#include "tstutils.h"
#include "drmcrt.h"

#include "drmsecureclock.h"
#include "drmmanager.h"
#include "tOEMIMP.h"

extern void OEM_wcscat(DRM_WCHAR *wszDestination, const DRM_WCHAR *wszSource);
extern int OEM_wcstombs (char *destination,const DRM_WCHAR *source,int  length);

const DRM_WCHAR   DEVCERT_FILE_NAME [] = { ONE_WCHAR('d', '\0'), ONE_WCHAR('e', '\0'), ONE_WCHAR('v', '\0'), ONE_WCHAR('c', '\0'), ONE_WCHAR('e', '\0'), ONE_WCHAR('r', '\0'), ONE_WCHAR('t', '\0'), ONE_WCHAR('.', '\0'), ONE_WCHAR('d', '\0'), ONE_WCHAR('a', '\0'), ONE_WCHAR('t', '\0'), ONE_WCHAR('\0', '\0') };
const DRM_WCHAR DEVCERT_TEMPLATE_FILE_NAME [] = { ONE_WCHAR('d', '\0'), ONE_WCHAR('e', '\0'), ONE_WCHAR('v', '\0'), ONE_WCHAR('c', '\0'), ONE_WCHAR('e', '\0'), ONE_WCHAR('r', '\0'), ONE_WCHAR('t', '\0'),ONE_WCHAR('t', '\0'),ONE_WCHAR('e', '\0'),ONE_WCHAR('m', '\0'),ONE_WCHAR('p', '\0'),ONE_WCHAR('l', '\0'),ONE_WCHAR('a', '\0'),ONE_WCHAR('t', '\0'),ONE_WCHAR('e', '\0'),ONE_WCHAR('.', '\0'), ONE_WCHAR('d', '\0'), ONE_WCHAR('a', '\0'), ONE_WCHAR('t', '\0'), ONE_WCHAR('\0', '\0') };
const DRM_WCHAR PRIVATE_KEY_FILE_NAME [] = { ONE_WCHAR('p', '\0'), ONE_WCHAR('r', '\0'), ONE_WCHAR('i', '\0'), ONE_WCHAR('v', '\0'), ONE_WCHAR('.', '\0'), ONE_WCHAR('d', '\0'), ONE_WCHAR('a', '\0'), ONE_WCHAR('t', '\0'), ONE_WCHAR('\0', '\0') };
const DRM_WCHAR DEVICE_STORE_FILE_NAME[] = {
		ONE_WCHAR('D', '\0'), ONE_WCHAR('R', '\0'),  ONE_WCHAR('M', '\0'),  ONE_WCHAR('D', '\0'), ONE_WCHAR('e', '\0'),
	    ONE_WCHAR('v', '\0'),ONE_WCHAR('i', '\0'),ONE_WCHAR('c', '\0'),ONE_WCHAR('e', '\0'), ONE_WCHAR('S', '\0'),
	    ONE_WCHAR('t', '\0'),ONE_WCHAR('o', '\0'),ONE_WCHAR('r', '\0'),ONE_WCHAR('e', '\0'), ONE_WCHAR('.', '\0'),
	    ONE_WCHAR('h', '\0'),  ONE_WCHAR('d', '\0'),  ONE_WCHAR('s', '\0'), ONE_WCHAR('\0', '\0')
	    };
void DRM_API tDRMSleep(DRM_DWORD dwMillSecond)
{
#if	defined(SIXTEEN_BIT_ADDRESSING) || (!defined(WIN32) || !defined(WIN_CE))  
	/*Do not have Sleep() available on 16-bit platform*/
		unsigned i;
		for(i=0;i<(dwMillSecond *1000);i++);
	#else
		sleep(dwMillSecond);
	#endif
}

#if !defined(SIXTEEN_BIT_ADDRESSING) && (defined(WIN32) || defined (WIN_CE))
/*Functions called by tMoveFile are not available on 16bit TI platform*/
DRM_BOOL DRM_API tMoveFile(const DRM_WCHAR *wszSrc, const DRM_WCHAR *wszTarget)
{
	SetFileAttributesW(wszTarget, FILE_ATTRIBUTE_NORMAL);
#ifdef WINCE_TEST
	return MoveFile(wszSrc, wszTarget);
#else
	return MoveFileExW(wszSrc, wszTarget, MOVEFILE_REPLACE_EXISTING);
#endif	
}
#endif /*sixteenbitaddressing or non windows systms*/

#ifdef WINCE_TEST
	static const DRM_WCHAR g_wszDrmPath[] = L"\\windows\\";
#else
	#ifndef DX_CC5_SEP_PLAT
		#ifdef IN_MW_SOFT_PRJ
		#ifdef __unix__
		static const DRM_WCHAR g_wszDrmPath[] = { ONE_WCHAR('.', '\0'), ONE_WCHAR('.', '\0'), ONE_WCHAR('/', '\0'), ONE_WCHAR('.', '\0'), ONE_WCHAR('.', '\0'), ONE_WCHAR('/', '\0'), ONE_WCHAR('.', '\0'), ONE_WCHAR('.', '\0'), ONE_WCHAR('/', '\0'),
		ONE_WCHAR('W', '\0'), ONE_WCHAR('M', '\0'), ONE_WCHAR('D', '\0'), ONE_WCHAR('R', '\0'), ONE_WCHAR('M', '\0'), ONE_WCHAR('_', '\0'), ONE_WCHAR('C', '\0'), ONE_WCHAR('O', '\0'), ONE_WCHAR('M', '\0'),
		ONE_WCHAR('P', '\0'), ONE_WCHAR('/', '\0'), ONE_WCHAR('W', '\0'), ONE_WCHAR('o', '\0'), ONE_WCHAR('r', '\0'), ONE_WCHAR('k', '\0'), ONE_WCHAR('s', '\0'), ONE_WCHAR('p', '\0'), ONE_WCHAR('a', '\0'), ONE_WCHAR('c', '\0'), ONE_WCHAR('e', '\0'), ONE_WCHAR('/', '\0'),
		ONE_WCHAR('W', '\0'), ONE_WCHAR('M', '\0'), ONE_WCHAR('D', '\0'), ONE_WCHAR('R', '\0'), ONE_WCHAR('M', '\0'), ONE_WCHAR('P', '\0'), ONE_WCHAR('D', '\0'), ONE_WCHAR('/', '\0'), ONE_WCHAR('\0', '\0') };

		#else
		
		static const DRM_WCHAR g_wszDrmPath[] = { ONE_WCHAR('.', '\0'), ONE_WCHAR('.', '\0'), ONE_WCHAR('/', '\0'), ONE_WCHAR('.', '\0'), ONE_WCHAR('.', '\0'), ONE_WCHAR('/', '\0'), ONE_WCHAR('.', '\0'), ONE_WCHAR('.', '\0'), ONE_WCHAR('/', '\0'),
		ONE_WCHAR('.', '\0'), ONE_WCHAR('.', '\0'), ONE_WCHAR('/', '\0'),  ONE_WCHAR('W', '\0'), ONE_WCHAR('M', '\0'), ONE_WCHAR('D', '\0'), ONE_WCHAR('R', '\0'), ONE_WCHAR('M', '\0'), ONE_WCHAR('_', '\0'), ONE_WCHAR('C', '\0'), ONE_WCHAR('O', '\0'), ONE_WCHAR('M', '\0'),
		ONE_WCHAR('P', '\0'), ONE_WCHAR('/', '\0'), ONE_WCHAR('W', '\0'), ONE_WCHAR('o', '\0'), ONE_WCHAR('r', '\0'), ONE_WCHAR('k', '\0'), ONE_WCHAR('s', '\0'), ONE_WCHAR('p', '\0'), ONE_WCHAR('a', '\0'), ONE_WCHAR('c', '\0'), ONE_WCHAR('e', '\0'), ONE_WCHAR('/', '\0'),
		ONE_WCHAR('W', '\0'), ONE_WCHAR('M', '\0'), ONE_WCHAR('D', '\0'), ONE_WCHAR('R', '\0'), ONE_WCHAR('M', '\0'), ONE_WCHAR('P', '\0'), ONE_WCHAR('D', '\0'), ONE_WCHAR('/', '\0'), ONE_WCHAR('\0', '\0') };

		#endif


			
		#else
			static const DRM_WCHAR g_wszDrmPath[] = { ONE_WCHAR('.', '\0'), ONE_WCHAR('.', '\0'), ONE_WCHAR('/', '\0'),
													  ONE_WCHAR('W', '\0'), ONE_WCHAR('M', '\0'), ONE_WCHAR('D', '\0'), ONE_WCHAR('R', '\0'), ONE_WCHAR('M', '\0'), ONE_WCHAR('P', '\0'), ONE_WCHAR('D', '\0'), ONE_WCHAR('/', '\0'), ONE_WCHAR('\0', '\0') };
		#endif
	#elif defined(__unix__)
		static const DRM_WCHAR g_wszDrmPath[] = { ONE_WCHAR('.', '\0'), ONE_WCHAR('/', '\0'), 
		ONE_WCHAR('W', '\0'), ONE_WCHAR('M', '\0'), ONE_WCHAR('D', '\0'), ONE_WCHAR('R', '\0'), ONE_WCHAR('M', '\0'), ONE_WCHAR('P', '\0'), ONE_WCHAR('D', '\0'), ONE_WCHAR('/', '\0'), ONE_WCHAR('\0', '\0') };
	#else
		#if !defined(DX_ENV) && !defined(DX_CC5_SEP_PLAT)
			static const DRM_WCHAR g_wszDrmPath[] = { ONE_WCHAR('C', '\0'), ONE_WCHAR(':', '\0'), ONE_WCHAR('\\', '\0'), ONE_WCHAR('W', '\0'), ONE_WCHAR('M', '\0'), ONE_WCHAR('D', '\0'), ONE_WCHAR('R', '\0'), ONE_WCHAR('M', '\0'), ONE_WCHAR('P', '\0'), ONE_WCHAR('D', '\0'), ONE_WCHAR('\\', '\0'), ONE_WCHAR('\0', '\0') };
		#else
			#ifndef DX_CC5_SEP_PLAT
					/*discretix PC simulation*/
					#ifdef IN_MW_SOFT_PRJ
static const DRM_WCHAR g_wszDrmPath[] = {ONE_WCHAR('.', '\0'), ONE_WCHAR('\\', '\0'), ONE_WCHAR('\0', '\0')};
						/*{ ONE_WCHAR('.', '\0'), ONE_WCHAR('.', '\0'), ONE_WCHAR('\\', '\0'), ONE_WCHAR('.', '\0'), ONE_WCHAR('.', '\0'), ONE_WCHAR('\\', '\0'), ONE_WCHAR('.', '\0'), ONE_WCHAR('.', '\0'), ONE_WCHAR('\\', '\0'), 
										ONE_WCHAR('.', '\0'), ONE_WCHAR('.', '\0'), ONE_WCHAR('\\', '\0'), ONE_WCHAR('W', '\0'), ONE_WCHAR('M', '\0'), ONE_WCHAR('D', '\0'), ONE_WCHAR('R', '\0'), ONE_WCHAR('M', '\0'), ONE_WCHAR('_', '\0'), 
										ONE_WCHAR('C', '\0'), ONE_WCHAR('O', '\0'), ONE_WCHAR('M', '\0'), ONE_WCHAR('P', '\0'), ONE_WCHAR('\\', '\0'), ONE_WCHAR('W', '\0'), ONE_WCHAR('o', '\0'), ONE_WCHAR('r', '\0'), ONE_WCHAR('k', '\0'), ONE_WCHAR('s', '\0'), 
										ONE_WCHAR('p', '\0'), ONE_WCHAR('a', '\0'), ONE_WCHAR('c', '\0'), ONE_WCHAR('e', '\0'), ONE_WCHAR('\\', '\0'), ONE_WCHAR('W', '\0'), ONE_WCHAR('M', '\0'), ONE_WCHAR('D', '\0'), ONE_WCHAR('R', '\0'), ONE_WCHAR('M', '\0'),
										ONE_WCHAR('P', '\0'), ONE_WCHAR('D', '\0'), ONE_WCHAR('\\', '\0'), ONE_WCHAR('\0', '\0') };*/
					#else
					static const DRM_WCHAR g_wszDrmPath[] = { ONE_WCHAR('.', '\0'), ONE_WCHAR('.', '\0'), ONE_WCHAR('\\', '\0'), 
									ONE_WCHAR('W', '\0'), ONE_WCHAR('M', '\0'), ONE_WCHAR('D', '\0'), ONE_WCHAR('R', '\0'), ONE_WCHAR('M', '\0'), ONE_WCHAR('P', '\0'), ONE_WCHAR('D', '\0'), ONE_WCHAR('\\', '\0'), ONE_WCHAR('\0', '\0') };

					#endif
			#else
				#ifdef DX_ARM_INTEGRATOR_DEBUG 
					/*discretix FPGA Environment*/
					static const DRM_WCHAR g_wszDrmPath[] = { ONE_WCHAR('.', '\0'), ONE_WCHAR('.', '\0'), ONE_WCHAR('/', '\0'), 
															  ONE_WCHAR('.', '\0'), ONE_WCHAR('.', '\0'), ONE_WCHAR('/', '\0'),
															  ONE_WCHAR('.', '\0'), ONE_WCHAR('.', '\0'), ONE_WCHAR('/', '\0'),
															  ONE_WCHAR('H', '\0'), ONE_WCHAR('O', '\0'), ONE_WCHAR('S', '\0'), ONE_WCHAR('T', '\0'), ONE_WCHAR('/', '\0'),
															  ONE_WCHAR('W', '\0'), ONE_WCHAR('M', '\0'), ONE_WCHAR('D', '\0'), ONE_WCHAR('R', '\0'), ONE_WCHAR('M', '\0'), ONE_WCHAR('P', '\0'), ONE_WCHAR('D', '\0'), ONE_WCHAR('/', '\0'), ONE_WCHAR('\0', '\0') };
				#else
					/*Release environment*/
					static const DRM_WCHAR g_wszDrmPath[] = { ONE_WCHAR('.', '\0'), ONE_WCHAR('.', '\0'), ONE_WCHAR('\\', '\0'),
															  ONE_WCHAR('.', '\0'), ONE_WCHAR('.', '\0'), ONE_WCHAR('\\', '\0'), 
															  ONE_WCHAR('.', '\0'), ONE_WCHAR('.', '\0'), ONE_WCHAR('\\', '\0'), 
															  ONE_WCHAR('.', '\0'), ONE_WCHAR('.', '\0'), ONE_WCHAR('\\', '\0'), 
															  ONE_WCHAR('W', '\0'), ONE_WCHAR('M', '\0'), ONE_WCHAR('D', '\0'), ONE_WCHAR('R', '\0'), ONE_WCHAR('M', '\0'), ONE_WCHAR('P', '\0'), ONE_WCHAR('D', '\0'), ONE_WCHAR('\\', '\0'), ONE_WCHAR('\0', '\0') };
				#endif
			#endif
		#endif
	#endif /*DX_CC5_SEP_PLAT*/
#endif	
static void _GetDRMFileName(DRM_CONST_STRING *pdstrPathname, const DRM_WCHAR *wszFileName)
{
	static DRM_WCHAR wszPathName[256] = {'\0'};
	DRM_DWORD slen = 0;
	 ZEROMEM(wszPathName,256);
	 
	if (pdstrPathname && wszFileName) {

		#ifdef SIXTEEN_BIT_ADDRESSING
			/*Using wcsncpy since it can work on 16-bit platform*/
			slen = DRM_wcslen(g_wszDrmPath);
	       	DRM_wcsncpy(&wszPathName[0], g_wszDrmPath,slen);
		#else
			slen = DRM_wcslen(g_wszDrmPath);
	       	DRM_wcsncpy(&wszPathName[0], g_wszDrmPath,slen);
		#endif
		OEM_wcscat(wszPathName, wszFileName);

		pdstrPathname->pwszString = &wszPathName[0];
		pdstrPathname->cchString = DRM_wcslen(wszPathName);
	}
}

void DRM_API tGetDeviceStorePathname(DRM_CONST_STRING *pwszPathname)
{
	_GetDRMFileName(pwszPathname, DEVICE_STORE_FILE_NAME);
}

static DRM_RESULT _RemoveFileW(const DRM_WCHAR *wcszPathname)
{
	DRM_RESULT dr = DRM_SUCCESS;
 	DRM_CHAR *szPathName = NULL;
	DRM_DWORD cchPathName = 0;

	cchPathName = DRM_wcslen(wcszPathname);
	/*we do not need to find the lenght required for wide char string, since it is the same as that 
	required by native char string on 16-bit*/
	#ifndef SIXTEEN_BIT_ADDRESSING
	    cchPathName = OEM_wcstombs(NULL, wcszPathname,cchPathName+1);
	#endif
	ChkMem(szPathName = (char*)OEM_malloc(cchPathName*CB_NATIVE_BYTE + 1));
	OEM_wcstombs(szPathName, wcszPathname, (int)(cchPathName + 1));
	
#ifdef WINCE_TEST
	DX_VOS_FDelete(szPathName);
#elif SIXTEEN_BIT_ADDRESSING
	if ( 0 != DX_VOS_FDelete(szPathName)){
		/*Cannot use the errorconversion based on Windows on 16-bit*/
		Log("Trace"," \t\tFrom RemoveFileW - Failed to Remove file\n");
		}
#else
		DX_VOS_FDelete(szPathName);
		/* It is not an error if the file does not exist. */

#endif
 
ErrorExit:
 	SAFE_OEM_FREE(szPathName);
	return dr;
}

DRM_RESULT DRM_API RemoveDRMFile(DRM_DWORD dwRemove)
{
	DRM_RESULT dr = DRM_SUCCESS;
	DRM_CONST_STRING dstrpath;

	if (dwRemove & RMFILE_STORE) {
		tGetDeviceStorePathname(&dstrpath);
		ChkDR(_RemoveFileW(dstrpath.pwszString));
	}

	if (dwRemove & RMFILE_DEVCERT) {
		_GetDRMFileName(&dstrpath, DEVCERT_FILE_NAME);
		ChkDR(_RemoveFileW(dstrpath.pwszString));
	}

	if (dwRemove & RMFILE_DEVCERTTEMPLATE) {
		_GetDRMFileName(&dstrpath, DEVCERT_TEMPLATE_FILE_NAME);
		ChkDR(_RemoveFileW(dstrpath.pwszString));
	}
	
	if (dwRemove & RMFILE_PRVKEY) {
		_GetDRMFileName(&dstrpath, PRIVATE_KEY_FILE_NAME);
		ChkDR(_RemoveFileW(dstrpath.pwszString));
	}
ErrorExit:
	return dr;
}

DRM_RESULT _CopyFileToDRMFolder(const DRM_WCHAR *wszSrc, const DRM_WCHAR *wszDest)
{
	DRM_RESULT dr = DRM_SUCCESS;
	DRM_CONST_STRING dstrDest = {0};
	DRM_DWORD cbData;
	DRM_BYTE *pbData = NULL;

	if (!wszSrc)
		goto ErrorExit;
	
	ChkArg(LoadTestFileW(NULL, wszSrc, &pbData, &cbData));

	_GetDRMFileName(&dstrDest, wszDest);
	ChkArg(SaveToFileW(dstrDest.pwszString, pbData, cbData));
ErrorExit:
	SAFE_OEM_FREE(pbData);
	return dr;
}

DRM_RESULT DRM_API SetDeviceEnv(const DRM_WCHAR *wszDevcertTemplateFileName, const DRM_WCHAR *wszPrvKeyFileName, DRM_BOOL fCreateDevCert)
{
	DRM_RESULT dr = DX_SUCCESS;
   	DRM_MANAGER_CONTEXT *poDrmContext = NULL;
 
	DRM_CONST_STRING dstrPathname;

	ChkDR(_CopyFileToDRMFolder(wszDevcertTemplateFileName, DEVCERT_TEMPLATE_FILE_NAME));

    /*wince version does not need private key file*/
#ifndef WINCE_TEST
 	ChkDR(_CopyFileToDRMFolder(wszPrvKeyFileName, PRIVATE_KEY_FILE_NAME));
#endif	

	ChkDR(RemoveDRMFile(RMFILE_DEVCERT));

	
     
	if (fCreateDevCert) {
		tGetDeviceStorePathname(&dstrPathname);

		poDrmContext = (DRM_MANAGER_CONTEXT *)OEM_malloc(SIZEOF(DRM_MANAGER_CONTEXT));
		/* DRM_MGR_Initialize creates a devcert if it is not there. */
		ChkDR(DRM_MGR_Initialize(poDrmContext, &dstrPathname));
		DRM_MGR_Uninitialize(poDrmContext);
 	}
ErrorExit:
	SAFE_OEM_FREE(poDrmContext);
  	return dr;
}

DRM_RESULT DRM_API tSetSecureClock(DRM_HDS_CONTEXT* poHdsContext, DRM_BYTE* rgbSSTPassword)
{
	DRM_RESULT dr;
	DRMFILETIME timeCurrent;
	DRM_SECSTORE_CLOCK_DATA oClkData;
    DRM_WORD wSecureDataLen =0;
	DRM_SECSTORE_CONTEXT *pSecStoreContext = NULL;

	/* From secureclockrequest.c */
	#ifndef SIXTEEN_BIT_ADDRESSING
	const DRM_ID g_idSData     = { 'S', 0, 'E', 0, 'C', 0, 'U', 0, 'R', 0, 'E', 0, '1', 0, '\0', 0 };
	const DRM_ID g_idSDataPrev = { 'S', 0, 'E', 0, 'C', 0, 'U', 0, 'R', 0, 'E', 0, '2', 0, '\0', 0 };
	#else
	const DRM_ID g_idSData     = { 'S', 'E', 'C', 'U', 'R', 'E', '1', '\0'  };
	const DRM_ID g_idSDataPrev = { 'S', 'E', 'C', 'U', 'R', 'E', '2', '\0'  };
	#endif

	



	OEM_GetDeviceTime(&timeCurrent);

	MEMSET(&oClkData, 0, SIZEOF(oClkData));
	oClkData.flag = CLK_LK_GSC_VALID | CLK_LK_RSC_VALID | CLK_REFRESHDATE_VALID | CLK_EVER_SET;
	FILETIME_TO_UI64(timeCurrent, oClkData.LastKnownGoodSecureClock);
	FILETIME_TO_UI64(timeCurrent, oClkData.LastKnownRealtimeSecureClock);

	/* Refresh date is 30 days later. */
	FILETIME_TO_UI64(timeCurrent, oClkData.RefreshDate);
	oClkData.RefreshDate = DRM_UI64Add(oClkData.RefreshDate, DRM_UI64Mul(DRM_UI64(30 * 24 * 60 * 60), DRM_UI64(FILETIME_TO_SECONDS)));

	ChkMem(pSecStoreContext = (DRM_SECSTORE_CONTEXT*)OEM_malloc(SIZEOF(DRM_SECSTORE_CONTEXT)));

	/* Now set the clock data to the secure store. */
	wSecureDataLen = SIZEOF(oClkData);
	ChkDR( DRM_SST_SetData( pSecStoreContext,
                        &g_idSData,
                        &g_idSDataPrev,
                        rgbSSTPassword,
                        SECURE_STORE_GLOBAL_DATA,
                        poHdsContext,
                        (DRM_BYTE *) &oClkData, 
                        wSecureDataLen ) );

	ChkDR(OEM_SetClockResetState(FALSE));
ErrorExit:
	SAFE_OEM_FREE(pSecStoreContext);
	return dr;
}

DRM_RESULT DRM_API tGetBBContext(DRM_BB_CONTEXT **ppBB)
{
	DRM_RESULT dr;
	DRM_BYTE rgbBuffer[MAX_DEVICE_CERT_SIZE];    
	DRM_CONST_STRING dstrDevCert;

	ChkArg(ppBB);
	ChkMem(*ppBB = (DRM_BB_CONTEXT*)OEM_malloc(SIZEOF(DRM_BB_CONTEXT)));
	DSTR_FROM_PB( &dstrDevCert, rgbBuffer, SIZEOF(rgbBuffer) );

	/*blackbox initialized */
	if (DRM_FAILED(DRM_DDC_GetDeviceCertificate( (DRM_STRING*)&dstrDevCert, 0, &((*ppBB)->CryptoContext)))) {
		ChkDR(SetDeviceEnv(DEVCERT_TEMPLATE_FILE_NAME, PRIVATE_KEY_FILE_NAME, FALSE));
		ChkDR(DRM_DDC_GetDeviceCertificate((DRM_STRING*)&dstrDevCert, DRM_DCP_CREATE_DEVCERT_IF_NOT_EXISTING, &((*ppBB)->CryptoContext)));
	}
	ChkDR( DRM_DCP_LoadPropertiesCache( &dstrDevCert, &((*ppBB)->cachedCertValues), &((*ppBB)->CryptoContext) ) );
	ChkDR( DRM_BBX_Initialize( *ppBB ) );
ErrorExit:
	return dr;
}

void DRM_API tFreeBBContext(DRM_BB_CONTEXT *pBB)
{
	if (pBB) {
		DRM_BBX_Shutdown(pBB);
		SAFE_OEM_FREE(pBB);
	}
}

void DRM_API tGetBBVersion(DRM_BB_CONTEXT *pBB, DRM_BYTE *pBBVer)
{
	/* The real current version of drm is 2.3.101.0 */
    MEMCPY( pBBVer, pBB->cachedCertValues.m_BBCompatibilityCert.pk.version, VERSION_LEN);
}
#if 0/* FINDME*/
static DRM_RESULT _tGetTCFileListImp(char *szFileNameTemplate, char **szPlatforms, char **szFileNames, DRM_DWORD *pdwCount)
{

	DRM_RESULT dr = DRM_SUCCESS;
/*WIN32 based Function calls and data types used here are not available on TI 16-bit platform */
#ifndef SIXTEEN_BIT_ADDRESSING
	DRM_BOOL fMoreFiles = TRUE;
	DRM_DWORD dwFound = 0;
	HANDLE hFindFile = INVALID_HANDLE_VALUE;
	WIN32_FIND_DATAW fd;
	DRM_CONST_STRING dstrFileNameTemplate = {0};
	char **szPlatform, szFileName[256];

	/* ChkArg(szFileNameTemplate && szPlatforms && pdwCount); */

/*wince does not have the same driver concept as the one in PC*/
#ifdef WINCE_TEST
	DX_VOS_SPrintf(szFileName,sizeof(szFileName) "%s\\%s", BASE_DIR, szFileNameTemplate);
	MakeDRMString(&dstrFileNameTemplate, szFileName);
#else
	MakeDRMString(&dstrFileNameTemplate, szFileNameTemplate);
#endif

	hFindFile = FindFirstFileW(dstrFileNameTemplate.pwszString, &fd);
	while (INVALID_HANDLE_VALUE != hFindFile && fMoreFiles) {
		for (szPlatform = szPlatforms; *szPlatform; szPlatform++) {
			OEM_wcstombs(szFileName, fd.cFileName, sizeof(szFileName));
			if (DX_VOS_FindStr(szFileName, *szPlatform)) {
				if (szFileNames && dwFound < *pdwCount) {

/*wince does not have the same driver concept as the one in PC*/
#ifdef WINCE_TEST
					ChkMem(szFileNames[dwFound] = (char*)DX_VOS_MemMalloc(DX_VOS_StrLen(szFileName) + strlen(BASE_DIR) + 2));
					DX_VOS_SPrintf(szFileNames[dwFound], "%s\\%s", BASE_DIR, szFileName);
#else

					ChkMem(szFileNames[dwFound] = (char*)DX_VOS_MemMalloc(DX_VOS_StrLen(szFileName) + 1));
					DX_VOS_StrNCopy(szFileNames[dwFound],(DX_VOS_StrLen(szFileName)+1), szFileName);
					
#endif
				}
				dwFound++;
				break;
			}
		}
		fMoreFiles = FindNextFileW(hFindFile, &fd);
	}

#ifdef WIN32
	if (fMoreFiles) {
		dr = GetLastError();
		ChkDR(DRM_RESULT_FROM_WIN32(dr));
	}
#endif /*WIN32*/
	if (!szFileNames || dwFound > *pdwCount)
		dr = DRM_E_BUFFERTOOSMALL;

	*pdwCount = dwFound;
ErrorExit:
	if (hFindFile != INVALID_HANDLE_VALUE)
		FindClose(hFindFile);
	OEM_free((DRM_WCHAR*)dstrFileNameTemplate.pwszString);
#endif /*SIXTEEN_BIT_ADDRESSING*/
	return dr;

}
#endif /*FINDME*/
#if 0 /*FINDME*/
DRM_RESULT DRM_API tGetTCFileList(char *szTestFilePrefix, char **szPlatforms, char ***pszTestFileNames)
{
	DRM_RESULT dr =DRM_SUCCESS;
	char szFN[260] = {0};
	DRM_DWORD dwCount = 0;
	ChkArg(szTestFilePrefix && szPlatforms && pszTestFileNames);

	DX_VOS_StrNCopy(szFN,260, szTestFilePrefix);/*strncpy*/
	DX_VOS_StrNCat(szFN,260,".*.txt");
/*	strncat(szFN, ".*.txt",7);*/
	if (DRM_E_BUFFERTOOSMALL != (dr = _tGetTCFileListImp(szFN, szPlatforms, NULL, &dwCount))) {
		ChkDR(dr);
	}

	ChkMem(*pszTestFileNames = (char**)OEM_malloc((dwCount + 1) * SIZEOF(char*)));
	ZEROMEM(*pszTestFileNames, (dwCount + 1) * SIZEOF(char*));
	ChkDR(_tGetTCFileListImp(szFN, szPlatforms, *pszTestFileNames, &dwCount));
ErrorExit:
	return dr;
}
#endif
void tFreeFileNameList(char **szTestFileNames)
{
	if (szTestFileNames) {
		char **p = NULL;
		for (p = szTestFileNames; *p; p++)
			SAFE_OEM_FREE(*p);
		SAFE_OEM_FREE(szTestFileNames);
	}
}

#ifdef PERF_TEST

static DxVosFile g_fpTestLog = NULL;	/* Need to have a log file iniitalized */

static DRM_UINT64 HrTmrGet( void )
{
#if defined(WINCE_TEST) || defined(_AMD64_)
	return 0;
#else
	__asm rdtsc;
#endif
}

DRM_UINT64 DRM_API GetTimer (void)
{
	DRM_UINT64 ullTimer;

#if defined(WINCE_TEST) || defined(_AMD64_)
	ullTimer = DRM_UI64(GetTickCount());
#else
	if ( IsProcessorFeaturePresent( PF_RDTSC_INSTRUCTION_AVAILABLE ) )
	{
		ullTimer = HrTmrGet();
	}
	else
	{
		ullTimer = DRM_UI64(GetTickCount());
	}
#endif 

	return ullTimer;
}

DRM_RESULT DRM_API InitPerfLog( DRM_CHAR* pszLogFileName )
{
	DRM_RESULT dr = DRM_SUCCESS;
	DRMSYSTEMTIME SystemTime;
	
	DX_VOS_FOpen(&g_fpTestLog,pszLogFileName,"w+");
	if ( NULL == g_fpTestLog )
	{
		return DRM_E_FAIL;
	}
	OEM_GetDeviceDateTime( &SystemTime ); 

	DX_VOS_FPrintf( g_fpTestLog, "Logs from Janus Performanc Logger.\n\n" );
	DX_VOS_FPrintf(g_fpTestLog, "Log Started: %04d/%02d/%02d %02d:%02d:%02d.%03d\n\n", 
						SystemTime.wYear, SystemTime.wMonth, SystemTime.wDay, 
						SystemTime.wHour, SystemTime.wMinute, SystemTime.wSecond, 
						SystemTime.wMilliseconds); 	
	return dr;
}

DRM_RESULT DRM_API ClosePerfLog()
{
	DRM_RESULT dr = DRM_SUCCESS;
	DRMSYSTEMTIME SystemTime;

	if ( NULL == g_fpTestLog )
	{
		return dr;
	}

	OEM_GetDeviceDateTime( &SystemTime ); 
	DX_VOS_FPrintf(g_fpTestLog, "\nLog finished: %04d/%02d/%02d %02d:%02d:%02d.%03d\n", 
						SystemTime.wYear, SystemTime.wMonth, SystemTime.wDay, 
						SystemTime.wHour, SystemTime.wMinute, SystemTime.wSecond, 
						SystemTime.wMilliseconds);
	
	DX_VOS_FFlush( g_fpTestLog );
	if ( 0 == DX_VOS_FClose( g_fpTestLog ) )
        return dr;
	else
		return DRM_E_FAIL;
}

void DRM_API PerfLog( DRM_CHAR* pszCounter, DRM_UINT64 llVlaue )
{
	if ( g_fpTestLog != NULL )
	{
		DX_VOS_FPrintf( g_fpTestLog, "%s:: %I64u\n", pszCounter, llVlaue );
	}
	DX_VOS_Printf( "%s:: %I64u\n", pszCounter, llVlaue );
}

#endif



#ifdef SIXTEEN_BIT_ADDRESSING
/*
//------------------------------------------------------------------------------
// Name: wcscat
// Desc:  This function is used to concatanate two wide char strings. Not available on TI sixteen
bit platform. 
//
//Parameters:
//	wszDestination        input/output wide char string
//    wszSource 		input wide char string.
//
// Copyright (c) 1999-2000, Microsoft Corporation. All rights reserved.
//------------------------------------------------------------------------------*/
void wcscat(DRM_WCHAR *wszDestination, const DRM_WCHAR *wszSource)
{
	DRM_DWORD sourcelen = 0;
	int i = 0;
	if(wszSource !=NULL && wszDestination !=NULL)
	{
	    sourcelen = DRM_wcslen(wszSource);

	    while(*wszDestination != g_wchNull)
		wszDestination++;
	    DRM_wcsncpy(wszDestination,wszSource,sourcelen);
	}
}


/*
//------------------------------------------------------------------------------
// Name: tFreeFileNameList_pfd
// Desc:  This function is used to free the memory used for storing the filenames on sixteen-bit platform. 
//
//Parameters:
//	szTestFileNames       input pointing to the location containing the list of flienames. 
//
// Copyright (c) 1999-2000, Microsoft Corporation. All rights reserved.
//------------------------------------------------------------------------------*/

void tFreeFileNameList_pfd(char **szTestFileNames)
{
#if defined(_MSC_VER)
	if (szTestFileNames) {
		char **p = NULL;
		for (p = szTestFileNames; *p; p++)
                {
                    SAFE_OEM_FREE(*p);
                }
		SAFE_OEM_FREE(szTestFileNames);
	}

#endif /* _MSC_VER */
}

/*
//------------------------------------------------------------------------------
// Name: tGetTCFileList_pfd
// Desc:  This function is used to get a list of filenames on 16-bit platform. 
//
//
// Copyright (c) 1999-2000, Microsoft Corporation. All rights reserved.
//------------------------------------------------------------------------------*/

DRM_RESULT DRM_API tGetTCFileList_pfd(char *szTestFilePrefix, char **szPlatforms, char ***pszTestFileNames)
{
#ifdef _MSC_VER

	DRM_RESULT dr = DRM_SUCCESS;
	char szFN[MAX_PATH] = {0};
	DRM_DWORD dwCount = 0;
	ChkArg(szTestFilePrefix && szPlatforms && pszTestFileNames);

	strncpy(szFN, szTestFilePrefix,260);
	strncat(szFN, ".*.txt",7);

	if (DRM_E_BUFFERTOOSMALL != (dr = _tGetTCFileListImp(szFN, szPlatforms, NULL, &dwCount))) {
		ChkDR(dr);
	}

	ChkMem(*pszTestFileNames = (char**)OEM_malloc((dwCount + 1) * SIZEOF(char*)));
	ZeroMemory(*pszTestFileNames, (dwCount + 1) * sizeof(char*));
	ChkDR(_tGetTCFileListImp(szFN, szPlatforms, *pszTestFileNames, &dwCount));
ErrorExit:
	return dr;
#else /* _MSC_VER */
#ifdef __TMS320C55X__
    static char *testfile = "files\\DailyTestDrmManager.pc.pk.ce.txt";
    *pszTestFileNames = &testfile;
    return DRM_SUCCESS;
#else
	return DRM_E_NOTIMPL;
#endif

#endif /* _MSC_VER */
}			
#endif /*SixteenBitAddressing*/



