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

#include <drmcommon.h>
#include <drmutilities.h>
#include <drmcrt.h>
#include <drmcontextsizes.h>
#include <drmsecurestore.h>
#include <drmmetering.h>


DRM_RESULT DRM_API DRM_MTR_OpenId (
    IN       DRM_METERING_CONTEXT *f_pcontextMTR,
    IN const DRM_MID              *f_pmid,
    IN const DRM_KID              *f_pkid,
    IN const DRM_BYTE              f_rgbPasswordMTR [__CB_DECL(SHA_DIGEST_LEN)],
    IN       DRM_HDS_CONTEXT      *f_pcontextHDS)
{
    DRM_RESULT       dr    = DRM_E_LOGICERR;
    DRM_WORD         cbKid = 0;
    
    ChkArg (f_pcontextMTR    != NULL
         && f_pmid           != NULL
         && f_pkid           != NULL
         && f_rgbPasswordMTR != NULL
         && f_pcontextHDS    != NULL);
    
    DRMCASSERT(SIZEOF(DRM_METERING_CONTEXT) == SIZEOF(DRM_SECSTORE_CONTEXT));

    ChkDR (DRM_SST_OpenKeyTokens(f_pcontextMTR, 
                      (DRM_ID *) f_pmid,
                      (DRM_ID *) f_pkid,
                                 f_rgbPasswordMTR,
                                 DRM_SECURE_STORE_CREATE_IF_NOT_EXISTS,
                                 SECURE_STORE_METERING_DATA,
                                 f_pcontextHDS));

 
    /* Metering context is setup successfully */
    dr = DRM_SUCCESS;

ErrorExit:
    return dr;
}


DRM_RESULT DRM_API DRM_MTR_IncrementCount( 
    IN       DRM_METERING_CONTEXT *f_pcontextMTR, 
    IN const DRM_CONST_STRING     *f_pdstrAction )
{
    DRM_RESULT dr = DRM_E_LOGICERR;
    TOKEN      token;

    ChkArg(f_pcontextMTR);
    ChkDRMString(f_pdstrAction);

    /* Store entry has been opened/created.  Try to read the KID.  If it doesn't exist add it. */    
    dr = DRM_SST_GetTokenValue(f_pcontextMTR, f_pdstrAction , &token);
    if (DRM_FAILED(dr))
    {
        dr = DRM_E_METERING_STORE_CORRUPT;
        goto ErrorExit;
    }

    if (dr == DRM_S_FALSE)
    {        
        /* Action doesn't exist.  Initialize the count to 0*/
        token.val.lValue = 0;
        token.TokenType  = TOKEN_LONG;
    }

    /* Increment it and write it back */
    token.val.lValue++;    
    ChkDR(DRM_SST_SetTokenValue(f_pcontextMTR, f_pdstrAction , &token));
    dr = DRM_SUCCESS;

ErrorExit:
    return dr;
}

DRM_RESULT DRM_API DRM_MTR_GetAllData (
    IN     DRM_METERING_CONTEXT *f_pcontextMTR,
    OUT    DRM_BYTE             *f_pbData,
    IN OUT DRM_DWORD            *f_pcbData)
{
    return DRM_SST_GetAllData (f_pcontextMTR, f_pbData, f_pcbData);
}

DRM_RESULT DRM_API DRM_MTR_CloseContext( 
    IN DRM_METERING_CONTEXT *f_pcontextMTR,
    IN DRM_HDS_CONTEXT      *f_pcontextHDS)
{
    return DRM_SST_CloseKey( f_pcontextMTR, f_pcontextHDS );
}

DRM_RESULT DRM_API DRM_MTR_InitEnum (
    IN  const DRM_MID                   *f_pmid,
    OUT       DRM_METERINGENUM_CONTEXT  *f_pcontextMTREnum,
    IN        DRM_HDS_CONTEXT           *f_pcontextHDS)
{
    return DRM_SST_OpenEnumerator ( SECURE_STORE_METERING_DATA, f_pmid, f_pcontextMTREnum, f_pcontextHDS, TRUE);
}

DRM_RESULT DRM_API DRM_MTR_EnumNext ( 
    IN  DRM_METERINGENUM_CONTEXT *f_pcontextMTREnum,
    OUT DRM_KID                  *f_pkid,
    OUT DRM_DWORD                *f_pcbData)
{
    return DRM_SST_EnumNext( f_pcontextMTREnum, f_pkid, f_pcbData);
}

DRM_RESULT DRM_API DRM_MTR_EnumLoadCurrent ( 
    IN       DRM_METERINGENUM_CONTEXT *f_pcontextMTREnum,
    IN       DRM_METERING_CONTEXT     *f_pcontextMTR,
    IN const DRM_BYTE                  f_rgbPasswordMTR[__CB_DECL(SHA_DIGEST_LEN)],
       OUT   DRM_KID                  *f_pkid,
       OUT   DRM_DWORD                *f_pcbData)
{
    return DRM_SST_EnumLoadCurrent(f_pcontextMTREnum, 
                                   f_pcontextMTR,
                                   f_rgbPasswordMTR,
                                   f_pkid,
                                   f_pcbData);
}


DRM_RESULT DRM_API DRM_MTR_EnumDeleteCurrent ( 
    IN       DRM_METERINGENUM_CONTEXT *f_pcontextMTREnum,
    IN       DRM_METERING_CONTEXT     *f_pcontextMTR)
{
    return DRM_SST_EnumDeleteCurrent(f_pcontextMTREnum, 
                                     f_pcontextMTR);
}
DRM_RESULT DRM_API DRM_MTR_UpdateData(
    DRM_MID                 *f_pmid,
    DRM_LID                 *f_plid,
    DRM_KID                 *f_pkid,
    const DRM_CONST_STRING **f_ppdstrActions,
    DRM_DWORD                f_cActions,
    DRM_METERING_CONTEXT    *f_pcontextMTR,
    DRM_HDS_CONTEXT         *f_pcontextHDS,
    DRM_BYTE                *f_pbcontextBBX)
{
    DRM_RESULT dr         = DRM_SUCCESS;
    DRM_DWORD  iAction    = 0;
    DRM_DWORD  cchMeterID =            CCH_BASE64_EQUIV(SIZEOF(DRM_MID));
    DRM_WCHAR  rgwchMeterID [CCH_BASE64_EQUIV(SIZEOF(DRM_MID))] = { 0 };
    DRM_BYTE   rgbPassword  [__CB_DECL(SHA_DIGEST_LEN)];

    DRM_PROFILING_ENTER_SCOPE(L"DRM_MTR_UpdateData", g_pwszEnteringFunction, DRM_PROFILING_DONT_START);
                            
    ChkDR(DRM_B64_EncodeW((DRM_BYTE *) f_pmid, 
                          SIZEOF(DRM_MID), 
                          rgwchMeterID, 
                         &cchMeterID, 
                          0));

    ChkDR(DRM_BBX_HashValue((DRM_BYTE *) rgwchMeterID, 
                             cchMeterID * SIZEOF(DRM_WCHAR),
                             rgbPassword,
                            (DRM_BB_CONTEXT *) f_pbcontextBBX));
    
    ChkDR( DRM_MTR_OpenId(f_pcontextMTR,
                          f_pmid,
                          f_pkid,
                          rgbPassword,
                          f_pcontextHDS));

    for (iAction = 0; iAction < f_cActions; iAction++)
    {            
        ChkDR(DRM_MTR_IncrementCount(f_pcontextMTR, 
                                     f_ppdstrActions [iAction]));
    }
    
    ChkDR(DRM_MTR_CloseContext(f_pcontextMTR,
                               f_pcontextHDS));

ErrorExit:

    DRM_PROFILING_LEAVE_SCOPE(L"DRM_MTR_UpdateData", g_pwszLeavingFunction);

    return dr;
}
