ホーム › Data.RightsManagement › DRMEncrypt
DRMEncrypt
関数RMSの暗号化プロバイダーでデータを暗号化する。
シグネチャ
// msdrm.dll
#include <windows.h>
HRESULT DRMEncrypt(
DWORD hCryptoProvider,
DWORD iPosition,
DWORD cNumInBytes,
BYTE* pbInData,
DWORD* pcNumOutBytes,
BYTE* pbOutData
);パラメーター
| 名前 | 型 | 方向 | 説明 |
|---|---|---|---|
| hCryptoProvider | DWORD | in | DRMCreateEnablingBitsEncryptor 関数を使用して作成された AD RMS 暗号化オブジェクトのハンドル。 |
| iPosition | DWORD | in | 暗号化を開始するバッファー内の位置。0 はバッファー内の最初のブロック、1 は 2 番目のブロックに対応し、以降も同様です。 注 発行ライセンスの署名時に AES キーを使用する場合、iPosition は常に 0 に設定できます。
|
| cNumInBytes | DWORD | in | 暗号化するバイト数。 |
| pbInData | BYTE* | inout | 暗号化するバイト列を格納したバッファーへのポインター。 |
| pcNumOutBytes | DWORD* | inout | 暗号化されたバイト数。 |
| pbOutData | BYTE* | inout | 暗号化されたバイト列へのポインター。 |
戻り値の型: HRESULT
公式ドキュメント
データを暗号化します。
戻り値
関数が成功した場合、S_OK を返します。
関数が失敗した場合は、エラーを示す HRESULT 値を返します。一般的なエラーコードの一覧については、Common HRESULT Values を参照してください。
解説(Remarks)
暗号化されたコンテンツのメモリの割り当てと解放は、呼び出し元の関数の責任です。次のコードサンプルは Encrypting Content からの引用で、コンテンツをブロック単位で暗号化する方法を示しています。この例では暗号化するコンテンツのサイズがあらかじめ分かっており、事前にメモリを割り当てています。ただし、割り当てるバイト数を判別する必要がある場合は、最初の呼び出しの後に必要なバッファーサイズが pcNumOutBytes パラメーターに返されます。メモリを割り当て、pbOutData が新しいメモリを指すように設定して、関数をもう一度呼び出してください。
#include "EncryptingContent.h"
/*===================================================================
File: Encryption_EncryptContent.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 EncryptContent function encrypts content. In this example,
// the content to be encrypted is defined in the header file.
// #define PLAINTEXT L"This is the content to be encrypted."
//
HRESULT EncryptContent(
DRMENVHANDLE hEnv,
DRMHANDLE hLib,
PWSTR pwszRAC,
PWSTR pwszGUID,
DRMHANDLE hIssuanceLic,
PWSTR pwszSignedIL,
BYTE** ppbEncrypted)
{
///////////////////////////////////////////////////////////////////
// Declare variables:
// hr........................Return value
// pwszOwnerLicense..........License with OWNER right
// pwszOutFile...............Name of file for encrypted content
// pbEncrypted...............Buffer to hold encrypted content
// uiOwnerLicenseLength......Owner licensee length, in characters
// uiBlock...................Decryption block size (16 bytes)
// uiBytes...................Size, in bytes, of uiBlock
// uiPlainText...............Number of bytes in the plain text
// uiPadding.................Blank space added to plain text
// uiBuffer..................uiPlainText + uiPadding
// uiEncrypted...............Size, bytes, of encrypted content
// uiOffset..................Offset into encryption buffer
// pbPlainText...............Pointer to unencrypted content
// hBoundLicense.............Handle to license bound to OWNER
// hEP.......................Enabling principal for binding
// hEBEncryptor..............Handle to encrypting object
// dwBytesWritten............WriteFile function bytes written
// idNULL....................DRMID structure
// idContent.................Structure for binding a license
// idStandardEP..............Structure for enabling principal
// oParams...................Structure for binding a license
// eType.....................Structure for license encoding
//
HRESULT hr = E_FAIL;
PWSTR pwszOwnerLicense = NULL;
PWSTR pwszOutFile = L"EncryptedContent.bin";
BYTE* pbEncrypted = NULL;
UINT uiOwnerLicenseLength = 0;
UINT uiBlock = 0;
UINT uiBytes = 0;
UINT uiPlainText = 0;
UINT uiBuffer = 0;
UINT uiPadding = 0;
UINT uiEncrypted = 0;
UINT uiOffset = 0;
BYTE* pbPlainText = NULL;
DRMHANDLE hBoundLicense = NULL;
DRMHANDLE hEP = NULL;
DRMHANDLE hEBEncryptor = NULL;
DWORD dwBytesWritten = 0;
DRMID idNULL;
DRMID idContent;
DRMID idStandardEP;
DRMBOUNDLICENSEPARAMS oParams;
DRMENCODINGTYPE eType;
wprintf(L"\r\nEntering EncryptContent.\r\n");
// Validate the input parameters.
if ( NULL==hEnv ||
NULL==hLib ||
NULL==pwszRAC ||
NULL==pwszGUID ||
NULL==hIssuanceLic ||
NULL==pwszSignedIL ||
NULL==ppbEncrypted)
return E_INVALIDARG;
// Create an enabling principal.
SecureZeroMemory(&idNULL, sizeof(idNULL));
SecureZeroMemory(&idStandardEP, sizeof(idStandardEP));
idStandardEP.wszIDType = L"ASCII Tag";
idStandardEP.wszID = L"UDStdPlg Enabling Principal";
hr = DRMCreateEnablingPrincipal (
hEnv, // Secure environment handle
hLib, // Library handle
idStandardEP.wszID, // Enabling principal type
&idNULL, // DRMID structure
pwszRAC, // Rights account certificate
&hEP); // enabling principal handle
if(FAILED(hr)) return hr;
wprintf(L"DRMCreateEnablingPrincipal: hEP %i \r\n", hEP);
// Call DRMGetOwnerLicense to get a license to bind to. An owner
// license contains the OWNER right which allows the user to
// exercise all rights regardless of whether they have been
// explicitly granted.
// - Call DRMGetOwnerLicense once to retrieve the length, in
// characters, of the owner license.
// - Allocate memory for the license.
// - Call DRMGetOwnerLicense again to retrieve the license.
// - You must release the memory before leaving this function.
hr = DRMGetOwnerLicense(
hIssuanceLic, // Issuance license handle
&uiOwnerLicenseLength, // License length
NULL); // Not used
if(FAILED(hr)) goto e_Exit;
pwszOwnerLicense = new WCHAR[uiOwnerLicenseLength];
if(NULL == pwszOwnerLicense)
{
hr = E_OUTOFMEMORY;
goto e_Exit;
}
hr = DRMGetOwnerLicense(
hIssuanceLic,
&uiOwnerLicenseLength,
pwszOwnerLicense);
if(FAILED(hr)) goto e_Exit;
wprintf(L"DRMGetOwnerLicense (pwszOwnerLicense) succeeded.\r\n");
// Bind the owner license to the OWNER right.
SecureZeroMemory(&idContent, sizeof(idContent));
idContent.wszIDType = L"MS-GUID";
idContent.wszID = pwszGUID;
SecureZeroMemory(&oParams, sizeof(oParams));
oParams.hEnablingPrincipal = hEP;
oParams.wszRightsRequested = L"OWNER";
oParams.wszRightsGroup = L"Main-Rights";
oParams.idResource = idContent;
hr = DRMCreateBoundLicense (
hEnv, // Secure environment handle
&oParams, // Additional license options
pwszOwnerLicense, // Owner license
&hBoundLicense, // Handle to the bound license
NULL ); // Reserved
if(FAILED(hr)) goto e_Exit;
wprintf(L"DRMCreateBoundLicense: (hBoundLicense) succeeded.\r\n");
// Create an encrypting object.
hr = DRMCreateEnablingBitsEncryptor(
hBoundLicense, // Bound license handle
oParams.wszRightsRequested, // Requested right
NULL, // Reserved
NULL, // Reserved
&hEBEncryptor); // Encrypting object handle
if(FAILED(hr)) goto e_Exit;
wprintf(L"DRMCreateEnablingBitsEncryptor succeeded.\r\n");
// Retrieve the size, in bytes, of the memory block that must
// be passed to DRMEncrypt.
uiBytes= sizeof(uiBlock);
hr = DRMGetInfo(
hEBEncryptor, // Encrypting object handle
g_wszQUERY_BLOCKSIZE, // Attribute to query for
&eType, // Type of encoding to apply
&uiBytes, // Size of uiBlock variable
(BYTE*)&uiBlock); // Size of memory block
if(FAILED(hr)) goto e_Exit;
wprintf(L"DRMGetInfo: uiBlock = %u\r\n", uiBlock);
// Determine the size of the buffer needed to store the
// encrypted content. The buffer must be an even multiple of
// the buffer size used during the [typically] iterative
// encryption process. In this example, the plain text
// is 72 bytes long and the encryption buffer is 16 bytes.
// However 72 % 16 = 8. The plain text must therefore be padded
// to 80 bytes (80 % 16 = 0).
uiPlainText = (UINT)(sizeof(WCHAR) * wcslen(PLAINTEXT));
uiPadding = uiBlock - (uiPlainText % uiBlock);
uiBuffer = uiPlainText + uiPadding;
pbPlainText = new BYTE[uiBuffer];
*ppbEncrypted = new BYTE[uiBuffer];
SecureZeroMemory(pbPlainText, sizeof(pbPlainText));
memcpy_s(
pbPlainText,
uiBuffer,
(BYTE*)PLAINTEXT,
uiPlainText);
// Encrypt the plain text.
for ( int j = 0; (UINT)j * uiBlock < uiBuffer; j++ )
{
hr = DRMEncrypt(
hEBEncryptor, // Encrypting object handle
j * uiBlock, // Position in buffer
uiBlock, // Number of bytes to encrypt
pbPlainText + (j*uiBlock), // Bytes to encrypt
&uiEncrypted, // Number of bytes encrypted
NULL); // NULL on first call
if(FAILED(hr)) goto e_Exit;
hr = DRMEncrypt(
hEBEncryptor, // Encrypting object handle
j * uiBlock, // Position in buffer
uiBlock, // Number of bytes to encrypt
pbPlainText + (j*uiBlock), // Bytes to encrypt
&uiEncrypted, // Number of bytes encrypted
*ppbEncrypted + uiOffset); // Encrypted content
if(FAILED(hr)) goto e_Exit;
uiOffset += uiEncrypted; // Increment the buffer offset
}
// Create a new file to write the encrypted content and issuance
// license to.
HANDLE hFile = CreateFile(
pwszOutFile, // File name
GENERIC_WRITE, // Access type
0, // Require exclusive access
NULL, // Default security attributes
CREATE_ALWAYS, // Allow write-only access
0, // No file attributes or flags
NULL); // No open file as template
if(INVALID_HANDLE_VALUE == hFile)
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto e_Exit;
}
wprintf(L"CreateFile: hFile = %i\r\n", hFile);
// Write the encrypted content and relevant data to the file.
if(!WriteFile(hFile,
&uiBuffer,
sizeof(UINT),
&dwBytesWritten,
NULL))
goto e_Exit;
size_t uiIssuanceLicenseLgth = (UINT)(sizeof(WCHAR) *
wcslen(pwszSignedIL));
if(!WriteFile(hFile,
&uiIssuanceLicenseLgth,
sizeof(size_t),
&dwBytesWritten,
NULL))
goto e_Exit;
if(!WriteFile(hFile,
*ppbEncrypted,
uiBuffer,
&dwBytesWritten,
NULL))
goto e_Exit;
if(!WriteFile(hFile,
pwszSignedIL,
uiIssuanceLicenseLgth,
&dwBytesWritten,
NULL))
goto e_Exit;
wprintf(L"Writing to file succeeded.\r\n");
e_Exit:
if (INVALID_HANDLE_VALUE != hFile)
{
CloseHandle(hFile);
}
if (NULL != hEP)
{
hr = DRMCloseHandle(hEP);
hEP = NULL;
}
if (NULL != hBoundLicense)
{
hr = DRMCloseHandle(hBoundLicense);
hBoundLicense = NULL;
}
if (NULL != hEBEncryptor)
{
hr = DRMCloseHandle(hEBEncryptor);
hEBEncryptor = NULL;
}
if (NULL != pwszOwnerLicense)
{
delete [] pwszOwnerLicense;
pwszOwnerLicense = NULL;
}
wprintf(L"Leaving EncryptContent: hr = %x \r\n", hr);
return hr;
}
次のコードサンプルは、暗号ブロック連鎖 (CBC) 暗号モードで AES アルゴリズムを使用してコンテンツを暗号化する方法を示しています。この機能は Windows 7 でのみ使用できます。
/*===================================================================
Functions: PerformCbcEncryption and PerformCbcDecryption
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.
===================================================================*/
#include "msdrm.h"
#include "msdrmgetinfo.h"
#define SZ_CBC_KEY_TYPE L"AES_CBC4K"
#define DW_WAIT_TIME 60000
#define SZ_ENABLING_PRINCIPAL_TYPE L"UDStdPlg Enabling Principal"
#define SZ_MAIN_RIGHTS_GROUP L"Main-Rights"
#define SZ_EDIT_RIGHT L"EDIT"
#define SZ_VIEW_RIGHT L"VIEW"
extern HRESULT __stdcall StatusCallback(DRM_STATUS_MSG msg,
HRESULT hr,
void* pvParam,
void* pvContext);
//
// Struct to hold DRMGetSignedIssuanceLicense callback information
//
typedef struct Drm_Context
{
HANDLE hEvent;
HRESULT hr;
PWSTR wszData;
} DRM_CONTEXT, *PDRM_CONTEXT;
//
// This helper function will perform steps required to get a bound
// license when provided the required information. It is listed
// here to demonstrate that this part of the CBC encryption and
// decryption flow is unchanged from the standard flow. In practice,
// since creating a new bound license for each encryption and
// decryption request is costly, you would instead obtain all
// requested rights at once in a comma-separated list and reuse
// a single bound license when possible.
//
inline HRESULT GetBoundLicense(__in DRMENVHANDLE hEnv,
__in PWCHAR pwszRac,
__in PWSTR pwszUseLicense,
__in PWSTR pwszRightsRequested,
__in DRMHANDLE hIssuanceLicense,
__out DRMHANDLE* phBoundLicense)
{
HRESULT hr = S_OK;
DRMHANDLE hEnablingPrincipal = NULL;
DRMID idNULL(NULL, NULL);
UINT uiContentId = 0;
UINT uiContentIdType = 0;
PWSTR pwszContentId = NULL;
PWSTR pwszContentIdType = NULL;
DRMID idContent;
DRMBOUNDLICENSEPARAMS bParams;
hr = DRMCreateEnablingPrincipal(
hEnv, // Environment handle
NULL, // No library specified
SZ_ENABLING_PRINCIPAL_TYPE, // Enabling principal type
&idNULL, // DRMID structure
pwszRac, // Current user certificate / RAC
&hEnablingPrincipal); // Enabling principal handle
if (FAILED(hr))
{
goto e_Exit;
}
// Obtain the sizes of the buffers needed for the
// content ID and content ID type
hr = DRMGetMetaData(
hIssuanceLicense, // Handle to the license
&uiContentId, // Content Id Length
NULL, // Content Id
&uiContentIdType, // Content Id Type Length
NULL, // Content Id Type
NULL, // SKU ID Length
NULL, // SKU ID
NULL, // SKU ID Type Length
NULL, // SKU ID Type
NULL, // Content Type Length
NULL, // Content Type
NULL, // Content Name Length
NULL); // Content Name
if (FAILED(hr))
{
goto e_Exit;
}
pwszContentId = new WCHAR[uiContentId];
if(NULL == pwszContentId)
{
hr = E_OUTOFMEMORY;
goto e_Exit;
}
pwszContentIdType = new WCHAR[uiContentIdType];
if(NULL == pwszContentIdType)
{
hr = E_OUTOFMEMORY;
goto e_Exit;
}
// Obtain the content ID and content ID type
hr = DRMGetMetaData(
hIssuanceLicense, // Handle to the license
&uiContentId, // Content Id Length
pwszContentId, // Content Id
&uiContentIdType, // Content Id Type Length
pwszContentIdType, // Content Id Type
NULL, // SKU ID Length
NULL, // SKU ID
NULL, // SKU ID Type Length
NULL, // SKU ID Type
NULL, // Content Type Length
NULL, // Content Type
NULL, // Content Name Length
NULL); // Content Name
if (FAILED(hr))
{
goto e_Exit;
}
idContent.uVersion = 0;
idContent.wszIDType = pwszContentIdType;
idContent.wszID = pwszContentId;
bParams.hEnablingPrincipal = hEnablingPrincipal;
bParams.hSecureStore = NULL;
bParams.wszRightsRequested = pwszRightsRequested;
bParams.wszRightsGroup = SZ_MAIN_RIGHTS_GROUP;
bParams.idResource = idContent;
bParams.wszDefaultEnablingPrincipalCredentials = NULL;
bParams.cAuthenticatorCount = 0;
hr = DRMCreateBoundLicense(
hEnv, // Environment handle
&bParams, // Additional license options
pwszUseLicense, // Use license
phBoundLicense, // Bound license handle
NULL); // Reserved
e_Exit:
if (NULL != hEnablingPrincipal)
{
DRMCloseHandle(hEnablingPrincipal);
}
if (NULL != pwszContentId)
{
delete [] pwszContentId;
}
if (NULL != pwszContentIdType)
{
delete [] pwszContentIdType;
}
return hr;
}
/////////////////////////////////////////////////////////////////////
// The PerformCbcEncryption function performs CBC encryption on the
// given unencrypted data buffer and returns the encrypted data
// in a single, freshly allocated buffer. In practice, you may want
// to modify this function so that larger amounts of data are
// streamed in, rather than having the entire block processed (and
// memory allocated) all at once.
//
// Arguments:
// pbDataToEncrypt - [in] Buffer containing the data
// that is to be encrypted
// uiUnencryptedDataLength - [in] Length of the unencrypted
// data (in bytes)
// hEnv - [in] Environment handle
// hIssuanceLicense - [in] Handle to an issuance
// license
// pwszCLC - [in] CLC of the publishing user
// pwszRac - [in] RAC of the publishing user
// ppbEncryptedData - [out] Buffer holding the newly
// encrypted data
// puiEncryptedDataLength - [out] Length of the encrypted
// data (in bytes)
HRESULT PerformCbcEncryption(__in BYTE* pbDataToEncrypt,
__in UINT uiUnencryptedDataLength,
__in DRMENVHANDLE hEnv,
__in DRMPUBHANDLE hIssuanceLicense,
__in PWSTR pwszCLC,
__in PWCHAR pwszRac,
__out PBYTE* ppbEncryptedData,
__out UINT* puiEncryptedDataLength)
{
HRESULT hr = S_OK; // Return code
DRM_CONTEXT context; // To hold callback information
DWORD dwWaitResult = 0; // Result of wait operation
PWSTR pwszOwnerLicense = NULL; // Owner use license
UINT uiOwnerLicenseLength = 0; // Size of the owner license
DRMHANDLE hBoundLicense = NULL; // Bound license handle
DRMHANDLE hEBEncryptor = NULL; // Encryptor handle
UINT uiBlockSize = 0; // Size of each block to be
// passed to DRMEncrypt
UINT uiBlockSizeInfo = 0; // Size of the uiBlockSize
// variable
DRMENCODINGTYPE encodingType; // Encoding type for DRMGetInfo
UINT uiPaddingSize = 0; // Length of padding needed to
// match block size
UINT uiOffset = 0; // Offset in encryption buffer
// For our example, we will be using the "EDIT" right
// during encryption
const PWSTR pwszRightsRequested = SZ_EDIT_RIGHT;
// Validate parameters
if ((NULL == pbDataToEncrypt)
|| (NULL == hEnv)
|| (NULL == hIssuanceLicense)
|| (NULL == pwszCLC)
|| (NULL == pwszRac)
|| (NULL == ppbEncryptedData)
|| (NULL == puiEncryptedDataLength))
{
hr = E_INVALIDARG;
goto e_Exit;
}
// Create an event for the callback function
context.hEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
if (NULL == context.hEvent)
{
hr = HRESULT_FROM_WIN32(::GetLastError());
goto e_Exit;
}
context.wszData = NULL;
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
SZ_CBC_KEY_TYPE, // CBC 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;
}
// Wait for callback to return
dwWaitResult = ::WaitForSingleObject(context.hEvent,
DW_WAIT_TIME);
if (WAIT_OBJECT_0 != dwWaitResult)
{
hr = HRESULT_FROM_WIN32(::GetLastError());
goto e_Exit;
}
else if (FAILED(context.hr))
{
hr = context.hr;
goto e_Exit;
}
// Obtain the length of the owner license
hr = DRMGetOwnerLicense(
hIssuanceLicense, // Issuance license handle
&uiOwnerLicenseLength, // Length of owner license
NULL); // Query for license length
if (FAILED(hr))
{
goto e_Exit;
}
pwszOwnerLicense = new WCHAR[uiOwnerLicenseLength];
if (NULL == pwszOwnerLicense)
{
hr = E_OUTOFMEMORY;
goto e_Exit;
}
hr = DRMGetOwnerLicense(
hIssuanceLicense, // Issuance license handle
&uiOwnerLicenseLength, // Length of owner license
pwszOwnerLicense); // Owner use license
if (FAILED(hr))
{
goto e_Exit;
}
// Proceed normally (as you would for non-CBC encryption) to
// obtain the bound license
hr = GetBoundLicense(hEnv,
pwszRac,
pwszOwnerLicense,
pwszRightsRequested,
hIssuanceLicense,
&hBoundLicense);
if (FAILED(hr))
{
goto e_Exit;
}
hr = DRMCreateEnablingBitsEncryptor(
hBoundLicense, // Bound license handle
pwszRightsRequested, // Requested rights
NULL, // Reserved
NULL, // Reserved
&hEBEncryptor); // Encryptor handle
if (FAILED(hr))
{
goto e_Exit;
}
// Determine the block size you need to pass to DRMEncrypt
uiBlockSizeInfo = sizeof(uiBlockSize);
hr = DRMGetInfo(
hEBEncryptor, // Encryptor handle
g_wszQUERY_BLOCKSIZE, // Queried attribute
&encodingType, // Type of encoding to apply
&uiBlockSizeInfo, // Size of uiBlockSize variable
(BYTE*)&uiBlockSize); // Block size to use
if (FAILED(hr))
{
goto e_Exit;
}
// Since the amount of data we encrypt must be a multiple of the
// block size, we must determine the amount of padding we need
// to add to our data and create a buffer of the appropriate
// size (the size of our original data + padding)
uiPaddingSize
= uiBlockSize - (uiUnencryptedDataLength % uiBlockSize);
*puiEncryptedDataLength
= uiUnencryptedDataLength + uiPaddingSize;
*ppbEncryptedData = new BYTE[*puiEncryptedDataLength];
if (NULL == *ppbEncryptedData)
{
hr = E_OUTOFMEMORY;
goto e_Exit;
}
// Fill the padding area with zeros
::SecureZeroMemory((*ppbEncryptedData + uiUnencryptedDataLength),
uiPaddingSize);
// In this example, we are encrypting our content with one call
// to DRMEncrypt for each 4 KB block (4096 bytes). In practice,
// you may want to reduce the number of calls by passing in
// a quantity of data that is some larger multiple of 4096 bytes.
for (int i = 0;
((UINT)i * uiBlockSize) < *puiEncryptedDataLength;
i++)
{
UINT uiNumBytesEncrypted = 0;
UINT uiBufferPosition = (i * uiBlockSize);
hr = DRMEncrypt(
// Encryptor handle
hEBEncryptor,
// Starting block number (1 block = uiBlockSize)
i,
// Number of bytes to encrypt
uiBlockSize,
// Starting location of bytes to encrypt
(pbDataToEncrypt + uiBufferPosition),
// Number of bytes encrypted
&uiNumBytesEncrypted,
// Starting location for encrypted content
(*ppbEncryptedData + uiOffset));
if (FAILED(hr))
{
goto e_Exit;
}
uiOffset += uiNumBytesEncrypted;
}
e_Exit:
if (NULL != context.hEvent)
{
::CloseHandle(context.hEvent);
}
if (NULL != context.wszData)
{
delete [] context.wszData;
}
if (NULL != pwszOwnerLicense)
{
delete [] pwszOwnerLicense;
}
if (NULL != hBoundLicense)
{
DRMCloseHandle(hBoundLicense);
}
if (NULL != hEBEncryptor)
{
DRMCloseHandle(hEBEncryptor);
}
return hr;
}
/////////////////////////////////////////////////////////////////////
// The PerformCbcDecryption function performs decryption on the
// given CBC encrypted data buffer and returns the decrypted data
// in a single freshly allocated buffer. In practice, you may want
// to modify this function so that larger quantities of data are
// streamed in, rather than having the entire block processed (and
// memory allocated) all at once.
// Arguments:
// pbEncryptedData - [in] Buffer containing the data
// that is to be decrypted
// uiEncryptedDataLength - [in] Length of the encrypted
// data (in bytes)
// hEnv - [in] Environment handle
// hIssuanceLicense - [in] Handle to an issuance
// license
// pwszUseLicense - [in] Use license
// pwszRac - [in] RAC of the publishing user
// ppbDecryptedData - [out] Buffer holding the newly
// decrypted data
HRESULT PerformCbcDecryption(__in BYTE* pbEncryptedData,
__in UINT uiEncryptedDataLength,
__in DRMENVHANDLE hEnv,
__in DRMPUBHANDLE hIssuanceLicense,
__in PWSTR pwszUseLicense,
__in PWCHAR pwszRac,
__out PBYTE* ppbDecryptedData)
{
HRESULT hr = S_OK; // Return code
DRMHANDLE hBoundLicense = NULL; // Bound license handle
DRMHANDLE hEBDecryptor = NULL; // Decryptor handle
PWSTR pwszKeyType = NULL; // Key type used
UINT uiKeyTypeLength = 0; // Length of pwszKeyType
UINT uiBlockSize = 0; // Size of each block to be
// passed to DRMEncrypt
UINT uiBlockSizeInfo = 0; // Size of the uiBlockSize
// variable
DRMENCODINGTYPE encodingType; // Encoding type for DRMGetInfo
UINT uiPaddingSize = 0; // Length of padding needed to
// match block size
UINT uiOffset = 0; // Offset in encryption buffer
// For the example, the "VIEW" right is used
// during decryption
const PWSTR pwszRightsRequested = SZ_VIEW_RIGHT;
// Validate parameters
if ((NULL == pbEncryptedData)
|| (NULL == hEnv)
|| (NULL == hIssuanceLicense)
|| (NULL == pwszUseLicense)
|| (NULL == pwszRac)
|| (NULL == ppbDecryptedData))
{
hr = E_INVALIDARG;
goto e_Exit;
}
// Proceed normally (as you would for non-CBC decryption) to
// obtain the bound license
hr = GetBoundLicense(hEnv,
pwszRac,
pwszUseLicense,
pwszRightsRequested,
hIssuanceLicense,
&hBoundLicense);
if (FAILED(hr))
{
goto e_Exit;
}
hr = DRMCreateEnablingBitsDecryptor(
hBoundLicense, // Bound license handle
pwszRightsRequested, // Requested rights
NULL, // Reserved
NULL, // Reserved
&hEBDecryptor); // Decryptor handle
if (FAILED(hr))
{
goto e_Exit;
}
// Verify/Determine that CBC decryption is needed. In practice,
// this may not be needed if you already know whether or not
// the cipher mode used is CBC
hr = DRMGetInfo(
hEBDecryptor, // Decryptor handle
g_wszQUERY_SYMMETRICKEYTYPE, // Queried attribute
&encodingType, // Type of encoding to apply
&uiKeyTypeLength, // Size of key type variable
NULL); // Query for length
if (FAILED(hr))
{
goto e_Exit;
}
pwszKeyType = new WCHAR[uiKeyTypeLength];
if (NULL == pwszKeyType)
{
hr = E_OUTOFMEMORY;
goto e_Exit;
}
hr = DRMGetInfo(
hEBDecryptor, // Decryptor handle
g_wszQUERY_SYMMETRICKEYTYPE, // Queried attribute
&encodingType, // Type of encoding to apply
&uiKeyTypeLength, // Size of key type variable
(BYTE*)pwszKeyType); // Key type used
if (FAILED(hr))
{
goto e_Exit;
}
if (!wcscmp(SZ_CBC_KEY_TYPE, pwszKeyType))
{
// Unexpected -- in practice, you may want to instead
// handle decryption for this non-CBC key type
hr = E_UNEXPECTED;
goto e_Exit;
}
// Verify/Determine the block size you need to pass to DRMDecrypt
uiBlockSizeInfo = sizeof(uiBlockSize);
hr = DRMGetInfo(
hEBDecryptor, // Decryptor handle
g_wszQUERY_BLOCKSIZE, // Queried attribute
&encodingType, // Type of encoding to apply
&uiBlockSizeInfo, // Size of uiBlockSize variable
(BYTE*)&uiBlockSize); // Block size to use
if (FAILED(hr))
{
goto e_Exit;
}
*ppbDecryptedData = new BYTE[uiEncryptedDataLength];
if (NULL == *ppbDecryptedData)
{
hr = E_OUTOFMEMORY;
goto e_Exit;
}
// In this example, the content is being decrypted with one call
// to DRMDecrypt for each 4 KB block (4096 bytes). In practice,
// you may want to reduce the number of calls by passing in
// a quantity of data that is some larger multiple of 4096 bytes.
for (int i = 0;
((UINT)i * uiBlockSize) < uiEncryptedDataLength;
i++)
{
UINT uiNumBytesDecrypted = 0;
UINT uiBufferPosition = (i * uiBlockSize);
hr = DRMDecrypt(
// Decryptor handle
hEBDecryptor,
// Starting block number (1 block = uiBlockSize)
i,
// Number of bytes to decrypt
uiBlockSize,
// Starting location of bytes to decrypt
(pbEncryptedData + uiBufferPosition),
// Number of bytes decrypted
&uiNumBytesDecrypted,
// Starting location for decrypted content
(*ppbDecryptedData + uiOffset));
if (FAILED(hr))
{
goto e_Exit;
}
uiOffset += uiNumBytesDecrypted;
}
e_Exit:
if (NULL != hBoundLicense)
{
DRMCloseHandle(hBoundLicense);
}
if (NULL != hEBDecryptor)
{
DRMCloseHandle(hEBDecryptor);
}
if (NULL != pwszKeyType)
{
delete [] pwszKeyType;
}
return hr;
}
出典・ライセンス: 上記「公式ドキュメント」の内容は Microsoft の Win32 API ドキュメント(MicrosoftDocs/sdk-api)を日本語に翻訳・改変したものです。© Microsoft Corporation. CC BY 4.0 で提供。
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)
各言語での呼び出し定義
// msdrm.dll
#include <windows.h>
HRESULT DRMEncrypt(
DWORD hCryptoProvider,
DWORD iPosition,
DWORD cNumInBytes,
BYTE* pbInData,
DWORD* pcNumOutBytes,
BYTE* pbOutData
);[DllImport("msdrm.dll", ExactSpelling = true)]
static extern int DRMEncrypt(
uint hCryptoProvider, // DWORD
uint iPosition, // DWORD
uint cNumInBytes, // DWORD
IntPtr pbInData, // BYTE* in/out
ref uint pcNumOutBytes, // DWORD* in/out
IntPtr pbOutData // BYTE* in/out
);<DllImport("msdrm.dll", ExactSpelling:=True)>
Public Shared Function DRMEncrypt(
hCryptoProvider As UInteger, ' DWORD
iPosition As UInteger, ' DWORD
cNumInBytes As UInteger, ' DWORD
pbInData As IntPtr, ' BYTE* in/out
ByRef pcNumOutBytes As UInteger, ' DWORD* in/out
pbOutData As IntPtr ' BYTE* in/out
) As Integer
End Function' hCryptoProvider : DWORD
' iPosition : DWORD
' cNumInBytes : DWORD
' pbInData : BYTE* in/out
' pcNumOutBytes : DWORD* in/out
' pbOutData : BYTE* in/out
Declare PtrSafe Function DRMEncrypt Lib "msdrm" ( _
ByVal hCryptoProvider As Long, _
ByVal iPosition As Long, _
ByVal cNumInBytes As Long, _
ByVal pbInData As LongPtr, _
ByRef pcNumOutBytes As Long, _
ByVal pbOutData As LongPtr) As Long
' VBA7前提(PtrSafe)。32bit Office では LongPtr→Long。Integer=16bit / Long=32bit / LongLong=64bit。import ctypes
from ctypes import wintypes
DRMEncrypt = ctypes.windll.msdrm.DRMEncrypt
DRMEncrypt.restype = ctypes.c_int
DRMEncrypt.argtypes = [
wintypes.DWORD, # hCryptoProvider : DWORD
wintypes.DWORD, # iPosition : DWORD
wintypes.DWORD, # cNumInBytes : DWORD
ctypes.POINTER(ctypes.c_ubyte), # pbInData : BYTE* in/out
ctypes.POINTER(wintypes.DWORD), # pcNumOutBytes : DWORD* in/out
ctypes.POINTER(ctypes.c_ubyte), # pbOutData : BYTE* in/out
]require 'fiddle'
require 'fiddle/import'
lib = Fiddle.dlopen('msdrm.dll')
DRMEncrypt = Fiddle::Function.new(
lib['DRMEncrypt'],
[
-Fiddle::TYPE_INT, # hCryptoProvider : DWORD
-Fiddle::TYPE_INT, # iPosition : DWORD
-Fiddle::TYPE_INT, # cNumInBytes : DWORD
Fiddle::TYPE_VOIDP, # pbInData : BYTE* in/out
Fiddle::TYPE_VOIDP, # pcNumOutBytes : DWORD* in/out
Fiddle::TYPE_VOIDP, # pbOutData : BYTE* in/out
],
Fiddle::TYPE_INT)#[link(name = "msdrm")]
extern "system" {
fn DRMEncrypt(
hCryptoProvider: u32, // DWORD
iPosition: u32, // DWORD
cNumInBytes: u32, // DWORD
pbInData: *mut u8, // BYTE* in/out
pcNumOutBytes: *mut u32, // DWORD* in/out
pbOutData: *mut u8 // BYTE* in/out
) -> i32;
}
// crates: windows-sys provides ready-made bindings for this API.$sig = @"
[DllImport("msdrm.dll")]
public static extern int DRMEncrypt(uint hCryptoProvider, uint iPosition, uint cNumInBytes, IntPtr pbInData, ref uint pcNumOutBytes, IntPtr pbOutData);
"@
$api = Add-Type -MemberDefinition $sig -Name 'msdrm_DRMEncrypt' -Namespace Win32 -PassThru
# $api::DRMEncrypt(hCryptoProvider, iPosition, cNumInBytes, pbInData, pcNumOutBytes, pbOutData)#uselib "msdrm.dll"
#func global DRMEncrypt "DRMEncrypt" sptr, sptr, sptr, sptr, sptr, sptr
; DRMEncrypt hCryptoProvider, iPosition, cNumInBytes, varptr(pbInData), varptr(pcNumOutBytes), varptr(pbOutData) ; 戻り値は stat
; hCryptoProvider : DWORD -> "sptr"
; iPosition : DWORD -> "sptr"
; cNumInBytes : DWORD -> "sptr"
; pbInData : BYTE* in/out -> "sptr"
; pcNumOutBytes : DWORD* in/out -> "sptr"
; pbOutData : BYTE* in/out -> "sptr"
; ※HSP3.7は #func のため戻り値はシステム変数 stat に格納されます。出力引数:
#uselib "msdrm.dll" #cfunc global DRMEncrypt "DRMEncrypt" int, int, int, var, var, var ; res = DRMEncrypt(hCryptoProvider, iPosition, cNumInBytes, pbInData, pcNumOutBytes, pbOutData) ; hCryptoProvider : DWORD -> "int" ; iPosition : DWORD -> "int" ; cNumInBytes : DWORD -> "int" ; pbInData : BYTE* in/out -> "var" ; pcNumOutBytes : DWORD* in/out -> "var" ; pbOutData : BYTE* in/out -> "var" ; ※出力/バッファ引数は var 方式(変数を直接渡す)。varptr 方式にも切替可。#uselib "msdrm.dll" #cfunc global DRMEncrypt "DRMEncrypt" int, int, int, sptr, sptr, sptr ; res = DRMEncrypt(hCryptoProvider, iPosition, cNumInBytes, varptr(pbInData), varptr(pcNumOutBytes), varptr(pbOutData)) ; hCryptoProvider : DWORD -> "int" ; iPosition : DWORD -> "int" ; cNumInBytes : DWORD -> "int" ; pbInData : BYTE* in/out -> "sptr" ; pcNumOutBytes : DWORD* in/out -> "sptr" ; pbOutData : BYTE* in/out -> "sptr" ; ※出力/バッファ引数はポインタ方式(token=sptr / 呼び出しは varptr(変数))。
出力引数:
; HRESULT DRMEncrypt(DWORD hCryptoProvider, DWORD iPosition, DWORD cNumInBytes, BYTE* pbInData, DWORD* pcNumOutBytes, BYTE* pbOutData) #uselib "msdrm.dll" #cfunc global DRMEncrypt "DRMEncrypt" int, int, int, var, var, var ; res = DRMEncrypt(hCryptoProvider, iPosition, cNumInBytes, pbInData, pcNumOutBytes, pbOutData) ; hCryptoProvider : DWORD -> "int" ; iPosition : DWORD -> "int" ; cNumInBytes : DWORD -> "int" ; pbInData : BYTE* in/out -> "var" ; pcNumOutBytes : DWORD* in/out -> "var" ; pbOutData : BYTE* in/out -> "var" ; ※出力/バッファ引数は var 方式(変数を直接渡す)。varptr 方式にも切替可。; HRESULT DRMEncrypt(DWORD hCryptoProvider, DWORD iPosition, DWORD cNumInBytes, BYTE* pbInData, DWORD* pcNumOutBytes, BYTE* pbOutData) #uselib "msdrm.dll" #cfunc global DRMEncrypt "DRMEncrypt" int, int, int, intptr, intptr, intptr ; res = DRMEncrypt(hCryptoProvider, iPosition, cNumInBytes, varptr(pbInData), varptr(pcNumOutBytes), varptr(pbOutData)) ; hCryptoProvider : DWORD -> "int" ; iPosition : DWORD -> "int" ; cNumInBytes : DWORD -> "int" ; pbInData : BYTE* in/out -> "intptr" ; pcNumOutBytes : DWORD* in/out -> "intptr" ; pbOutData : BYTE* in/out -> "intptr" ; ※出力/バッファ引数はポインタ方式(token=intptr / 呼び出しは varptr(変数))。
import (
"golang.org/x/sys/windows"
"unsafe"
)
var (
msdrm = windows.NewLazySystemDLL("msdrm.dll")
procDRMEncrypt = msdrm.NewProc("DRMEncrypt")
)
// hCryptoProvider (DWORD), iPosition (DWORD), cNumInBytes (DWORD), pbInData (BYTE* in/out), pcNumOutBytes (DWORD* in/out), pbOutData (BYTE* in/out)
r1, _, err := procDRMEncrypt.Call(
uintptr(hCryptoProvider),
uintptr(iPosition),
uintptr(cNumInBytes),
uintptr(pbInData),
uintptr(pcNumOutBytes),
uintptr(pbOutData),
)
_ = err // syscall.Errno (valid when the call sets last-error)
_ = r1 // HRESULTfunction DRMEncrypt(
hCryptoProvider: DWORD; // DWORD
iPosition: DWORD; // DWORD
cNumInBytes: DWORD; // DWORD
pbInData: Pointer; // BYTE* in/out
pcNumOutBytes: Pointer; // DWORD* in/out
pbOutData: Pointer // BYTE* in/out
): Integer; stdcall;
external 'msdrm.dll' name 'DRMEncrypt';result := DllCall("msdrm\DRMEncrypt"
, "UInt", hCryptoProvider ; DWORD
, "UInt", iPosition ; DWORD
, "UInt", cNumInBytes ; DWORD
, "Ptr", pbInData ; BYTE* in/out
, "Ptr", pcNumOutBytes ; DWORD* in/out
, "Ptr", pbOutData ; BYTE* in/out
, "Int") ; return: HRESULT●DRMEncrypt(hCryptoProvider, iPosition, cNumInBytes, pbInData, pcNumOutBytes, pbOutData) = DLL("msdrm.dll", "int DRMEncrypt(dword, dword, dword, void*, void*, void*)")
# 呼び出し: DRMEncrypt(hCryptoProvider, iPosition, cNumInBytes, pbInData, pcNumOutBytes, pbOutData)
# hCryptoProvider : DWORD -> "dword"
# iPosition : DWORD -> "dword"
# cNumInBytes : DWORD -> "dword"
# pbInData : BYTE* in/out -> "void*"
# pcNumOutBytes : DWORD* in/out -> "void*"
# pbOutData : BYTE* in/out -> "void*"
# なでしこ1は32bit・ANSI(Shift_JIS)。文字列=char*(ANSI)、ポインタ/ハンドル=void*(4byte)。const std = @import("std");
extern "msdrm" fn DRMEncrypt(
hCryptoProvider: u32, // DWORD
iPosition: u32, // DWORD
cNumInBytes: u32, // DWORD
pbInData: [*c]u8, // BYTE* in/out
pcNumOutBytes: [*c]u32, // DWORD* in/out
pbOutData: [*c]u8 // BYTE* in/out
) callconv(std.os.windows.WINAPI) i32;proc DRMEncrypt(
hCryptoProvider: uint32, # DWORD
iPosition: uint32, # DWORD
cNumInBytes: uint32, # DWORD
pbInData: ptr uint8, # BYTE* in/out
pcNumOutBytes: ptr uint32, # DWORD* in/out
pbOutData: ptr uint8 # BYTE* in/out
): int32 {.importc: "DRMEncrypt", stdcall, dynlib: "msdrm.dll".}pragma(lib, "msdrm");
extern(Windows)
int DRMEncrypt(
uint hCryptoProvider, // DWORD
uint iPosition, // DWORD
uint cNumInBytes, // DWORD
ubyte* pbInData, // BYTE* in/out
uint* pcNumOutBytes, // DWORD* in/out
ubyte* pbOutData // BYTE* in/out
);ccall((:DRMEncrypt, "msdrm.dll"), stdcall, Int32,
(UInt32, UInt32, UInt32, Ptr{UInt8}, Ptr{UInt32}, Ptr{UInt8}),
hCryptoProvider, iPosition, cNumInBytes, pbInData, pcNumOutBytes, pbOutData)
# hCryptoProvider : DWORD -> UInt32
# iPosition : DWORD -> UInt32
# cNumInBytes : DWORD -> UInt32
# pbInData : BYTE* in/out -> Ptr{UInt8}
# pcNumOutBytes : DWORD* in/out -> Ptr{UInt32}
# pbOutData : BYTE* in/out -> Ptr{UInt8}
# stdcall は 32bit のみ意味を持つ(x64 では無視)。local ffi = require("ffi")
ffi.cdef[[
int32_t DRMEncrypt(
uint32_t hCryptoProvider,
uint32_t iPosition,
uint32_t cNumInBytes,
uint8_t* pbInData,
uint32_t* pcNumOutBytes,
uint8_t* pbOutData);
]]
local msdrm = ffi.load("msdrm")
-- msdrm.DRMEncrypt(hCryptoProvider, iPosition, cNumInBytes, pbInData, pcNumOutBytes, pbOutData)
-- hCryptoProvider : DWORD
-- iPosition : DWORD
-- cNumInBytes : DWORD
-- pbInData : BYTE* in/out
-- pcNumOutBytes : DWORD* in/out
-- pbOutData : BYTE* in/out
-- 構造体/GUIDへのポインタは cdef が通るよう void* で表記(実型は各引数コメント参照)。値渡し構造体・enum は対応する typedef を cdef に追加すること。const koffi = require('koffi');
const lib = koffi.load('msdrm.dll');
const DRMEncrypt = lib.func('__stdcall', 'DRMEncrypt', 'int32_t', ['uint32_t', 'uint32_t', 'uint32_t', 'uint8_t *', 'uint32_t *', 'uint8_t *']);
// DRMEncrypt(hCryptoProvider, iPosition, cNumInBytes, pbInData, pcNumOutBytes, pbOutData)
// hCryptoProvider : DWORD -> 'uint32_t'
// iPosition : DWORD -> 'uint32_t'
// cNumInBytes : DWORD -> 'uint32_t'
// pbInData : BYTE* in/out -> 'uint8_t *'
// pcNumOutBytes : DWORD* in/out -> 'uint32_t *'
// pbOutData : BYTE* in/out -> 'uint8_t *'
// 出力ポインタは koffi.out(...) で包む。構造体は koffi.struct で定義。const lib = Deno.dlopen("msdrm.dll", {
DRMEncrypt: { parameters: ["u32", "u32", "u32", "pointer", "pointer", "pointer"], result: "i32" },
});
// lib.symbols.DRMEncrypt(hCryptoProvider, iPosition, cNumInBytes, pbInData, pcNumOutBytes, pbOutData)
// hCryptoProvider : DWORD -> "u32"
// iPosition : DWORD -> "u32"
// cNumInBytes : DWORD -> "u32"
// pbInData : BYTE* in/out -> "pointer"
// pcNumOutBytes : DWORD* in/out -> "pointer"
// pbOutData : BYTE* in/out -> "pointer"
// 文字列引数は "buffer"(NUL 終端のバイト列を Uint8Array で渡す)。
// 値渡し構造体は { struct: [ ...field types... ] } を使用。<?php
$ffi = FFI::cdef(<<<C
int32_t DRMEncrypt(
uint32_t hCryptoProvider,
uint32_t iPosition,
uint32_t cNumInBytes,
uint8_t* pbInData,
uint32_t* pcNumOutBytes,
uint8_t* pbOutData);
C, "msdrm.dll");
// $ffi->DRMEncrypt(hCryptoProvider, iPosition, cNumInBytes, pbInData, pcNumOutBytes, pbOutData);
// hCryptoProvider : DWORD
// iPosition : DWORD
// cNumInBytes : DWORD
// pbInData : BYTE* in/out
// pcNumOutBytes : DWORD* in/out
// pbOutData : BYTE* in/out
// 構造体/GUIDへのポインタは cdef が通るよう void* で表記(実型は各引数コメント参照)。値渡し構造体・enum は対応する typedef を cdef に追加すること。
// WINAPI(stdcall): x64 では呼出規約が統一されるため問題なし。x86 では __stdcall 対応のラッパが必要な場合あり。import com.sun.jna.*;
import com.sun.jna.ptr.*;
import com.sun.jna.win32.StdCallLibrary;
import com.sun.jna.win32.W32APIOptions;
public interface Msdrm extends StdCallLibrary {
Msdrm INSTANCE = Native.load("msdrm", Msdrm.class);
int DRMEncrypt(
int hCryptoProvider, // DWORD
int iPosition, // DWORD
int cNumInBytes, // DWORD
byte[] pbInData, // BYTE* in/out
IntByReference pcNumOutBytes, // DWORD* in/out
byte[] pbOutData // BYTE* in/out
);
}@[Link("msdrm")]
lib Libmsdrm
fun DRMEncrypt = DRMEncrypt(
hCryptoProvider : UInt32, # DWORD
iPosition : UInt32, # DWORD
cNumInBytes : UInt32, # DWORD
pbInData : UInt8*, # BYTE* in/out
pcNumOutBytes : UInt32*, # DWORD* in/out
pbOutData : UInt8* # BYTE* in/out
) : Int32
end
# 構造体/GUID/enum は lib 内に対応する型定義が必要。
# 呼出規約: x64 は規約統一のため OK。x86(32bit)は WINAPI=stdcall だが Crystal の fun に stdcall 付与構文がなく非対応。import 'dart:ffi';
import 'package:ffi/ffi.dart';
typedef DRMEncryptNative = Int32 Function(Uint32, Uint32, Uint32, Pointer<Uint8>, Pointer<Uint32>, Pointer<Uint8>);
typedef DRMEncryptDart = int Function(int, int, int, Pointer<Uint8>, Pointer<Uint32>, Pointer<Uint8>);
final DRMEncrypt = DynamicLibrary.open('msdrm.dll')
.lookupFunction<DRMEncryptNative, DRMEncryptDart>('DRMEncrypt');
// hCryptoProvider : DWORD -> Uint32
// iPosition : DWORD -> Uint32
// cNumInBytes : DWORD -> Uint32
// pbInData : BYTE* in/out -> Pointer<Uint8>
// pcNumOutBytes : DWORD* in/out -> Pointer<Uint32>
// pbOutData : BYTE* in/out -> Pointer<Uint8>
// 文字列は package:ffi の "...".toNativeUtf16()/toNativeUtf8() で変換。{$mode objfpc}{$H+}
function DRMEncrypt(
hCryptoProvider: DWORD; // DWORD
iPosition: DWORD; // DWORD
cNumInBytes: DWORD; // DWORD
pbInData: Pointer; // BYTE* in/out
pcNumOutBytes: Pointer; // DWORD* in/out
pbOutData: Pointer // BYTE* in/out
): Integer; stdcall;
external 'msdrm.dll' name 'DRMEncrypt';import Foreign
import Foreign.C.Types
import Foreign.C.String
foreign import stdcall safe "DRMEncrypt"
c_DRMEncrypt :: Word32 -> Word32 -> Word32 -> Ptr Word8 -> Ptr Word32 -> Ptr Word8 -> IO Int32
-- hCryptoProvider : DWORD -> Word32
-- iPosition : DWORD -> Word32
-- cNumInBytes : DWORD -> Word32
-- pbInData : BYTE* in/out -> Ptr Word8
-- pcNumOutBytes : DWORD* in/out -> Ptr Word32
-- pbOutData : BYTE* in/out -> Ptr Word8
-- 要 GHC(Windows)。stdcall は x64 では ccall として扱われる。ブロックする API は safe 呼び出し推奨。open Ctypes
open Foreign
let drmencrypt =
foreign "DRMEncrypt"
(uint32_t @-> uint32_t @-> uint32_t @-> (ptr uint8_t) @-> (ptr uint32_t) @-> (ptr uint8_t) @-> returning int32_t)
(* hCryptoProvider : DWORD -> uint32_t *)
(* iPosition : DWORD -> uint32_t *)
(* cNumInBytes : DWORD -> uint32_t *)
(* pbInData : BYTE* in/out -> (ptr uint8_t) *)
(* pcNumOutBytes : DWORD* in/out -> (ptr uint32_t) *)
(* pbOutData : BYTE* in/out -> (ptr uint8_t) *)
(* foreign は cdecl 前提。x64 Windows では WINAPI と一致。構造体は ctypes structure を定義のこと。 *)(cffi:define-foreign-library msdrm (t "msdrm.dll"))
(cffi:use-foreign-library msdrm)
(cffi:defcfun ("DRMEncrypt" drmencrypt :convention :stdcall) :int32
(h-crypto-provider :uint32) ; DWORD
(i-position :uint32) ; DWORD
(c-num-in-bytes :uint32) ; DWORD
(pb-in-data :pointer) ; BYTE* in/out
(pc-num-out-bytes :pointer) ; DWORD* in/out
(pb-out-data :pointer)) ; BYTE* in/out
; isize/usize(INT_PTR/SIZE_T)は x64 前提で :int64/:uint64。x86 では :int32/:uint32。use Win32::API;
my $DRMEncrypt = Win32::API::More->new('msdrm',
'int DRMEncrypt(DWORD hCryptoProvider, DWORD iPosition, DWORD cNumInBytes, LPVOID pbInData, LPVOID pcNumOutBytes, LPVOID pbOutData)');
# my $ret = $DRMEncrypt->Call($hCryptoProvider, $iPosition, $cNumInBytes, $pbInData, $pcNumOutBytes, $pbOutData);
# hCryptoProvider : DWORD -> DWORD
# iPosition : DWORD -> DWORD
# cNumInBytes : DWORD -> DWORD
# pbInData : BYTE* in/out -> LPVOID
# pcNumOutBytes : DWORD* in/out -> LPVOID
# pbOutData : BYTE* in/out -> LPVOID
# 値渡し構造体は pack() した文字列、または Win32::API::Struct を使用。関連項目
公式の関連項目
- f DRMCreateEnablingBitsEncryptor — バインドライセンスから暗号化用のビット処理器を作成する。
- f DRMDecrypt — RMSの暗号化プロバイダーでデータを復号する。