Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
.gif)
| Previous | Next |
Supporting Device-Side Content
Because device-side content is not accessible through the file system in Windows Vista, you'll need to use either the Windows Shell API or the WPD API to retrieve data for device objects. This is the primary difference between a normal context menu handler and a WPD context menu handler. The following sample code demonstrates the retrieval of device-side content using the Windows Shell API.
The first step is the initialization of the item identifier list or PIDL. (This list contains the unique identifier for the given device object.)
HRESULT CWPDContextMenu::_InitializePIDLArray(IDataObject *pDataObj)
{
if (m_cfHIDA == 0)
{
m_cfHIDA = (CLIPFORMAT)RegisterClipboardFormat(CFSTR_SHELLIDLIST);
}
STGMEDIUM medium;
FORMATETC fmte = {m_cfHIDA, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
HRESULT hr = pDataObj->GetData(&fmte;, &medium;);
if (SUCCEEDED(hr))
{
SIZE_T cb = GlobalSize(medium.hGlobal);
CIDA *pida = (CIDA*)GlobalAlloc(GPTR, cb);
if (pida)
{
void *pv = GlobalLock(medium.hGlobal);
if (pv != NULL)
{
CopyMemory(pida, pv, cb);
GlobalUnlock(medium.hGlobal);
m_pida = pida;
_ExaminePIDLArray();
}
else
{
hr = E_UNEXPECTED;
}
}
else
{
hr = E_OUTOFMEMORY;
}
ReleaseStgMedium(&medium;);
}
return hr;
}
The initialization function calls the _ExaminePIDLArray function, which retrieves the properties for object identified by a PIDL in the PIDL array.
HRESULT CWPDContextMenu::_ExaminePIDLArray()
{
CComPtr<IShellFolder2> spParentFolder;
CComVariant variant;
LPITEMIDLIST pidl = NULL;
HRESULT hr = S_OK;
UINT index = 0;
pidl = GetPIDL(m_pida, index);
if (pidl)
{
hr = SHBindToParent(pidl, IID_PPV_ARGS(&spParentFolder;), NULL);
IF_FAILED_JUMP(hr, Exit);
}
do
{
CComPtr<IPropertySetStorage> spSetStorage;
CComPtr<IPropertyStorage> spPropStorage;
// Get the IpropertySetStorage interface for this PIDL. This method could also
// be used to retrieve an IPortableDevice interface to allow more low-level interaction
// with the WPD API.
hr = spParentFolder->BindToObject(ILFindLastID(pidl), NULL, IID_PPV_ARGS(&spSetStorage;));
if (SUCCEEDED(hr))
{
hr = spSetStorage->Open(WPD_FUNCTIONAL_OBJECT_PROPERTIES_V1, STGM_READ, &spPropStorage;);
if (SUCCEEDED(hr))
{
PROPVARIANT PropVar = {0};
PROPSPEC PropSpec = {0};
PropSpec.ulKind = PRSPEC_PROPID;
PropSpec.propid = 2; // WPD_FUNCTIONAL_OBJECT_CATEGORY
PropVariantInit(&PropVar;);
hr = spPropStorage->ReadMultiple(1, &PropSpec;, &PropVar;);
if (SUCCEEDED(hr) && PropVar.vt == VT_CLSID)
{
// The PIDL array contains a non-file object.
// This means we don't want to take over the
// default menu action.
m_bPIDAContainsOnlyFiles = FALSE;
PropVariantClear(&PropVar;);
break;
}
else
{
CComPtr<IPropertyStorage> spObjectProperties;
hr = spSetStorage->Open(WPD_OBJECT_PROPERTIES_V1, STGM_READ, &spObjectProperties;);
if (SUCCEEDED(hr))
{
PropSpec.ulKind = PRSPEC_PROPID;
PropSpec.propid = 7; // WPD_OBJECT_CONTENT_TYPE
PropVariantClear(&PropVar;);
hr = spObjectProperties->ReadMultiple(1, &PropSpec;, &PropVar;);
if (SUCCEEDED(hr) && PropVar.vt == VT_CLSID)
{
if (IsEqualGUID(*PropVar.puuid, WPD_CONTENT_TYPE_FOLDER))
{
// The PIDL array contains a folder object.
// This means we don't want to take over the
// default menu action.
m_bPIDAContainsOnlyFiles = FALSE;
PropVariantClear(&PropVar;);
break;
}
}
}
}
PropVariantClear(&PropVar;);
}
}
UI_SAFE_ILFREE(pidl);
pidl = GetPIDL(m_pida, ++index);
} while (pidl != NULL && index < m_pida->cidl);
Exit:
UI_SAFE_ILFREE(pidl);
return hr;
}
See Also
| Previous | Next |