Adding the Use License to the Compound File
After you have added a new issuance license to a file, you can acquire a use license for a requesting user and store it right in the document. That way, the user can view the document immediately, without making an additional call to a server for a use license.
The use license is stored as a new stream within the \009DRMTransform storage object that holds the signed issuance license. The new use license stream is given a unique name, beginning with "EUL-", so that it will not conflict with any other streams within the compound file. The data after "EUL-" is not particularly important, as long as it is unique and 27 or fewer WCHARs long (32 WCHARs – 1 for a terminating null WCHAR, – 4 for "EUL-"). In the following example, a random GUID is generated by using the NewGuid method of the .NET Framework Guid object, and then it is compressed by base32-encoding it.
The following example, from Cdoclib.cpp, shows adding a use license to a compound file.
AddEndUserLicense(WCHAR* wszEUL,
WCHAR*wszbase64ConsumerName,
WCHAR*wszRmhFilePath,
WCHAR* EULClassID) // Unique ID created by application.
{
int HeaderLen = 0;
int EntryCount = 0;
int EntryLength = 0;
int RefComponentCount = 0;
int RefComponentType = 0;
int RefComponentLen = 0;
int RefComponentPad = 0;
int DataSpaceNameLen = 0;
int DataSpaceNamePad = 0;
int TotalLength = 0;
LPWSTR RefComponent = NULL;
LPWSTR DataSpaceName = NULL;
WCHAR StorageName_DataSpaces[12] = L"*DataSpaces";
WCHAR StorageName_DataSpaceInfo[14] = L"DataSpaceInfo";
WCHAR StorageName_TransformInfo[14] = L"TransformInfo";
WCHAR StorageName_DRMTransform[14] = L"*DRMTransform";
WCHAR StreamName_DRMViewerContent[18] = L"*DRMViewerContent";
WCHAR StreamName_Version[8] = L"Version";
WCHAR StreamName_DataSpaceMap[13] = L"DataSpaceMap";
WCHAR StreamName_DRMDataSpace[14] = L"*DRMDataSpace";
WCHAR StreamName_Primary[9] = L"*Primary";
// 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);
// Storages and streams.
IStorage *pStorage = NULL;
IStorage *pDataSpaceStorage = NULL;
IStorage *pTransformInfoStorage = NULL;
IStorage *pDRMTransformStorage = NULL;
IStream *pStream = NULL;
HRESULT hResult = NULL;
ULONG bytesWritten = 0;
BYTE *EncryptedBuffer = NULL;
DWORD dwBufferSize = 0;
BYTE *dataspacemap = NULL;
LPSTR wszEUL64 = NULL;
BYTE *eul_stream = NULL;
LPSTR szRightsLabel = NULL;
BYTE *drm_transform = NULL;
VERSIONSTAMP version;
version.ReaderVersionMajor = 1;
version.ReaderVersionMinor = 0;
version.UpdaterVersionMajor = 1;
version.UpdaterVersionMinor = 0;
version.WriterVersionMajor = 1;
version.WriterVersionMinor = 0;
// Open the previously created compound file.
hResult = StgOpenStorageEx(
wszRmhFilePath, // 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
// Navigate to \009DRMTransform storage space
// to add a new stream to hold the use license.
memcpy(StorageName_DataSpaces, &char_six,2);
hResult = pStorage->OpenStorage(
StorageName_DataSpaces,
NULL,
STGM_READWRITE|STGM_SHARE_EXCLUSIVE,
NULL,
0,
&pDataSpaceStorage);
hResult = pDataSpaceStorage->OpenStorage(
StorageName_TransformInfo,
NULL,
STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
NULL,
0,
&pTransformInfoStorage);
memcpy(StorageName_DRMTransform, &char_nine,2);
hResult = pTransformInfoStorage->OpenStorage(
StorageName_DRMTransform,
NULL,
STGM_READWRITE|STGM_SHARE_EXCLUSIVE,
NULL,
0,
&pDRMTransformStorage);
// Create a new, uniquely named stream to hold
// the use license.
hResult = pDRMTransformStorage->CreateStream(
EULClassID, // Required name
STGM_READWRITE | // File access
STGM_SHARE_EXCLUSIVE,
0, // Required
0, // Required
&pStream); // IStream pointer
// base64-encode the EUL.
LPWSTR wszEUL64 = wszEUL;
int b64usernamelen = (int)wcslen(wcsbase64ConsumerName);
int licenselength = (int)wcslen(wszEUL64);
int dwordalign = PaddingLength(b64usernamelen,sizeof(DWORD));
int eulstreamLength = 8 + b64usernamelen + dwordalign;
wszEUL64 = (CHAR *)HeapAlloc(
GetProcessHeap(),
HEAP_ZERO_MEMORY,
wcslen(wszEUL64)+1);
if ( NULL == wszEUL64 )
{
printf("Error (%s): E_OUTOFMEMORY\n", "HeapAlloc");
goto e_Exit;
}
StringCchPrintf(wszEUL64,
wcslen(wszEUL64)+1,
"%S",
wszEUL64);
// Copy the data to a buffer.
eul_stream = (BYTE *)HeapAlloc(
GetProcessHeap(),
0,
eulstreamLength + licenselength + 4 +
PaddingLength(licenselength,sizeof(DWORD)));
if ( NULL == eul_stream )
{
printf("Error (%s): E_OUTOFMEMORY\n", "HeapAlloc");
goto e_Exit;
}
ZeroMemory(eul_stream,
eulstreamLength + licenselength + 4
+ PaddingLength(licenselength,sizeof(DWORD)));
memcpy(eul_stream+0,
&euIstreamLength,
4);
memcpy(eul_stream+4,
&b64usernamelen,
4);
memcpy(eul_stream+8,
wszbase64ConsumerName,
b64usernamelen);
memcpy(eul_stream+8+b64usernamelen+dwordalign,
&licenselength,
4);
memcpy(eul_stream+12+b64usernamelen+dwordalign,
wszEUL64,
licenselength);
// Copy buffer to the stream.
hResult = pStream->Write(
(void *)eul_stream,
eulstreamLength+licenselength+4
+PaddingLength(licenselength,
sizeof(DWORD)),
&bytesWritten);
CHECK_STG_ERROR("IStream::Write",hResult);
// Save changes to container file.
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();
return hResult;
}
See Also
Building a Protected Document Library
Send comments about this topic to Microsoft
Build date: 3/13/2008