IWMDMStorage3
COM公式ドキュメント
IWMDMStorage3 インターフェイスは、メタデータを公開することで IWMDMStorage2 を拡張します。
メソッド 4
vtbl = vtable インデックス(0始まり)。HSP等からCOMメソッドをインデックス指定で呼ぶ際に使用します。0〜2 は IUnknown。
GetMetadata メソッドは、ストレージに関連付けられたメタデータを取得します。
| ppMetadata | IWMDMMetaData** | out | ストレージに関連付けられた IWMDMMetaData ポインターを受け取るポインター。呼び出し元は、使用を終えた時点でこのインターフェイスと割り当てられたすべての値を解放する (Release を呼び出す) 責任があります。詳細については、Discovering Device Format Capabilities の「Clearing allocated memory」を参照してください。 |
戻り値
このメソッドは HRESULT を返します。Windows Media Device Manager のすべてのインターフェイスメソッドは、次のいずれかの種類のエラーコードを返す可能性があります。
- 標準の COM エラーコード
- HRESULT 値に変換された Windows エラーコード
- Windows Media Device Manager のエラーコード
解説(Remarks)
このメソッドは、ストレージに関連付けられたすべてのメタデータを取得します。アプリケーションが特定のメタデータのみを必要とする場合は、IWMDMStorage4::GetSpecifiedMetadata を呼び出す方が効率的な場合があります。
Windows Portable Devices (WPD) デバイスからデータを取得する場合、データはバイナリ形式で返されます。アプリケーションは、実際のプロパティ値を得るためにこのデータを逆シリアル化する必要があります。
例
次の C++ 関数は、ストレージに関連付けられたすべてのメタデータを取得します。
// Function to print out all the metadata associated with a storage.
HRESULT CWMDMController::GetMetadata(IWMDMStorage *pStorage)
{
HRESULT hr = S_OK;
// A dummy loop to handle unrecoverable errors. When we hit an error we
// can't handle or don't like, we just use a 'break' statement.
// The custom BREAK_HR macro checks for failed HRESULT values and does this.
do
{
CComPtr<IWMDMStorage3> pStorage3;
CComPtr<IWMDMMetaData> pMetadata;
hr = pStorage->QueryInterface(__uuidof(IWMDMStorage3), (void**)&pStorage3);
BREAK_HR(hr, "Got an IWMDMStorage3 interface in GetMetadata.", "Couldn't get an IWMDMStorage3 interface in GetMetadata.");
hr = pStorage3->GetMetadata(&pMetadata);
BREAK_HR(hr, "Got an IWMDMMetaData interface in GetMetadata.", "Couldn't get an IWMDMMetaData interface in GetMetadata.");
//
// Loop through all metadata properties, and print out the value of each.
//
BYTE* value;
WMDM_TAG_DATATYPE type;
UINT len = 0;
UINT count = 0;
WCHAR* name;
// Get the number of metadata items.
hr = pMetadata->GetItemCount(&count);
BREAK_HR(hr, "Got a metadata count in GetMetadata.", "Couldn't get a metadata count in GetMetadata.");
for(;count > 0; count--)
{
// Get the metadata property by index.
WCHAR* name;
hr = pMetadata->QueryByIndex(count-1, &name, &type, &value, &len);
if (SUCCEEDED(hr))
{
// TODO: Display the property name.
CoTaskMemFree(name);
// Print out the value of the property, according to the value type.
switch (type)
{
case WMDM_TYPE_QWORD:
case WMDM_TYPE_DWORD:
case WMDM_TYPE_WORD:
// TODO: Display the value.
break;
case WMDM_TYPE_STRING:
// TODO: Display the value.
// Release the method-allocated property value memory.
if (SUCCEEDED(hr))
CoTaskMemFree(value);
break;
case WMDM_TYPE_BOOL:
// TODO: Display the value.
break;
case WMDM_TYPE_BINARY:
// TODO: Display the value.
break;
case WMDM_TYPE_DATE:
{
WMDMDATETIME *val = (WMDMDATETIME*)value;
// TODO: Display the month, day, and year.
}
break;
case WMDM_TYPE_GUID:
{
WCHAR strGuid[64];
StringFromGUID2(reinterpret_cast<GUID&>(value),(LPOLESTR)strGuid, 64);
// TODO: Display the GUID value.
}
break;
default:
// TODO: Display the message: "Could not understand the returned value type
}
}
else // Couldn't get the metadata property at index count - 1.
// TODO: Display the message:
// "Couldn't get a value for index "
// followed by the current index value.
}
// Now get a specific property by name.
// If this property isn't supported, the method returns E_INVALIDARG.
hr = pMetadata->QueryByName(g_wszWMDMFileName, &type, &value, &len);
if (hr == S_OK)
{
wstring wstr((wchar_t*)value, len / 2); // Create a string from the name.
// TODO: Display the file name.
CoTaskMemFree(value);
}
// See if file is DRM-protected.
hr = pMetadata->QueryByName(g_wszWMDMIsProtected, &type, &value, &len);
if (hr == S_OK)
{
// TODO: Display a message that the object is DRM protected.
}
}while(FALSE);// End of dummy loop.
// Clean up and return.
return hr;
}
SetMetadata メソッドは、ストレージにメタデータを設定します。
| pMetadata | IWMDMMetaData* | inoptional | オブジェクトに設定するメタデータを含む IWMDMMetaData ポインター。このインターフェイスを作成するには、CreateEmptyMetadataObject を呼び出します。 |
戻り値
このメソッドは HRESULT を返します。Windows Media Device Manager のすべてのインターフェイスメソッドは、次のいずれかの種類のエラーコードを返す可能性があります。
- 標準の COM エラーコード
- HRESULT 値に変換された Windows エラーコード
- Windows Media Device Manager のエラーコード
解説(Remarks)
ストレージ内に同じ名前の既存のプロパティがある場合は上書きされます。それ以外の既存のプロパティは変更も削除もされません。
Windows Portable Devices (WPD) デバイスにプロパティを設定する場合、アプリケーションは IPortableDeviceValues オブジェクトを作成し、そのコレクションに各プロパティを設定します。次に、アプリケーションはそのコレクションをバイナリラージオブジェクト (BLOB) にシリアル化します。データをシリアル化したら、g_wszWPDPassthroughPropertyValues メタデータ定数を使用して、pMetadata 引数で参照される IWMDMMetaData にそのデータを追加します。
例
次の C++ コードは、あらかじめストレージから取得しておいた (コードには示されていない) IWMDMMetaData インターフェイスを使用して、ストレージ (pStorage3) にメタデータとしてサブタイトルを追加します。
// Set metadata values on a storage.
WCHAR* station = L"Mysubtitle";
UINT numBytes = (wcslen(station) + 1) * sizeof(WCHAR); // WCHAR string is 2 * length of characters long
// plus the terminating null character.
hr = pMetadata->AddItem(WMDM_TYPE_STRING, g_wszWMDMMediaStationName, (BYTE*)station, numBytes) ;
BREAK_HR(hr, "Added a metadata value to the interface in TestUpdateMetadata.", "Couldn't add a metadata value to the interface in TestUpdateMetadata.");
// Add the metadata to the storage.
hr = pStorage3->SetMetadata(pMetadata);
BREAK_HR(hr, "Set metadata on the storage in TestUpdateMetadata.", "Couldn't set metadata on the storage in TestUpdateMetadata: " << hex << hr << dec);
CreateEmptyMetadataObject メソッドは、新しい IWMDMMetaData インターフェイスを作成します。このインターフェイスは、ストレージのメタデータプロパティを設定または取得するために使用します。
| ppMetadata | IWMDMMetaData** | out | 新しい IWMDMMetaData インターフェイスを受け取ります。呼び出し元は、使用を終えたらこのインターフェイスを解放する必要があります。 |
戻り値
このメソッドは HRESULT を返します。Windows Media Device Manager のすべてのインターフェイスメソッドは、次のいずれかの種類のエラーコードを返す可能性があります。
- 標準の COM エラーコード
- HRESULT 値に変換された Windows エラーコード
- Windows Media Device Manager のエラーコード
解説(Remarks)
作成されたメタデータインターフェイスは、それを作成したストレージに暗黙的に結び付けられるわけではありません。単なる空のメタデータコンテナーです。メタデータ値を設定または取得するには、このインターフェイスをメソッドに渡す必要があります。
例
次の C++ 関数は、ファイルをデバイスに送信します。転送の一環として、新しいストレージの種類を指定するために、ストレージにメタデータを追加する必要があります。
HRESULT mySendFile(LPCWSTR pwszFileName, IWMDMStorage* pStorage, IWMDMOperation* pOperation)
{
HRESULT hr = S_OK;
// A dummy loop to handle unrecoverable errors. When we hit an error we
// can't handle or don't like, we just use a 'break' statement.
// The custom BREAK_HR macro checks for failed HRESULT values and does this.
do
{
if (pwszFileName == NULL || pStorage == NULL)
{
BREAK_HR(E_POINTER,"","Bad pointer passed in.");
return E_POINTER;
}
// Make sure the destination is a folder.
DWORD attributes = 0;
_WAVEFORMATEX format;
hr = pStorage->GetAttributes(&attributes, &format);
if (!(attributes | WMDM_FILE_ATTR_FOLDER))
{
BREAK_HR(E_FAIL, "", "Storage submitted to mySendFile is not a folder.");
return E_FAIL;
}
// Transcode the file
hr = myTranscodeMethod(pwszFileName);
BREAK_HR(hr, "Couldn't transcode the file in mySendFile.", "Transcoded the file in mySendFile.");
//
// Let's set some metadata in the storage.
//
CComPtr<IWMDMStorage3> pStorage3;
hr = pStorage->QueryInterface(__uuidof(IWMDMStorage3), (void**)(&pStorage3));
BREAK_HR(hr, "Got an IWMDMStorage3 interface in mySendFile.","Couldn't get an IWMDMStorage3 in mySendFile.");
// First create the IWMDMMetaData interface.
IWMDMMetaData* pMetadata;
hr = pStorage3->CreateEmptyMetadataObject(&pMetadata);
BREAK_HR(hr,"Created an IWMDMMetaData interface in mySendFile.","Couldn't create an IWMDMMetaData interface in mySendFile.");
//
// Set the file format.
//
WMDM_FORMATCODE fileFormat = myGetWMDM_FORMATCODE(pwszFileName);
hr = pMetadata->AddItem(WMDM_TYPE_DWORD, g_wszWMDMFormatCode, (BYTE*)&fileFormat, sizeof(WMDM_TYPE_DWORD));
//
// Get the proper interface and transfer the file.
//
CComPtr<IWMDMStorageControl3> pStgCtl3;
CComPtr<IWMDMStorage> pNewStorage;
hr = pStorage->QueryInterface(__uuidof(IWMDMStorageControl3),(void**)(&pStgCtl3));
// Get the simple file name to use for the destination file.
wstring destFile = pwszFileName;
destFile = destFile.substr(destFile.find_last_of(L"\\") + 1);
// Get a progress indicator.
CComQIPtr<IWMDMProgress> pProgress(this);
// Set the flags for the operation
UINT flags = WMDM_MODE_BLOCK | // Synchronous call.
WMDM_STORAGECONTROL_INSERTINTO | // Insert it into the destination folder.
WMDM_CONTENT_FILE | // We're inserting a file.
WMDM_FILE_CREATE_OVERWRITE; // Overwrite existing files.
if (pOperation != NULL)
flags |= WMDM_CONTENT_OPERATIONINTERFACE;
// Send the file and metadata.
hr = pStgCtl3->Insert3(
flags,
WMDM_FILE_ATTR_FOLDER, // The current storage is a folder.
const_cast<WCHAR*>(pwszFileName), // Source file.
NULL, // Destination file name.
pOperation, // Null to allow WMDM to read the file; non-null to present raw data bytes to WMDM.
pProgress, // Interface to send simple progress notifications.
pMetadata, // IWMDMMetaData interface previously created and filled.
NULL,
&pNewStorage);
if (FAILED(hr))
m_pLogger->LogDword(WMDM_LOG_SEV_ERROR, NULL, "Error calling Insert3 in mySendFile: %lX", hr);
BREAK_HR(hr, "Wrote a file to the device in mySendFile", "Couldn't write to the device in mySendFile.");
} while (FALSE); // End of dummy loop
return hr;
}
SetEnumPreference メソッドは、ストレージに対して優先される表示モードを設定します。
| pMode | WMDM_STORAGE_ENUM_MODE* | inout | ストレージ列挙子に指定するモード。モードの詳細については、WMDM_STORAGE_ENUM_MODE を参照してください。pMode の値に ENUM_MODE_USE_DEVICE_PREF を設定した場合、戻り時にはデバイスの設定に基づいて ENUM_MODE_RAW または ENUM_MODE_METADATA_VIEWS が設定されます。 |
| nViews | DWORD | in | 指定するビュー定義の数。 pMode の値が ENUM_MODE_RAW の場合、または pMode の値が ENUM_MODE_USE_DEVICE_PREF でデバイスがメタデータビューを優先しない場合、このパラメーターは無視されます。 pMode の値が ENUM_MODE_METADATA_VIEWS の場合、または pMode の値が ENUM_MODE_USE_DEVICE_PREF でデバイスがメタデータビューを優先する場合でも、このパラメーターに 0 を指定できます。その場合、Windows Media Device Manager は既定のメタデータビューを使用します。 nViews の値が 0 の場合、ppViews は NULL でなければなりません。nViews の値が 0 以外の場合、ppViews は nViews 個の要素を持つ WMDMMetadataView 構造体の配列を指している必要があります。 |
| pViews | WMDMMetadataView* | inoptional | ビュー定義の配列。配列の長さは nViews と等しくなければなりません。 pMode の値が ENUM_MODE_RAW の場合、または pMode の値が ENUM_MODE_USE_DEVICE_PREF でデバイスがメタデータビューを優先しない場合、このパラメーターは無視されます。 pMode の値が ENUM_MODE_METADATA_VIEWS の場合、または pMode の値が ENUM_MODE_USE_DEVICE_PREF でデバイスがメタデータビューを優先する場合でも、このパラメーターに NULL を指定できます。その場合、Windows Media Device Manager は既定のメタデータビューを使用します。 nViews の値が 0 の場合、このパラメーターの値は NULL でなければなりません。nViews の値が 0 以外の場合、ppViews は nViews 個の要素を持つ WMDMMetadataView 構造体の配列を指している必要があります。 |
戻り値
このメソッドは HRESULT を返します。次の表に、返される可能性のあるすべての値を示します。
| 戻り値 | 説明 |
|---|---|
| メソッドは成功しました。 | |
| 項目を割り当てるためのメモリが不足しています。 | |
| 1 つ以上のパラメーターが無効です。 | |
|
呼び出し元にこの操作を実行する権限がありません。 |
| オブジェクトはこのメソッドをサポートしていません。 | |
| 原因不明のエラーが発生しました。 |
解説(Remarks)
Windows Media Device Manager は、デバイス上のコンテンツをメタデータビューとして提示できます。最上位のストレージ (内部メモリやストレージカードなど) 上のすべてのコンテンツを走査し、コンテンツのメタデータによって整理されたコンテンツを提示するストレージ列挙子を返します。メタデータビューの定義は WMDMMetadataView 構造体で指定します。
この動作は pMode パラメーターによって制御されます。pMode に ENUM_MODE_RAW を設定すると、Windows Media Device Manager はデバイスのストレージ上のファイルシステムの階層をそのまま反映する列挙子を返します。pMode に ENUM_MODE_METADATA_VIEWS を設定すると、Windows Media Device Manager はメタデータビューを生成します。
デバイスは、インストール時にデバイスパラメーター UseMetadataViews を設定することで、どちらを優先するかを示します。UseMetadataViews の詳細については、Device Parameters を参照してください。返されるストレージ列挙子の種類をデバイスに決めさせる場合、アプリケーションは pMode に ENUM_MODE_USE_DEVICE_PREF を設定してください。
このメソッドを呼び出した後、IWMDMStorage::EnumStorage を呼び出すと、このメソッドで設定したストレージ列挙の設定に従って動作します。このメソッドを再度呼び出せば、以降の IWMDMStorage::EnumStorage の呼び出しの動作を変更できます。
このメソッドは通常、最上位のストレージに対して呼び出します。メタデータビュー内のいずれかのストレージに対して呼び出した場合は、WMDM_E_NOTSUPPORTED が返されます。
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)
HSP用 COM定義
#usecom / #comfunc によるHSPのCOM呼び出し定義。数字は vtbl インデックス(0始まり)。クラスIDが無い場合 #usecom の末尾は "{}"、ある場合は "{CLSID}"。
#define global IID_IWMDMStorage3 "{97717EEA-926A-464E-96A4-247B0216026E}" #usecom global IWMDMStorage3 IID_IWMDMStorage3 "{807B3CE0-357A-11D3-8471-00C04F79DBC0}" #comfunc global IWMDMStorage3_GetMetadata 15 sptr #comfunc global IWMDMStorage3_SetMetadata 16 sptr #comfunc global IWMDMStorage3_CreateEmptyMetadataObject 17 sptr #comfunc global IWMDMStorage3_SetEnumPreference 18 var,int,var ; ※数字は vtbl インデックス(0始まり)。0/1/2 は IUnknown(QueryInterface/AddRef/Release)。 ; ※#usecom 末尾は CoCreateInstance 用のクラスID(コクラスCLSID, SDKから自動取得)。 ; ※出力/バッファ引数は var(変数直渡し)。varptr 方式にも切替可。 ; ※ハンドル/void*等の不透明ポインタは IronHSP では intptr 指定が可能。#define global IID_IWMDMStorage3 "{97717EEA-926A-464E-96A4-247B0216026E}" #usecom global IWMDMStorage3 IID_IWMDMStorage3 "{807B3CE0-357A-11D3-8471-00C04F79DBC0}" #comfunc global IWMDMStorage3_GetMetadata 15 sptr #comfunc global IWMDMStorage3_SetMetadata 16 sptr #comfunc global IWMDMStorage3_CreateEmptyMetadataObject 17 sptr #comfunc global IWMDMStorage3_SetEnumPreference 18 sptr,int,sptr ; ※数字は vtbl インデックス(0始まり)。0/1/2 は IUnknown(QueryInterface/AddRef/Release)。 ; ※#usecom 末尾は CoCreateInstance 用のクラスID(コクラスCLSID, SDKから自動取得)。 ; ※出力/バッファ引数はポインタ方式(token=sptr / 呼び出しは varptr(変数))。 ; ※ハンドル/void*等の不透明ポインタは IronHSP では intptr 指定が可能。