HOWTO: Web Browser Navigation Using a PIDLLast reviewed: January 19, 1998Article ID: Q167834 |
The information in this article applies to:
SUMMARYThis article illustrates programmatic navigation via a pointer to an item identifier list (PIDL) by providing an example of navigating to the Favorites Folder (CSIDL_FAVORITES).
MORE INFORMATIONThe Web Browser object model implemented in Shdocvw.dll exposes two component classes that provide browsing services: WebBrowser and InternetExplorer. While the former represents the WebBrowser ActiveX Control, the latter represents the stand-alone browser. In Internet Explorer (IE) 3.x, both classes implemented the IWebBrowser interface. Using the Navigate method of this interface, clients could easily navigate to a specified URL (for example, http://www.microsoft.com). IE 4.0 extends these classes to implement the IWebBrowser2 interface, which introduces the Navigate2 method. Navigate2 provides the same capabilities as Navigate, but it also can be used to navigate to a folder by specifying a pointer to an item identifier list (PIDL). PIDLs were introduced with Windows 95 and provide a way to uniquely identify an item within the shell's namespace. PIDLs are also supported on NT 4.0. For more information on PIDLs and the shell namespace, see the reference to the Internet Client SDK below. The following code demonstrates how to obtain a PIDL from the shell, how to create an instance of the browser and obtain the IWebBrowser2 interface, and how to call the Navigate2 method. Observe that the Web browser expects the first parameter in the call to Navigate2 to be a SAFEARRAY of bytes. The following code provides a generic routine, InitVARIANTFromPidl, that packs a PIDL into a VARIANT, which holds such an array. Note that because it is not currently possible to represent a PIDL in Visual Basic it is not possible to call the Navigate2 method from a Visual Basic application:
#include <windows.h> #define INITGUID #include <initguid.h> #include <exdisp.h> #include <shlguid.h> #include <memory.h> #include <shlobj.h> // macros for walking PIDLs #define _ILSkip(pidl, cb) ((LPITEMIDLIST)(((BYTE*)(pidl))+cb)) #define _ILNext(pidl) _ILSkip(pidl, (pidl)->mkid.cb) HRESULT FreeResources(LPVOID pData); HRESULT TestPidl(LPITEMIDLIST pidl); LPITEMIDLIST PidlFromVARIANT(VARIANT* pvarLoc); LPSAFEARRAY MakeSafeArrayFromData(LPBYTE pData,DWORD cbData); HRESULT InitVARIANTFromPidl(LPVARIANT pVar, LPITEMIDLIST pidl); UINT ILGetSize(LPITEMIDLIST pidl); void main() { HRESULT hr; LPMALLOC pMalloc = NULL; LPITEMIDLIST pidl, pidl2 = NULL; IWebBrowser2* pWebBrowser = NULL; VARIANT vPIDL = {0}, vDummy = {0}; if (FAILED(CoInitialize(NULL))) { return; } // Get the pidl for your favorite special folder, // in this case literally, the Favorites folder if (FAILED(hr = SHGetSpecialFolderLocation(NULL, CSIDL_FAVORITES, &pidl))) { goto Error; } // Pack the pidl into a VARIANT if (FAILED(hr = InitVARIANTFromPidl(&vPIDL, pidl))) { goto Error; } // Verify for testing purposes only that the pidl was packed // properly. Don't clean up pidl2 because it's a copy of the // pointer, not a clone of the id list itself pidl2 = PidlFromVARIANT(&vPIDL); if (FAILED(hr = TestPidl(pidl2))) { OutputDebugString("PIDL test failed"); goto Error; } // Instantiate a browser if (FAILED(hr = CoCreateInstance(CLSID_InternetExplorer, NULL, CLSCTX_SERVER, IID_IWebBrowser2, (LPVOID*)&pWebBrowser))) { goto Error; } // Show the browser, and navigate to the special location // represented by the pidl hr = pWebBrowser->put_Visible(VARIANT_TRUE); hr = pWebBrowser->Navigate2(&vPIDL, &vDummy, &vDummy, &vDummy, &vDummy); Error: // Clean up VariantClear(&vPIDL); if (pWebBrowser) { pWebBrowser->Release(); } if (pidl) { FreeResources((LPVOID)pidl); } CoUninitialize(); } // Exercise the PIDL by performing common operations upon it. // HRESULT TestPidl(LPITEMIDLIST pidl) { HRESULT hr; LPSHELLFOLDER pshfDesktop = NULL, pshf = NULL; DWORD uFlags = SHGDN_NORMAL; STRRET strret; if (!pidl) { return E_INVALIDARG; } hr = SHGetDesktopFolder(&pshfDesktop); if (!pshfDesktop) { return hr; } hr = pshfDesktop->BindToObject(pidl, NULL, IID_IShellFolder, (LPVOID*)&pshf); if (!pshf) { goto Error; } hr = pshfDesktop->GetDisplayNameOf(pidl, uFlags, &strret); if (STRRET_WSTR == strret.uType) { FreeResources((LPVOID)strret.pOleStr); } Error: if (pshf) pshf->Release(); if (pshf) pshfDesktop->Release(); return hr; } // Use the shell's IMalloc implementation to free resources HRESULT FreeResources(LPVOID pData) { HRESULT hr; LPMALLOC pMalloc = NULL; if (SUCCEEDED(hr = SHGetMalloc(&pMalloc))) { pMalloc->Free((LPVOID)pData); pMalloc->Release(); } return hr; } // Given a VARIANT, pull out the PIDL using brute force LPITEMIDLIST PidlFromVARIANT(LPVARIANT pvarLoc) { if (pvarLoc) { if (V_VT(pvarLoc) == (VT_ARRAY|VT_UI1)) { LPITEMIDLIST pidl = (LPITEMIDLIST)pvarLoc->parray->pvData; return pidl; } } return NULL; } // Pack a PIDL into a VARIANT HRESULT InitVARIANTFromPidl(LPVARIANT pvar, LPITEMIDLIST pidl) { if (!pidl || !pvar) { return E_POINTER; } // Get the size of the pidl and allocate a SAFEARRAY of // equivalent size UINT cb = ILGetSize(pidl); LPSAFEARRAY psa = MakeSafeArrayFromData((LPBYTE)pidl, cb); if (!psa) { VariantInit(pvar); return E_OUTOFMEMORY; } V_VT(pvar) = VT_ARRAY|VT_UI1; V_ARRAY(parray) = psa; return NOERROR; } // Allocate a SAFEARRAY of cbData size and pack pData into it LPSAFEARRAY MakeSafeArrayFromData(LPBYTE pData, DWORD cbData) { LPSAFEARRAY psa; if (!pData || 0 == cbData) { return NULL; // nothing to do } // create a one-dimensional safe array of BYTEs psa = SafeArrayCreateVector(VT_UI1, 0, cbData); if (psa) { // copy data into the area in safe array reserved for data // Note we party directly on the pointer instead of using locking/ // unlocking functions. Since we just created this and no one // else could possibly know about it or be using it, this is okay. memcpy(psa->pvData,pData,cbData); } return psa; } // Get the size of the PIDL by walking the item id list UINT ILGetSize(LPITEMIDLIST pidl) { UINT cbTotal = 0; if (pidl) { cbTotal += sizeof(pidl->mkid.cb); // Null terminator while (pidl->mkid.cb) { cbTotal += pidl->mkid.cb; pidl = _ILNext(pidl); } } return cbTotal; } REFERENCESInternet Client SDK Documentation: Application and Internet Services, Windows Shell API, Shell's Namespace. Keywords : kbcode Version : 4.0 Platform : WINDOWS Issue type : kbhowto |
================================================================================
© 1998 Microsoft Corporation. All rights reserved. Terms of Use. |