Supporting Device-Side Content
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 |