/*===================================================================== File: PublishingACL.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 Corporation. All rights reserved. =====================================================================*/ // // This sample shows how to create an issuance license. See the // comments at the beginning of wmain() for a more detailed description. // Note: To retrieve an object's DACL, you must be the object's owner or // have READ_CONTROL access to the object. To run this sample, you must // have READ_CONTROL on the path you provide on the command line. // #define _WIN32_DCOM #ifndef _WIN32_WINNT #define _WIN32_WINNT 0x0500 #endif #include #include #include #include #include #include #include #include #include #include #include #include "msdrm.h" #include "msdrmdefs.h" #include "msdrmerror.h" #pragma comment( lib, "wbemuuid.lib" ) // // Time to wait for "downloads" to complete // static const DWORD DW_WAIT_TIME_SECONDS = 60 * 1000; // // Length of a GUID string // static const UINT GUID_STRING_LENGTH = 128; // // Define the two rights that are used in this sample // #define EDIT_RIGHT L"EDIT" #define VIEW_RIGHT L"VIEW" // // Define the file to save the template into // #define TEMPLATE_FILE L".\\ILTemplate.xml" // // Define the known domains to exclude from the issuance license // #define NT_AUTHORITY L"NT AUTHORITY" #define BUILTIN L"BUILTIN" // // Print the correct usage of this application // void PrintUsage() { wprintf( L"Usage:\n" ); wprintf( L"\n PublishingACL -P Path\n" ); wprintf( L" -P: Path to the directory to use for the "\ L"issuance license's rights.\n" ); wprintf( L" example: c:\\myDir\n" ); } // // Parse the values passed in through the command line // HRESULT ParseCommandLine( int argc, __in_ecount( argc )WCHAR **argv, __deref_out PWCHAR *pwszPath ) { HRESULT hr = S_OK; size_t uiPathLength = 0; // // Check input parameters. // if ( ( 3 != argc ) ) { return E_INVALIDARG; } for( int i = 1; SUCCEEDED( hr ) && i < argc - 1; i ++ ) { if ( ( '-' != argv[ i ][ 0 ] ) && ( '/' != argv[ i ][ 0 ] ) ) { hr = E_INVALIDARG; break; } else if ( ( '-' == argv[ i + 1 ][ 0 ] ) || ( '/' == argv[ i + 1 ][ 0 ] ) ) { hr = E_INVALIDARG; break; } // // Path to directory for publishing license rights // if ( 'P' == toupper( argv[ i ][ 1 ] ) ) { // // Retrieve the length of the path // hr = StringCchLengthW( argv[ i + 1 ], STRSAFE_MAX_CCH, &uiPathLength ); if ( FAILED( hr ) ) { wprintf( L"StringCchLengthW failed. hr = 0x%x\n", hr ); break; } // // Allocate memory for the path // *pwszPath = new WCHAR[ uiPathLength + 1 ]; if ( NULL == *pwszPath ) { wprintf( L"Failed to allocate memory for pwszPath\n" ); hr = E_OUTOFMEMORY; break; } // // Copy the URL into the pwszPath buffer // hr = StringCchCopyW( ( wchar_t* )*pwszPath, uiPathLength + 1, argv[ i + 1 ] ); if ( FAILED( hr ) ) { wprintf( L"StringCchCopyW failed. hr = 0x%x\n", hr ); break; } i++; } else { hr = E_INVALIDARG; break; } } if ( NULL == pwszPath ) { wprintf( L"A path is required.\n" ); hr = E_INVALIDARG; } return hr; } // // Write the template string to a unicode file // HRESULT WriteTemplateToUnicodeFile( __in LPCWSTR szFileName, __in PWSTR wszTemplateString ) { HRESULT hr = E_FAIL; HANDLE hFile = INVALID_HANDLE_VALUE; size_t cchTemplate = 0; DWORD dwBytesWritten = 0; // // Validate the parameters // if ( ( NULL == szFileName ) || ( FAILED( StringCchLengthW( ( LPCWSTR )szFileName, MAX_PATH, NULL ) ) ) || ( NULL == wszTemplateString ) ) { hr = E_INVALIDARG; goto e_Exit; } hr = StringCchLengthW( wszTemplateString, STRSAFE_MAX_CCH, &cchTemplate ); if ( FAILED( hr ) ) { wprintf( L"\nStringCchLengthW failed. hr = 0x%x\n", hr ); goto e_Exit; } // // Create a handle to the file to write to // hFile = CreateFileW( szFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL ); if ( INVALID_HANDLE_VALUE == hFile ) { hr = HRESULT_FROM_WIN32( GetLastError() ); wprintf( L"\nCreateFileW failed. hr = 0x%x\n", hr ); goto e_Exit; } // // Write the template string to the file // if ( !WriteFile( hFile, wszTemplateString, ( DWORD )( sizeof( wchar_t ) * cchTemplate), &dwBytesWritten, NULL ) ) { hr = HRESULT_FROM_WIN32( GetLastError() ); wprintf( L"\nWriteFile failed. hr = 0x%x\n", hr ); goto e_Exit; } e_Exit: if ( ( NULL != hFile ) && ( INVALID_HANDLE_VALUE != hFile ) ) { CloseHandle( hFile ); } return hr; } // // Determine if the machine the sample is running on is a domain controller // bool IsDomainController() { HRESULT hr; bool result = false; IWbemLocator *pLocator = NULL; IWbemServices *pSvc = NULL; IEnumWbemClassObject *pEnumerator = NULL; IWbemClassObject *pclsObj = NULL; ULONG uReturn = 0; VARIANT vtProp; // // Initialize COM // hr = CoInitializeEx( 0, COINIT_MULTITHREADED ); if ( FAILED( hr ) ) { wprintf( L"CoInitializeEx failed. hr = 0x%x\n", hr ); result = false; goto e_Exit; } // // Set general COM security levels. // NOTE: If you are using Windows 2000, you need to specify the default // authentication credentials for a user by using a // SOLE_AUTHENTICATION_LIST structure in the pAuthList parameter // hr = CoInitializeSecurity( NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL ); if ( FAILED( hr ) ) { wprintf( L"CoInitializeSecurity failed. hr = 0x%x\n", hr ); result = false; goto e_Exit; } // // Obtain the initial locator to WMI // hr = CoCreateInstance( CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, ( LPVOID* )&pLocator ); if ( FAILED( hr ) ) { wprintf( L"CoCreateInstance failed. hr = 0x%x\n", hr ); result = false; goto e_Exit; } // // Connect to WMI through the IWbemLocator::ConnectServer method // // Connect to the root\cimv2 namespace with the current user and obtain // pointer pSvc to make IWbemServices calls. // if ( NULL == pLocator ) { wprintf( L"pLocator was NULL\n" ); goto e_Exit; } hr = pLocator->ConnectServer( _bstr_t( L"ROOT\\CIMV2" ), NULL, NULL, 0, NULL, 0, 0, &pSvc ); if ( FAILED( hr ) ) { wprintf( L"ConnectServer failed. hr = 0x%x\n", hr ); result = false; goto e_Exit; } // // Set security levels on the proxy // hr = CoSetProxyBlanket( pSvc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE ); if ( FAILED( hr ) ) { wprintf( L"CoSetProxyBlanket failed. hr = 0x%x\n", hr ); result = false; goto e_Exit; } // // Use the IWbemServices pointer to make requests of WMI // hr = pSvc->ExecQuery( _bstr_t( L"WQL" ), _bstr_t( L"SELECT * FROM Win32_ComputerSystem" ), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator ); if ( FAILED( hr ) ) { wprintf( L"ExecQuery failed. hr = 0x%x\n", hr ); result = false; goto e_Exit; } // // Use the data from the query to determine if the machine // is a domain controller // while ( pEnumerator ) { hr = pEnumerator->Next( WBEM_INFINITE, 1, &pclsObj, &uReturn ); if ( FAILED( hr ) ) { wprintf( L"Next failed. hr = 0x%x\n", hr ); result = false; goto e_Exit; } if ( 0 == uReturn ) { break; } VariantInit( &vtProp ); // // Get the value of the DomainRole property // hr = pclsObj->Get( L"DomainRole", 0, &vtProp, 0, 0); if ( FAILED( hr ) ) { wprintf( L"Get failed. hr = 0x%x\n", hr ); result = false; goto e_Exit; } if ( ( vtProp.lVal == 4 ) || ( vtProp.lVal == 5 ) ) { result = true; } } e_Exit: VariantClear( &vtProp ); if ( pSvc ) { pSvc->Release(); } if ( pLocator ) { pLocator->Release(); } CoUninitialize(); return result; } // // This sample will perform the following actions: // 1. Create an unsigned issuance license from scratch // 2. Determine what the ACLs are on the directory // passed in as the command line argument // 3. For each ACL: // (a) Get the user name for the ACL // (b) Determine if the user should be added to the issuance // license // (c) Get the SID in the form of a string // (d) Get the right name for the ACL // (e) Create a user based on the ACL // (f) Create a right based on the ACL // (g) Add the user and right to the unsigned issuance license // 4. Set the metadata in the issuance license // 5. Generate a template from the issuance license // 6. Clean up and free memory // int __cdecl wmain( int argc, __in_ecount( argc )WCHAR **argv ) { HRESULT hr = E_FAIL; int iDaclPresent, iDaclDefault, iMask; int count = 0; size_t uiRightLength = 0; DWORD dwSize; DWORD pdwNameLength = 0; DWORD pdwDomainLength = 0; DWORD dwMachNameLength = 0; PWCHAR wszTemplate = NULL; PWCHAR wszRight = NULL; PWCHAR wszPath = NULL; PWCHAR wszSid = NULL; PWCHAR wszName = NULL; PWCHAR wszDomain = NULL; PWCHAR wszMachineName = NULL; ACL *pDacl = NULL; ACL_SIZE_INFORMATION asi; SID_NAME_USE sidNameUse; SECURITY_DESCRIPTOR *pSD = NULL; ACCESS_ALLOWED_ACE *pAccessAllowed = NULL; SID *pSid = NULL; void *pAce = NULL; SYSTEMTIME stTimeFrom, stTimeUntil; DRMPUBHANDLE hIssuanceLicense = NULL; DRMPUBHANDLE hUser = NULL; DRMPUBHANDLE hRight = NULL; UINT uiTemplateLength = 0; GUID guid; PWSTR wszGUID = NULL; UINT uiGUIDLength; WCHAR *p = NULL; if ( FAILED ( ParseCommandLine( argc, argv, &wszPath ) ) ) { PrintUsage(); goto e_Exit; } wprintf( L"\nRunning sample PublishingACL...\n" ); // // Get the system time for the starting and ending validity times // in the unsigned issuance license // GetSystemTime( &stTimeFrom ); GetSystemTime( &stTimeUntil ); FILETIME ft = { 0 }; SystemTimeToFileTime(&stTimeUntil, &ft); ULARGE_INTEGER u = { 0 }; memcpy(&u, &ft, sizeof(u)); u.QuadPart += 90 * 24 * 60 * 60 * 10000000LLU; // 90 days memcpy(&ft, &u, sizeof(ft)); FileTimeToSystemTime(&ft, &stTimeUntil); // // 1. Create an unsigned issuance license from scratch // hr = DRMCreateIssuanceLicense( &stTimeFrom, &stTimeUntil, NULL, NULL, NULL, NULL, NULL, &hIssuanceLicense ); if ( FAILED( hr ) ) { wprintf( L"\nDRMCreateIssuanceLicense failed. hr = 0x%x\n", hr ); goto e_Exit; } // // 2. Determine what the ACLs are on the directory passed in as // the command line argument // // Get the DACL information from the path from the command line argument. // if ( GetFileSecurityW( wszPath, DACL_SECURITY_INFORMATION, NULL, NULL, &dwSize ) ) { wprintf( L"GetFileSecurityW should not have returned true\n" ); goto e_Exit; } if ( ERROR_INSUFFICIENT_BUFFER != GetLastError() ) { wprintf( L"GetFileSecurityW failed. Error: %d\n", GetLastError() ); goto e_Exit; } pSD = ( SECURITY_DESCRIPTOR* )new BYTE[ dwSize ]; if ( NULL == pSD ) { hr = E_OUTOFMEMORY; wprintf( L"Failed to allocate memory for the "\ L"SECURITY_DESCRIPTOR: hr = 0x%x\n", hr ); goto e_Exit; } if ( !GetFileSecurityW( wszPath, DACL_SECURITY_INFORMATION, pSD, dwSize, &dwSize ) ) { wprintf( L"GetFileSecurityW failed. Error: %d\n", GetLastError() ); goto e_Exit; } // // Get the Dacl from the SECURITY_DESCRIPTOR // if ( !GetSecurityDescriptorDacl( pSD, &iDaclPresent, &pDacl, &iDaclDefault ) ) { wprintf( L"GetSecurityDescriptorDacl failed. "\ L"Error: %d\n", GetLastError() ); goto e_Exit; } // // If there was no Dacl present, then fail since no user/right // information will be put into the issuance license // if ( !iDaclPresent ) { wprintf( L"There was no DACL present in the security descriptor\n" ); hr = E_FAIL; goto e_Exit; } // // Get Acl information from the Dacl // if ( !GetAclInformation( pDacl, ( void* ) &asi, sizeof( asi ), AclSizeInformation ) ) { wprintf( L"GetAclInformation failed. Error: %d\n", GetLastError() ); goto e_Exit; } // // Get the machine name // if ( !GetComputerNameExW( ComputerNamePhysicalDnsHostname, NULL, &dwMachNameLength ) ) { if ( ERROR_MORE_DATA != GetLastError() ) { wprintf( L"GetComputerNameExW failed. "\ L"Error = %d\n", GetLastError() ); goto e_Exit; } wszMachineName = new WCHAR[ dwMachNameLength ]; if ( NULL == *wszMachineName ) { wprintf( L"Failed to allocate memory for the machine name.\n" ); goto e_Exit; } } if ( !GetComputerNameExW( ComputerNamePhysicalDnsHostname, wszMachineName, &dwMachNameLength ) ) { wprintf( L"GetComputerNameExW failed. "\ L"Error = %d\n", GetLastError() ); goto e_Exit; } // // Make the machine name all upper case // for ( p = wszMachineName; p < wszMachineName + dwMachNameLength; p++ ) { if ( iswlower( *p ) ) { *p = towupper( *p ); } } // // 3. For each ACL: // // // Parse each Acl and create the appropriate user and // right for the issuance license // for ( int i = 0; i < ( int )asi.AceCount; i++ ) { pdwDomainLength = pdwNameLength = 0; pAccessAllowed = NULL; pSid = NULL; pAce = NULL; uiRightLength = 0; iMask = 0; if ( !GetAce( pDacl, i, &pAce ) ) { wprintf( L"GetAce failed. Error: %d\n", GetLastError() ); goto e_Exit; } if ( !pAce ) { wprintf( L"Invalid ACE. Continuing...\n" ); continue; } // // If the Ace was an ACCESS_ALLOWED_ACE_TYPE // if ( ( ( ACCESS_ALLOWED_ACE* )pAce )->Header.AceType == ACCESS_ALLOWED_ACE_TYPE ) { pAccessAllowed = ( ACCESS_ALLOWED_ACE* )pAce; pSid = ( SID* ) &pAccessAllowed->SidStart; iMask = pAccessAllowed->Mask; // // Verify that we have a valid SID // if ( IsValidSid( pSid ) ) { count++; // // 3(a). Get the user name for the ACL // // // Lookup the account name and domain associated with the SID // if ( LookupAccountSidW( 0, pSid, ( wchar_t* )wszName, &pdwNameLength, ( wchar_t* )wszDomain, &pdwDomainLength, &sidNameUse ) ) { wprintf( L"LookupAccountSidW passed when it "\ L"should have failed." ); goto e_Exit; } if ( ERROR_INSUFFICIENT_BUFFER != GetLastError() ) { if ( ERROR_NONE_MAPPED == GetLastError() ) { // // Skip this SID since it cannot be resolved // continue; } wprintf( L"LookUpAccountSidW failed. "\ L"Error: %d\n", GetLastError() ); goto e_Exit; } wszName = new WCHAR[ pdwNameLength ]; wszDomain = new WCHAR[ pdwDomainLength ]; if ( NULL == wszName || NULL == wszDomain ) { wprintf( L"Memory allocation failed for wszName "\ L"or wszDomain\n" ); goto e_Exit; } if ( !LookupAccountSidW( 0, pSid, ( wchar_t* )wszName, &pdwNameLength, ( wchar_t* )wszDomain, &pdwDomainLength, &sidNameUse ) ) { wprintf( L"LookupAccountSidW failed. "\ L"Error: %d\n", GetLastError() ); goto e_Exit; } // // 3(b) Determine if the user should be added to the issuance // license. If the SID is not a SID we want to put into // the issuance license, then clean up memory and // continue through the for loop // if ( ( wcscmp( ( wchar_t* )wszDomain, NT_AUTHORITY ) == 0 ) || ( wcscmp( ( wchar_t* )wszDomain, BUILTIN ) == 0 ) || ( wcscmp( ( wchar_t* )wszDomain, L"" ) == 0 ) || ( wcscmp( ( wchar_t* )wszDomain, L"NT SERVICE" ) == 0 ) || ( ( !IsDomainController() && wcscmp( ( wchar_t* )wszDomain, ( wchar_t* )wszMachineName ) == 0 ) ) ) { if ( NULL != wszName ) { delete [] wszName; wszName = NULL; } if ( NULL != wszDomain ) { delete [] wszDomain; wszDomain = NULL; } continue; } // // 3(c). Get the SID in the form of a string // if ( !ConvertSidToStringSidW( pSid, &wszSid ) ) { wprintf( L"ConvertSidToStringSidW failed. "\ L"Error: %d\n", GetLastError() ); goto e_Exit; } // // 3(d). Get the right name for the ACL // // // If the access allowed is a "write" access, then that will // be considered an EDIT_RIGHT for the purposes of this sample // if ( iMask & FILE_SHARE_WRITE ) { hr = StringCchLengthW( EDIT_RIGHT, STRSAFE_MAX_CCH, &uiRightLength ); if ( FAILED( hr ) ) { wprintf( L"StringCchLengthW failed. "\ L"hr = 0x%x\n", hr ); goto e_Exit; } // // Allocate memory for the right // wszRight = new WCHAR[ uiRightLength + 1 ]; if ( NULL == wszRight ) { wprintf( L"Failed to allocate memory for "\ L"wszRight.\n" ); hr = E_OUTOFMEMORY; goto e_Exit; } hr = StringCchCopyW( ( wchar_t* )wszRight, uiRightLength + 1, EDIT_RIGHT ); if ( FAILED( hr ) ) { wprintf( L"StringCchCopyW failed. hr = 0x%x\n", hr ); break; } } // // If the access allowed is a "read" access, then that will be // considered a VIEW_RIGHT for the purposes of this sample // else if ( iMask & FILE_SHARE_READ ) { hr = StringCchLengthW( VIEW_RIGHT, STRSAFE_MAX_CCH, &uiRightLength ); if ( FAILED( hr ) ) { wprintf( L"StringCchLengthW failed. "\ L"hr = 0x%x\n", hr ); goto e_Exit; } // // Allocate memory for the right // wszRight = new WCHAR[ uiRightLength + 1 ]; if ( NULL == wszRight ) { wprintf( L"Failed to allocate memory "\ L"for wszRight.\n" ); hr = E_OUTOFMEMORY; goto e_Exit; } hr = StringCchCopyW( ( wchar_t* )wszRight, uiRightLength + 1, VIEW_RIGHT ); if ( FAILED( hr ) ) { wprintf( L"StringCchCopyW failed. hr = 0x%x\n", hr ); break; } } else { wprintf( L"An unknown right was encountered. "\ L"Continuing...\n" ); if ( NULL != wszName ) { delete [] wszName; wszName = NULL; } if ( NULL != wszDomain ) { delete [] wszDomain; wszDomain = NULL; } continue; } } } // // 3(e). Create a user based on the ACL // hr = DRMCreateUser( wszName, wszSid, L"Windows", &hUser ); if ( FAILED( hr ) ) { wprintf( L"\nDRMCreateUser failed. hr = 0x%x\n", hr ); goto e_Exit; } // // 3(f). Create a right based on the ACL // hr = DRMCreateRight( wszRight, &stTimeFrom, &stTimeUntil, NULL, NULL, NULL, &hRight ); if ( FAILED( hr ) ) { wprintf( L"\nDRMCreateRight failed. hr = 0x%x\n", hr ); goto e_Exit; } // // 3(g). Add the user and right to the unsigned issuance license // hr = DRMAddRightWithUser( hIssuanceLicense, hRight, hUser ); if ( FAILED( hr ) ) { wprintf( L"\nDRMAddRightWithUser failed. hr = 0x%x\n", hr ); goto e_Exit; } // // Clean up the memory and variables before // continuing through the loop // if ( NULL != wszName ) { delete [] wszName; wszName = NULL; } if ( NULL != wszDomain ) { delete [] wszDomain; wszDomain = NULL; } if ( NULL != wszRight ) { delete [] wszRight; wszRight = NULL; } if ( NULL != wszSid ) { LocalFree( wszSid ); wszSid = NULL; } if ( NULL != hUser ) { hr = DRMClosePubHandle( hUser ); if ( FAILED( hr ) ) { wprintf( L"DRMClosePubHandle failed while closing hUser. "\ L"hr = 0x%x\n", hr ); hr = E_FAIL; } hUser = NULL; } if ( NULL != hRight ) { hr = DRMClosePubHandle( hRight ); if ( FAILED( hr ) ) { wprintf( L"DRMClosePubHandle failed while closing hRight. "\ L"hr = 0x%x\n", hr ); hr = E_FAIL; } hRight = NULL; } } // // Create a GUID to use as a unique content ID // in the issuance license // hr = CoCreateGuid( &guid ); if ( FAILED( hr ) ) { wprintf( L"CoCreateGuid failed. hr = 0x%x\n", hr ); goto e_Exit; } wszGUID = new WCHAR[ GUID_STRING_LENGTH ]; if ( NULL == wszGUID ) { wprintf( L"Failed to allocate memory for wszGUID\n" ); goto e_Exit; } uiGUIDLength = StringFromGUID2( guid, wszGUID, GUID_STRING_LENGTH ); if ( 0 == uiGUIDLength ) { wprintf( L"StringFromGUID2 failed.\n" ); hr = E_FAIL; goto e_Exit; } // // 4. Set the metadata in the issuance license // hr = DRMSetMetaData( hIssuanceLicense, wszGUID, L"MS-GUID", NULL, NULL, NULL, NULL ); if ( FAILED( hr ) ) { wprintf( L"DRMSetMetaData failed. hr = 0x%x\n", hr ); goto e_Exit; } // // If there were no valid SIDs, then fail since no users/rights will be // added to the issuance license // if ( 0 == count ) { wprintf( L"No valid SIDs were found for the provided directory.\n" ); hr = E_FAIL; goto e_Exit; } // // 5. Generate a template from the issuance license // hr = DRMGetIssuanceLicenseTemplate( hIssuanceLicense, &uiTemplateLength, NULL ); if ( FAILED( hr ) ) { wprintf( L"\nDRMGetIssuanceLicenseTemplate failed. hr = 0x%x\n", hr ); goto e_Exit; } wszTemplate = new WCHAR[ uiTemplateLength ]; if ( NULL == wszTemplate ) { wprintf( L"\nMemory allocation failed for the template.\n" ); hr = E_OUTOFMEMORY; goto e_Exit; } hr = DRMGetIssuanceLicenseTemplate( hIssuanceLicense, &uiTemplateLength, wszTemplate ); if ( FAILED( hr ) ) { wprintf( L"\nDRMGetIssuanceLicenseTemplate failed. hr = 0x%x\n", hr ); goto e_Exit; } // // Write the template to a file // hr = WriteTemplateToUnicodeFile( TEMPLATE_FILE, wszTemplate ); if ( FAILED( hr ) ) { wprintf( L"WriteTemplateToUnicodeFile failed. hr = 0x%x\n", hr ); goto e_Exit; } wprintf( L"PublishingACL succeeded.\n" ); e_Exit: // // 6. Clean up and free memory // if ( NULL != pSD ) { delete [] pSD; } if ( NULL != wszName ) { delete [] wszName; } if ( NULL != wszDomain ) { delete [] wszDomain; } if ( NULL != wszRight ) { delete [] wszRight; } if ( NULL != wszSid ) { LocalFree( wszSid ); wszSid = NULL; } if ( NULL != wszPath ) { delete [] wszPath; } if ( NULL != wszMachineName ) { delete [] wszMachineName; } if ( NULL != wszTemplate ) { delete [] wszTemplate; } if ( NULL != hIssuanceLicense ) { hr = DRMClosePubHandle( hIssuanceLicense ); if ( FAILED( hr ) ) { wprintf( L"DRMClosePubHandle failed while closing "\ L"hIssuanceLicense. hr = 0x%x\n", hr ); hr = E_FAIL; } } if ( NULL != hUser ) { hr = DRMClosePubHandle( hUser ); if ( FAILED( hr ) ) { wprintf( L"DRMClosePubHandle failed while closing hUser. "\ L"hr = 0x%x\n", hr ); hr = E_FAIL; } } if ( NULL != hRight ) { hr = DRMClosePubHandle( hRight ); if ( FAILED( hr ) ) { wprintf( L"DRMClosePubHandle failed while closing hRight. "\ L"hr = 0x%x\n", hr ); hr = E_FAIL; } } if ( FAILED( hr ) ) { wprintf( L"\nPublishingACL failed. hr = 0x%x\n", hr ); } return hr; }