Win32 API 日本語リファレンス
ホームMedia.DeviceManager › IWMDMOperation

IWMDMOperation

COM
IID1dcb3a0b-33ed-11d3-8470-00c04f79dbc0継承元IUnknown自前メソッド開始 vtbl3

公式ドキュメント

このオプションの、アプリケーション側で実装する IWMDMOperation インターフェイスを使用すると、ファイル転送中にコンピューターとの間でデータをどのように読み取り・書き込みするかをアプリケーション側で制御できます。

メソッド 10

vtbl = vtable インデックス(0始まり)。HSP等からCOMメソッドをインデックス指定で呼ぶ際に使用します。0〜2 は IUnknown。

vtbl 3 HRESULT BeginRead()

BeginRead メソッドは、「デバイスからの読み取り」動作が開始されることを示します。Windows Media Device Manager は、アプリケーションが IWMDMStorageControl::Read を呼び出し、この IWMDMOperation インターフェイスを渡した場合にのみ、このメソッドを呼び出します。

戻り値

アプリケーションは次のいずれかの HRESULT 値を返してください。

戻り値 説明
S_OK
読み取り操作を継続します。
WMDM_E_USER_CANCELLED
読み取り操作を完了せずにキャンセルします。
E_FAIL
不明なエラーが発生したため、読み取り操作を完了せずにキャンセルします。

解説(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;
}
vtbl 4 HRESULT BeginWrite()

BeginWrite メソッドは、「デバイスへの書き込み」動作が開始されることを示します。Windows Media Device Manager は、アプリケーションが IWMDMStorageControl/2/3::Insert/2/3 を呼び出し、このインターフェイスを渡した場合にのみ、このメソッドを呼び出します。

戻り値

アプリケーションは次のいずれかの HRESULT 値を返してください。

戻り値 説明
S_OK
読み取り操作を継続します。
WMDM_E_USER_CANCELLED
読み取り操作を完了せずにキャンセルします。
E_FAIL
不明なエラーが発生したため、読み取り操作を完了せずにキャンセルします。

解説(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;
}
vtbl 5 HRESULT GetObjectName(LPWSTR pwszName, DWORD nMaxChars)

Windows Media Device Manager は、オブジェクトをデバイスに書き込む前に、デバイス上で付けるべき名前を知るために GetObjectName を呼び出します。

pwszNameLPWSTRoutオブジェクト名を格納する、null 終端のワイド文字列へのポインターです。必要に応じてファイル拡張子を含めてください。このバッファーの確保と解放は Windows Media Device Manager が行います。nMaxChars には、終端の null 文字を含む最大文字数を指定します。
nMaxCharsDWORDinpwszName の文字数を指定する整数値です(終端の null 文字を含みます)。

戻り値

アプリケーションは次のいずれかの HRESULT 値を返してください。

戻り値 説明
S_OK
読み取り操作を継続します。
WMDM_E_USER_CANCELLED
読み取り操作を完了せずにキャンセルします。
E_FAIL
不明なエラーが発生したため、読み取り操作を完了せずにキャンセルします。

解説(Remarks)

このメソッドは、アプリケーションが Insert メソッドのパラメーターとして名前を指定しなかった場合にのみ呼び出されます。

vtbl 6 HRESULT SetObjectName(LPWSTR pwszName, DWORD nMaxChars)

SetObjectName メソッドは、読み取りまたは書き込み対象のコンテンツに名前を割り当てます。このメソッドは現在、Windows Media Device Manager からは呼び出されません。

pwszNameLPWSTRinオブジェクト名を指定する、null 終端のワイド文字列へのポインターです。
nMaxCharsDWORDinこの文字列が保持できる最大文字数を指定する整数値です。

戻り値

アプリケーションは次のいずれかの HRESULT 値を返してください。

戻り値 説明
S_OK
読み取り操作を継続します。
WMDM_E_USER_CANCELLED
読み取り操作を完了せずにキャンセルします。
E_FAIL
不明なエラーが発生したため、読み取り操作を完了せずにキャンセルします。

解説(Remarks)

このメソッドは、BeginRead が呼び出された後に呼び出されます。

vtbl 7 HRESULT GetObjectAttributes(DWORD* pdwAttributes, WAVEFORMATEX* pFormat)

GetObjectAttributes メソッドを使用すると、デバイスに書き込まれるオブジェクトの属性をアプリケーション側で指定できます。Windows Media Device Manager は、ファイルをデバイスに書き込む前に、そのファイルの属性を取得するためにこのメソッドを呼び出します。

pdwAttributesDWORD*outIWMDMStorage::GetAttributes メソッドで定義されている属性を指定する DWORD へのポインターです。
pFormatWAVEFORMATEX*inoutoptionalオーディオデータ属性を持つファイルのオーディオ形式を指定する _WAVEFORMATEX 構造体へのポインターです。

戻り値

アプリケーションは次のいずれかの HRESULT 値を返してください。

戻り値 説明
S_OK
読み取り操作を継続します。
WMDM_E_USER_CANCELLED
読み取り操作を完了せずにキャンセルします。
E_FAIL
不明なエラーが発生したため、読み取り操作を完了せずにキャンセルします。

解説(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;
}
vtbl 8 HRESULT SetObjectAttributes(DWORD dwAttributes, WAVEFORMATEX* pFormat)

SetObjectAttributes メソッドはファイル属性を指定します。このメソッドは現在、Windows Media Device Manager からは呼び出されません。

dwAttributesDWORDinIWMDMStorage::SetAttributes メソッドで定義されているオブジェクト属性を指定する DWORD です。
pFormatWAVEFORMATEX*inoptionalオーディオデータ属性を持つファイルの形式を指定する _WAVEFORMATEX 構造体へのポインターです。ファイルにオーディオデータが含まれる場合は、このパラメーターを設定する必要があります。

戻り値

アプリケーションは次のいずれかの HRESULT 値を返してください。

戻り値 説明
S_OK
読み取り操作を継続します。
WMDM_E_USER_CANCELLED
読み取り操作を完了せずにキャンセルします。
E_FAIL
不明なエラーが発生したため、読み取り操作を完了せずにキャンセルします。

解説(Remarks)

オーディオ属性には、サンプルレート(毎秒のサンプル数)や1 サンプルあたりのバイト数などが含まれます。

vtbl 9 HRESULT GetObjectTotalSize(DWORD* pdwSize, DWORD* pdwSizeHigh)

Windows Media Device Manager は、ファイルをデバイスに書き込む前に、オブジェクト全体のサイズ(バイト単位)を取得するために GetObjectTotalSize を呼び出します。

pdwSizeDWORD*out戻り値として、オブジェクトサイズ(バイト単位)の下位ビットを格納する DWORD へのポインターです。
pdwSizeHighDWORD*out戻り値として、オブジェクトサイズ(バイト単位)の上位ビットを格納する DWORD へのポインターです。

戻り値

アプリケーションは次のいずれかの HRESULT 値を返してください。

戻り値 説明
S_OK
読み取り操作を継続します。
WMDM_E_USER_CANCELLED
読み取り操作を完了せずにキャンセルします。
E_FAIL
不明なエラーが発生したため、読み取り操作を完了せずにキャンセルします。

解説(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;
}
vtbl 10 HRESULT SetObjectTotalSize(DWORD dwSize, DWORD dwSizeHigh)

SetObjectTotalSize メソッドは、オブジェクト全体のサイズ(バイト単位)を割り当てます。このメソッドは現在、Windows Media Device Manager からは呼び出されません。

dwSizeDWORDinオブジェクトサイズ(バイト単位)の下位ビットを指定する DWORD です。
dwSizeHighDWORDinオブジェクトサイズ(バイト単位)の上位ビットを指定する DWORD です。

戻り値

アプリケーションは次のいずれかの HRESULT 値を返してください。

戻り値 説明
S_OK
読み取り操作を継続します。
WMDM_E_USER_CANCELLED
読み取り操作を完了せずにキャンセルします。
E_FAIL
不明なエラーが発生したため、読み取り操作を完了せずにキャンセルします。

解説(Remarks)

このメソッドは、SetObjectAttributes の後に呼び出されます。

vtbl 11 HRESULT TransferObjectData(BYTE* pData, DWORD* pdwSize, BYTE* abMac)

TransferObjectData メソッドは、アプリケーションがコンピューターとの間でデータブロックを転送できるようにするために呼び出されます。

pDataBYTE*inout

データを格納するバッファーへのポインターです。このバッファーの確保と解放は常に Windows Media Device Manager が行います。アプリケーション側でこのバッファーを確保・解放してはいけません。

BeginRead[in] デバイスからの読み取り時は、CSecureChannelClient::DecryptParam メソッドで復号化する必要がある受信データです。アプリケーションがこのバッファーを解放する必要はありません。

BeginWrite[in, out] デバイスへの書き込み時、入力時には Windows Media Device Manager が確保した pdwSize バイトのメモリバッファーです。アプリケーションは、CSecureChannelClient::EncryptParam メソッドで暗号化したデータをこのバッファーに格納してください。

pdwSizeDWORD*inout

転送バッファーのサイズを指定する DWORD へのポインターです。

BeginRead[in, out] 入力時は pData 内の受信データのサイズ、出力時はアプリケーションが実際に読み取ったデータ量です。

BeginWrite 入力時は pData バッファーのサイズ、出力時は実際に送信されたデータのサイズです。

abMacBYTE*inout

このメソッドのパラメーターデータに対するメッセージ認証コード(MAC)を指定するバイト配列です。

BeginRead[in] pDatapdwSize から生成された MAC です。アプリケーションは pData を復号化した後にこれを検証し、データが改ざんされていないことを確認してください。

BeginWrite[out] pData を暗号化する前に pDatapdwSize から生成した MAC です。

戻り値

アプリケーションは次のいずれかの HRESULT 値を返してください。

戻り値 説明
S_OK
読み取り操作を継続します。
WMDM_E_USER_CANCELLED
読み取り操作を完了せずにキャンセルします。
E_FAIL
不明なエラーが発生したため、読み取り操作を完了せずにキャンセルします。

解説(Remarks)

アプリケーションは、このメソッドの呼び出し直前に BeginReadBeginWrite のどちらが呼び出されたかを監視することで、デバイスからデータを読み取っているのか、デバイスに書き込んでいるのかを判別できます。

次の 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;
}
vtbl 12 HRESULT End(HRESULT* phCompletionCode, IUnknown* pNewObject)

End メソッドは、読み取りまたは書き込み操作が、成否にかかわらず終了したことを示し、完了コードを返します。

phCompletionCodeHRESULT*in操作の完了コードです。
pNewObjectIUnknown*inoptionalデバイスへ送信する場合は、デバイスに送信された新しいオブジェクトを表す新規の IWMDMStorage オブジェクトへのポインターです。デバイスから読み取る場合は、デバイスから読み取られた IWMDMStorage オブジェクトへのポインターです。

戻り値

このメソッドは HRESULT を返します。Windows Media Device Manager のすべてのインターフェイスメソッドは、次のいずれかの種類のエラーコードを返す可能性があります。

発生し得るエラーコードの詳細な一覧については、Error Codes を参照してください。

解説(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 の Win32 API ドキュメント(MicrosoftDocs/sdk-api)を日本語に翻訳・改変したものです。© Microsoft Corporation. CC BY 4.0 で提供。
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 指定が可能。