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


/*Most of function has additional argument using as flags to
  decide which input should be overwritten:
	1st bit overwrite g_pManagerContext_MNGR
	2nd bit overwrite g_pDecryptContext
	3rd bit overwrite g_pEncryptContext
 	4th bit overwrite g_oConditions 
	5th bit overwrite size 
	6th bit overwrite response
	7th bit overwrite g_pbData 
	8th bit Don't free g_pbData
*/

/*global variables*/
const DRM_WCHAR wszDevcertTemplateFileName[] = {
	    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 wszPrvKeyFileName[] = {
	    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')
	};

/**********************************************************/

DRM_CONST_STRING g_wszDeviceStoreName_MNGR = {0};
DRM_MANAGER_CONTEXT *g_pManagerContext_MNGR = NULL;
DRM_MANAGER_DECRYPT_CONTEXT *g_pDecryptContext = NULL;
DRM_MANAGER_ENCRYPT_CONTEXT *g_pEncryptContext = NULL;

DRM_BYTE *g_pbResponse = NULL;
DRM_DWORD g_cbResponse=0;

#define RESPONSECONTEXTSIZE 50000
_XMBContext *g_pbResponseContext = NULL;

DRM_BYTE *g_pbRevocationBuffer = NULL;

DRM_DWORD g_cbData=0; 
DRM_BYTE *g_pbData=NULL;


#define MAX_RIGHTS 5
DRM_DWORD g_numRights;
DRM_CONST_STRING *g_pwszRights[MAX_RIGHTS];

 
/*antirollback clock*/
long g_lOffset_MNGR=0;

static DRM_WORD g_wCurrentYear;

/*output protection level*/
const char *g_guidWMDRMDeviceCopy = "{00000507-0001-0010-8000-00AA006D2EA4}";
const char *g_guidPDDRMDeviceCopy = "{00000507-0002-0010-8000-00AA006D2EA4}";
const char *g_guidDownsample1 = "{00000507-0003-0010-8000-00AA006D2EA4}";
const char *g_guidDownsample2 = "{00000507-0004-0010-8000-00AA006D2EA4}";
const char *g_guidExtension1 = "{00000507-0005-0010-8000-00AA006D2EA4}";
const char *g_guidExtension2 = "{00000507-0006-0010-8000-00AA006D2EA4}";
const DRM_BYTE g_byteExtension1 =0x01;
const DRM_BYTE g_byteExtension2 =0x02;
DRM_WORD g_OPL[7];
#if DRM_SUPPORT_REVOCATION
DRM_STRING g_RevocationInfo = {NULL, 0};
DRM_STRING g_Revocation     = {NULL, 0};
#endif /* DRM_SUPPORT_REVOCATION */

/*multiple stores*/
char *g_szFilePath_MNGR=NULL;


/*Perf - timing info */
#ifdef PERF_TEST
DRM_UINT64 g_CurrTime, g_DiffTime;
#endif
/*GetLicenseData*/
static const DRM_WCHAR playonpcstring1 [] = { ONE_WCHAR('P', '\0'), ONE_WCHAR('l', '\0'), ONE_WCHAR('a', '\0'), ONE_WCHAR('y', '\0'), ONE_WCHAR('\0', '\0') };
static const DRM_WCHAR backupstring1[] = { ONE_WCHAR('B', '\0'), ONE_WCHAR('a', '\0'), ONE_WCHAR('c', '\0'), ONE_WCHAR('k', '\0'), ONE_WCHAR('u', '\0'), ONE_WCHAR('p', '\0'), ONE_WCHAR('\0', '\0') };
static const DRM_WCHAR burntocdstring1 [] = { ONE_WCHAR('P', '\0'), ONE_WCHAR('r', '\0'), ONE_WCHAR('i', '\0'), ONE_WCHAR('n', '\0'), ONE_WCHAR('t', '\0'), ONE_WCHAR('.', '\0'), ONE_WCHAR('r', '\0'), ONE_WCHAR('e', '\0'), ONE_WCHAR('d', '\0'), ONE_WCHAR('b', '\0'), ONE_WCHAR('o', '\0'), ONE_WCHAR('o', '\0'), ONE_WCHAR('k', '\0'), ONE_WCHAR('\0', '\0') };
static const DRM_WCHAR createpmlicensestring1 [] = { ONE_WCHAR('C', '\0'), ONE_WCHAR('R', '\0'), ONE_WCHAR('E', '\0'), ONE_WCHAR('A', '\0'), ONE_WCHAR('T', '\0'), ONE_WCHAR('E', '\0'), ONE_WCHAR('_', '\0'), ONE_WCHAR('P', '\0'), ONE_WCHAR('M', '\0'), ONE_WCHAR('_', '\0'), ONE_WCHAR('L', '\0'), ONE_WCHAR('I', '\0'), ONE_WCHAR('C', '\0'), ONE_WCHAR('E', '\0'), ONE_WCHAR('N', '\0'), ONE_WCHAR('S', '\0'), ONE_WCHAR('E', '\0'), ONE_WCHAR('\0', '\0') };
static const DRM_WCHAR badstring [] = { ONE_WCHAR('B', '\0'), ONE_WCHAR('a', '\0'), ONE_WCHAR('d', '\0'), ONE_WCHAR('S', '\0'), ONE_WCHAR('t', '\0'), ONE_WCHAR('r', '\0'), ONE_WCHAR('i', '\0'), ONE_WCHAR('n', '\0'), ONE_WCHAR('g', '\0'), ONE_WCHAR('\0', '\0') };
	
#ifdef SIXTEEN_BIT_ADDRESSING
const DRM_WCHAR   DEVCERT_FILE_NAME16 []           = { 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 testfilespath[] = { ONE_WCHAR('f','\0'),ONE_WCHAR('i','\0'),ONE_WCHAR('l','\0'),ONE_WCHAR('e','\0'),ONE_WCHAR('s','\0'),ONE_WCHAR('\0','\0')};
int track;
#endif
static DRM_RESULT tDRM_KG_GenerateContentKey(DRM_CONST_STRING *pszKeySeed, DRM_CONST_STRING *pszKid, DRM_CONST_STRING *pszKey)
{
	DRM_RESULT dr;
	dr = DRM_KG_GenerateContentKey((DRM_WCHAR*)pszKeySeed->pwszString, pszKeySeed->cchString, (DRM_WCHAR*)pszKid->pwszString, pszKid->cchString, NULL, &pszKey->cchString);
	if (dr != DRM_E_BUFFERTOOSMALL)
		ChkDR(dr);
	OEM_free((void *)(pszKey->pwszString));
	ChkMem(pszKey->pwszString = (DRM_WCHAR*)OEM_malloc(pszKey->cchString * SIZEOF(DRM_WCHAR)));
	ChkDR(DRM_KG_GenerateContentKey((DRM_WCHAR*)pszKeySeed->pwszString, pszKeySeed->cchString, (DRM_WCHAR*)pszKid->pwszString, pszKid->cchString, (DRM_WCHAR*)pszKey->pwszString, &pszKey->cchString));
ErrorExit:
	return dr;
}

/* stolen from blackbox.c */
static DRM_RESULT _GetDevicePrivkey( 
    IN OUT DRM_BB_CONTEXT *f_pcontextBBX,
       OUT PRIVKEY        *f_pDevPrivkey)
{
    DRM_RESULT dr=DRM_SUCCESS;
    PRIVKEY    GCPrivkey;

    ChkArg( f_pcontextBBX != NULL 
         && f_pDevPrivkey != NULL);

    ChkDR(OEM_GetGroupCertPrivateKey(&GCPrivkey));

    ChkDR( DRM_PK_SymmetricCrypt( (DRM_BYTE*)&GCPrivkey,
                                    SIZEOF(GCPrivkey),
                                    SIZEOF(PRIVKEY),
                                    f_pcontextBBX->cachedCertValues.m_blobDevicePrivkey,
                                    SIZEOF(PRIVKEY),
                                    (DRM_BYTE *)f_pDevPrivkey ) );

ErrorExit:
    ZEROMEM((DRM_BYTE*)&GCPrivkey, SIZEOF(PRIVKEY));  /* trash the key in memory */
    return dr;    
}

/* Scan the context memory for the device private key. This verifies the context doesn't contain the key by accident. */
static DRM_RESULT TestScanDevicePrivateKey(DRM_MANAGER_CONTEXT *pManagerContext)
{
	DRM_RESULT dr;
	DRM_DWORD i;
	PRIVKEY pvkDevice;
	DRM_MANAGER_CONTEXT_INTERNAL *pContext = (DRM_MANAGER_CONTEXT_INTERNAL*)pManagerContext;

	ChkArg(pContext);

	/* Get the device private key */
	ChkDR(_GetDevicePrivkey(&pContext->oBlackBoxContext, &pvkDevice));
	
	for (i = 0; i < DRM_DRMMANAGER_CONTEXT_BUFFER_SIZE - SIZEOF(PRIVKEY) + 1; i++) {
		if (!MEMCMP(((DRM_BYTE*)pContext) + i, (DRM_BYTE*)&pvkDevice, SIZEOF(PRIVKEY))) {
			Log("Trace", "DRMManager context keeps the device private key in memory!");
			ChkDR(DRM_E_FAIL);
			
		}
	}
ErrorExit:
	return dr;
}

DRM_RESULT TestManagerReinitialize(long argc, char **argv)
{
	DRM_RESULT dr=DRM_SUCCESS;
	int iIndex=0;
	
	if(argv){
		iIndex=(int)OEM_atoi(argv[0]);
	}
	if(iIndex==0||iIndex==1){
		ChkDR(TestScanDevicePrivateKey(g_pManagerContext_MNGR));
	
		START_TIMER(g_CurrTime);
		DRM_MGR_Uninitialize(g_pManagerContext_MNGR);
		STOP_TIMER("DRM_MGR_Uninitialize",g_CurrTime,g_DiffTime);
		MEMSET(g_pManagerContext_MNGR, 0, SIZEOF(DRM_MANAGER_CONTEXT));
		if(argc==1||(argc==2 && 1==OEM_atoi(argv[1]))){
			/*for multple store case, we will initialize drmmanager context with different store address*/
			START_TIMER(g_CurrTime);
			dr = DRM_MGR_Initialize(g_pManagerContext_MNGR, &g_wszDeviceStoreName_MNGR);
			#if DRM_SUPPORT_REVOCATION
       		     ChkDR( DRM_MGR_SetRevocationBuffer( g_pManagerContext_MNGR, g_pbRevocationBuffer, REVOCATION_BUFFER_SIZE ) );
			#endif
		
			STOP_TIMER("DRM_MGR_Initialize",g_CurrTime,g_DiffTime);
			ChkDR( dr );
		}
	}
	
#if 0
	if(iIndex==0||iIndex==4){		
		START_TIMER(g_CurrTime);
	 	DRM_MGR_Commit(g_pManagerContext_MNGR); /*Need to call Bind first */
		STOP_TIMER("DRM_MGR_Commit",g_CurrTime,g_DiffTime); 		
	}
#endif
	if(iIndex==0||iIndex==2){
		if (!g_pDecryptContext) {
			ChkMem(g_pDecryptContext = (DRM_MANAGER_DECRYPT_CONTEXT*)OEM_malloc(SIZEOF(DRM_MANAGER_DECRYPT_CONTEXT)));
		}
 		MEMSET(g_pDecryptContext, 0, SIZEOF(DRM_MANAGER_DECRYPT_CONTEXT)); 
	}
	if(iIndex==0||iIndex==3){
 		if (!g_pEncryptContext) {
			ChkMem(g_pEncryptContext = (DRM_MANAGER_ENCRYPT_CONTEXT*)OEM_malloc(SIZEOF(DRM_MANAGER_ENCRYPT_CONTEXT)));
		}
		MEMSET(g_pEncryptContext, 0, SIZEOF(DRM_MANAGER_ENCRYPT_CONTEXT)); 
	}
 	if(iIndex==0||iIndex==5){
 		SAFE_OEM_FREE(g_pbResponse);
		g_pbResponse=NULL;
		g_cbResponse=0;
	}
	if(iIndex==0||iIndex==6){
 		SAFE_OEM_FREE(g_pbData);
		g_pbData=NULL;
		g_cbData=0;
	}

	/*for multiple store purpose, we sometimes don't want to remove this store  */
	if((iIndex==0 && argc==1)||iIndex==20||(iIndex==0&& argc==2 && 2==OEM_atoi(argv[1])))
		RemoveDRMFile(RMFILE_STORE);
ErrorExit:
	return dr;
}

/* Only test this for the NULL parameter case. PreTestCase calls DRM_MGR_Initialize for other cases. */
DRM_RESULT TestManagerInitialize(long argc, char **argv)
{
	DRM_RESULT dr;
	
	if (argc == 1 && !argv[0])
	{
		START_TIMER(g_CurrTime);
		dr = DRM_MGR_Initialize(NULL, &g_wszDeviceStoreName_MNGR);
		
		STOP_TIMER("DRM_MGR_Initialize",g_CurrTime,g_DiffTime);
	}
	else
		dr = DRM_SUCCESS;
  	
	return dr;
}

/*argv[0]: offset in seconds, positive to go forward, negative to rollback*/
DRM_RESULT TestManagerChangeTime(long argc, char **argv)
{
	DRM_RESULT dr=DRM_SUCCESS;
	long lOffset;
 
	ChkArg(argc == 1 && argv[0]);
	lOffset = OEM_atol(argv[0]);
	tChangeSystemTime(lOffset);
	g_lOffset_MNGR += lOffset;
#ifdef WINCE_TEST
	Sleep(2000);
#endif
ErrorExit:
  	return dr;
}

#if DRM_SUPPORT_REVOCATION
/*
	Read in Revocation Info from file (wide char b64 encoded)
	argv[0]: file path
*/
DRM_RESULT TestManagerSetRevocationInfo(long argc, char **argv)
{
	DRM_RESULT dr = DRM_SUCCESS;
 	ChkArg(argc == 1);

	SAFE_OEM_FREE(g_RevocationInfo.pwszString);
	g_RevocationInfo.pwszString = NULL;

	if (argv[0])
	{
		ChkArg(LoadTestFile(NULL,
				    argv[0],
				    (DRM_BYTE**)(&(g_RevocationInfo.pwszString)),
				    &g_RevocationInfo.cchString));
	}
	g_RevocationInfo.cchString = DRM_wcslen(g_RevocationInfo.pwszString);
	ChkDR(TestResponseAddRevocationInfo(g_pbResponseContext, (DRM_CONST_STRING *) &g_RevocationInfo));
    
ErrorExit:
	return dr;
}

/*
Read in Revocation from file (wide char b64 encoded)
argv[0]: file path
*/
DRM_RESULT TestManagerSetRevocation(long argc, char **argv)
{
	DRM_RESULT dr = DRM_SUCCESS;
	DRM_CONST_STRING dstrGUID = {NULL, 0};

	ChkArg(argc == 2);


	#ifdef SIXTEEN_BIT_ADDRESSING
	/*Using MakeDRMString rather than mbstowcs, since it is the prefered way of conversion to wide
  	   char. Eventually, all mbstowcs will be replaced even on 32-bit*/
		MakeDRMString(&dstrGUID,argv[0]);
	#else
		dstrGUID.cchString = DX_VOS_StrLen(argv[0]);
		dstrGUID.pwszString = (DRM_WCHAR *) OEM_malloc(SIZEOF(DRM_WCHAR) * (dstrGUID.cchString + 1));
		ChkMem(dstrGUID.pwszString);
		OEM_mbstowcs((DRM_WCHAR *) dstrGUID.pwszString, argv[0], dstrGUID.cchString + 1);
	#endif

	SAFE_OEM_FREE(g_Revocation.pwszString);
	g_Revocation.pwszString = NULL;
	if (argv[1])
	{
		ChkArg(LoadTestFile(NULL,
				    argv[1],
				    ((DRM_BYTE**)&(g_Revocation.pwszString)),
				    &g_Revocation.cchString));
	}

	g_Revocation.cchString = DRM_wcslen(g_Revocation.pwszString);

	ChkDR(TestResponseAddRevocation(g_pbResponseContext, &dstrGUID, (DRM_CONST_STRING *) &g_Revocation));

 ErrorExit:
	OEM_free((DRM_WCHAR *) dstrGUID.pwszString);
    
	return dr;
}

/*
	Get Revocation Info
        argv[0] - optional file to compare against
*/
DRM_RESULT TestManagerGetRevocationInfo(long argc, char **argv)
{
	DRM_RESULT  dr = DRM_SUCCESS;
        DRM_BYTE   *pbRevInfo = NULL;
        DRM_DWORD   cbRevInfo;
        DRM_BYTE   *pbExpected = NULL;
        DRM_DWORD   cbExpected = 0;

	
	dr = DRM_MGR_GetRevInfo(g_pManagerContext_MNGR, pbRevInfo, &cbRevInfo);
        if ( DRM_E_BUFFERTOOSMALL == dr )
        {
            pbRevInfo = (DRM_BYTE *) OEM_malloc(cbRevInfo);
            ChkMem(pbRevInfo);
            dr = DRM_MGR_GetRevInfo(g_pManagerContext_MNGR, pbRevInfo, &cbRevInfo);
        }
        ChkDR(dr);

        if ( 1 == argc )
	{
            if ( NULL == argv[0] )
            {
                ChkArg( 0 == cbRevInfo );
            }
            else
            {
		ChkArg(LoadTestFile(NULL,
				    argv[0],
				    &pbExpected,
				    &cbExpected));
                ChkArg( cbExpected == cbRevInfo
                    &&  0 == MEMCMP(pbExpected, pbRevInfo, cbRevInfo) );
            }
	}

ErrorExit:
        SAFE_OEM_FREE(pbRevInfo);
        SAFE_OEM_FREE(pbExpected);

	return dr;
}

/*
Get Revocation List
argv[0]: GUID to retrieve
*/
DRM_RESULT TestManagerGetRevocationList(long argc, char **argv)
{
	DRM_RESULT dr = DRM_SUCCESS;
	DRM_CONST_STRING dstrGUID = {NULL, 0};
        DRM_REVOCATION_TYPE_ENUM eRevType = WM_DRM_REVOCATION_TYPE_WMDRMND;
        DRM_BYTE *pbBuffer = NULL;
        DRM_DWORD cbBuffer = 0;
	 DRM_BYTE *pbExpected = NULL;
        DRM_DWORD cbExpected = 0;
        DRM_DWORD dwVersion;
	 DRM_BYTE *pbDecoded = NULL;
        DRM_DWORD cbDecoded = 0;
        DRM_STRING dstrEncodedData;
        DRM_STRING dstrRevocationList;
        DRM_STRING dstrTemplate = {NULL, 0};
	DRM_CONST_STRING *buff = {0};
	const DRM_DWORD level=0;
	DRM_DWORD level1 = 1;
	

	ChkArg(argc >= 1);

        if ( 0 == DX_VOS_StrCmp(argv[0], "{90A37313-0ECF-4CAA-A906-B188F6129300}") )
        {
            eRevType =  WM_DRM_REVOCATION_TYPE_APP;
        }
        else if ( 0 == DX_VOS_StrCmp(argv[0], "{3129E375-CEB0-47D5-9CCA-9DB74CFD4332}") )
        {
            eRevType = WM_DRM_REVOCATION_TYPE_WMDRMPD;
        }
        else if ( 0 == DX_VOS_StrCmp(argv[0], "{CD75E604-543D-4A9C-9F09-FE6D24E8BF90}") )
        {
            eRevType = WM_DRM_REVOCATION_TYPE_WMDRMND;
        }
        else
        {
            ChkArg(0 /* not a recognized guid */);
        }

        dr = DRM_MGR_GetRevocationList(g_pManagerContext_MNGR,
                                       eRevType,
                                       pbBuffer,
                                       &cbBuffer,
                                       &dwVersion);
        if ( DRM_E_BUFFERTOOSMALL == dr )
        {
            pbBuffer = (DRM_BYTE *) OEM_malloc(cbBuffer);
            ChkMem(pbBuffer);
            dr = DRM_MGR_GetRevocationList(g_pManagerContext_MNGR,
                                           eRevType,
                                           pbBuffer,
                                           &cbBuffer,
                                           &dwVersion);
        }
      ChkDR(dr);

        if ( 2 == argc )
	{
                if ( NULL == argv[1] ) {
                    ChkArg( 0 == cbBuffer );
                }
                else
                {
                    ChkArg(LoadTestFile(NULL,
                                        argv[1],
                                        &pbExpected,
                                        &cbExpected));
                    /* decode the XML for the new exclusion list */
                    cbDecoded = cbExpected;
                    pbDecoded = (DRM_BYTE *) OEM_malloc(cbDecoded);
                    ChkMem(pbDecoded);
                    DSTR_FROM_PB(&dstrEncodedData, pbExpected, cbExpected);
                    ChkDR( DRM_B64_DecodeW( (DRM_CONST_STRING *) &dstrEncodedData,
                                             &cbDecoded, 
                                            pbDecoded, 
                                            0 ) );
                    
                    if ( WM_DRM_REVOCATION_TYPE_WMDRMND == eRevType )
                    {



						DSTR_FROM_PB( &dstrRevocationList, pbDecoded, cbDecoded );
	
                      /* find the <TEMPLATE> tag and base64 decode its delicious contents */
			/*Note that the parameter buff is used to pass NULL. It is used here instead
                          of actually passing NULL for making it work on 16-bit TI emulator*/
						ChkDR( DRM_XML_GetSubNode(  (DRM_CONST_STRING*)&dstrRevocationList, 
                                                    &g_dstrTemplate, 
                                                    buff,
                                                    buff, 
                                                    level, 
                                                    buff,
                                 (DRM_CONST_STRING*)&dstrTemplate,
                                                    level1 ) );
						  
                       ChkDR( DRM_B64_DecodeW( (DRM_CONST_STRING*)&dstrTemplate,
                                            &cbDecoded,
                                            NULL,
                                            DRM_BASE64_DECODE_IN_PLACE ) );

                       ChkArg( cbDecoded == cbBuffer
                                &&  0 == MEMCMP(dstrTemplate.pwszString, pbBuffer, cbBuffer) );
                        
                    }
                    else
                    {
                        ChkArg( cbDecoded == cbBuffer
                                &&  0 == MEMCMP(pbDecoded, pbBuffer, cbBuffer) );                    
                    }
                }

	}

 ErrorExit:
	SAFE_OEM_FREE(pbExpected);
        SAFE_OEM_FREE(pbBuffer);
        SAFE_OEM_FREE(pbDecoded);

	return dr;
}

/*
Name: TestUpdateRevocationVersionsCache
Desc: This method is used to verify DRM_MGR_UpdateRevocationVersionsCache. This should be called before
DRM_MGR_BIND is called. If RevInfo is present in the secure store, the Boolean pointer passed will be set to
TRUE, else it would be set to FALSE. 
Parameters:
    Parameter 1: flag indicating whether we expect the Boolean value passed to
                        DRM_MGR_UpdateRevocationVersionsCache to be set TRUE or FALSE. 
 */
TestUpdateRevocationVersionsCache(long argc, char **argv)
{
    DRM_RESULT dr = DRM_SUCCESS; 
    DRM_BOOL fUpdated;
    int fExpected;
    
    

    if(argc != 1)
    {
         Log("Trace", "\t\tFrom TesUpdateRevocationVersionsCache : Incorrect number of arguments\n");
	  ChkDR(DRM_E_FAIL);
    }
    if(g_pManagerContext_MNGR == NULL)
    {
         Log("Trace", "\t\tFrom TesUpdateRevocationVersionsCache : Drm manager context is NULL\n");
	  ChkDR(DRM_E_FAIL);
    }

    fExpected = (int)OEM_atoi(argv[0]);

    dr = DRM_MGR_UpdateRevocationVersionsCache(g_pManagerContext_MNGR,&fUpdated);
    ChkDR(dr);
    if(fExpected != fUpdated)
    {
         Log("Trace", "\t\tFrom TesUpdateRevocationVersionsCache : Revocation Cache result was not as expected\n");
	  ChkDR(DRM_E_FAIL);
    }
	
ErrorExit:
    return dr;
}

/* TestManagerStoreRevocationLists sets several revocation lists to the store at once from an
array of DRM_RVK_LIST structures.  argv contains a list of an arbitrary set of GUID/data file 
pairs.  This API builds a set of revocation lists from the specified args.

argv[0]= number of rev lists to store.

Odd argvs are GUIDs.  Even argvs are file paths for the rev lists to use.
*/
DRM_RESULT TestManagerStoreRevocationLists(long argc, char **argv)
{
	DRM_RESULT dr = DRM_SUCCESS;
	DRM_DWORD dwRevLists = 0;
	DRM_DWORD i = 0;
	DRM_RVK_LIST *pRevLists = NULL;
	DRM_RVK_LIST *pTemp = NULL;
	DRM_CONST_STRING dstrGUID = EMPTY_DRM_STRING;
	DRM_CONST_STRING dstrCRL = EMPTY_DRM_STRING;
	DRM_GUID revTypeGUID = {0};
	DRM_BYTE *pbRevList = NULL;
	DRM_DWORD cbRevList = 0;

	ChkArg( argc >= 1 && argv[0] );

	dwRevLists = OEM_atoi(argv[0]);

	//allocate enough space for all the revlist/GUID pairs passed as arguments 
	pRevLists = OEM_malloc(SIZEOF(DRM_RVK_LIST) * dwRevLists);
	ZEROMEM( (DRM_BYTE*)pRevLists, SIZEOF(DRM_RVK_LIST) * dwRevLists );
	pTemp=pRevLists;

	//iterate through argvs, filling out the DRM_RVK_LIST 
	//structure for each GUID/RL pair.
	for ( i = 1; (long)i < argc ; i=i+2)
	{

		//Get the GUID from the command line and set it in the DRM_RVK_LIST struct.
		if (argv[i])
		{
			MakeDRMString(&dstrGUID, argv[i]);
			ChkDR(DRM_UTL_StringToGuid(&dstrGUID, &pTemp->guidRevocationList));
		}

		//Get the rev list and store it.
		if (argv[i+1])
		{
			ChkArg(LoadTestFile(NULL, argv[i+1], &pbRevList, &cbRevList));
			pTemp->pbRevocationList = pbRevList;
			pTemp->cbRevocationList = cbRevList;

		}
		pTemp++;

	}

	ChkDR(DRM_MGR_StoreRevocationLists ( g_pManagerContext_MNGR, dwRevLists, pRevLists ) );

ErrorExit:
	OEM_free(pRevLists);
	return dr;
}

/*
Name: TestManagerGetLicenseRevInfoVersion
Desc: This method is used to verify the rev info returned by DRM_MGR_GetLicenseRevInfoVersion
Parameters:
    Parameter 1: revinfo version which is expcted to be present in drm manager context.
    Parameter 2: Flag indicating whether NULL should be passed for DRM Manager Context.
    Parameter 3: Flag indicating whether NULL should be passed for the variable holding the rev info
                        result from the API
*/
DRM_RESULT TestManagerGetLicenseRevInfoVersion(long argc, char **argv)
{
    DRM_RESULT dr = DRM_SUCCESS;
    DRM_LONG lRevInfoVer = 0;
    DRM_MANAGER_CONTEXT *pContext = NULL;
    DRM_DWORD dwReturnedRevInfoVer = 0;
    DRM_DWORD *pdwReturnedRevInfoVer = NULL;

    if(argc != 3)
    {
        Log("Trace", "\t\tFrom TestManagerGetLicenseRevInfoVersion: error in argument.");
        ChkDR( DRM_E_FAIL );
    }
    
    lRevInfoVer = (DRM_LONG)OEM_atol(argv[0]);
    
    if( OEM_atol(argv[1]) != 0 )
    {
        pContext = g_pManagerContext_MNGR;
    }

    if( OEM_atol(argv[2]) != 0 )
    {
        pdwReturnedRevInfoVer = &dwReturnedRevInfoVer;
    }

    ChkDR( DRM_MGR_GetLicenseRevInfoVersion( pContext, pdwReturnedRevInfoVer ) );

    if(dwReturnedRevInfoVer != lRevInfoVer)
    {
        Log("Trace", "\t\tFrom TestManagerGetLicenseRevInfoVersion: Rev Info Version Mismatch");
        ChkDR(DRM_E_FAIL);
    }	
ErrorExit:
	return dr;
}

#endif /* DRM_SUPPORT_REVOCATION */

/* Add a right string to the global g_wszRights array.
	argv[0]: the right string
*/
DRM_RESULT TestManagerSetRights(long argc, char **argv)
{
	DRM_RESULT dr=DRM_SUCCESS;
	ChkArg(argc == 1 && argv[0]);
	ChkArg(g_numRights < MAX_RIGHTS);

	ChkMem(g_pwszRights[g_numRights] = (DRM_CONST_STRING*)OEM_malloc(SIZEOF(DRM_CONST_STRING)));
	MakeDRMString(g_pwszRights[g_numRights], argv[0]);
	g_numRights++;
ErrorExit:
  	return dr;
}

/*
	argv[0]: DRMManager context status: NULL or Normal
	argv[1]: v2 header file name or NULL
	argv[2]: optional length for the header
*/
DRM_RESULT TestManagerSetV2Header(long argc, char **argv)
{
	DRM_RESULT dr=DRM_SUCCESS;
	DRM_DWORD cbHeader=0; 
	DRM_BYTE *pbHeader=NULL;
	DRM_CONST_STRING dstrHeader = {0};
	
	ChkArg(argc >= 2);

	if (argv[1]) {
		
		ChkArg(LoadTestFile("files", argv[1], &pbHeader, &cbHeader));
		MakeDRMString(&dstrHeader, (DRM_CHAR*)pbHeader);
		dstrHeader.cchString *= SIZEOF(DRM_WCHAR);
	}

	if (argc > 2 && argv[2]) {
		cbHeader = OEM_atol(argv[2]);
		ChkArg(cbHeader <= dstrHeader.cchString);
		dstrHeader.cchString = cbHeader;
	}

	START_TIMER(g_CurrTime);
	
		
	dr = DRM_MGR_SetV2Header(argv[0]? g_pManagerContext_MNGR: NULL, (const DRM_BYTE*)dstrHeader.pwszString, dstrHeader.cchString);
	
	STOP_TIMER("DRM_MGR_SetV2Header",g_CurrTime,g_DiffTime);

	ChkDR( dr );
	
ErrorExit:
	SAFE_OEM_FREE(pbHeader);
	OEM_free((DRM_VOID*)dstrHeader.pwszString);
  	return dr;
}

DRM_RESULT TestManagerGetLicenseData(long argc, char **argv)
{
	DRM_RESULT dr=DRM_SUCCESS;
	DRM_MANAGER_CONTEXT *pLocalManagerContext = NULL;
	DRM_DWORD dwNumActionsQueried;
	long i, iOption, iActionOption;
	
#define DRM_RIGHTS_STRING_COUNT 3
	DRM_LICENSE_STATE_DATA pStateData[DRM_RIGHTS_STRING_COUNT] = {0};
	const DRM_CONST_STRING **ppwszAction = NULL;

	static const DRM_CONST_STRING PLAY_ON_PC_STRING1 = CREATE_DRM_STRING( playonpcstring1);
	static const DRM_CONST_STRING BACKUP_STRING1 = CREATE_DRM_STRING(backupstring1 );
	static const  DRM_CONST_STRING BURN_TO_CD_STRING1 = CREATE_DRM_STRING(burntocdstring1);
	static const DRM_CONST_STRING CREATE_PM_LICENSE_STRING1   = CREATE_DRM_STRING(createpmlicensestring1);
	static const DRM_CONST_STRING BAD_STRING   = CREATE_DRM_STRING(badstring);
	/*three valid actions*/
	const DRM_CONST_STRING *DRM_RIGHT_BITS_TO_STRING_1[DRM_RIGHTS_STRING_COUNT] = 
	{
		&PLAY_ON_PC_STRING1,
		&CREATE_PM_LICENSE_STRING1,
		&BURN_TO_CD_STRING1,    
	};
	/*include invalid actions*/
	const DRM_CONST_STRING *DRM_RIGHT_BITS_TO_STRING_2[DRM_RIGHTS_STRING_COUNT] = 
	{
		&PLAY_ON_PC_STRING1,
		&BAD_STRING,
		&BACKUP_STRING1,    
	};
	/*only one valid action*/
	const DRM_CONST_STRING *DRM_RIGHT_BITS_TO_STRING_3[1] = 
	{
		&PLAY_ON_PC_STRING1,
 	};
 
 	for(i=0; i<argc; i++){
		Log("Trace", "\t\tFrom TestManagerGetLicenseData: argv[%d]=%s", i, argv[i]);
	}
 	/*at least 5 arguments. The last one is used to decide whether we need to overwrite the context*/
 	if(argc<5){
		Log("Trace", "\t\tFrom TestManagerGetLicenseData: error in number of arguments.");
		ChkDR(DRM_E_FAIL);
	}
	
	if(!IsDigitalOnlyString(argv[3])||!IsDigitalOnlyString(argv[4])){ 
		Log("Trace", "\t\tFrom TestManagerGetLicenseData: error in the argument.");
		ChkDR(DRM_E_FAIL);
	}
  
 	iOption=OEM_atol(argv[4]);
	/*manager context*/
	if ((iOption&1) && argv[0]) { /*Context is from the input*/
		ChkMem(pLocalManagerContext = (DRM_MANAGER_CONTEXT*)OEM_malloc(SIZEOF(DRM_MANAGER_CONTEXT)));
		MEMSET(pLocalManagerContext, 0, SIZEOF(DRM_MANAGER_CONTEXT));
		MEMCPY(pLocalManagerContext->rgbOpaqueBuffer, argv[0], min(DX_VOS_StrLen(argv[0])+1, DRM_DRMMANAGER_CONTEXT_BUFFER_SIZE));
	}
	
	/*num actions queried*/
	dwNumActionsQueried = argv[3]? (DRM_DWORD)OEM_atol(argv[3]): 0;

	iActionOption = argv[1]? OEM_atol(argv[1]): 0;
	switch (iActionOption) {
		case 1:
			ppwszAction = DRM_RIGHT_BITS_TO_STRING_1;
			break;
		case 2:
			ppwszAction = DRM_RIGHT_BITS_TO_STRING_2;
			break;
		case 3:
			ppwszAction = DRM_RIGHT_BITS_TO_STRING_3;
			break;
		default:
			ppwszAction = NULL;
	}

	START_TIMER(g_CurrTime);
	dr = DRM_MGR_GetLicenseData(
		(iOption & 1)? pLocalManagerContext: g_pManagerContext_MNGR,
		ppwszAction,
		argv[2]? pStateData: NULL,
		dwNumActionsQueried);

	
	STOP_TIMER("DRM_MGR_GetLicenseData",g_CurrTime,g_DiffTime);
	ChkDR( dr );
 
ErrorExit:
	SAFE_OEM_FREE(pLocalManagerContext);
   	return dr;
}

DRM_RESULT TestManagerPrepareOPLCallback(long argc, char **argv)
{
	DRM_RESULT dr=DRM_SUCCESS;
 	/*
			wCompressedDigitalVideo;
			wUncompressedDigitalVideo;
			wAnalogVideo;
			wCompressedDigitalAudio;
			wUncompressedDigitalAudio;
			downsample number
			extension number
	*/
	#ifdef SIXTEEN_BIT_ADDRESSING
		g_OPL[0]=(DRM_WORD)OEM_atoi(argv[0]);
		g_OPL[1]=(DRM_WORD)OEM_atoi(argv[1]);
		g_OPL[2]=(DRM_WORD)OEM_atoi(argv[2]);
		g_OPL[3]=(DRM_WORD)OEM_atoi(argv[3]);
		g_OPL[4]=(DRM_WORD)OEM_atoi(argv[4]);
		g_OPL[5]=(DRM_WORD)OEM_atoi(argv[5]);
		g_OPL[6]=(DRM_WORD)OEM_atoi(argv[6]);
	#else
		g_OPL[0]=(DRM_WORD)OEM_atol(argv[0]);
		g_OPL[1]=(DRM_WORD)OEM_atol(argv[1]);
		g_OPL[2]=(DRM_WORD)OEM_atol(argv[2]);
		g_OPL[3]=(DRM_WORD)OEM_atol(argv[3]);
		g_OPL[4]=(DRM_WORD)OEM_atol(argv[4]);
		g_OPL[5]=(DRM_WORD)OEM_atol(argv[5]);
		g_OPL[6]=(DRM_WORD)OEM_atol(argv[6]);
	#endif

	
  
 	return dr;	
}

DRM_RESULT DRM_API OPLCallback(
    IN const DRM_VOID  *f_pvOutputLevelsData,
    IN       DRM_DWORD  f_dwCallbackType,
    IN const DRM_VOID  *f_pv )
{
	DRM_RESULT dr=DRM_SUCCESS;
 	DRM_PLAY_OPL *f_pOutputLevels=NULL; 
 	DRM_GUID localGuid;
 	DRM_CONST_STRING wszGUID = {0};
 
	if(f_dwCallbackType==DRM_PLAY_OPL_CALLBACK){
		f_pOutputLevels=(DRM_PLAY_OPL*)f_pvOutputLevelsData;
		/* 1. check wCompressedDigitalVideo;
			wUncompressedDigitalVideo;
			wAnalogVideo;
			wCompressedDigitalAudio;
			wUncompressedDigitalAudio;
		*/
		/*check the min level of wCompressedDigitalVideo*/
		if(f_pOutputLevels->minOPL.wCompressedDigitalVideo!=g_OPL[0]){
			ChkDR(DRM_E_FAIL);
		}		
		/*check the min level of wCompressedDigitalVideo*/
		if(f_pOutputLevels->minOPL.wUncompressedDigitalVideo!=g_OPL[1]){
			ChkDR(DRM_E_FAIL);
		}		
		/*check the min level of wCompressedDigitalVideo*/
		if(f_pOutputLevels->minOPL.wAnalogVideo!=g_OPL[2]){
			ChkDR(DRM_E_FAIL);
		}		
		/*check the min level of wCompressedDigitalVideo*/
		if(f_pOutputLevels->minOPL.wCompressedDigitalAudio!=g_OPL[3]){
			ChkDR(DRM_E_FAIL);
		}		
		/*check the min level of wCompressedDigitalVideo*/
		if(f_pOutputLevels->minOPL.wUncompressedDigitalAudio!=g_OPL[4]){
			ChkDR(DRM_E_FAIL);
		}		


		//2. the number of downsamples should be matched
		if(f_pOutputLevels->oplIdReserved.cIds!=g_OPL[5]){
			ChkDR(DRM_E_FAIL);	
		}

		// examine the downsamples. Only check up to two downsamples
 
		if(f_pOutputLevels->oplIdReserved.cIds>=1){
			MakeDRMString(&wszGUID,g_guidDownsample1);
		    DRM_UTL_StringToGuid(&wszGUID, (DRM_GUID*)&localGuid);
			OEM_free((void*)(wszGUID.pwszString));
			if(MEMCMP(&(f_pOutputLevels->oplIdReserved.rgIds[0]), &localGuid, SIZEOF(DRM_GUID)) != 0 ){
				/*Using DRM_E_FAIL for 16-bit since S_FALSE is not defined on 16-bit platform*/
				 #ifdef SIXTEEN_BIT_ADDRESSING
				     ChkDR(DRM_E_FAIL);
				 #else
				     ChkDR(S_FALSE);
				 #endif
			}
		}
		if(f_pOutputLevels->oplIdReserved.cIds>=2){
			MakeDRMString(&wszGUID,g_guidDownsample2);
		    DRM_UTL_StringToGuid(&wszGUID, (DRM_GUID*)&localGuid);
			OEM_free((void*)(wszGUID.pwszString));
			if(MEMCMP(&(f_pOutputLevels->oplIdReserved.rgIds[1]), &localGuid, SIZEOF(DRM_GUID)) != 0 ){
				/*Using DRM_E_FAIL for 16-bit since S_FALSE is not defined on 16-bit platform*/
				 #ifdef SIXTEEN_BIT_ADDRESSING
				     ChkDR(DRM_E_FAIL);
				 #else
				     ChkDR(S_FALSE);
				 #endif
			}
		}
    
		//3. the number of extension entries should be matched
		if(f_pOutputLevels->vopi.cEntries!=g_OPL[6]){
			ChkDR(DRM_E_FAIL);	
		}
    
		/*extension GUID and configuration data, up to two*/
		if(f_pOutputLevels->vopi.cEntries>=1){
			MakeDRMString(&wszGUID,g_guidExtension1);
		    DRM_UTL_StringToGuid(&wszGUID, (DRM_GUID*)&localGuid);
			OEM_free((void*)(wszGUID.pwszString));
			if(MEMCMP(&(f_pOutputLevels->vopi.rgVop[0].guidId), &localGuid, SIZEOF(DRM_GUID)) != 0 ){
				/*Using DRM_E_FAIL for 16-bit since S_FALSE is not defined on 16-bit platform*/
				#ifdef SIXTEEN_BIT_ADDRESSING
				     ChkDR(DRM_E_FAIL);
				 #else
				     ChkDR(S_FALSE);
				 #endif
			}
			if(MEMCMP(&(f_pOutputLevels->vopi.rgVop[0].bConfigData), &g_byteExtension1, SIZEOF(DRM_BYTE)) != 0 ){
				/*Using DRM_E_FAIL for 16-bit since S_FALSE is not defined on 16-bit platform*/
				#ifdef SIXTEEN_BIT_ADDRESSING
				     ChkDR(DRM_E_FAIL);
				 #else
				     ChkDR(S_FALSE);
				 #endif
			}
		}

		if(f_pOutputLevels->vopi.cEntries>=2){
			MakeDRMString(&wszGUID,g_guidExtension2);
		    DRM_UTL_StringToGuid(&wszGUID, (DRM_GUID*)&localGuid);
			OEM_free((void*)(wszGUID.pwszString));
			if(MEMCMP(&(f_pOutputLevels->vopi.rgVop[1].guidId), &localGuid, SIZEOF(DRM_GUID)) != 0 ){
				/*Using DRM_E_FAIL for 16-bit since S_FALSE is not defined on 16-bit platform*/
				#ifdef SIXTEEN_BIT_ADDRESSING
				     ChkDR(DRM_E_FAIL);
				 #else
				     ChkDR(S_FALSE);
				 #endif
			}
			if(MEMCMP(&(f_pOutputLevels->vopi.rgVop[1].bConfigData), &g_byteExtension2, SIZEOF(DRM_BYTE)) != 0 ){
				/*Using DRM_E_FAIL for 16-bit since S_FALSE is not defined on 16-bit platform*/
				#ifdef SIXTEEN_BIT_ADDRESSING
				     ChkDR(DRM_E_FAIL);
				 #else
				     ChkDR(S_FALSE);
				 #endif
			}
		}
	}
	else if(f_dwCallbackType==DRM_COPY_OPL_CALLBACK){
		ChkDR(DRM_E_FAIL);
	}
    else if(f_dwCallbackType==DRM_INCLUSION_LIST_CALLBACK)
    {
        dr = DRM_SUCCESS;
    }
	else{
		ChkDR(DRM_E_FAIL);
	}

ErrorExit:
     return dr;
}
		

DRM_RESULT TestManagerBind(long argc, char **argv)
{
	DRM_RESULT dr=DRM_SUCCESS;
	DRM_MANAGER_CONTEXT *pLocalManagerContext = NULL;
   	DRM_MANAGER_DECRYPT_CONTEXT *pLocalDecryptContext = NULL;
 	long iOption=0;
    
	/*argv[0] whethere oevrwrite the drmamanger content
	  argv[1] the content to overwrite to the local drmmanager context
	  argv[2] the context to overwrite to the local decrypt context
	  argv[3] whethere need to use callback function for output protection level
    */
   	#ifdef SIXTEEN_BIT_ADDRESSING
		iOption=(long)OEM_atoi(argv[0]);
	#else
		iOption=(long)OEM_atol(argv[0]);
	#endif

	
	/*manager context*/
	if ((iOption&1) && (argv[1] != NULL)) { /*Context is from the input*/
		ChkMem(pLocalManagerContext = OEM_malloc(SIZEOF(DRM_MANAGER_CONTEXT)));
		MEMSET(pLocalManagerContext, 0, SIZEOF(DRM_MANAGER_CONTEXT)); 
		MEMCPY(pLocalManagerContext->rgbOpaqueBuffer, argv[1], min(DX_VOS_StrLen(argv[1])+1, DRM_DRMMANAGER_CONTEXT_BUFFER_SIZE));
	}

 	/*decrypt context*/
 	if ((iOption&2) && (argv[2] != NULL)) { /*Context is from the input*/
		ChkMem(pLocalDecryptContext = (DRM_MANAGER_DECRYPT_CONTEXT*)OEM_malloc(SIZEOF(DRM_MANAGER_DECRYPT_CONTEXT)));
		MEMSET(pLocalDecryptContext, 0, SIZEOF(DRM_MANAGER_DECRYPT_CONTEXT)); 
		MEMCPY(pLocalDecryptContext->rgbBuffer, argv[1], min(DX_VOS_StrLen(argv[1])+1, SIZEOF(DRM_CIPHER_CONTEXT)));
	}

	if(argv[3] != NULL){
		/*need to call TestManagerPrepareOPLCallback first*/
		START_TIMER(g_CurrTime);
		dr = DRM_MGR_Bind((iOption&1)? pLocalManagerContext: g_pManagerContext_MNGR,
			(const DRM_CONST_STRING **)g_pwszRights,
			g_numRights,
			OPLCallback, 
			NULL,
			(iOption&2)? pLocalDecryptContext: g_pDecryptContext );
		
		STOP_TIMER("DRM_MGR_Bind",g_CurrTime,g_DiffTime);
		ChkDR( dr );
  	}
	else{
		START_TIMER(g_CurrTime);
		dr = DRM_MGR_Bind((iOption&1)? pLocalManagerContext: g_pManagerContext_MNGR,
			(const DRM_CONST_STRING **)g_pwszRights,
			g_numRights,
			NULL, 
			NULL,
			(iOption&2)? pLocalDecryptContext: g_pDecryptContext );		

		STOP_TIMER("DRM_MGR_Bind",g_CurrTime,g_DiffTime);
		ChkDR( dr );
 	}

ErrorExit:
	SAFE_OEM_FREE(pLocalManagerContext);
	SAFE_OEM_FREE(pLocalDecryptContext);
   	return dr;
}

DRM_RESULT TestManagerDecrypt(long argc, char **argv)
{
	DRM_RESULT dr=DRM_SUCCESS;
	DRM_MANAGER_DECRYPT_CONTEXT *pLocalDecryptContext = NULL;
 	long i,iOption=0;
	int iNumBytes=0;
	DRM_BYTE *pbLocalData=NULL, *pbTempData=NULL;

 	for(i=0; i<argc; i++){
		Log("Trace", "\t\tFrom TestManagerDecrypt: argv[%d]=%s", i, argv[i]);
	}
 	/*at least 6 arguments. The last one is used to decide whether we need to overwrite the context*/
 	/*4th argument is the number of bytes for mis-alignment tests*/
	/*5th argument is to verify the decrypted data*/
	if(argc<6){
		Log("Trace", "\t\tFrom TestManagerDecrypt: error in number of arguments.");
		ChkDR(DRM_E_FAIL);
	}
	
	if(!IsDigitalOnlyString(argv[1])||!IsDigitalOnlyString(argv[3])||!IsDigitalOnlyString(argv[5])){ 
		Log("Trace", "\t\tFrom TestManagerDecrypt: error in the argument.");
		ChkDR(DRM_E_FAIL);
	}
  
 	iOption=(long)OEM_atol(argv[5]);
	iNumBytes=(int)OEM_atoi(argv[3]);

	/*encrypt context*/
	if ((iOption&2) && argv[0]) { /*Context is from the input*/
		ChkMem(pLocalDecryptContext = (DRM_MANAGER_DECRYPT_CONTEXT*)OEM_malloc(SIZEOF(DRM_MANAGER_DECRYPT_CONTEXT)));
		MEMSET(pLocalDecryptContext, 0, SIZEOF(DRM_MANAGER_DECRYPT_CONTEXT)); 
		MEMCPY(pLocalDecryptContext->rgbBuffer, argv[0], min(DX_VOS_StrLen(argv[0])+1, SIZEOF(DRM_CIPHER_CONTEXT)));
	}

	/*get data*/
	if ((iOption&64) && argv[2]) {
		g_cbData = DX_VOS_StrLen(argv[2]);
		SAFE_OEM_FREE(g_pbData);
 		ChkMem(g_pbData=(DRM_BYTE*)OEM_malloc(g_cbData+1));
		DX_VOS_StrNCopy((DxChar* )g_pbData,g_cbData+1, argv[2]);
	}

	if((iOption&16) && argv[1]){ /*get size*/
		DRM_DWORD tmpcbData = (DRM_DWORD)OEM_atol(argv[1]);
		ChkArg(tmpcbData <= g_cbData);
		g_cbData = tmpcbData;
	}

	/*mis-alignment*/
	if(iNumBytes>0 && g_cbData>0){
		ChkMem(pbLocalData=(DRM_BYTE*)OEM_malloc(g_cbData+iNumBytes+1));
		/*keep original pointer*/
 		pbTempData=pbLocalData+iNumBytes;
		MEMCPY(pbTempData, g_pbData,g_cbData);

		START_TIMER(g_CurrTime);
		dr = DRM_MGR_InitDecrypt( (iOption&2)? pLocalDecryptContext: g_pDecryptContext, 
                                    (g_cbData <15 ? pbTempData: pbTempData + g_cbData - 15),
                                    g_cbData );
		
		STOP_TIMER("DRM_MGR_InitDecrypt",g_CurrTime,g_DiffTime);
		ChkDR(dr );

		dr = DRM_MGR_Decrypt(
			(iOption&2)? pLocalDecryptContext: g_pDecryptContext,
			pbTempData, g_cbData);

		
		STOP_TIMER("DRM_MGR_Decrypt",g_CurrTime,g_DiffTime);
		ChkDR( dr );
	
		#ifdef SIXTEEN_BIT_ADDRESSING
		/*verify - strncmp replaced by MEMCMP*/
			if(argv[4] && MEMCMP(argv[4],pbTempData,DX_VOS_StrLen(argv[4])))
				dr = DRM_E_FAIL;
		#else
			if(argv[4] && DX_VOS_StrNCmp(argv[4],(DxChar* )pbTempData,DX_VOS_StrLen(argv[4])))
				dr = DRM_E_FAIL;
		#endif
	}
	else{
		START_TIMER(g_CurrTime);		
		dr = DRM_MGR_InitDecrypt( (iOption&2)? pLocalDecryptContext: g_pDecryptContext, 
                                    (g_cbData <15 ? g_pbData: g_pbData + g_cbData - 15),
                                    g_cbData );
		
		
		STOP_TIMER("DRM_MGR_InitDecrypt",g_CurrTime,g_DiffTime);
		ChkDR(dr );
		
		dr = DRM_MGR_Decrypt(
			(iOption&2)? pLocalDecryptContext: g_pDecryptContext,
			g_pbData, g_cbData);

		
		STOP_TIMER("DRM_MGR_Decrypt",g_CurrTime,g_DiffTime);
		ChkDR(dr );
	
		#ifdef SIXTEEN_BIT_ADDRESSING
		/*verify - DX_VOS_StrCmp replaced by MEMCMP*/
			if(argv[4] && MEMCMP(argv[4],g_pbData,DX_VOS_StrLen(argv[4])))
			dr = DRM_E_FAIL;
		#else
			if(argv[4] && DX_VOS_StrNCmp(argv[4],(DxChar* )g_pbData,DX_VOS_StrLen(argv[4])))
			dr = DRM_E_FAIL;
		#endif
	}

 ErrorExit:
	if(!(iOption&128)){
 		SAFE_OEM_FREE(g_pbData);
		g_pbData=NULL;
		g_cbData=0;
	}
	SAFE_OEM_FREE(pLocalDecryptContext);
  	SAFE_OEM_FREE(pbLocalData);
	return dr;
}

DRM_RESULT TestManagerCreateEncryptContext(long argc, char **argv)
{
	DRM_RESULT dr=DRM_SUCCESS;

#if DRM_SUPPORT_ENCRYPTION
    
  	long i;
	DRM_BYTE rgbKey[DRMCIPHERKEYLEN]={0};
	DRM_WCHAR SeedKey[100]={0}, KID[50]={0};
	DRM_STRING pwszSeedKey, pwszKID, pwszContentKey;
	
 	for(i=0; i<argc; i++){
		Log("Trace", "\t\tFrom TestManagerCreateEncryptContext: argv[%d]=%s", i, argv[i]);
	}
 	/*at least 5 arguments. The last one is used to decide whether we need to overwrite the context*/
	/*2nd argument is seedkey*/
	/*3rd argument is KID*/
 	if(argc<5){
		Log("Trace", "\t\tFrom TestManagerCreateEncryptContext: error in number of arguments.");
		ChkDR(DRM_E_FAIL);
	}
	
	if(!IsDigitalOnlyString(argv[4])){ 
		Log("Trace", "\t\tFrom TestManagerCreateEncryptContext: error in the argument.");
		ChkDR(DRM_E_FAIL);
	}
  
	/*get key*/
	if(argv[0])
		DX_VOS_StrNCopy((DxChar* )rgbKey,sizeof(rgbKey),argv[0]);

	/*seedkey and KID*/
	if(argv[1] && argv[2]){
		OEM_mbstowcs(SeedKey,argv[1],DX_VOS_StrLen(argv[1])+1);
		pwszSeedKey.pwszString=SeedKey;
		pwszSeedKey.cchString=(DRM_DWORD)DX_VOS_StrLen(argv[1]);
		OEM_mbstowcs(KID,argv[2],DX_VOS_StrLen(argv[2])+1);
		pwszKID.pwszString=KID;
		pwszKID.cchString=(DRM_DWORD)DX_VOS_StrLen(argv[2]);
		tDRM_KG_GenerateContentKey((DRM_CONST_STRING*)&pwszSeedKey, (DRM_CONST_STRING*)&pwszKID, (DRM_CONST_STRING*)&pwszContentKey);
		OEM_wcstombs((DxChar*)rgbKey,pwszContentKey.pwszString,pwszContentKey.cchString+1);
	}

	/*Context is from the input*/
	if(argv[3]) {
		ChkArg(g_pEncryptContext);
		MEMSET(g_pEncryptContext, 0, SIZEOF(DRM_MANAGER_ENCRYPT_CONTEXT)); 
		MEMCPY(g_pEncryptContext->rgbBuffer, argv[3], min(DX_VOS_StrLen(argv[3])+1, SIZEOF(DRM_CIPHER_CONTEXT)));
	}

	START_TIMER(g_CurrTime);
	dr = DRM_MGR_CreateEncryptContext(argv[0]? rgbKey: NULL,
		argv[3]? g_pEncryptContext: NULL);

	STOP_TIMER("DRM_MGR_CreateEncryptContext",g_CurrTime,g_DiffTime);
	ChkDR(dr );
 
 ErrorExit:

#endif
    
   	return dr;
}

DRM_RESULT TestManagerEncrypt(long argc, char **argv)
{
	DRM_RESULT dr=DRM_SUCCESS;

#if DRM_SUPPORT_ENCRYPTION

	DRM_MANAGER_ENCRYPT_CONTEXT *pLocalEncryptContext = NULL;
 	long i,iOption=0;
	int iNumBytes=0;
	DRM_BYTE *pbLocalData=NULL,*pbTempData=NULL;
	
 	for(i=0; i<argc; i++){
		Log("Trace", "\t\tFrom TestManagerEncrypt: argv[%d]=%s", i, argv[i]);
	}
	/*at least 6 arguments. The last one is used to decide whether we need to overwrite the context*/
 	/*4th argument is the number of bytes for mis-alignment test*/
	/*5th argument is to verify the encrypted data*/
	if(argc<6){
		Log("Trace", "\t\tFrom TestManagerEncrypt: error in number of arguments.");
		ChkDR(DRM_E_FAIL);
	}
	
	if(!IsDigitalOnlyString(argv[1])||!IsDigitalOnlyString(argv[3])||!IsDigitalOnlyString(argv[5])){ 
		Log("Trace", "\t\tFrom TestManagerEncrypt: error in the argument.");
		ChkDR(DRM_E_FAIL);
	}
  
 	iOption=(long)OEM_atol(argv[5]);
	iNumBytes=(int)OEM_atoi(argv[3]);

	/*encrypt context*/
	if ((iOption&4) && argv[0]) { /*Context is from the input*/
		ChkMem(pLocalEncryptContext = (DRM_MANAGER_ENCRYPT_CONTEXT*)OEM_malloc(SIZEOF(DRM_MANAGER_ENCRYPT_CONTEXT)));
		MEMSET(pLocalEncryptContext, 0, SIZEOF(DRM_MANAGER_ENCRYPT_CONTEXT)); 
		MEMCPY(pLocalEncryptContext->rgbBuffer, argv[0], min(DX_VOS_StrLen(argv[0])+1, SIZEOF(DRM_CIPHER_CONTEXT)));
	}

	/*get data*/
	if((iOption&64) && argv[2]) {
		if(0==DX_VOS_StrCmp(argv[2], "SPACE")){
			DX_VOS_StrNCopy(argv[2],0x10, " ");
		}
		g_cbData=(DRM_DWORD)DX_VOS_StrLen(argv[2]);
		ChkMem(g_pbData=(DRM_BYTE*)OEM_malloc(g_cbData+1));
		DX_VOS_StrNCopy((DxChar*)g_pbData,(g_cbData+1),argv[2]);
	}
	/*overwrite size*/
	if((iOption&16) && argv[1])
		g_cbData=(DRM_DWORD)OEM_atol(argv[1]);

 	/*mis-alignment*/
	if(iNumBytes>0 && g_cbData>0){
		ChkMem(pbLocalData=(DRM_BYTE*)OEM_malloc(g_cbData+iNumBytes+1));
		/*keep original pointer*/
 		pbTempData=pbLocalData+iNumBytes;
		MEMCPY(pbTempData, g_pbData,g_cbData);

		START_TIMER(g_CurrTime);
		dr = DRM_MGR_Encrypt(
			(iOption&4)? pLocalEncryptContext: g_pEncryptContext,
			pbTempData, g_cbData);

		STOP_TIMER("DRM_MGR_Encrypt",g_CurrTime,g_DiffTime);
		ChkDR( dr );
		/*verify strncmp replaced by MEMCMP for 16-bit*/
		#ifdef SIXTEEN_BIT_ADDRESSING
			if(argv[4] && MEMCMP(argv[4],pbTempData,DX_VOS_StrLen(argv[4])))
				dr = DRM_E_FAIL;
		#else
			if(argv[4] && DX_VOS_StrNCmp(argv[4],(DxChar*)pbTempData,DX_VOS_StrLen(argv[4])))
				dr = DRM_E_FAIL;
		#endif
			
	}
	else{
		START_TIMER(g_CurrTime);		
		dr = DRM_MGR_Encrypt(
			(iOption&4)? pLocalEncryptContext: g_pEncryptContext,
			g_pbData, g_cbData);

		STOP_TIMER("DRM_MGR_Encrypt",g_CurrTime,g_DiffTime);
		ChkDR( dr );
 
		/*verify strncmp replaced by MEMCMP for 16-bit*/
		#ifdef SIXTEEN_BIT_ADDRESSING
			if(argv[4] && MEMCMP(argv[4],g_pbData,DX_VOS_StrLen(argv[4])))
				dr = DRM_E_FAIL;
		#else
			if(argv[4] && DX_VOS_StrNCmp(argv[4],(DxChar*)g_pbData,DX_VOS_StrLen(argv[4])))
				dr = DRM_E_FAIL;
		#endif

	}

ErrorExit:
	if(!(iOption&128)){
 		SAFE_OEM_FREE(g_pbData);
		g_pbData=NULL;
		g_cbData=0;
	}
	SAFE_OEM_FREE(pLocalEncryptContext);
	SAFE_OEM_FREE(pbLocalData);
#endif

	return dr;
}

DRM_RESULT TestManagerCommit(long argc, char **argv)
{
 	DRM_RESULT dr=DRM_SUCCESS;

	START_TIMER(g_CurrTime);
	dr = DRM_MGR_Commit(g_pManagerContext_MNGR);

	STOP_TIMER("DRM_MGR_Commit",g_CurrTime,g_DiffTime);
	ChkDR( dr );

ErrorExit:
  	return dr;
}

DRM_RESULT TestManagerGenerateChallenge(long argc, char **argv)
{
#if DRM_SUPPORT_DLA
	DRM_RESULT dr=DRM_SUCCESS;
	DRM_MANAGER_CONTEXT *pLocalManagerContext = NULL;
 	long i,iOption=0, iMisAlignment=0;
	DRM_DWORD iTempSize1=0, iTempSize2=0;
	DRM_CONST_STRING wszUrl={0};
	DRM_DWORD cchChallenge=0;
	DRM_CHAR *pszChallenge=NULL, *pszTempChallenge=NULL;
	
	for(i=0; i<argc; i++){
		Log("Trace", "\t\tFrom TestManagerGenerateChallenge: argv[%d]=%s", i, argv[i]);
	}
 	/*at least 10 arguments. The last one is used to decide whether we need to overwrite the context*/
	/*6th argument is to verify url*/
	/*7th argument is to verify url size*/
	/*8th argument is name of the file which contains the content for comparison*/
	/*9th argument is number of mis-alignment*/
	if(argc<10){
		Log("Trace", "\t\tFrom TestManagerGenerateChallenge: error in number of arguments.");
		ChkDR(DRM_E_FAIL);
	}
	
	if(!IsDigitalOnlyString(argv[9])){
		Log("Trace", "\t\tFrom TestManagerGenerateChallenge: error in the argument.");
		ChkDR(DRM_E_FAIL);
	}
  
 	iOption=(long)OEM_atol(argv[9]);
	/*manager context*/
	if ((iOption&1) && argv[0]) { /*Context is from the input*/
		ChkMem(pLocalManagerContext = (DRM_MANAGER_CONTEXT*)OEM_malloc(SIZEOF(DRM_MANAGER_CONTEXT)));
		MEMSET(pLocalManagerContext, 0, SIZEOF(DRM_MANAGER_CONTEXT)); 
	}

	/*get URL*/
	if(argv[1]){
		MakeDRMString(&wszUrl, argv[1]);
  	}

	if(argv[2]) {
		iTempSize1 = OEM_atol(argv[2]);
		ChkArg(iTempSize1 <= wszUrl.cchString);
		wszUrl.cchString = iTempSize1;
	}

	/*get challenge*/
	if(argv[3]){
 		cchChallenge = DX_VOS_StrLen(argv[3]);
 		ChkMem(pszChallenge = (DRM_CHAR*)OEM_malloc(cchChallenge + 1));
		DX_VOS_StrNCopy(pszChallenge,(cchChallenge + 1),argv[3]);
  	}

	if(argv[4]) {
		iTempSize1 = OEM_atol(argv[4]);
		ChkArg(iTempSize1 <= cchChallenge);
		cchChallenge = iTempSize1;
	}

	/*keep the old numbers*/
	iTempSize1=wszUrl.cchString;
	iTempSize2=cchChallenge;

	START_TIMER(g_CurrTime);
	
	dr=DRM_MGR_GenerateLicenseChallenge((iOption&1)? pLocalManagerContext: g_pManagerContext_MNGR,
		(const DRM_CONST_STRING **)g_pwszRights, g_numRights, (DRM_WCHAR*)wszUrl.pwszString, 
		argv[2]? &wszUrl.cchString: NULL,
		pszChallenge,
		argv[4]? &cchChallenge: NULL);

	STOP_TIMER("DRM_MGR_GenerateLicenseChallenge",g_CurrTime,g_DiffTime);

	if(DRM_E_BUFFERTOOSMALL==dr){
		iMisAlignment=OEM_atoi(argv[8]);
		if(wszUrl.cchString!=iTempSize1){
			SAFE_OEM_FREE(wszUrl.pwszString);
			ChkMem(wszUrl.pwszString=(DRM_WCHAR*)OEM_malloc((wszUrl.cchString+1)*SIZEOF(DRM_WCHAR)));
		}
		if(cchChallenge!=iTempSize2){
  			SAFE_OEM_FREE(pszChallenge);
 			ChkMem(pszChallenge=(DRM_CHAR*)OEM_malloc(cchChallenge+1+iMisAlignment));
 			pszTempChallenge=pszChallenge+iMisAlignment;				
 		}

		START_TIMER(g_CurrTime);
		dr = DRM_MGR_GenerateLicenseChallenge((iOption&1)? pLocalManagerContext:g_pManagerContext_MNGR,
			(const DRM_CONST_STRING **)g_pwszRights, g_numRights,
			(DRM_WCHAR*)wszUrl.pwszString,&wszUrl.cchString,pszTempChallenge,&cchChallenge);

		STOP_TIMER("DRM_MGR_GenerateLicenseChallenge",g_CurrTime,g_DiffTime);
		ChkDR(dr);
	} else {
		ChkDR(dr);
	}
 
	/*verify url and size*/
	if(argv[5] && CompWideString(wszUrl.pwszString, argv[5])) {
		ChkDR(DRM_E_FAIL);
	}

	if(argv[6] && (DRM_DWORD)OEM_atol(argv[6])!=(wszUrl.cchString-1)){
		ChkDR(DRM_E_FAIL);
	}

	/*verify challenge*/
	if(argv[7] && DX_VOS_FindStr(pszChallenge,argv[7])==NULL){
		ChkDR(DRM_E_FAIL);
	}
ErrorExit:
	SAFE_OEM_FREE(pLocalManagerContext);
 	SAFE_OEM_FREE(pszChallenge);
	SAFE_OEM_FREE(wszUrl.pwszString);
   	return dr;
#else
	return DRM_E_NOTIMPL;
#endif
}

DRM_RESULT TestManagerInitResponse(long argc, char **argv)
{
	DRM_RESULT dr=DRM_SUCCESS;
  	
	/*initialize the response xml frame*/
	SAFE_OEM_FREE(g_pbResponseContext);
	ChkMem(g_pbResponseContext = OEM_malloc(RESPONSECONTEXTSIZE));
	ChkDR(TestResponseInit(g_pbResponseContext, RESPONSECONTEXTSIZE));
ErrorExit:
 	return dr;
}

DRM_RESULT TestManagerAddLicenseToResponse(long argc, char **argv)
{
	DRM_RESULT dr=DRM_SUCCESS;
  	long i=0;
	DRM_CONST_STRING pwszLicense;
	ELicenseType eLicType = MAKE_SIMPLE_LICENSE;
 	/*
	argv[0]: KID 
	argv[1]: LID 
	argv[2]: option in creating a test license
	argv[3]: extra xml string to add to the license
	argv[4]: content sign key
	argv[5]: key seed
	argv[6]: optional license type: 0(simple), 1(leaf), 2(root)
	argv[7]: optional uplink kid
 	*/
	 
  	for(i=0; i<argc; i++){
		Log("Trace", "\t\tAdd license from the file %s", argv[i]);
	}
	if(argc>6) {
		ChkArg(argv[6]);
		eLicType = (ELicenseType)OEM_atol(argv[6]);
	}
	/*add encrypted and encoded license*/
	ChkDR(TestLicGenInit(10000));
	if (argv[0]) TestLicGenSetKeys("LICENSE_KID",argv[0]);
	if (argv[1]) TestLicGenSetKeys("LICENSE_LID",argv[1]);
	if (argv[4]) TestLicGenSetKeys("CONTENT_OWNER_PUB_KEY",argv[4]);
	if (argv[5]) TestLicGenSetKeys("LICENSE_SERVER_KEYSEED", argv[5]);

	if (argc > 7) {
		ChkDR(TestLicGenSetKeys("LICENSE_UPLINK_KID",argv[7]));
	}

	
	ChkDR(TestLicGenMakeLicense(
		OEM_atoi(argv[2]),	
		argv[3],
		NULL,
		eLicType, 
		&pwszLicense));
	ChkDR(TestResponseAddLicense(g_pbResponseContext,&pwszLicense));
    
ErrorExit:
	TestLicGenShutDown();
 	return dr;
}

DRM_RESULT TestManagerGenerateResponse(long argc, char **argv)
{
	DRM_RESULT dr=DRM_SUCCESS;

  	Log("Trace", "\t\tTestManagerGenerateResponse");
 
	/*get the response*/
	SAFE_OEM_FREE(g_pbResponse);
	g_pbResponse = NULL;

   	ChkDR(TestResponseGetResponse(g_pbResponseContext,&g_pbResponse,&g_cbResponse));  
	
ErrorExit:
 	return dr;
}

DRM_RESULT TestManagerProcessResponse(long argc, char **argv)
{
	DRM_RESULT dr=DRM_SUCCESS;
	DRM_MANAGER_CONTEXT *pLocalManagerContext = NULL;
 	long i,iOption=0;
	
 	for(i=0; i<argc; i++){
		Log("Trace", "\t\tFrom TestManagerProcessResponse: argv[%d]=%s", i, argv[i]);
	}
 	/*at least 4 arguments. The last one is used to decide whether we need to overwrite the context*/
	if(argc<4){
		Log("Trace", "\t\tFrom TestManagerProcessResponse: error in number of arguments.");
		ChkDR(DRM_E_FAIL);
	}
	
	if(!IsDigitalOnlyString(argv[2])||!IsDigitalOnlyString(argv[3])){
		Log("Trace", "\t\tFrom TestManagerProcessResponse: error in the argument.");
		ChkDR(DRM_E_FAIL);
	}
  
	#ifdef SIXTEEN_BIT_ADDRESSING
		iOption=(long)OEM_atoi(argv[3]);
	#else
		iOption=(long)OEM_atol(argv[3]);
	#endif

	/*manager context*/
	if(iOption&1){ /*Context is from the input*/
		ChkMem(pLocalManagerContext = (DRM_MANAGER_CONTEXT*)OEM_malloc(SIZEOF(DRM_MANAGER_CONTEXT)));
		MEMSET(pLocalManagerContext, 0, SIZEOF(DRM_MANAGER_CONTEXT)); 
	}

	/*overwrite the response*/
	if(iOption&32){
		SAFE_OEM_FREE(g_pbResponse);
 		if(argv[1]){
  			ChkMem(g_pbResponse=(DRM_BYTE*)OEM_malloc((DRM_DWORD)DX_VOS_StrLen(argv[1])+1));
			MEMCPY(g_pbResponse, argv[1],DX_VOS_StrLen(argv[1])+1);		
			g_cbResponse=(DRM_DWORD)DX_VOS_StrLen(argv[1]);
		}
		else{
			g_pbResponse=NULL;
			g_cbResponse=0;
		}
	}
 
	/*overwrite data size*/
	if(iOption&16){
		g_cbResponse=(DRM_DWORD)OEM_atol(argv[2]);
	}

	START_TIMER(g_CurrTime);
	dr = DRM_MGR_ProcessLicenseResponse((iOption&1)? pLocalManagerContext:g_pManagerContext_MNGR, NULL, NULL,
		g_pbResponse, g_cbResponse);

	STOP_TIMER("DRM_MGR_ProcessLicenseResponse",g_CurrTime,g_DiffTime);
	ChkDR( dr );
 
ErrorExit:
	SAFE_OEM_FREE(g_pbResponse);
	g_pbResponse=NULL;
	SAFE_OEM_FREE(pLocalManagerContext);
   	return dr;
}

/*for multiple store testing*/
DRM_RESULT TestManagerInitializeForNewStore(long argc, char **argv)
{
	DRM_RESULT dr = DRM_SUCCESS;
	DRM_CONST_STRING wszDeviceStoreName = {0};
	
	/*give a inital 20 bytes. It should be sufficient*/
	int iSize=20;

	/*argv[0] folder
	  argv[1] file name
	*/
	if(argv[0])
		iSize=DX_VOS_StrLen(argv[0])+DX_VOS_StrLen(argv[1])+iSize;
	else
		iSize=DX_VOS_StrLen(argv[1])+iSize;
	g_szFilePath_MNGR=(char*)OEM_malloc(iSize);

#ifdef WINCE_TEST
  	if (argv[0])
		DX_VOS_SPrintf(g_szFilePath_MNGR,sizeof(g_szFilePath), "%s\\%s\\%s", BASE_DIR, argv[0],  argv[1]);
	else
		DX_VOS_SPrintf(g_szFilePath_MNGR,sizeof(g_szFilePath), "%s\\%s", BASE_DIR,  argv[1]);
#else
 	if (argv[0])
		DX_VOS_SPrintf(g_szFilePath_MNGR, sizeof(g_szFilePath_MNGR),".\\%s\\%s",  argv[0],  argv[1]);
	else
		DX_VOS_SPrintf(g_szFilePath_MNGR,sizeof(g_szFilePath_MNGR), ".\\%s",  argv[1]);
#endif

	if(atoi(argv[2]))
  		DX_VOS_FDelete(g_szFilePath_MNGR);
	MakeDRMString(&wszDeviceStoreName, g_szFilePath_MNGR);

	START_TIMER(g_CurrTime);
 	dr = DRM_MGR_Initialize(g_pManagerContext_MNGR, &wszDeviceStoreName);
	
	STOP_TIMER("DRM_MGR_Initialize",g_CurrTime,g_DiffTime);
	ChkDR( dr );

#if DRM_SUPPORT_REVOCATION
	{
        if( g_pbRevocationBuffer == NULL )
        {
            ChkMem( g_pbRevocationBuffer = OEM_malloc( REVOCATION_BUFFER_SIZE ) );
        }
        ChkDR( DRM_MGR_SetRevocationBuffer( g_pManagerContext_MNGR, g_pbRevocationBuffer, REVOCATION_BUFFER_SIZE ) );
	}
#endif /* DRM_SUPPORT_REVOCATION */


ErrorExit:
	return dr;
}

static _SetYearOnMachineClock(DRM_WORD wYear)
{
	DRMSYSTEMTIME ost;

	OEM_GetDeviceDateTime(&ost);
	if (!g_wCurrentYear)
		g_wCurrentYear = ost.wYear;
	ost.wYear = wYear;
	OEM_SetSystemTime(&ost);
}

/*	Set the machine clock to a different year
	argv[0]: year.
*/
DRM_RESULT TestManagerSetMachineClock(long argc, char **argv)
{
	DRM_RESULT dr = DRM_SUCCESS;

	ChkArg(argc == 1 && argv[0]);
	_SetYearOnMachineClock((DRM_WORD)OEM_atol(argv[0]));
ErrorExit:
	return dr;
}

DRM_RESULT TestManagerGetDeviceProperty(long argc, char **argv)
{
#if DRM_SUPPORT_DLA
	DRM_RESULT dr = DRM_SUCCESS;
	DRM_DWORD cbProperty=0;
	_XMBContext *pbProperty=NULL;
	DRM_CONST_STRING wszProperty = {0};


	/*argv[0] for property index; argv[1] for verify*/
	ChkArg(argc == 2 && argv[0]);

	dr=DRM_MGR_GetDeviceProperty(g_pManagerContext_MNGR,(DRM_DEVICE_PROPERTY)OEM_atoi(argv[0]),pbProperty,&cbProperty );
	if(DRM_E_BUFFERTOOSMALL==dr){
		ChkMem(pbProperty=(_XMBContext*)OEM_malloc(cbProperty));
		ChkDR(DRM_MGR_GetDeviceProperty(g_pManagerContext_MNGR,(DRM_DEVICE_PROPERTY)OEM_atoi(argv[0]),pbProperty,&cbProperty ));
	}
	else{
		ChkDR(dr);
	}
	/*verify the perperty*/
 
	if(pbProperty && argv[1]){
		MakeDRMString(&wszProperty, argv[1]);
		if (DRM_wcsncmp((DRM_WCHAR*)pbProperty, wszProperty.pwszString,wszProperty.cchString)){
			ChkDR(DRM_E_FAIL);
		}
	}

ErrorExit:
	SAFE_OEM_FREE(wszProperty.pwszString);
	if(pbProperty)
		SAFE_OEM_FREE(pbProperty);
	return dr;
#else
	return DRM_E_NOTIMPL;
#endif
}

/* Set or Verify the OEM secure clock state 
	argv[0]: operation: Set, Verify
	argv[1]: BOOL value to set or the expected BOOL value
*/
DRM_RESULT TestManagerSetGetClockState(long argc, char **argv)
{
	DRM_RESULT dr = DRM_SUCCESS;
	DRM_BOOL fState;
	ChkArg(argc == 2 && argv[0] && argv[1]);
	
	fState = !DX_VOS_StrCmp(argv[1], "TRUE");
	
	if (!DX_VOS_StrCmp(argv[0], "Set")) {
		ChkDR(OEM_SetClockResetState(fState));
	} else if (!DX_VOS_StrCmp(argv[0], "Verify")) {
		DRM_BOOL fGot;
		ChkDR(OEM_GetClockResetState(&fGot));
		if (fGot != fState)
			dr = DRM_S_FALSE;
	}
ErrorExit:
	return dr;
}

DRM_RESULT DRM_API  ReportProgress(
    IN const DRM_VOID  *pvCallerData, 
    IN       DRM_DWORD  cLicensesProcessed,
    IN       DRM_DWORD  cTotalLicenses  /*  # of licenses remaining */
    )
{
    DRM_RESULT   dr = DRM_SUCCESS;

    DX_VOS_Printf("%d license(s) out of %d licenses processed\n", cLicensesProcessed, cTotalLicenses );
    if (pvCallerData)
    {
        dr = DRM_E_DEVICENOTINIT;
    }
    
   return dr;
}

DRM_RESULT TestManagerCleanLicenseStore(long argc, char **argv)
{
	DRM_RESULT dr = DRM_SUCCESS;
 	
	if ( argv[0] )
	{
		START_TIMER(g_CurrTime);
		dr = DRM_MGR_CleanupLicenseStore( g_pManagerContext_MNGR, 
                                       NULL,
                                       20,
                                       ReportProgress);
		STOP_TIMER("DRM_MGR_CleanupLicenseStore",g_CurrTime,g_DiffTime);
		ChkDR( dr );
	}
	
ErrorExit:
	return dr;
}

DRM_RESULT GetLicenseEnum(DRM_KID KID, DRM_DWORD* pdwCount, DRM_LICSTORE_CONTEXT* pLicStoreContext, DRM_LICSTOREENUM_CONTEXT** ppLicEnumContext)
{	
	DRM_RESULT dr=DRM_SUCCESS;

	ChkArg(pdwCount && ppLicEnumContext);
	
	ChkMem(*ppLicEnumContext = (DRM_LICSTOREENUM_CONTEXT*)DX_VOS_MemMalloc(sizeof(DRM_LICSTOREENUM_CONTEXT)));
	DX_VOS_MemSet(*ppLicEnumContext, 0, sizeof(DRM_LICSTOREENUM_CONTEXT));							

	
	ChkDR(DRM_LST_InitEnum(pLicStoreContext, 
							  &KID,
							  FALSE, //prioritize
							  *ppLicEnumContext));

	ChkDR(DRM_LST_LicCount(*ppLicEnumContext,
							 pdwCount));	
ErrorExit:	
	
	return dr;
}

DRM_RESULT TestEnumLicense(long argc, char **argv)	
{
	/*argv[0]: KID
	    argv[1]: filename to dump license
	    argv[2]: optional, expected number of licenses in the Enum
	  */
	DRM_KID kid;
	DRM_SUBSTRING ssKID = {0,0};/*{0, DX_VOS_StrLen(argv[0])};*/
	DRM_DWORD dwSize = DRM_ID_SIZE;
	DRM_LICSTOREENUM_CONTEXT* pLicStoreEnumContext = NULL;
	DRM_DWORD dwNOLicenses = 0;
	DRM_HDS_CONTEXT oHdsContext;
	DRM_MANAGER_CONTEXT_INTERNAL*  pMgrInternal = (DRM_MANAGER_CONTEXT_INTERNAL*)g_pManagerContext_MNGR;
	
	DRM_RESULT dr = DRM_SUCCESS;
	ChkArg(argv[0]);
	ChkArg(argv[1] || argv[2]);
	
	/* instead ot declaration init */
	ssKID.m_cch = DX_VOS_StrLen(argv[0]);
	//convert from LPSTR to KID		
	ChkDR(DRM_B64_DecodeA(argv[0],
							  &ssKID,
							  &dwSize,
							  kid.rgb,
							  0));	

	ChkDR(DRM_HDS_Init(&oHdsContext));
	ChkDR(DRM_HDS_OpenStore(g_wszDeviceStoreName_MNGR.pwszString, &oHdsContext));
	ChkDR(DRM_LST_Open(&pMgrInternal->oLicStoreContext, &oHdsContext));

	ChkDR(GetLicenseEnum(kid, &dwNOLicenses, &pMgrInternal->oLicStoreContext, &pLicStoreEnumContext));

	if (argc > 1 && argv[1] != NULL) //check the number of licenses expected
	{
		if (OEM_atol(argv[1]) != dwNOLicenses)
		{
			Log("Trace", "Number of License (%d)  with the KID is not match expected", dwNOLicenses);
			ChkDR(E_FAIL);
		}
	}
	
ErrorExit:

	DRM_LST_Close(&pMgrInternal->oLicStoreContext);
	DRM_HDS_CloseStore(&oHdsContext);
	DRM_HDS_Uninit(&oHdsContext);

	if (NULL != pLicStoreEnumContext)
	{
		DX_VOS_MemFree(pLicStoreEnumContext);
	}
	
	return dr;
}


/*
Name: TestManagerGetSourceID
Desc: This method is used to verify the source id in drm manager context. This should be called
DRM_MGR_BIND. 
Parameters:
    Parameter 1: source id which is expcted to be present in drm manager context.
    Parameter 2: Flag indicating whether NULL should be passed for DRM Manager Context.
    Parameter 3: Flag indicating whether NULL should be passed for the variable holding the sourcid
                        result from the API
*/
DRM_RESULT TestManagerGetSourceID(long argc, char **argv)
{
DRM_RESULT dr = DRM_SUCCESS;
    long SourceID = 0, iOption1 = 0, iOption2 = 0;
    DRM_DWORD dwSourceID;

    if(argc != 3)
    {
         Log("Trace", "\t\tFrom TestManagerGetSourceID: error in argument.");
	  ChkDR(DRM_E_FAIL);
    }
    
	SourceID=(long)OEM_atol(argv[0]);
	iOption1=(long)OEM_atol(argv[1]);
	iOption2=(long)OEM_atol(argv[2]);

    if(iOption1 && iOption2)
	{
		dr =DRM_MGR_GetSourceID(g_pManagerContext_MNGR, &dwSourceID);
	}
	else if(!iOption1 && iOption2)
	{
		dr =DRM_MGR_GetSourceID(NULL, &dwSourceID);
	}
	else if(iOption1 && !iOption2)
	{
		dr =DRM_MGR_GetSourceID(g_pManagerContext_MNGR, NULL);
	}
	else if(!iOption1 && !iOption2)
	{
		dr =DRM_MGR_GetSourceID(NULL,NULL);
	}

    ChkDR(dr);
    if(dwSourceID != SourceID)
    {
        Log("Trace", "\t\tFrom TestManagerGetSourceID: SourceID mismatch");
	 ChkDR(DRM_E_FAIL);
    }	
ErrorExit:
	return dr;
}

/*
DRM_RESULT DRM_API DRM_MGR_GetLicenseState(
    IN       DRM_MANAGER_CONTEXT            *pDrmContext,
    IN  const DRM_CONST_STRING              *pdstrQuery,
    OUT      DRM_LICENSE_STATE_CATEGORY     *pCategory,
    OUT      DRM_DWORD                      *pdwReserved1,
    OUT      DRM_DWORD                      *pdwReserved2,
    OUT      DRM_DWORD                      *pdwReserved3)
*/
DRM_RESULT TestManagerGetLicenseState(long argc, char **argv)
{
	DRM_RESULT dr = DRM_SUCCESS;
	DRM_CONST_STRING pdstrQuery = {0};
	DRM_DWORD dwReserved1=0,dwReserved2=0,dwReserved3=0; 
	DRM_LICENSE_STATE_CATEGORY iLicenseStateCategory=WM_DRM_LICENSE_STATE_NORIGHT;
	if(argv[0]){
		MakeDRMString(&pdstrQuery, argv[0]);
	}

	START_TIMER(g_CurrTime);
	dr=DRM_MGR_GetLicenseState(g_pManagerContext_MNGR,
								&pdstrQuery,
								&iLicenseStateCategory,
								&dwReserved1,
								&dwReserved2,
								&dwReserved3);
	STOP_TIMER("DRM_MGR_GetLicenseState",g_CurrTime,g_DiffTime);
	ChkDR( dr );

	if(argv[1] && iLicenseStateCategory!=(DRM_LICENSE_STATE_CATEGORY)OEM_atoi(argv[1])){
		ChkDR(DRM_E_FAIL);
	}

ErrorExit:
	OEM_free((void*)pdstrQuery.pwszString);

	return dr;
}


DRM_RESULT DRMM_PreTestCase(long lTCID, char *strTCName)
{
	DRM_RESULT dr;
	CLIENTID clientID;
	DRM_CHAR szPerfLogFile[60];

	DX_VOS_SPrintf( szPerfLogFile,sizeof(szPerfLogFile), "%d_JanusPerf.log", lTCID );
	START_PERFLOG(szPerfLogFile);

	
	g_numRights = 0;
	g_wCurrentYear = 0;
	g_lOffset_MNGR = 0;
	g_pbDLRB = NULL;


	ChkDR(RemoveDRMFile(RMFILE_STORE));
 	ChkDR(SetDeviceEnv(wszDevcertTemplateFileName,wszPrvKeyFileName, TRUE));
	ChkDR(OEM_SetClockResetState(FALSE));

	ChkMem(g_pManagerContext_MNGR = (DRM_MANAGER_CONTEXT*)OEM_malloc(SIZEOF(DRM_MANAGER_CONTEXT)));
	tGetDeviceStorePathname(&g_wszDeviceStoreName_MNGR);

	START_TIMER(g_CurrTime);
	dr = DRM_MGR_Initialize(g_pManagerContext_MNGR, &g_wszDeviceStoreName_MNGR);

	STOP_TIMER("DRM_MGR_Initialize",g_CurrTime,g_DiffTime);
	ChkDR( dr );

	ChkDR(TestGetClientID(&clientID));
	ChkDR(TestLicResponseSetClientID(&clientID));

#if DRM_SUPPORT_REVOCATION
	{
		           		
        if( g_pbRevocationBuffer == NULL )
        {
            ChkMem( g_pbRevocationBuffer = OEM_malloc( REVOCATION_BUFFER_SIZE ) );
        }
        ChkDR( DRM_MGR_SetRevocationBuffer( g_pManagerContext_MNGR, g_pbRevocationBuffer, REVOCATION_BUFFER_SIZE ) );

	}
#endif /* DRM_SUPPORT_REVOCATION */

ErrorExit:
	return dr;
}

DRM_RESULT DRMM_PostTestCase(long lTCID, char *strTCName)
{
	DRM_RESULT dr = DRM_SUCCESS;

	tChangeSystemTime(-g_lOffset_MNGR); /* Reverse any time changes in the test case.*/
	g_lOffset_MNGR=0;

	SAFE_OEM_FREE(g_pbResponse);
	g_pbResponse=NULL;

	SAFE_OEM_FREE(g_pbResponseContext);
	g_pbResponseContext = NULL;

	SAFE_OEM_FREE(g_pDecryptContext);
	g_pDecryptContext = NULL;

	SAFE_OEM_FREE(g_pEncryptContext);
	g_pEncryptContext = NULL;

	SAFE_OEM_FREE(g_pbData);
	g_pbData = NULL;

	SAFE_OEM_FREE(g_pbDLRB);
	g_pbDLRB = NULL;

#if DRM_SUPPORT_REVOCATION
	{
	       SAFE_OEM_FREE( g_pbRevocationBuffer );
	}
#endif /* DRM_SUPPORT_REVOCATION */

	if (g_pManagerContext_MNGR) {
		ChkDR(TestScanDevicePrivateKey(g_pManagerContext_MNGR));
		START_TIMER(g_CurrTime);
		DRM_MGR_Uninitialize(g_pManagerContext_MNGR);
		
		STOP_TIMER("DRM_MGR_Uninitialize",g_CurrTime,g_DiffTime);
		SAFE_OEM_FREE(g_pManagerContext_MNGR);
		g_pManagerContext_MNGR = NULL;
	}

	RemoveDRMFile(RMFILE_STORE);
	if(g_szFilePath_MNGR)
	  	DX_VOS_FDelete(g_szFilePath_MNGR);

	while (g_numRights > 0) {
		g_numRights--;
		OEM_free((DRM_WCHAR*)g_pwszRights[g_numRights]->pwszString);
		SAFE_OEM_FREE(g_pwszRights[g_numRights]);
	}

	if (g_wCurrentYear) { /* Set the clock back to current year */
		_SetYearOnMachineClock(g_wCurrentYear);
		g_wCurrentYear = 0;
	}
	STOP_PERFLOG;

ErrorExit:
	return dr;
}



		
	

#ifdef SIXTEEN_BIT_ADDRESSING
		
/*
//------------------------------------------------------------------------------
// Name: mbstowcs()
//
// Desc: This function is not available on 16-bit platform, so implemented it keeping in mind its use.
//           It returns the number of elements converted to UNICODE, or the number of UNICODE 
		characters required if destination is NULL. 
//Parameters:
//	destination        output wchar string
//    source             input char string
//	int			number of elements to be converted
//
// Copyright (c) 1999-2000, Microsoft Corporation. All rights reserved.
//------------------------------------------------------------------------------*/

int mbstowcs (DRM_WCHAR *destination,char *source,int  length){

	DRM_SUBSTRING f_pad = {0};
	DRM_STRING f_pdstrout = {0};
	int wlength = 0;
	
	if(source == NULL)
		{
		destination[0] = ONE_WCHAR('\0','\0');
		return (-1);
		}
		
	/*Transform the string to multi byte only if destination is not NULL, else we only need
	to determine the memory required for transformation */
	if(destination != NULL){

		f_pad.m_cch = length;
		f_pad.m_ich = 0;
		f_pdstrout.pwszString = destination;
		testDRM_16B_Pack8BitBytes(source,DX_VOS_StrLen(source)+1,NULL,DRM_PACK_BYTES_IN_PLACE);
		DRM_UTL_PromoteANSItoUNICODE((const DRM_CHAR *)source,&f_pad,&f_pdstrout);
		}
	else{	
		
		wlength=0;
		do{
	
		   if(*source == NULL)
				break;
			source++;
			wlength++;
			}
		while(wlength <= length);
		}
	return(wlength);
}


/*
//------------------------------------------------------------------------------
// Name: testDRM_16B_Pack8BitBytes
//
// Desc: This function is introduced for 16-bit paltform. It converts native representation to packed 
//ANSII representation 
//Parameters:
//	f_pbNative        input native string
//    f_cbNative        number of elements of native string
//	f_pvPacked      output packed ansi string
//	f_fOptions        options, can used to specify inplace conversion
//
// Copyright (c) 1999-2000, Microsoft Corporation. All rights reserved.
//------------------------------------------------------------------------------*/

DRM_VOID *DRM_API testDRM_16B_Pack8BitBytes(
    DRM_NATIVE_BYTE *f_pbNative,
    int        f_cbNative,
    DRM_VOID        *f_pvPacked,
    DRM_DWORD        f_fOptions)
{
    DRM_DWORD ib     = 0;
    DRM_NATIVE_BYTE *pbOut = f_pbNative;
    
    if (f_pvPacked != NULL)
    {
        DRMASSERT((f_fOptions & DRM_PACK_BYTES_IN_PLACE) == 0);
        
        /*pbOut = (DRM_NATIVE_BYTE *) f_pvPacked;*/
    }
    else
    {
        DRMASSERT((f_fOptions & DRM_PACK_BYTES_IN_PLACE) != 0);
        
        pbOut = f_pbNative;
    }
        
    for (ib = 0; ib < f_cbNative; ib += CB_NATIVE_BYTE)
    {
        pbOut [ib / 2] = ((f_pbNative [ib] << 8) | (f_pbNative [ib+1] & 0xFF));
    }
	pbOut[ib/2] = '\0';
	    
    return (DRM_VOID *) pbOut;
}                  
	
		

/*
//------------------------------------------------------------------------------
// Name: LoadandSave
// Desc:  This fuction is the work-around for getting the license response from files on disk, 
	till the dev code for lic response generation is made 16-bit compatible. 
//Parameters:
//	source        source file to read the data from
//    destination  destination file to save the data read from source
//
// Copyright (c) 1999-2000, Microsoft Corporation. All rights reserved.
//------------------------------------------------------------------------------*/

void LoadandSave(char *source,char *destination){
	DRM_BYTE *pb = NULL;
	DRM_DWORD cb =0;
	DRM_CONST_STRING wSource = {0};


	MakeDRMString(&wSource, source);		
	LoadTestFileW(NULL,wSource.pwszString, &pb, &cb);
	OEM_free((DRM_VOID *)wSource.pwszString);
	MakeDRMString(&wSource,destination);
	SaveToFileW(wSource.pwszString, pb,cb);
	OEM_free((DRM_VOID *)wSource.pwszString);
}

#endif
	

		
#if 0
IMPLEMENT_DEFAULT_WARPTEST


BEGIN_APIMAP(testdrmmanager_ansi, "DailyTestDrmManager")
	API_ENTRY(TestManagerInitialize)
	API_ENTRY(TestManagerGenerateChallenge)
	API_ENTRY(TestManagerProcessResponse)
	API_ENTRY(TestManagerSetRights)
	API_ENTRY(TestManagerSetV2Header)
	API_ENTRY(TestManagerGetLicenseData)
	API_ENTRY(TestManagerCommit)
	API_ENTRY(TestManagerDecrypt)
	API_ENTRY(TestManagerCreateEncryptContext)
	API_ENTRY(TestManagerEncrypt)
	API_ENTRY(TestManagerBind)
 	API_ENTRY(TestManagerReinitialize)
	API_ENTRY(TestManagerGenerateResponse)
	API_ENTRY(TestManagerAddLicenseToResponse)
	API_ENTRY(TestManagerInitResponse)
	API_ENTRY(TestManagerChangeTime)
	API_ENTRY(TestManagerPrepareOPLCallback)
	API_ENTRY(TestManagerInitializeForNewStore)
	API_ENTRY(TestManagerSetMachineClock)
	API_ENTRY(TestManagerGetDeviceProperty)
	API_ENTRY(TestManagerSetGetClockState)
	API_ENTRY(TestManagerCleanLicenseStore)
	API_ENTRY(TestManagerGetLicenseState)
	API_ENTRY(TestManagerMakeDeviceLicenseRevocationBlob)
	API_ENTRY(TestManagerProcessDeviceLicenseRevocation)
	API_ENTRY(TestManagerGetSourceID)
	API_ENTRY(TestEnumLicense)
#if DRM_SUPPORT_REVOCATION
    API_ENTRY(TestManagerGetLicenseRevInfoVersion)
	API_ENTRY(TestManagerSetRevocationInfo)
	API_ENTRY(TestManagerSetRevocation)
	API_ENTRY(TestManagerGetRevocationInfo)
	API_ENTRY(TestManagerGetRevocationList)
	API_ENTRY(TestUpdateRevocationVersionsCache)
	API_ENTRY(TestManagerStoreRevocationLists)
#endif // DRM_SUPPORT_REVOCATION 
END_APIMAP

#endif


