OfflineSigning_GetSignedIL.cpp
[The AD RMS SDK leveraging functionality exposed by the client in Msdrm.dll is available for use in Windows Server 2008, Windows Vista, Windows Server 2008 R2, Windows 7, Windows Server 2012, and Windows 8. It may be altered or unavailable in subsequent versions. Instead, use Active Directory Rights Management Services SDK 2.1, which leverages functionality exposed by the client in Msipc.dll.]
The following code example shows how to create, configure, and sign an issuance license. The function performs the following actions:
- Retrieves the lockbox path.
- Initializes a secure environment.
- Calls DRMCreateIssuanceLicense to create an empty issuance license.
- Creates a GUID and assigns it to the license as a content ID.
- Creates an example name/value pair.
- Creates an example use policy.
- Creates a user object from the user account specified on the command line.
- Creates an EDIT right for the user and associates the right and the user with the new license.
#include "OfflineILSigning.h"
/*===================================================================
File: OfflineSigning_GetSignedIL.cpp
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Copyright (C) Microsoft. All rights reserved.
===================================================================*/
/////////////////////////////////////////////////////////////////////
// The GetOfflineSignedIL function creates an unsigned issuance
// license, specifies a user and associated right, and signs the
// license offline by using the client licensor certificate.
//
HRESULT GetOfflineSignedIL(PWSTR pwszUserID,
PWSTR pwszMachineCert,
PWSTR pwszCLC,
PWSTR pwszManifest,
PWSTR *ppwszSignedIL)
{
HRESULT hr = S_OK; // HRESULT return code
PWSTR pwszSecProvType = NULL; // Secure provider type
UINT uiProvTypeLgth = 0; // Provider type length
PWSTR pwszSecProvPath = NULL; // Secure provider path
UINT uiProvPathLgth = 0; // Provider path length
DRMPUBHANDLE hIssuanceLicense = NULL; // Issuance license handle
DRMENVHANDLE hEnv = NULL; // Environment handle
DRMHANDLE hLib = NULL; // Library handle
DRMPUBHANDLE hUser = NULL; // User handle
DRMPUBHANDLE hRight = NULL; // Right handle
const UINT GUID_LENGTH = 128; // GUID string length
PWSTR pwszGUID = NULL; // Unique content ID
UINT uiGUIDLength = 0; // GUID length
GUID guid; // Raw unique content ID
const DWORD DW_WAIT_TIME = 60000; // Maximum signal duration
DWORD dwWaitResult = 0; // Actual signal duration
SYSTEMTIME stTimeFrom; // Validity period start
SYSTEMTIME stTimeUntil; // Validity period end
DRM_CONTEXT context; // Callback context
wprintf(L"\r\nEntering GetOfflineSignedIL. \r\n");
// Initialize the callback context.
SecureZeroMemory(&context, sizeof(context));
// Retrieve the client lockbox:
// - Call DRMGetSecurityProvider once to retrieve the number of
// characters for the provider type and provider path.
// - Allocate memory for the type and path strings.
// - Call DRMGetSecurityProvider again to retrieve the secure
// provider type and path information.
hr = DRMGetSecurityProvider(
0, // Reserved
&uiProvTypeLgth, // Length of the type string
NULL, // Type string - NULL on input
&uiProvPathLgth, // Length of the path string
NULL); // Path string - NULL on input
if(FAILED(hr)) return hr;
pwszSecProvType = new WCHAR[uiProvTypeLgth];
pwszSecProvPath = new WCHAR[uiProvPathLgth];
if(NULL==pwszSecProvType || NULL==pwszSecProvPath)
{
hr = E_OUTOFMEMORY;
return hr;
}
hr = DRMGetSecurityProvider(
0, // Reserved
&uiProvTypeLgth, // Length of the type string
pwszSecProvType, // Return type string
&uiProvPathLgth, // Length of the path string
pwszSecProvPath ); // Path string
if(FAILED(hr)) return hr;
wprintf(L"DRMGetSecurityProvider: pwszSecProvType %s \r\n",
pwszSecProvType);
wprintf(L"DRMGetSecurityProvider: pwszSecProvPath %s \r\n",
pwszSecProvPath);
// Initialize a secure environment. This requires a lockbox,
// a signed manifest, and the machine certificate associated
// with the user.
hr = DRMInitEnvironment(
DRMSECURITYPROVIDERTYPE_SOFTWARESECREP,
DRMSPECTYPE_FILENAME, // Provider is in a file
pwszSecProvPath, // Path to the provider
pwszManifest, // Application manifest
pwszMachineCert, // Machine certificate
&hEnv, // Return environment handle
&hLib); // Return library
if(FAILED(hr)) goto e_Exit;
wprintf(L"DRMInitEnvironment: hEnv = %i \r\n", hEnv);
wprintf(L"DRMInitEnvironment: hLib = %i \r\n", hLib);
wprintf(L"Attach debugger here, set a breakpoint,");
wprintf(L"and enter any key to continue: \r\n");
_getch();
// Get the system time for the starting and ending times that
// specify the validity period of the unsigned issuance license.
// Add one year to the ending time.
GetSystemTime( &stTimeFrom );
GetSystemTime( &stTimeUntil );
stTimeUntil.wYear++;
// Create an unsigned issuance license from scratch.
hr = DRMCreateIssuanceLicense(
&stTimeFrom, // Starting validity time
&stTimeUntil, // Ending validity time
NULL, // Not supported
NULL, // Not supported
NULL, // Handle to license owner
NULL, // Template or existing license
NULL, // Bound license handle
&hIssuanceLicense); // Handle to the license
if(FAILED(hr)) goto e_Exit;
wprintf(L"DRMCreateIssuanceLicense: hIssuanceLicense = %i \r\n",
hIssuanceLicense);
// Create a GUID to use as the unique content ID.
hr = CoCreateGuid(&guid);
if(FAILED(hr)) goto e_Exit;
pwszGUID = new WCHAR[GUID_LENGTH];
if (NULL == pwszGUID)
{
hr = E_OUTOFMEMORY;
goto e_Exit;
}
uiGUIDLength = StringFromGUID2( guid, pwszGUID, GUID_LENGTH );
if (0 == uiGUIDLength)
{
hr = E_FAIL;
goto e_Exit;
}
wprintf(L"StringFromGUID2: pwszGUID = %s \r\n", pwszGUID);
// Set your metadata in the unsigned issuance license.
hr = DRMSetMetaData(
hIssuanceLicense, // Issuance license handle
pwszGUID, // Unique content ID
L"MS-GUID", // Type of content ID
L"SKUId", // SKU ID
L"SKUIdType", // SKU ID type
L"ContentType", // Content type
L"ContentName"); // Content name
if(FAILED(hr)) goto e_Exit;
wprintf(L"DRMSetMetaData succeeded. \r\n");
// Set an application specific name/value pair in the license.
hr = DRMSetApplicationSpecificData(
hIssuanceLicense, // Issuance license handle
false, // Add the name/value pair
L"SomeName", // Name portion of pair
L"SomeValue" ); // Value portion of pair
if(FAILED(hr)) goto e_Exit;
wprintf(L"DRMSetApplicationSpecificData succeeded. \r\n");
// Set the interval time in the license.
hr = DRMSetIntervalTime(
hIssuanceLicense, // Issuance license handle
30); // Interval period in days
if(FAILED(hr)) goto e_Exit;
wprintf(L"DRMSetIntervalTime succeeded. \r\n");
// Set the usage policy
hr = DRMSetUsagePolicy(
hIssuanceLicense, // Issuance license handle
DRM_USAGEPOLICY_TYPE_BYNAME, // Policy type
false, // Add the policy
true, // Rights are prohibited
L"ApplicationName", // Application name
L"1.0.0.0", // Minimum version number
L"3.0.0.0", // Maximum version number
NULL, // Public key not required
NULL, // Digest algorithm
NULL, // Pointer to the digest
NULL ); // Digest length
if(FAILED(hr)) goto e_Exit;
wprintf(L"DRMSetUsagePolicy succeeded. \r\n");
// Create a user handle.
hr = DRMCreateUser(
pwszUserID, // User ID or name
NULL, // Verified ID
L"Windows", // Type of user ID
&hUser ); // Handle to the user
if(FAILED(hr)) goto e_Exit;
wprintf(L"DRMCreateUser: hUser = %i \r\n", hUser);
// Create a right.
hr = DRMCreateRight(
L"EDIT", // Name of the right to create
&stTimeFrom, // Starting validity time
&stTimeUntil, // Ending validity time
0, // No extended information
NULL, // Extended information name
NULL, // Extended information value
&hRight ); // Handle to the created right
if(FAILED(hr)) goto e_Exit;
wprintf(L"DRMCreateRight: hRight = %i \r\n", hRight);
// Associate the right with the user and add both to the
// unsigned issuance license.
hr = DRMAddRightWithUser(
hIssuanceLicense, // Issuance license handle
hRight, // Right from DRMCreateRight
hUser ); // User from DRMCreateUser
if(FAILED(hr)) goto e_Exit;
wprintf(L"DRMAddRightWithUser succeeded. \r\n");
// Create an event to signal when the license has been signed.
context.hEvent = CreateEvent(
NULL, // No attributes
FALSE, // Automatic reset
FALSE, // Initial state not signaled
NULL); // Event object not named
if(NULL == context.hEvent) goto e_Exit;
// Sign the issuance license offline by using the client
// licensor certificate
hr = DRMGetSignedIssuanceLicense(
hEnv, // Environment handle
hIssuanceLicense, // Issuance license handle
DRM_SIGN_OFFLINE | // Sign offline with a CLC
DRM_AUTO_GENERATE_KEY, // Generate a content key
NULL, // No symmetric key specified
0, // No length specified
L"AES", // Encryption key type
pwszCLC, // Client licensor certificate
&StatusCallback, // Callback function
NULL, // No licensing URL specified
(void*)&context); // Callback context parameter
if(FAILED(hr)) goto e_Exit;
wprintf(L"DRMGetSignedIssuanceLicense succeeded. \r\n");
// Wait for the callback to return.
dwWaitResult = WaitForSingleObject(context.hEvent, DW_WAIT_TIME);
if(WAIT_TIMEOUT == dwWaitResult || FAILED(context.hr)) goto e_Exit;
// Assign the license pointer to the output parameter.
*ppwszSignedIL = context.pwszData;
e_Exit:
if(NULL != context.hEvent)
{
CloseHandle(context.hEvent);
context.hEvent = NULL;
}
if(NULL != hIssuanceLicense)
{
DRMClosePubHandle(hIssuanceLicense);
hIssuanceLicense = NULL;
}
if(NULL != hUser)
{
DRMClosePubHandle(hUser);
hUser = NULL;
}
if(NULL != hRight)
{
DRMClosePubHandle(hRight);
hRight = NULL;
}
if(NULL != hLib)
{
DRMCloseHandle(hLib);
hLib = NULL;
}
if(NULL != pwszGUID)
{
delete [] pwszGUID;
pwszGUID = NULL;
}
if(NULL != pwszSecProvType)
{
delete [] pwszSecProvType;
pwszSecProvType = NULL;
}
if(NULL != pwszSecProvPath)
{
delete [] pwszSecProvPath;
pwszSecProvPath = NULL;
}
if(NULL != hEnv)
{
DRMCloseEnvironmentHandle(hEnv);
hEnv = NULL;
}
wprintf(L"Leaving GetOfflineSignedIL: hr = %x \r\n", hr);
return hr;
}
Related topics