Get Storage Information from a Portable Device using WPD
I've been doing some WPD development recently and I wanted to share some information about getting storage information from a portable device, but first I wanted to thank dimeby8 (https://blogs.msdn.com/dimeby8) for the great posts on WPD development.
One issue with WPD development that I didn't find any reference to was getting storage information so I jumped into it by trying to use GetDiskFreeSpaceEx(). I thought that this was a safe place to start, but my assumptions got the best of me. It turns out that WPD devices dont hook into the System Volume APIs, and you need to get storage information through the WPD Storage Properties.
I've included a short sample below. I hope it saves someone from making the same assumption I did.
HRESULT hr = S_OK;
DWORD cPnPDeviceIDs = 0;
LPWSTR DeviceId = NULL;
TCHAR szDebugMsg[256] = TEXT("");
try
{
CComPtr<IPortableDeviceManager> spDevMgr;
hr = CoCreateInstance(CLSID_PortableDeviceManager, NULL, CLSCTX_INPROC_SERVER,
IID_IPortableDeviceManager, (VOID**) &spDevMgr);
// Get the device (I use a helper function here. Not shown)
DeviceId = CCommonFunctions::GetDevice(spDevMgr, deviceFriendlyName);
// Create an instance of a Values collection to hold the client information
CComPtr<IPortableDeviceValues> spClientInfo;
hr = CoCreateInstance(CLSID_PortableDeviceValues, NULL, CLSCTX_INPROC_SERVER, IID_IPortableDeviceValues, (VOID**)&spClientInfo);
// Add client information to the Values collection
hr = spClientInfo->SetStringValue(WPD_CLIENT_NAME, L"Enumerator");
hr = spClientInfo->SetUnsignedIntegerValue(WPD_CLIENT_MAJOR_VERSION, 1);
hr = spClientInfo->SetUnsignedIntegerValue(WPD_CLIENT_MINOR_VERSION, 0);
hr = spClientInfo->SetUnsignedIntegerValue(WPD_CLIENT_REVISION, 0);
// Create an instance of the first WPD device
CComPtr<IPortableDevice> spDevice;
hr = CoCreateInstance(CLSID_PortableDevice, NULL, CLSCTX_INPROC_SERVER, IID_IPortableDevice, (VOID**) &spDevice);
// Connect to the device
BOOL bDeviceOpened = TRUE;
hr = spDevice->Open(_bstr_t(DeviceId), spClientInfo);
CComPtr<IPortableDeviceContent> spContent;
hr = spDevice->Content(&spContent);
CComPtr<IPortableDeviceProperties> spProperties;
hr = spContent->Properties(&spProperties);
// Enumerate children (if any) of provided object
CComPtr<IEnumPortableDeviceObjectIDs> spEnum;
hr = spContent->EnumObjects(0, WPD_DEVICE_OBJECT_ID, NULL, &spEnum);
// Get the first object. This should be the primary storage object
LPWSTR pwszStorageObjectId = NULL;
ULONG celtFetched = 0;
hr = spEnum->Next(1, &pwszStorageObjectId, &celtFetched);
// We'll need an IPortableDeviceKeyCollection instance
CComPtr<IPortableDeviceKeyCollection> spKeys;
hr = CoCreateInstance(CLSID_PortableDeviceKeyCollection, NULL, CLSCTX_INPROC_SERVER, IID_IPortableDeviceKeyCollection, (VOID**) &spKeys);
//Specify the properties that we need to retrieve
hr = spKeys->Add(WPD_STORAGE_CAPACITY);
CComPtr<IPortableDeviceValues> spValues;
hr = spProperties->GetValues(pwszStorageObjectId, spKeys, &spValues);
ULONGLONG ullDiskTotalBytes = 0;
hr = spValues->GetUnsignedLargeIntegerValue(WPD_STORAGE_CAPACITY, &ullDiskTotalBytes);
*ReturnVal = ullDiskTotalBytes;
// Cleanup
CoTaskMemFree(pwszStorageObjectId);
ullDiskTotalBytes = NULL;
// Close connection to the device
if (bDeviceOpened)
{
hr = spDevice->Close();
}
// Free memory allocated by the GetDevices call
if (DeviceId != NULL)
{
CoTaskMemFree(DeviceId);
}
}
catch (_com_error &e)
{
HRESULT _hr = e.Error();
wsprintf(szDebugMsg, TEXT("Caught an error %08x - %s"), _hr, e.Description());
OutputDebugString(szDebugMsg);
AtlThrow(_hr);
}
return S_OK;
Comments
- Anonymous
March 12, 2008
PingBack from http://bordercrossingstatsblog.info/mumblings-of-an-infraloper-get-storage-information-from-a-portable/