Share via


Replacing the Issuance License in the Compound File

After you have the new signed issuance license, you replace the old one with it in the compound file.

To replace an existing issuance license, navigate to the stream that is holding the issuance license in the compound file (\006Primary), and overwrite the stream.

To overwrite the stream, set the size of the stream to zero (pStream->SetSize(0)) and rewrite the stream.

This will not clear the existing data from the stream, but because you are overwriting the stream with a header that lists the size of the issuance license, your application should only read the data size specified by the new header. Any remaining information after this will be ignored.

The following C++ example shows how to do this.

// PaddingLength is a custom function in Cdoclib.cpp that returns the 
// number of padding bytes required to bring a submitted number up to 
// a submitted block size.

// The VERSIONSTAMP structure is defined in Cdoclib.cpp.

// Error handling macro used in the function.
#define CHECK_STG_ERROR(api, hresult) if(FAILED(hresult))            \
{                                                                    \
printf("Error (%s): %S [%d]\n", api, StorageError(hresult), hresult);\
goto e_Exit;                                                         \
}

CDOCLIB_API HRESULT __stdcall UpdatePublishingLicense(
              WCHAR* wcsRmhFilePath, 
              WCHAR* wcsEditedLicense)
{
    // Storages and streams.
    IStorage    *pStorage               = NULL;
    IStorage    *pDataSpaceStorage      = NULL;
    IStorage    *pTransformInfoStorage  = NULL;
    IStorage    *pDRMTransformStorage   = NULL;
    IStream     *pStream                = NULL;
    HRESULT     hResult                 = NULL;
    ULONG       bytesWritten            = 0;
    LPSTR       szRightsLabel           = NULL;
    BYTE        *drm_transform          = NULL;
    LPWSTR      ClassID                 = 
                L"{C73DFACD-061F-43B0-8B64-0C620D2A8B50}";
    LPWSTR      FeatureIdentifier       = 
                L"Microsoft.Metadata.DRMTransform";
    LPWSTR      wszSignedIL             = wcsEditedLicense;
    int         IndexOfFeatureIdentifierLength = 88;
    int         TheNumberOne            = 1;
    int         ClassIDLength           = 
                (int)wcslen(ClassID)*sizeof(WCHAR);
    int         FeatureIdentifierLength = 
                (int)wcslen(FeatureIdentifier)*sizeof(WCHAR);
    int         TheNumberFour           = 4;
    short       TheNumberZero           = 0;

    // Insert special characters into storage/stream names.
    short char_nine = 9;
    short char_six  = 6;
    memcpy(StorageName_DataSpaces, &char_six, 2);
    memcpy(StorageName_DRMTransform, &char_nine, 2);
    memcpy(StreamName_DRMDataSpace, &char_nine, 2);
    memcpy(StreamName_Primary, &char_six, 2);


    // Structure needed for the transform header.
    VERSIONSTAMP version;
    version.ReaderVersionMajor  = 1;
    version.ReaderVersionMinor  = 0;
    version.UpdaterVersionMajor = 1;
    version.UpdaterVersionMinor = 0;
    version.WriterVersionMajor  = 1;
    version.WriterVersionMinor  = 0;

    // Specifies the new stream size.
    ULARGE_INTEGER ui = {0,0};


    // Open the output compound file.
    hResult = StgOpenStorageEx(
                wcsRmhFilePath,         // File name
                STGM_READWRITE|         // File access
                  STGM_SHARE_EXCLUSIVE, 
                STGFMT_STORAGE,         // Compound file
                0,                      // Required
                NULL,                   // Required
                0,                      // Required
                IID_IStorage,           // IStorage IID
                (void **)&pStorage);    // IStorage pointer
    CHECK_STG_ERROR("StgOpenStorageEx", hResult);

    // Now navigate down to \006Primary stream, where 
    // the issuance license is stored.
    // \006DataSpaces->TransformInfo->\009DRMTransform->\006Primary.
    
    // \006DataSpaces storage.
    memcpy(StorageName_DataSpaces, &char_six, 2);
    hResult = pStorage->OpenStorage(
                            StorageName_DataSpaces,
                            NULL,
                            STGM_READWRITE|STGM_SHARE_EXCLUSIVE,
                            NULL,
                            0,
                            &pDataSpaceStorage);
    CHECK_STG_ERROR("OpenStorage", hResult);
    
    // TransformInfo storage.
    hResult = pDataSpaceStorage->OpenStorage(
                            StorageName_TransformInfo,
                            NULL,
                            STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
                            NULL,
                            0,
                            &pTransformInfoStorage);
    CHECK_STG_ERROR("OpenStorage[TransformInfo]", hResult);
    
    // \009DRMTransform storage.
    memcpy(StorageName_DRMTransform, &char_nine, 2);
    hResult = pTransformInfoStorage->OpenStorage(
                            StorageName_DRMTransform,
                            NULL,
                            STGM_READWRITE|STGM_SHARE_EXCLUSIVE,
                            NULL,
                            0,
                            &pDRMTransformStorage);
    CHECK_STG_ERROR("OpenStorage[DRMTransform]:", hResult);

    // \006Primary stream.
    hResult = pDRMTransformStorage->OpenStream(
                            StreamName_Primary,
                            NULL,
                            STGM_READWRITE|STGM_SHARE_EXCLUSIVE,
                            0,
                            &pStream);
    CHECK_STG_ERROR("OpenStream[StreamName_Primary]:", hResult);

    // Remove existing issuance license.
    hResult = pStream->SetSize(ui);
    CHECK_STG_ERROR("SetSize:", hResult);

    // Allocate new buffer to hold new issuance license.
    szRightsLabel = (CHAR *)HeapAlloc(
                            GetProcessHeap(),
                            0, 
                            wcslen(wszSignedIL)+1);
    if ( NULL == szRightsLabel )
    {
        printf("Error (%s): E_OUTOFMEMORY\n", "HeapAlloc");
        goto e_Exit;
    }

    // Copy new issuance license into buffer.
    StringCchPrintf(szRightsLabel, 
                    wcslen(wszSignedIL)+1, 
                    "%S", 
                    wszSignedIL);

    // Calculate size of new buffer needed to hold new 
    // stream and allocate memory.
    int RightsLabelLength = (int)strlen(szRightsLabel);
    int TransformLength = 38 + ClassIDLength + 
                          FeatureIdentifierLength + 
                          RightsLabelLength +      
                          PaddingLength(RightsLabelLength,
                                        sizeof(DWORD));
    drm_transform = (BYTE *)HeapAlloc(
                            GetProcessHeap(), 
                            0, 
                            TransformLength);
    if ( NULL == drm_transform )
    {
        printf("Error (%s): E_OUTOFMEMORY\n", "HeapAlloc");
        goto e_Exit;
    }
    ZeroMemory(drm_transform, TransformLength);

    // Copy headers and new issuance license into buffer.
    memcpy(drm_transform+0, &IndexOfFeatureIdentifierLength, 4);
    memcpy(drm_transform+4, &TheNumberOne, 4);
    memcpy(drm_transform+8, &ClassIDLength, 4);
    memcpy(drm_transform+12, ClassID, ClassIDLength);
    memcpy(drm_transform+12+ClassIDLength,
           &FeatureIdentifierLength,
           4);
    memcpy(drm_transform+16+ClassIDLength, 
           FeatureIdentifier, 
           FeatureIdentifierLength);
    memcpy(drm_transform+16+ClassIDLength+FeatureIdentifierLength,
           &TheNumberZero, 2);
    memcpy(drm_transform+18+ClassIDLength+FeatureIdentifierLength,
           &version, 12);
    memcpy(drm_transform+30+ClassIDLength+FeatureIdentifierLength,
           &TheNumberFour, 4);
    memcpy(drm_transform+34+ClassIDLength+FeatureIdentifierLength,
           &RightsLabelLength, 4);
    memcpy(drm_transform+38+ClassIDLength+FeatureIdentifierLength,
           szRightsLabel, RightsLabelLength);

    //Write buffer to stream.
    hResult = pStream->Write(
                            (void *)drm_transform, 
                            TransformLength, 
                            &bytesWritten); 
    CHECK_STG_ERROR("IStream::Write", hResult);

    // Commit changes to root storage.
    pStorage->Commit(STGC_DEFAULT);

e_Exit:
    // Clean up.
    if (pStorage != NULL)
        pStorage->Release();
    if (pDataSpaceStorage != NULL)
        pDataSpaceStorage->Release();
    if (pTransformInfoStorage != NULL)
        pTransformInfoStorage->Release();
    if (pDRMTransformStorage != NULL)
        pDRMTransformStorage->Release();
    if (pStream != NULL)
        pStream->Release();
    if (drm_transform != NULL)
        HeapFree(GetProcessHeap(), NULL, drm_transform);
    if (szRightsLabel != NULL)
        HeapFree(GetProcessHeap(), NULL, szRightsLabel);
    
    return hResult;
}

See Also

Updating the Issuance License

Send comments about this topic to Microsoft

Build date: 3/13/2008