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


/*Most of function has additional argument using as flags to
  decide which input should be overwritten:
    1st bit overwrite g_HdsContext
    2nd bit overwrite g_pNsContext
    3rd bit overwrite g_pbQueryContext
     4th bit overwrite g_EnumContext 
    5th bit overwrite g_SlotContext 
    6th bit overwrite KID for adding multiple
*/

#include "tclib.h"
#include "tstutils.h"
#include "drmhds.h"
#include "oemimpl.h"
#include "tOEMIMP.h"

#define MAX_NAMESPACE_NUM    5 

/*global variables*/
static DRM_HDS_CONTEXT g_oHdsContext;
static DRM_HDS_NAMESPACE_CONTEXT g_pNsContext[MAX_NAMESPACE_NUM];
static DRM_HDS_ENUM_CONTEXT g_EnumContext;
static DRM_HDS_SLOT_CONTEXT g_SlotContext;
static DRM_BYTE *g_pbQueryContext=NULL;
static DRM_CHAR g_szHdsName[256]={0};
 
DRM_RESULT TestHdsCreateStore(long argc, char **argv);
DRM_RESULT TestHdsOpenStore(long argc, char **argv);
DRM_RESULT TestHdsCloseStore(long argc, char **argv);
DRM_RESULT TestHdsCreateNamespace(long argc, char **argv);
DRM_RESULT TestHdsDeleteNamespace(long argc, char **argv);
DRM_RESULT TestHdsOpenNamespace(long iIndex, char **argv);
DRM_RESULT TestHdsCloseNamespace(long argc, char **argv);
DRM_RESULT TestHdsCommitStore(long argc, char **argv);
DRM_RESULT TestHdsInitSlotEnum(long argc, char **argv);
DRM_RESULT TestHdsSlotEnumNext(long argc, char **argv);
DRM_RESULT TestHdsOpenSlot(long argc, char **argv);
DRM_RESULT TestHdsCloseSlot(long iIndex, char **argv);
DRM_RESULT TestHdsDeleteSlot(long argc, char **argv);
DRM_RESULT TestHdsSlotResize(long argc, char **argv);
DRM_RESULT TestHdsSlotSeek(long argc, char **argv);
DRM_RESULT TestHdsSlotRead(long argc, char **argv);
DRM_RESULT TestHdsSlotWrite(long argc, char **argv);
DRM_RESULT TestHdsReinitialize(long iIndex, char **argv);
  
DRM_RESULT TestHdsReinitialize(long iIndex, char **argv)
{
    DRM_RESULT dr=DRM_SUCCESS;
    int i=0;

    if (argv!=NULL){
        iIndex=(int)OEM_atoi(argv[0]);
    }
    if(iIndex==0||iIndex==1){
        ChkDR(DRM_HDS_Uninit(&g_oHdsContext));
        DX_VOS_MemSet(&g_oHdsContext, 0, sizeof(DRM_HDS_CONTEXT)); 
        ChkDR(DRM_HDS_Init(&g_oHdsContext));
    }
    if(iIndex==0||iIndex==2){
        for(i=0; i<5; i++)
            DX_VOS_MemSet(&g_pNsContext[i], 0, sizeof(DRM_HDS_NAMESPACE_CONTEXT)); 
    }
    if(iIndex==0||iIndex==3){
        DX_VOS_MemFree(g_pbQueryContext);
        g_pbQueryContext=NULL;
    }
    if(iIndex==0||iIndex==4){
        DX_VOS_MemSet(&g_EnumContext, 0, sizeof(DRM_HDS_ENUM_CONTEXT)); 
    }
    if(iIndex==0||iIndex==5){
        DX_VOS_MemSet(&g_SlotContext, 0, sizeof(DRM_HDS_SLOT_CONTEXT)); 
    }

       if(iIndex==0||iIndex==20){
        /*delete store*/
        if(DX_VOS_StrLen(g_szHdsName)){
               DX_VOS_FDelete(g_szHdsName);
         }
       }
ErrorExit:
     return dr;
}

DRM_RESULT TestHdsCreateStore(long argc, char **argv)
{
    DRM_RESULT dr=DRM_SUCCESS;
 
    long iOption=0;
    int  iContextNull=0, iHdsNameNull=0, iBlkNumType=2;
    DRM_DWORD wBlockSize=0;
    DRM_HDSBLKNUM eBlkNumType=eDRM_HDSBLKNUM_WORD;
    DRM_WCHAR wszHdsName[256]={0};
    DRM_BOOL fTruncateExist=TRUE;

     /*at least 6 arguments. The last one is used to decide whether we need to overwrite the context*/
    if(argc<6){
        Log("Trace", "\t\tFrom TestHdsCreateStore: error in number of arguments.");
        ChkDR(DRM_E_FAIL);
    }
    
     if(!IsDigitalOnlyString(argv[1])||!IsDigitalOnlyString(argv[2])||!IsDigitalOnlyString(argv[4])||!IsDigitalOnlyString(argv[5])){
        Log("Trace", "\t\tFrom TestHdsCreateStore: error in the argument.");
        ChkDR(DRM_E_FAIL);
    }
  
     iOption=(long)OEM_atol(argv[5]);
    /*the first bit is to overwrite flag for Context*/
    if(iOption&1){
         /*Context is from the input*/
        if(argv[3]!=NULL)
             DX_VOS_FastMemCpy(g_oHdsContext.rgbOpaqueData, argv[3],DX_VOS_StrLen(argv[3])+1);
         else
            iContextNull=1;
       }
    /*block size*/
    wBlockSize=OEM_atol(argv[1]);
    /*HDS name*/
    if(argv[0]!=NULL){
        DX_VOS_FastMemCpy(g_szHdsName, argv[0], DX_VOS_StrLen(argv[0])+1);
        OEM_mbstowcs(wszHdsName, argv[0], DX_VOS_StrLen(argv[0])+1);
    }
    else
        iHdsNameNull=1;
    /*block number type*/
		iBlkNumType=(int)OEM_atoi(argv[2]);
    
    if(iBlkNumType==4)
        eBlkNumType=eDRM_HDSBLKNUM_DWORD;
    else
        eBlkNumType=eDRM_HDSBLKNUM_WORD;
   
    /*truncate flag*/
    if(OEM_atoi(argv[4])!=0)
        fTruncateExist=TRUE;
    else
        fTruncateExist=FALSE;

    /*remove the same store if any*/
    TestHdsReinitialize(20,NULL);

      ChkDR(DRM_HDS_CreateStore(iHdsNameNull>0?NULL:wszHdsName,wBlockSize,eBlkNumType,iContextNull>0?NULL:&g_oHdsContext,fTruncateExist));
ErrorExit:
      return dr;
}

DRM_RESULT TestHdsOpenStore(long argc, char **argv)
{
    DRM_RESULT dr=DRM_SUCCESS;
    DRM_HDS_CONTEXT pLocalHdsContext;
    long iOption=0;
    int iContextNull=0, iHdsNameNull=0;
    DRM_WCHAR wszHdsName[256]={0};

     /*at least 3 arguments. The last one is used to decide whether we need to overwrite the context*/
    if(argc<3){
        Log("Trace", "\t\tFrom TestHdsOpenStore: error in number of arguments.");
        ChkDR(DRM_E_FAIL);
    }
    if(!IsDigitalOnlyString(argv[2])){
        Log("Trace", "\t\tFrom TestHdsOpenStore: error in the argument.");
        ChkDR(DRM_E_FAIL);
    }
  
    iOption=(long)OEM_atol(argv[2]);
    /*the first bit is to overwrite flag for Context*/
    if(iOption&1){
         /*Context is from the input*/
        DX_VOS_MemSet(&pLocalHdsContext, 0, sizeof(DRM_HDS_CONTEXT)); 
        if(argv[1]!=NULL)
             DX_VOS_FastMemCpy(pLocalHdsContext.rgbOpaqueData, argv[1],DX_VOS_StrLen(argv[1])+1);
        else
            iContextNull=1;
       }
     /*HDS name*/
    if(argv[0]!=NULL){
         OEM_mbstowcs(wszHdsName, argv[0], DX_VOS_StrLen(argv[0])+1);
        DX_VOS_FastMemCpy(g_szHdsName, argv[0], DX_VOS_StrLen(argv[0])+1);
    }
    else
        iHdsNameNull=1;
    if(iOption&1){
         ChkDR(DRM_HDS_OpenStore(iHdsNameNull>0?NULL:wszHdsName,iContextNull>0?NULL:&pLocalHdsContext));
    }
    else{
         ChkDR(DRM_HDS_OpenStore(iHdsNameNull>0?NULL:wszHdsName,&g_oHdsContext));
    }
ErrorExit:
      return dr;
}
 
DRM_RESULT TestHdsCloseStore(long argc, char **argv)
{
    DRM_RESULT dr=DRM_SUCCESS;
    DRM_HDS_CONTEXT pLocalHdsContext;
    long iOption=0;
    int  iContextNull=0;
 
     /*at least 2 arguments. The last one is used to decide whether we need to overwrite the context*/
    if(argc<2){
        Log("Trace", "\t\tFrom TestHdsCloseStore: error in number of arguments.");
        ChkDR(DRM_E_FAIL);
    }
    if(!IsDigitalOnlyString(argv[1])){
        Log("Trace", "\t\tFrom TestHdsCloseStore: error in the argument.");
        ChkDR(DRM_E_FAIL);
    }
  
     iOption=(long)OEM_atol(argv[1]);
    /*the first bit is to overwrite flag for Context*/
    if(iOption&1){
         /*Context is from the input*/
        DX_VOS_MemSet(&pLocalHdsContext, 0, sizeof(DRM_HDS_CONTEXT)); 
        if(argv[0]!=NULL)
             DX_VOS_FastMemCpy(pLocalHdsContext.rgbOpaqueData, argv[0],DX_VOS_StrLen(argv[0])+1);
        else
            iContextNull=1;
       }
      if(iOption&1){
         ChkDR(DRM_HDS_CloseStore(iContextNull>0?NULL:&pLocalHdsContext));
    }
    else{
         ChkDR(DRM_HDS_CloseStore(&g_oHdsContext));
    }
ErrorExit:
      return dr;
}

DRM_RESULT TestHdsCommitStore(long argc, char **argv)
{
    DRM_RESULT dr=DRM_SUCCESS;
    DRM_HDS_CONTEXT pLocalHdsContext;
    long iOption=0;
    int iContextNull=0;
 
     /*at least 2 arguments. The last one is used to decide whether we need to overwrite the context*/
    if(argc<2){
        Log("Trace", "\t\tFrom TestHdsCommitStore: error in number of arguments.");
        ChkDR(DRM_E_FAIL);
    }
    if(!IsDigitalOnlyString(argv[1])){
        Log("Trace", "\t\tFrom TestHdsCommitStore: error in the argument.");
        ChkDR(DRM_E_FAIL);
    }
  
     iOption=(long)OEM_atol(argv[1]);
    /*the first bit is to overwrite flag for Context*/
    if(iOption&1){
         /*Context is from the input*/
        DX_VOS_MemSet(&pLocalHdsContext, 0, sizeof(DRM_HDS_CONTEXT)); 
        if(argv[0]!=NULL)
             DX_VOS_FastMemCpy(pLocalHdsContext.rgbOpaqueData, argv[0],DX_VOS_StrLen(argv[0])+1);
        else
            iContextNull=1;
       }
      if(iOption&1){
         ChkDR(DRM_HDS_CommitStore(iContextNull>0?NULL:&pLocalHdsContext));
    }
    else{
         ChkDR(DRM_HDS_CommitStore(&g_oHdsContext));
    }
ErrorExit:
      return dr;
}

DRM_RESULT TestHdsDeleteNamespace(long argc, char **argv)
{
    DRM_RESULT dr=DRM_SUCCESS;
 
    long iOption=0;
    int iContextNull=0, iHdsNamespaceNull=0;
      DRM_HDS_NAMESPACE HdsNamespace;
    DRM_HDS_CONTEXT pLocalHdsContext;
         
     /*at least 3 arguments. The last one is used to decide whether we need to overwrite the context*/
    if(argc<3){
        Log("Trace", "\t\tFrom TestHdsDeleteNamespace: error in number of arguments.");
        ChkDR(DRM_E_FAIL);
    }
    if(!IsDigitalOnlyString(argv[2])){
        Log("Trace", "\t\tFrom TestHdsDeleteNamespace: error in the argument.");
        ChkDR(DRM_E_FAIL);
    }
  
     iOption=(long)OEM_atol(argv[2]);
    /*the first bit is to overwrite flag for Context*/
    if(iOption&1){
         /*Context is from the input*/
        DX_VOS_MemSet(&pLocalHdsContext, 0, sizeof(DRM_HDS_CONTEXT)); 
        if(argv[0]!=NULL)
             DX_VOS_FastMemCpy(pLocalHdsContext.rgbOpaqueData, argv[0],DX_VOS_StrLen(argv[0])+1);
        else
            iContextNull=1;
       }
     /*name space*/
    if(argv[1]!=NULL)
         DX_VOS_FastMemCpy(HdsNamespace.rgb, argv[1], min(DX_VOS_StrLen(argv[1])+1, DRM_HDS_NSNAME_SIZE));
    else
        iHdsNamespaceNull=1;

    if(iOption&1){
        ChkDR(DRM_HDS_DeleteNamespace(iContextNull>0?NULL:&pLocalHdsContext,iHdsNamespaceNull>0?NULL:&HdsNamespace, TRUE));
    }
    else{
        ChkDR(DRM_HDS_DeleteNamespace(&g_oHdsContext,iHdsNamespaceNull>0?NULL:&HdsNamespace, TRUE));
    }

ErrorExit:
      return dr;
}

DRM_RESULT TestHdsOpenNamespace(long argc, char **argv)
{
    DRM_RESULT dr=DRM_SUCCESS;
    DRM_HDS_CONTEXT pLocalHdsContext;
    long iOption=0;
    int iContextNull=0, iHdsNamespaceNull=0,iNsContextNull=0, iNamespaceIndex=0;
	DRM_WORD wMaxNumChildren=0;
    DRM_HDS_NAMESPACE HdsNamespace;
	DRM_HDS_OPENMODE namespaceOpenMode=eDRM_HDS_CREATE_IF_NEW;
    
    iOption=(long)OEM_atol(argv[6]);
    /*the first bit is to overwrite flag for Context*/
    if(iOption&1){
         /*Context is from the input*/
        DX_VOS_MemSet(&pLocalHdsContext, 0, sizeof(DRM_HDS_CONTEXT)); 
        if(argv[0]!=NULL)
             DX_VOS_FastMemCpy(pLocalHdsContext.rgbOpaqueData, argv[0],DX_VOS_StrLen(argv[0])+1);
        else
            iContextNull=1;
    }
     /*name space*/
    if(argv[1]!=NULL)
         DX_VOS_FastMemCpy(HdsNamespace.rgb, argv[1], min(DX_VOS_StrLen(argv[1])+1, DRM_HDS_NSNAME_SIZE));
    else
        iHdsNamespaceNull=1;

	if(OEM_atoi(argv[2])==2)
		namespaceOpenMode=eDRM_HDS_OPEN_EXISTING;
	else
		namespaceOpenMode=eDRM_HDS_CREATE_IF_NEW;

    /*number of children*/
    wMaxNumChildren=(DRM_WORD)OEM_atol(argv[3]);
 
    /*name space context*/
    iNamespaceIndex=(int)OEM_atoi(argv[5]);
    if(iNamespaceIndex>=MAX_NAMESPACE_NUM||iNamespaceIndex<0)
        iNamespaceIndex=0;

	if(argv[4]!=NULL)
         DX_VOS_FastMemCpy(g_pNsContext[iNamespaceIndex].rgbOpaqueData, argv[4],DX_VOS_StrLen(argv[4])+1);
    else
        iNsContextNull=1;

    if(iOption&1){
        ChkDR( DRM_HDS_OpenNamespace( iContextNull>0?NULL:&pLocalHdsContext,
                                      iHdsNamespaceNull>0?NULL:&HdsNamespace,
                                      namespaceOpenMode,
                                      wMaxNumChildren,                                      
                                      iNsContextNull>0?NULL:&g_pNsContext[iNamespaceIndex]));
    }
    else{
          ChkDR( DRM_HDS_OpenNamespace( &g_oHdsContext,
                                        iHdsNamespaceNull>0?NULL:&HdsNamespace,
                                        namespaceOpenMode,
                                        wMaxNumChildren,
                                        iNsContextNull>0?NULL:&g_pNsContext[iNamespaceIndex]));
     }

ErrorExit:
      return dr;
}

DRM_RESULT TestHdsCloseNamespace(long argc, char **argv)
{
    DRM_RESULT dr=DRM_SUCCESS;
    DRM_HDS_NAMESPACE_CONTEXT pLocalNsContext;
    long iOption=0;
    int iContextNull=0,iNamespaceIndex=0;
 
     /*at least 3 arguments. The last one is used to decide whether we need to overwrite the context*/
    /*second argument to decide which name space*/
    if(argc<3){
        Log("Trace", "\t\tFrom TestHdsCloseNamespace: error in number of arguments.");
        ChkDR(DRM_E_FAIL);
    }
    if(!IsDigitalOnlyString(argv[1])||!IsDigitalOnlyString(argv[2])){
        Log("Trace", "\t\tFrom TestHdsCloseNamespace: error in the argument.");
        ChkDR(DRM_E_FAIL);
    }
  
     iOption=(long)OEM_atol(argv[2]);
    /*the second bit is to overwrite flag for Context*/
    if(iOption&2){
         /*Context is from the input*/
        DX_VOS_MemSet(&pLocalNsContext, 0, sizeof(DRM_HDS_NAMESPACE_CONTEXT)); 
        if(argv[0]!=NULL)
             DX_VOS_FastMemCpy(pLocalNsContext.rgbOpaqueData, argv[0],DX_VOS_StrLen(argv[0])+1);
        else
            iContextNull=1;
       }
      if(iOption&2){
         ChkDR(DRM_HDS_CloseNamespace(iContextNull>0?NULL:&pLocalNsContext));
    }
    else{
        iNamespaceIndex=(int)OEM_atoi(argv[1]);
         if(iNamespaceIndex>=MAX_NAMESPACE_NUM||iNamespaceIndex<0)
            iNamespaceIndex=0;
         ChkDR(DRM_HDS_CloseNamespace(&g_pNsContext[iNamespaceIndex]));
      }
ErrorExit:
      return dr;
}

DRM_RESULT TestHdsOpenSlot(long argc, char **argv)
{
    DRM_RESULT dr=DRM_SUCCESS;
    DRM_HDS_NAMESPACE_CONTEXT pLocalNsContext;
    long iOption=0;
    int iNsContextNull=0,iSizeNull=0, iSlotContextNull=0;
    int iHashKeyNull=0, iUniqueKeyNull=0, iNamespaceIndex=0;
      DRM_HDS_HASHKEY HashKey;
    DRM_HDS_UNIQUEKEY UniqueKey;
    DRM_DWORD eMode=0;
    DRM_DWORD cbSlotSize=0;

     /*at least 8 arguments. The last one is used to decide whether we need to overwrite the context*/
    /*7th argument to decide which name space*/
    if(argc<8){
        Log("Trace", "\t\tFrom TestHdsOpenSlot: error in number of arguments.");
        ChkDR(DRM_E_FAIL);
    }
    if(!IsDigitalOnlyString(argv[1])||!IsDigitalOnlyString(argv[6])||!IsDigitalOnlyString(argv[7])){
        Log("Trace", "\t\tFrom TestHdsOpenSlot: error in the argument.");
        ChkDR(DRM_E_FAIL);
    }
  
     iOption=(long)OEM_atol(argv[7]);
    /*the second bit is to overwrite flag for name space Context*/
    if(iOption&2){
         /*Context is from the input*/
        DX_VOS_MemSet(&pLocalNsContext, 0, sizeof(DRM_HDS_NAMESPACE_CONTEXT)); 
        if(argv[0]!=NULL)
             DX_VOS_FastMemCpy(pLocalNsContext.rgbOpaqueData, argv[0],DX_VOS_StrLen(argv[0])+1);
        else
            iNsContextNull=1;
       }

     /*open mode*/
    eMode=(DRM_DWORD)OEM_atoi(argv[1]);
 
    /*hash key*/
    if(argv[2]!=NULL)
         DX_VOS_FastMemCpy(HashKey.rgb, argv[2], min(DX_VOS_StrLen(argv[2])+1, DRM_ID_SIZE));
    else
        iHashKeyNull=1;

    /*unique key*/
    if(argv[3]!=NULL)
         DX_VOS_FastMemCpy(UniqueKey.rgb, argv[3], min(DX_VOS_StrLen(argv[3])+1, DRM_ID_SIZE));
    else
        iUniqueKeyNull=1;

    /*slot size*/
      if(argv[4]!=NULL)
         cbSlotSize=OEM_atol(argv[4]); 
    else
        iSizeNull=1;
 
    /*slot context*/
    if(argv[5]!=NULL)
         DX_VOS_FastMemCpy(g_SlotContext.rgbOpaqueData, argv[5],DX_VOS_StrLen(argv[5])+1);
    else
        iSlotContextNull=1;

    if(iOption&2){
        ChkDR(DRM_HDS_OpenSlot(iNsContextNull>0?NULL:&pLocalNsContext,eMode, 
            iHashKeyNull>0?NULL:&HashKey,
            iUniqueKeyNull>0?NULL:&UniqueKey,
            NULL,
            iSizeNull>0?NULL:&cbSlotSize,
            iSlotContextNull>0?NULL:&g_SlotContext));
    }
    else{
        iNamespaceIndex=(int)OEM_atoi(argv[6]);
         if(iNamespaceIndex>=MAX_NAMESPACE_NUM||iNamespaceIndex<0)
            iNamespaceIndex=0;
        ChkDR(DRM_HDS_OpenSlot(&g_pNsContext[iNamespaceIndex],eMode,
            iHashKeyNull>0?NULL:&HashKey,
            iUniqueKeyNull>0?NULL:&UniqueKey,
            NULL,
            iSizeNull>0?NULL:&cbSlotSize,
            iSlotContextNull>0?NULL:&g_SlotContext));
     }

ErrorExit:
      return dr;
}

DRM_RESULT TestHdsCloseSlot(long argc, char **argv)
{
    DRM_RESULT dr=DRM_SUCCESS;
    DRM_HDS_SLOT_CONTEXT pLocalSlotContext;
    long iOption=0;
    int iContextNull=0;
 
     /*at least 2 arguments. The last one is used to decide whether we need to overwrite the context*/
    if(argc<2){
        Log("Trace", "\t\tFrom TestHdsCloseSlot: error in number of arguments.");
        ChkDR(DRM_E_FAIL);
    }
    if(!IsDigitalOnlyString(argv[1])){
        Log("Trace", "\t\tFrom TestHdsCloseSlot: error in the argument.");
        ChkDR(DRM_E_FAIL);
    }
  
     iOption=(long)OEM_atol(argv[1]);
    /*the 5th bit is to overwrite flag for slot Context*/
    if(iOption&16){
         /*Context is from the input*/
        DX_VOS_MemSet(&pLocalSlotContext, 0, sizeof(DRM_HDS_SLOT_CONTEXT)); 
        if(argv[0]!=NULL)
             DX_VOS_FastMemCpy(pLocalSlotContext.rgbOpaqueData, argv[0],DX_VOS_StrLen(argv[0])+1);
        else
            iContextNull=1;
       }
      if(iOption&16){
         ChkDR(DRM_HDS_CloseSlot(iContextNull>0?NULL:&pLocalSlotContext));
    }
    else{
         ChkDR(DRM_HDS_CloseSlot(&g_SlotContext));
    }
ErrorExit:
      return dr;
}

DRM_RESULT TestHdsDeleteSlot(long argc, char **argv)
{
    DRM_RESULT dr=DRM_SUCCESS;
    DRM_HDS_NAMESPACE_CONTEXT pLocalNsContext;
    long iOption=0;
    int iNsContextNull=0,iHashKeyNull=0, iUniqueKeyNull=0, iNamespaceIndex=0;
      DRM_HDS_HASHKEY HashKey;
    DRM_HDS_UNIQUEKEY UniqueKey;
 
     /*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 TestHdsDeleteSlot: error in number of arguments.");
        ChkDR(DRM_E_FAIL);
    }
    if(!IsDigitalOnlyString(argv[4])){
        Log("Trace", "\t\tFrom TestHdsDeleteSlot: error in the argument.");
        ChkDR(DRM_E_FAIL);
    }
  
     iOption=(long)OEM_atol(argv[4]);

    /*the second bit is to overwrite flag for name space Context*/
    if(iOption&2){
         /*Context is from the input*/
        DX_VOS_MemSet(&pLocalNsContext, 0, sizeof(DRM_HDS_NAMESPACE_CONTEXT)); 
        if(argv[0]!=NULL)
             DX_VOS_FastMemCpy(pLocalNsContext.rgbOpaqueData, argv[0],DX_VOS_StrLen(argv[0])+1);
        else
            iNsContextNull=1;
       }
 
    /*hash key*/
    if(argv[1]!=NULL)
         DX_VOS_FastMemCpy(HashKey.rgb, argv[1], min(DX_VOS_StrLen(argv[1])+1, DRM_ID_SIZE));
    else
        iHashKeyNull=1;

    /*unique key*/
    if(argv[2]!=NULL)
         DX_VOS_FastMemCpy(UniqueKey.rgb, argv[2], min(DX_VOS_StrLen(argv[2])+1, DRM_ID_SIZE));
    else
        iUniqueKeyNull=1;

    if(iOption&2){
        ChkDR(DRM_HDS_DeleteSlot(iNsContextNull>0?NULL:&pLocalNsContext, 
            iHashKeyNull>0?NULL:&HashKey,
            iUniqueKeyNull>0?NULL:&UniqueKey, NULL, TRUE));
     }
    else{
        iNamespaceIndex=(int)OEM_atoi(argv[3]);
         if(iNamespaceIndex>=MAX_NAMESPACE_NUM||iNamespaceIndex<0)
            iNamespaceIndex=0;
        ChkDR(DRM_HDS_DeleteSlot(&g_pNsContext[iNamespaceIndex], 
            iHashKeyNull>0?NULL:&HashKey,
            iUniqueKeyNull>0?NULL:&UniqueKey, NULL, TRUE));
      }
 
ErrorExit:
      return dr;
}
 
DRM_RESULT TestHdsInitSlotEnum(long argc, char **argv)
{
    DRM_RESULT dr=DRM_SUCCESS;
    DRM_HDS_NAMESPACE_CONTEXT pLocalNsContext;
    long iOption=0;
    int iNsContextNull=0, iEnumContextNull=0, iNamespaceIndex=0,iHashKeyNull=0;
    DRM_HDS_LOCKMODE eLockMode=eDRM_HDS_LOCKSHARED;
    DRM_HDS_HASHKEY HashKey;

    /*at least 6 arguments. The last one is used to decide whether we need to overwrite the context*/
    /*6th argument to decide which name space to use*/
    if(argc<6){
        Log("Trace", "\t\tFrom TestHdsInitSlotEnum: error in number of arguments.");
        ChkDR(DRM_E_FAIL);
    }
    if(!IsDigitalOnlyString(argv[2])||!IsDigitalOnlyString(argv[4])||!IsDigitalOnlyString(argv[5])){
        Log("Trace", "\t\tFrom TestHdsInitSlotEnum: error in the argument.");
        ChkDR(DRM_E_FAIL);
    }
  
     iOption=(long)OEM_atol(argv[5]);
    /*the second bit is to overwrite flag for name space Context*/
    if(iOption&2){
         /*Context is from the input*/
        DX_VOS_MemSet(&pLocalNsContext, 0, sizeof(DRM_HDS_NAMESPACE_CONTEXT)); 
        if(argv[0]!=NULL)
             DX_VOS_FastMemCpy(pLocalNsContext.rgbOpaqueData, argv[0],DX_VOS_StrLen(argv[0])+1);
        else
            iNsContextNull=1;
       }

    /*hash key*/
    if(argv[1]!=NULL)
         DX_VOS_FastMemCpy(HashKey.rgb, argv[1], min(DX_VOS_StrLen(argv[1])+1, DRM_ID_SIZE));
    else
        iHashKeyNull=1;

    /*lock mode*/
    eLockMode=(DRM_HDS_LOCKMODE)OEM_atoi(argv[2]); 
  
    /*enum context*/
    if(argv[3]!=NULL)
         DX_VOS_FastMemCpy(g_EnumContext.rgbOpaqueData, argv[3],DX_VOS_StrLen(argv[3])+1);
    else
        iEnumContextNull=1;
  
    if(iOption&2){
        ChkDR(DRM_HDS_InitSlotEnum(iNsContextNull>0?NULL:&pLocalNsContext,iHashKeyNull>0?NULL:&HashKey,eLockMode,iEnumContextNull>0?NULL:&g_EnumContext));
    }
    else{
        iNamespaceIndex=(int)OEM_atoi(argv[4]);
        if(iNamespaceIndex>=MAX_NAMESPACE_NUM||iNamespaceIndex<0)
            iNamespaceIndex=0;

        ChkDR(DRM_HDS_InitSlotEnum(&g_pNsContext[iNamespaceIndex],iHashKeyNull>0?NULL:&HashKey,eLockMode,iEnumContextNull>0?NULL:&g_EnumContext));
    }

ErrorExit:
      return dr;
}

DRM_RESULT TestHdsSlotEnumNext(long argc, char **argv)
{
    DRM_RESULT dr=DRM_SUCCESS;
    DRM_HDS_UNIQUEKEY UniqueKey;
    DRM_HDS_HASHKEY HashKey;
      DRM_HDS_ENUM_CONTEXT pLocalEnumContext;
    long iOption=0;
    int iSlotContextNull=0, iSizeNull=0, iEnumContextNull=0,iHashKeyNull=0, iUniqueKeyNull=0;
       DRM_DWORD cbSize=0;
 
     /*at least 9 arguments. The last one is used to decide whether we need to overwrite the context*/
    /*8th argument is size of slot*/
    /*7th argument is Unique Key*/
    /*6th argument is Hash Key*/
    if(argc<9){
        Log("Trace", "\t\tFrom TestHdsSlotEnumNext: error in number of arguments.");
        ChkDR(DRM_E_FAIL);
    }
    if(!IsDigitalOnlyString(argv[8])){
        Log("Trace", "\t\tFrom TestHdsSlotEnumNext: error in the argument.");
        ChkDR(DRM_E_FAIL);
    }
  
     iOption=(long)OEM_atol(argv[8]);
    /*the 4th bit is to overwrite flag for enum Context*/
    if(iOption&8){
         if(argv[0]!=NULL)
             DX_VOS_FastMemCpy(pLocalEnumContext.rgbOpaqueData, argv[0],DX_VOS_StrLen(argv[0])+1);
        else
            iEnumContextNull=1;
       }
      /*slot context*/
    if(argv[1]!=NULL)
         DX_VOS_FastMemCpy(g_SlotContext.rgbOpaqueData + sizeof(DRM_DWORD), argv[1],DX_VOS_StrLen(argv[1])+1);
    else
        iSlotContextNull=1;

    /*hash key*/
    if(argv[2]!=NULL)
          DX_VOS_FastMemCpy(HashKey.rgb, argv[2], min(DX_VOS_StrLen(argv[2])+1, DRM_ID_SIZE));
     else
        iHashKeyNull=1;

    /*unique key*/
    if(argv[3]!=NULL)
          DX_VOS_FastMemCpy(UniqueKey.rgb, argv[3], min(DX_VOS_StrLen(argv[3])+1, DRM_ID_SIZE));
     else
        iUniqueKeyNull=1;
  
    /*slot size*/
    if(argv[4]!=NULL)
         cbSize=(DRM_DWORD)OEM_atol(argv[4]);
    else
        iSizeNull=1;

    if(iOption&8){
        ChkDR(DRM_HDS_SlotEnumNext(iEnumContextNull>0?NULL:&pLocalEnumContext,
            iSlotContextNull>0?NULL:&g_SlotContext,
            iHashKeyNull>0?NULL:&HashKey,
            iUniqueKeyNull>0?NULL:&UniqueKey,
            iSizeNull>0?NULL:&cbSize));
    }
    else{
        ChkDR(DRM_HDS_SlotEnumNext(&g_EnumContext,
            iSlotContextNull>0?NULL:&g_SlotContext,
            iHashKeyNull>0?NULL:&HashKey,
            iUniqueKeyNull>0?NULL:&UniqueKey,
            iSizeNull>0?NULL:&cbSize));
    }

    /*verify the results*/
    if(argv[7]!=NULL){
        if(cbSize!=(DRM_DWORD)OEM_atol(argv[7])){
            ChkDR(DRM_E_FAIL);
        }
    }
    if(argv[6]!=NULL){
        if(DX_VOS_StrNCmp(argv[6],(const DxChar*)UniqueKey.rgb, DX_VOS_StrLen(argv[6]))){
            Log("Trace", "\t\tFrom TestHdsSlotEnumNext: bUniqueKey=%s", UniqueKey.rgb);
            ChkDR(DRM_E_FAIL);
        }
    }
    if(argv[5]!=NULL){
        if(DX_VOS_StrNCmp(argv[5],(const DxChar*)HashKey.rgb, DX_VOS_StrLen(argv[5]))){
            ChkDR(DRM_E_FAIL);
        }
    }

ErrorExit:
       return dr;
}

DRM_RESULT TestHdsSlotResize(long argc, char **argv)
{
    DRM_RESULT dr=DRM_SUCCESS;
       DRM_HDS_SLOT_CONTEXT pLocalSlotContext;
    long iOption=0;
    int iSlotContextNull=0;
       DRM_DWORD cbSize=0;
 
     /*at least 3 arguments. The last one is used to decide whether we need to overwrite the context*/
    if(argc<3){
        Log("Trace", "\t\tFrom TestHdsSlotResize: error in number of arguments.");
        ChkDR(DRM_E_FAIL);
    }
    if(!IsDigitalOnlyString(argv[1])||!IsDigitalOnlyString(argv[2])){
        Log("Trace", "\t\tFrom TestHdsSlotResize: error in the argument.");
        ChkDR(DRM_E_FAIL);
    }
  
     iOption=(long)OEM_atol(argv[2]);
    /*the 5th bit is to overwrite flag for slot Context*/
    if(iOption&16){
         if(argv[0]!=NULL)
             DX_VOS_FastMemCpy(pLocalSlotContext.rgbOpaqueData, argv[0],DX_VOS_StrLen(argv[0])+1);
        else
            iSlotContextNull=1;
       }
   
    /*slot size*/
     cbSize=OEM_atol(argv[1]);
 
    if(iOption&16){
        ChkDR(DRM_HDS_SlotResize(iSlotContextNull>0?NULL:&pLocalSlotContext,cbSize));
    }
    else{
        ChkDR(DRM_HDS_SlotResize(&g_SlotContext,cbSize));
    }

ErrorExit:
       return dr;
}

DRM_RESULT TestHdsSlotSeek(long argc, char **argv)
{
    DRM_RESULT dr=DRM_SUCCESS;
       DRM_HDS_SLOT_CONTEXT pLocalSlotContext;
    long iOption=0;
    int iSlotContextNull=0, iSeekPointerNull=0, iSeekMode=0;
       DRM_DWORD nOffset=0;
    DRM_DWORD wSeekPointer=0;
    DRM_HDS_SEEKMODE eOrigin=eDRM_HDS_SEEKCUR;
 
     /*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 TestHdsSlotSeek: error in number of arguments.");
        ChkDR(DRM_E_FAIL);
    }
    if(!IsDigitalOnlyString(argv[1])||!IsDigitalOnlyString(argv[2])||!IsDigitalOnlyString(argv[4])){
        Log("Trace", "\t\tFrom TestHdsSlotSeek: error in the argument.");
        ChkDR(DRM_E_FAIL);
    }
  
     iOption=(long)OEM_atol(argv[4]);
    /*the 5th bit is to overwrite flag for slot Context*/
    if(iOption&16){
         if(argv[0]!=NULL)
             DX_VOS_FastMemCpy(pLocalSlotContext.rgbOpaqueData, argv[0],DX_VOS_StrLen(argv[0])+1);
        else
            iSlotContextNull=1;
       }
   
    /*offset*/
     nOffset=(DRM_SHORT)OEM_atol(argv[1]);
 
    /*seek mode*/
    iSeekMode=(int)OEM_atoi(argv[2]);
    if(iSeekMode==1){
        eOrigin=eDRM_HDS_SEEKCUR;
    }
    else if(iSeekMode==2){
        eOrigin=eDRM_HDS_SEEKEND;
    }
    else if(iSeekMode==3){
        eOrigin=eDRM_HDS_SEEKSET;
    }
    else
        eOrigin=iSeekMode;

    /*seek pointer*/
    if(argv[3]!=NULL)
         wSeekPointer=OEM_atol(argv[3]); 
    else
        iSeekPointerNull=1;
 
    if(iOption&16){
        ChkDR(DRM_HDS_SlotSeek(iSlotContextNull>0?NULL:&pLocalSlotContext,nOffset,eOrigin,iSeekPointerNull>0?NULL:&wSeekPointer));
    }
    else{
        ChkDR(DRM_HDS_SlotSeek(&g_SlotContext,nOffset,eOrigin,iSeekPointerNull>0?NULL:&wSeekPointer));
    }

ErrorExit:
       return dr;
}

DRM_RESULT TestHdsSlotRead(long argc, char **argv)
{
    DRM_RESULT dr=DRM_SUCCESS;
       DRM_HDS_SLOT_CONTEXT pLocalSlotContext;
    DRM_BYTE *pbData=NULL;
    long iOption=0;
    int iSlotContextNull=0, iReadNull=0;
      DRM_DWORD cbData=0, cbRead=0;
  
     /*at least 6 arguments. The last one is used to decide whether we need to overwrite the context*/
    /*the 5th argument is used to verify the read content*/
    if(argc<6){
        Log("Trace", "\t\tFrom TestHdsSlotRead: error in number of arguments.");
        ChkDR(DRM_E_FAIL);
    }
    if(!IsDigitalOnlyString(argv[1])||!IsDigitalOnlyString(argv[5])){
        Log("Trace", "\t\tFrom TestHdsSlotRead: error in the argument.");
        ChkDR(DRM_E_FAIL);
    }
  
     iOption=(long)OEM_atol(argv[5]);
    /*the 5th bit is to overwrite flag for slot Context*/
    if(iOption&16){
         if(argv[0]!=NULL)
             DX_VOS_FastMemCpy(pLocalSlotContext.rgbOpaqueData, argv[0],DX_VOS_StrLen(argv[0])+1);
        else
            iSlotContextNull=1;
       }
    /* data size*/
    cbData=OEM_atol(argv[1]); 

    /*data*/
    if(argv[2]!=NULL){
        pbData=(DRM_BYTE*)DX_VOS_MemMalloc(DX_VOS_StrLen(argv[2])+1);        
        DX_VOS_FastMemCpy(pbData, argv[2],DX_VOS_StrLen(argv[2])+1);
    }
  
     /*size read*/
    if(argv[3]!=NULL)
         cbRead=OEM_atol(argv[3]); 
    else
        iReadNull=1;
 
    if(iOption&16){
        ChkDR(DRM_HDS_SlotRead(iSlotContextNull>0?NULL:&pLocalSlotContext,cbData,pbData,iReadNull>0?NULL:&cbRead));
    }
    else{
        ChkDR(DRM_HDS_SlotRead(&g_SlotContext,cbData,pbData,iReadNull>0?NULL:&cbRead));
    }
    
    /*check the read result*/
    if(argv[4]!=NULL){
        if(cbRead!=0 && DX_VOS_StrNCmp((const DxChar*)pbData,argv[4], DX_VOS_StrLen(argv[4]))!=0){
            ChkDR(DRM_E_FAIL);
        }
    }

ErrorExit:
    DX_VOS_MemFree(pbData);
       return dr;
}

DRM_RESULT TestHdsSlotWrite(long argc, char **argv)
{
    DRM_RESULT dr=DRM_SUCCESS;
       DRM_HDS_SLOT_CONTEXT pLocalSlotContext;
    DRM_BYTE *pbData=NULL;
    long iOption=0;
    int iSlotContextNull=0, iWrittenNull=0;
      DRM_DWORD cbData=0, cbWritten=0;
  
     /*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 TestHdsSlotWrite: error in number of arguments.");
        ChkDR(DRM_E_FAIL);
    }
    if(!IsDigitalOnlyString(argv[1])||!IsDigitalOnlyString(argv[4])){
        Log("Trace", "\t\tFrom TestHdsSlotWrite: error in the argument.");
        ChkDR(DRM_E_FAIL);
    }
  
     iOption=(long)OEM_atol(argv[4]);
    /*the 5th bit is to overwrite flag for slot Context*/
    if(iOption&16){
         if(argv[0]!=NULL)
             DX_VOS_FastMemCpy(pLocalSlotContext.rgbOpaqueData, argv[0],DX_VOS_StrLen(argv[0])+1);
        else
            iSlotContextNull=1;
       }

    /* data size*/
    cbData=OEM_atol(argv[1]); 

    /*data*/
    if(argv[2]!=NULL){
        pbData=(DRM_BYTE*)DX_VOS_MemMalloc(DX_VOS_StrLen(argv[2])+1);        
        DX_VOS_FastMemCpy(pbData, argv[2],DX_VOS_StrLen(argv[2])+1);
    }
  
     /*size written*/
    if(argv[3]!=NULL)
         cbWritten=OEM_atol(argv[3]); 
    else
        iWrittenNull=1;
 
    if(iOption&16){
        ChkDR(DRM_HDS_SlotWrite(iSlotContextNull>0?NULL:&pLocalSlotContext,cbData,pbData,iWrittenNull>0?NULL:&cbWritten));
    }
    else{
        ChkDR(DRM_HDS_SlotWrite(&g_SlotContext,cbData,pbData,iWrittenNull>0?NULL:&cbWritten));
    }

ErrorExit:
    DX_VOS_MemFree(pbData);
       return dr;
}

/*this function was introduced during metering QFE. Currently only meter used this function.*/
DRM_RESULT TestHdsBlockScanDelete(long argc, char **argv)
{
    DRM_RESULT dr=DRM_SUCCESS;
    DRM_HDS_HASHKEY HashKey;
    DRM_HDS_UNIQUEKEY UniqueKey[100];

 	DRM_DWORD  nKID=0, i=0;
    DRM_HDS_BLOCKSCAN_CONTEXT    *pcontextBlockScan = NULL;
	
	pcontextBlockScan=(DRM_HDS_BLOCKSCAN_CONTEXT*)DX_VOS_MemMalloc(SIZEOF (DRM_HDS_BLOCKSCAN_CONTEXT));

    /*hash key. e,g, MID*/
    DX_VOS_FastMemCpy(HashKey.rgb, argv[0], min(DX_VOS_StrLen(argv[0])+1, DRM_ID_SIZE));
  
	/*number of KID*/
	nKID=(DRM_DWORD)OEM_atol(argv[1]);

    /*unique key. e.g. KID*/
	for(i=0; i<nKID; i++){
		DX_VOS_FastMemCpy(UniqueKey[i].rgb, argv[2+i], min(DX_VOS_StrLen(argv[2+i])+1, DRM_ID_SIZE));
	}
  
    ChkDR(DRM_HDS_BlockScanDelete(&g_pNsContext[0], 
            &HashKey,
            UniqueKey, 
			nKID,
			TRUE,/* Wait for locks */
			pcontextBlockScan
			));
     
ErrorExit:
	DX_VOS_MemFree(pcontextBlockScan);
    return dr;
}

/* remove the specified file */
DRM_RESULT TestDeleteFile(long argc, char **argv)
{
    DRM_RESULT dr = DRM_SUCCESS;
    ChkArg(argc == 1 && argv[0]);
    DX_VOS_FDelete(argv[0]); /* ignore any error here */
ErrorExit:
    return dr;
}

DRM_RESULT HDS_PreTestCase(long lTCID, char *strTCName)
{
      return DRM_HDS_Init(&g_oHdsContext);
}

DRM_RESULT HDS_PostTestCase(long lTCID, char *strTCName)
{
     DRM_HDS_CloseStore(&g_oHdsContext);
    return DRM_HDS_Uninit(&g_oHdsContext);
}

static DRM_RESULT WrapTestRun(long lTCID, DRM_BOOL fPreTestRun)
{
    return DRM_SUCCESS;
}

/*
BEGIN_TEST_SCRIPT_LIST
    TEST_SCRIPT_ENTRY("DailyTestHDS")    
    TEST_SCRIPT_ENTRY("NegativeTestHDS")
     TEST_SCRIPT_ENTRY("InvalidArgumentTestHDS")
END_TEST_SCRIPT_LIST

BEGIN_APIMAP_WITH_SCRIPT_LIST(testhds_ansi)
    API_ENTRY(TestHdsCreateStore)
    API_ENTRY(TestHdsOpenStore)
    API_ENTRY(TestHdsCloseStore)
    API_ENTRY(TestHdsDeleteNamespace)
    API_ENTRY(TestHdsOpenNamespace)
    API_ENTRY(TestHdsCloseNamespace)
     API_ENTRY(TestHdsInitSlotEnum)
    API_ENTRY(TestHdsSlotEnumNext)
    API_ENTRY(TestHdsCommitStore)
    API_ENTRY(TestHdsOpenSlot)
    API_ENTRY(TestHdsCloseSlot)
    API_ENTRY(TestHdsDeleteSlot)
    API_ENTRY(TestHdsSlotResize)
    API_ENTRY(TestHdsSlotSeek)
    API_ENTRY(TestHdsSlotRead)
    API_ENTRY(TestHdsSlotWrite)
    API_ENTRY(TestHdsReinitialize)
    API_ENTRY(TestDeleteFile)
	API_ENTRY(TestHdsBlockScanDelete)
END_APIMAP
*/
