IWMDMOperation
COM公式ドキュメント
このオプションの、アプリケーション側で実装する IWMDMOperation インターフェイスを使用すると、ファイル転送中にコンピューターとの間でデータをどのように読み取り・書き込みするかをアプリケーション側で制御できます。
メソッド 10
vtbl = vtable インデックス(0始まり)。HSP等からCOMメソッドをインデックス指定で呼ぶ際に使用します。0〜2 は IUnknown。
BeginRead メソッドは、「デバイスからの読み取り」動作が開始されることを示します。Windows Media Device Manager は、アプリケーションが IWMDMStorageControl::Read を呼び出し、この IWMDMOperation インターフェイスを渡した場合にのみ、このメソッドを呼び出します。
戻り値
アプリケーションは次のいずれかの HRESULT 値を返してください。
| 戻り値 | 説明 |
|---|---|
| 読み取り操作を継続します。 | |
| 読み取り操作を完了せずにキャンセルします。 | |
| 不明なエラーが発生したため、読み取り操作を完了せずにキャンセルします。 |
解説(Remarks)
このメソッドは、Windows Media Device Manager が IWMDMOperation::TransferObjectData を呼び出す直前に呼び出されます。
例
次の C++ コード例は、BeginRead メソッドを実装し、デバイスからの読み取り動作が開始される際にメッセージを出力します。
HRESULT BeginRead()
{
// TODO: Display the message: "IWMDMOperation event--BeginRead."
// If the global handle of the source file is uninitialized, fail.
if (m_File == INVALID_HANDLE_VALUE)
return E_FAIL;
// Global status to let TransferObjectData know what kind of
// operation is happening.
m_OperationStatus = OPERATION_READ;
return S_OK;
}
BeginWrite メソッドは、「デバイスへの書き込み」動作が開始されることを示します。Windows Media Device Manager は、アプリケーションが IWMDMStorageControl/2/3::Insert/2/3 を呼び出し、このインターフェイスを渡した場合にのみ、このメソッドを呼び出します。
戻り値
アプリケーションは次のいずれかの HRESULT 値を返してください。
| 戻り値 | 説明 |
|---|---|
| 読み取り操作を継続します。 | |
| 読み取り操作を完了せずにキャンセルします。 | |
| 不明なエラーが発生したため、読み取り操作を完了せずにキャンセルします。 |
解説(Remarks)
このメソッドは、Windows Media Device Manager がデバイスへのデータ書き込みを開始するために IWMDMOperation::TransferObjectData を呼び出す直前に呼び出されます。
例
次の C++ コード例は、BeginWrite メソッドを実装し、デバイスへの書き込み動作が開始される際にメッセージを出力します。
HRESULT BeginWrite()
{
// TODO: Display the message: "IWMDMOperation event--BeginWrite."
// If the global handle of the destination file is uninitialized, fail.
if (m_File == INVALID_HANDLE_VALUE)
return E_FAIL;
// Global status to let TransferObjectData know what kind of
// operation is happening.
m_OperationStatus = OPERATION_WRITE;
return S_OK;
}
Windows Media Device Manager は、オブジェクトをデバイスに書き込む前に、デバイス上で付けるべき名前を知るために GetObjectName を呼び出します。
| pwszName | LPWSTR | out | オブジェクト名を格納する、null 終端のワイド文字列へのポインターです。必要に応じてファイル拡張子を含めてください。このバッファーの確保と解放は Windows Media Device Manager が行います。nMaxChars には、終端の null 文字を含む最大文字数を指定します。 |
| nMaxChars | DWORD | in | pwszName の文字数を指定する整数値です(終端の null 文字を含みます)。 |
戻り値
アプリケーションは次のいずれかの HRESULT 値を返してください。
| 戻り値 | 説明 |
|---|---|
| 読み取り操作を継続します。 | |
| 読み取り操作を完了せずにキャンセルします。 | |
| 不明なエラーが発生したため、読み取り操作を完了せずにキャンセルします。 |
解説(Remarks)
このメソッドは、アプリケーションが Insert メソッドのパラメーターとして名前を指定しなかった場合にのみ呼び出されます。
SetObjectName メソッドは、読み取りまたは書き込み対象のコンテンツに名前を割り当てます。このメソッドは現在、Windows Media Device Manager からは呼び出されません。
| pwszName | LPWSTR | in | オブジェクト名を指定する、null 終端のワイド文字列へのポインターです。 |
| nMaxChars | DWORD | in | この文字列が保持できる最大文字数を指定する整数値です。 |
戻り値
アプリケーションは次のいずれかの HRESULT 値を返してください。
| 戻り値 | 説明 |
|---|---|
| 読み取り操作を継続します。 | |
| 読み取り操作を完了せずにキャンセルします。 | |
| 不明なエラーが発生したため、読み取り操作を完了せずにキャンセルします。 |
解説(Remarks)
このメソッドは、BeginRead が呼び出された後に呼び出されます。
GetObjectAttributes メソッドを使用すると、デバイスに書き込まれるオブジェクトの属性をアプリケーション側で指定できます。Windows Media Device Manager は、ファイルをデバイスに書き込む前に、そのファイルの属性を取得するためにこのメソッドを呼び出します。
| pdwAttributes | DWORD* | out | IWMDMStorage::GetAttributes メソッドで定義されている属性を指定する DWORD へのポインターです。 |
| pFormat | WAVEFORMATEX* | inoutoptional | オーディオデータ属性を持つファイルのオーディオ形式を指定する _WAVEFORMATEX 構造体へのポインターです。 |
戻り値
アプリケーションは次のいずれかの HRESULT 値を返してください。
| 戻り値 | 説明 |
|---|---|
| 読み取り操作を継続します。 | |
| 読み取り操作を完了せずにキャンセルします。 | |
| 不明なエラーが発生したため、読み取り操作を完了せずにキャンセルします。 |
解説(Remarks)
デバイスへデータを転送する際は、転送を最適化するためにオブジェクト属性を提供してください。
例
次の C++ コードは GetObjectAttributes メソッドを実装した例です。読み取り対象のファイル(m_File)がファイルかフォルダーかを判定し、それに応じて返す属性を設定します。
HRESULT GetObjectAttributes(DWORD* pdwAttributes, _WAVEFORMATEX* pFormat)
{
// TODO: Display the message: IWMDMOperation event--GetObjectAttributes.
*pdwAttributes = WMDM_FILE_ATTR_FILE |
WMDM_STORAGE_ATTR_REMOVABLE |
WMDM_FILE_ATTR_AUDIO;
BY_HANDLE_FILE_INFORMATION fileInformation;
if (GetFileInformationByHandle(m_File, &fileInformation))
{
if (fileInformation.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
*pdwAttributes |= WMDM_FILE_ATTR_FOLDER;
else
*pdwAttributes |= WMDM_FILE_ATTR_FILE;
if (fileInformation.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
*pdwAttributes |= FILE_ATTRIBUTE_READONLY;
}
return S_OK;
}
SetObjectAttributes メソッドはファイル属性を指定します。このメソッドは現在、Windows Media Device Manager からは呼び出されません。
| dwAttributes | DWORD | in | IWMDMStorage::SetAttributes メソッドで定義されているオブジェクト属性を指定する DWORD です。 |
| pFormat | WAVEFORMATEX* | inoptional | オーディオデータ属性を持つファイルの形式を指定する _WAVEFORMATEX 構造体へのポインターです。ファイルにオーディオデータが含まれる場合は、このパラメーターを設定する必要があります。 |
戻り値
アプリケーションは次のいずれかの HRESULT 値を返してください。
| 戻り値 | 説明 |
|---|---|
| 読み取り操作を継続します。 | |
| 読み取り操作を完了せずにキャンセルします。 | |
| 不明なエラーが発生したため、読み取り操作を完了せずにキャンセルします。 |
解説(Remarks)
オーディオ属性には、サンプルレート(毎秒のサンプル数)や1 サンプルあたりのバイト数などが含まれます。
Windows Media Device Manager は、ファイルをデバイスに書き込む前に、オブジェクト全体のサイズ(バイト単位)を取得するために GetObjectTotalSize を呼び出します。
| pdwSize | DWORD* | out | 戻り値として、オブジェクトサイズ(バイト単位)の下位ビットを格納する DWORD へのポインターです。 |
| pdwSizeHigh | DWORD* | out | 戻り値として、オブジェクトサイズ(バイト単位)の上位ビットを格納する DWORD へのポインターです。 |
戻り値
アプリケーションは次のいずれかの HRESULT 値を返してください。
| 戻り値 | 説明 |
|---|---|
| 読み取り操作を継続します。 | |
| 読み取り操作を完了せずにキャンセルします。 | |
| 不明なエラーが発生したため、読み取り操作を完了せずにキャンセルします。 |
解説(Remarks)
このメソッドは、GetObjectAttributes メソッドが呼び出された後に呼び出されます。転送時には、このインターフェイスを実装するオブジェクトに、送信されるコンテンツ全体のサイズが渡されます。
例
次の C++ コードは GetObjectTotalSize を実装した例です。Win32 関数 GetFileInformationByHandle を使用して、デバイスに書き込まれようとしているファイル(m_File)のサイズを取得し、その値を返します。
// About to start writing to the device.
HRESULT GetObjectTotalSize(DWORD* pdwSize, DWORD* pdwSizeHigh)
{
BY_HANDLE_FILE_INFORMATION fileInfo;
GetFileInformationByHandle(
m_File,
&fileInfo);
*pdwSize = fileInfo.nFileSizeLow;
*pdwSizeHigh = fileInfo.nFileSizeHigh;
// TODO: Display the message: "IWMDMOperation event--GetObjectTotalSize."
return S_OK;
}
SetObjectTotalSize メソッドは、オブジェクト全体のサイズ(バイト単位)を割り当てます。このメソッドは現在、Windows Media Device Manager からは呼び出されません。
| dwSize | DWORD | in | オブジェクトサイズ(バイト単位)の下位ビットを指定する DWORD です。 |
| dwSizeHigh | DWORD | in | オブジェクトサイズ(バイト単位)の上位ビットを指定する DWORD です。 |
戻り値
アプリケーションは次のいずれかの HRESULT 値を返してください。
| 戻り値 | 説明 |
|---|---|
| 読み取り操作を継続します。 | |
| 読み取り操作を完了せずにキャンセルします。 | |
| 不明なエラーが発生したため、読み取り操作を完了せずにキャンセルします。 |
解説(Remarks)
このメソッドは、SetObjectAttributes の後に呼び出されます。
TransferObjectData メソッドは、アプリケーションがコンピューターとの間でデータブロックを転送できるようにするために呼び出されます。
| pData | BYTE* | inout | データを格納するバッファーへのポインターです。このバッファーの確保と解放は常に Windows Media Device Manager が行います。アプリケーション側でこのバッファーを確保・解放してはいけません。 BeginRead[in] デバイスからの読み取り時は、CSecureChannelClient::DecryptParam メソッドで復号化する必要がある受信データです。アプリケーションがこのバッファーを解放する必要はありません。 BeginWrite[in, out] デバイスへの書き込み時、入力時には Windows Media Device Manager が確保した pdwSize バイトのメモリバッファーです。アプリケーションは、CSecureChannelClient::EncryptParam メソッドで暗号化したデータをこのバッファーに格納してください。 |
| pdwSize | DWORD* | inout | 転送バッファーのサイズを指定する DWORD へのポインターです。 BeginRead[in, out] 入力時は pData 内の受信データのサイズ、出力時はアプリケーションが実際に読み取ったデータ量です。 BeginWrite 入力時は pData バッファーのサイズ、出力時は実際に送信されたデータのサイズです。 |
| abMac | BYTE* | inout | このメソッドのパラメーターデータに対するメッセージ認証コード(MAC)を指定するバイト配列です。 BeginRead[in] pData と pdwSize から生成された MAC です。アプリケーションは pData を復号化した後にこれを検証し、データが改ざんされていないことを確認してください。 BeginWrite[out] pData を暗号化する前に pData と pdwSize から生成した MAC です。 |
戻り値
アプリケーションは次のいずれかの HRESULT 値を返してください。
| 戻り値 | 説明 |
|---|---|
| 読み取り操作を継続します。 | |
| 読み取り操作を完了せずにキャンセルします。 | |
| 不明なエラーが発生したため、読み取り操作を完了せずにキャンセルします。 |
解説(Remarks)
アプリケーションは、このメソッドの呼び出し直前に BeginRead と BeginWrite のどちらが呼び出されたかを監視することで、デバイスからデータを読み取っているのか、デバイスに書き込んでいるのかを判別できます。
例
次の C++ コードは、アプリケーションがファイル転送を自分で処理するために TransferObjectData を実装する例です。このコードは、デバイスからのデータ読み取りとデバイスへのデータ書き込みの両方を処理します。データの方向は、直前の BeginRead または BeginWrite の呼び出しで設定されるメンバー変数 m_OperationStatus で示されます。
HRESULT TransferObjectData(BYTE* pData, DWORD* pdwSize, BYTE* pMac)
{
HRESULT hr = S_OK;
// Verify parameters.
if (pData == NULL || pdwSize == NULL || pMac == NULL || m_File == INVALID_HANDLE_VALUE)
{
// TODO: Display the message: "Invalid argument in SetObjectTotalSize."
return E_INVALIDARG;
}
if ((m_OperationStatus != OPERATION_READ) && (m_OperationStatus != OPERATION_WRITE))
{
// TODO: Display the message: "Unable to determine direction of data transfer."
return E_FAIL;
}
//////////////////////////////////////////////////////////////////////////
// Sending data to the device.
//////////////////////////////////////////////////////////////////////////
if (m_OperationStatus == OPERATION_WRITE)
{
DWORD dwReadLen;
// The SAC is used to encrypt the data sent to the device.
if (m_pSAC == NULL)
{
// TODO: Display the message: "SAC not initialized in TransferObjectData."
return E_FAIL;
}
// Read pdwSize bytes from the file into pData.
dwReadLen = *pdwSize;
if (ReadFile(m_File, pData, dwReadLen, pdwSize, NULL) == FALSE)
{
// TODO: Display the message: "Couldn't read the file in TransferObjectData."
return E_FAIL;
}
// If there is no more data, terminate the transfer.
if (*pdwSize == 0)
{
return S_FALSE;
}
// Create the MAC to return to Windows Media Device Manager.
HMAC hMAC;
hr = m_pSAC->MACInit(&hMAC);
hr = m_pSAC->MACUpdate(hMAC, (BYTE*)(pData), *pdwSize);
hr = m_pSAC->MACUpdate(hMAC, (BYTE*)(pdwSize), sizeof(DWORD));
hr = m_pSAC->MACFinal(hMAC, (BYTE*)pMac);
if (hr != S_OK) return E_FAIL;
// Encrypt the data to send to the service provider/device.
hr = m_pSAC->EncryptParam((BYTE*)(pData), *pdwSize);
if (hr != S_OK)
{
return E_FAIL;
}
}
//////////////////////////////////////////////////////////////////////////
// Receiving data from the device.
//////////////////////////////////////////////////////////////////////////
else
{
// Copy the data to a temporary file for decryption.
BYTE *pTmpData = new BYTE [*pdwSize];
if (pTmpData == NULL)
{
return E_OUTOFMEMORY;
}
memcpy(pTmpData, pData, *pdwSize);
// Decrypt the pData Parameter
hr = m_pSAC->DecryptParam(pTmpData, *pdwSize);
// Verify the MAC of the decrypted data.
HMAC hMAC;
BYTE pTestMac[WMDM_MAC_LENGTH];
hr = m_pSAC->MACInit(&hMAC);
hr = m_pSAC->MACUpdate(hMAC, (BYTE*)(pTmpData), *pdwSize);
hr = m_pSAC->MACUpdate(hMAC, (BYTE*)(pdwSize), sizeof(*pdwSize));
hr = m_pSAC->MACFinal(hMAC, pTestMac);
if ((memcmp(pMac, pTestMac, WMDM_MAC_LENGTH) != 0) || (hr != S_OK))
{
delete [] pTmpData;
return WMDM_E_MAC_CHECK_FAILED;
}
// Write the data to file, and record the amount of data written.
DWORD dwWritten = 0;
if (WriteFile(m_File,pTmpData,*pdwSize,&dwWritten,NULL))
{
hr = S_OK;
*pdwSize = dwWritten;
}
else
{
hr = HRESULT_FROM_WIN32(GetLastError());
}
if (pTmpData)
{
delete [] pTmpData;
}
}
return hr;
}
End メソッドは、読み取りまたは書き込み操作が、成否にかかわらず終了したことを示し、完了コードを返します。
| phCompletionCode | HRESULT* | in | 操作の完了コードです。 |
| pNewObject | IUnknown* | inoptional | デバイスへ送信する場合は、デバイスに送信された新しいオブジェクトを表す新規の IWMDMStorage オブジェクトへのポインターです。デバイスから読み取る場合は、デバイスから読み取られた IWMDMStorage オブジェクトへのポインターです。 |
戻り値
このメソッドは HRESULT を返します。Windows Media Device Manager のすべてのインターフェイスメソッドは、次のいずれかの種類のエラーコードを返す可能性があります。
- 標準的な COM エラーコード
- HRESULT 値に変換された Windows エラーコード
- Windows Media Device Manager のエラーコード
解説(Remarks)
End メソッドは転送の成否にかかわらず呼び出され、最後に呼び出される IWMDMOperation メソッドです。このメソッドは、読み取りまたは書き込み操作で必要となったすべてのファイルハンドルやオブジェクトを閉じるようアプリケーションに通知する目的で利用できます。
例
次の C++ コードは、読み取りまたは書き込み動作の後にグローバルなファイルハンドルを閉じ、メッセージを出力します。
HRESULT End(HRESULT* phCompletionCode, IUnknown* pNewObject)
{
// TODO: Display the message: "IWMDMOperation event--End."
// Close the file handle now that we're done with it.
if (m_File != INVALID_HANDLE_VALUE)
if (!CloseHandle(m_File))
// TODO: Display the message: "Couldn't close the file."
// Reset global status flag.
m_OperationStatus = OPERATION_UNINITIALIZED;
return S_OK;
}
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)
HSP用 COM定義
#usecom / #comfunc によるHSPのCOM呼び出し定義。数字は vtbl インデックス(0始まり)。クラスIDが無い場合 #usecom の末尾は "{}"、ある場合は "{CLSID}"。
#define global IID_IWMDMOperation "{1DCB3A0B-33ED-11D3-8470-00C04F79DBC0}" #usecom global IWMDMOperation IID_IWMDMOperation "{}" #comfunc global IWMDMOperation_BeginRead 3 #comfunc global IWMDMOperation_BeginWrite 4 #comfunc global IWMDMOperation_GetObjectName 5 var,int #comfunc global IWMDMOperation_SetObjectName 6 wstr,int #comfunc global IWMDMOperation_GetObjectAttributes 7 var,var #comfunc global IWMDMOperation_SetObjectAttributes 8 int,var #comfunc global IWMDMOperation_GetObjectTotalSize 9 var,var #comfunc global IWMDMOperation_SetObjectTotalSize 10 int,int #comfunc global IWMDMOperation_TransferObjectData 11 var,var,var #comfunc global IWMDMOperation_End 12 var,sptr ; ※数字は vtbl インデックス(0始まり)。0/1/2 は IUnknown(QueryInterface/AddRef/Release)。 ; ※このインターフェースは直接 CoCreateInstance するクラスIDが無いため "{}"(他メソッド/アクティベーションで取得)。 ; ※出力/バッファ引数は var(変数直渡し)。varptr 方式にも切替可。 ; ※ハンドル/void*等の不透明ポインタは IronHSP では intptr 指定が可能。#define global IID_IWMDMOperation "{1DCB3A0B-33ED-11D3-8470-00C04F79DBC0}" #usecom global IWMDMOperation IID_IWMDMOperation "{}" #comfunc global IWMDMOperation_BeginRead 3 #comfunc global IWMDMOperation_BeginWrite 4 #comfunc global IWMDMOperation_GetObjectName 5 sptr,int #comfunc global IWMDMOperation_SetObjectName 6 wstr,int #comfunc global IWMDMOperation_GetObjectAttributes 7 sptr,sptr #comfunc global IWMDMOperation_SetObjectAttributes 8 int,sptr #comfunc global IWMDMOperation_GetObjectTotalSize 9 sptr,sptr #comfunc global IWMDMOperation_SetObjectTotalSize 10 int,int #comfunc global IWMDMOperation_TransferObjectData 11 sptr,sptr,sptr #comfunc global IWMDMOperation_End 12 sptr,sptr ; ※数字は vtbl インデックス(0始まり)。0/1/2 は IUnknown(QueryInterface/AddRef/Release)。 ; ※このインターフェースは直接 CoCreateInstance するクラスIDが無いため "{}"(他メソッド/アクティベーションで取得)。 ; ※出力/バッファ引数はポインタ方式(token=sptr / 呼び出しは varptr(変数))。 ; ※ハンドル/void*等の不透明ポインタは IronHSP では intptr 指定が可能。