Using the Shell Namespace To Get Network Computers, Printers and Recycle Bin Items

Sample Image

Environment: VC6

This article explains how to make use of the COM interfaces implemented by Shell Extensions to get the required information on a local machine or network. In this example I have demonstrated it to get the list of all user machines logged onto the network, printers attached to network and items in the recycle bin of local machine. The CShellExt wrapper class can be extended to include the functionality to extract all kind of information. Although there are a lot of wrapper shell functions present to get the same information, but use of COM interfaces gives an insight into what foes on behind the scene in windows explorer and how we can extend the shell's namespace.

Before we ask for any information from Shell, there are couple of environment variables, which needs to be initialized. First we need to allocate memory in Shell's address space. Asking for IMalloc interface pointer, which we will release before we exit our application, can do this. The Desktop folder is the root of Shell's name space, therefore we will need the interface pointer to that. These steps have been implemented in InitializeEnvironment function of CShellExt class.


HRESULT  hr = SHGetMalloc (&m_pMalloc);
HRESULT  hr = SHGetDesktopFolder (&m_pDesktopFolder);

Network Neighborhood, Printers, RecycleBin, etc. fall under the category of Special Folders a.k.a Virtual Folders. Windows API provides bunch of functions to work with them. We use SHGetSpecialFolderPath function to obtain the path to required folder. E.g. to obtain path to printers folder


HRESULT  hr = SHGetSpecialFolderLocation (NULL, CSIDL_PRINTERS, &netItemIdLst);

To get more information about second argument to this function call, look in the on-line help. This argument specifies the special folder for which IShellFolder interface is needed. The link between special folders and their paths is stored in the registry as:

HKEY_CURRENT_USER
 \Software
  \Microsoft
   \Windows
     \CurrentVersion
       \Explorer
        \Shell Folders

After we have IShellFolder interface pointer to special folder, we can ask for contents of folder by creating an item enumeration object (a set of item identifiers) that can be retrieved using the IEnumIDList interface. E.g. for printer folder

HRESULT hr = pPrinterFolder->EnumObjects (NULL, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &pEnumIds);

After we have ID list enumeration, the display name for each item can be obtained by using GetDisplayNameOf method of IShellFolder interface.

while ((hr = pEnumIds->Next (1, &pidlItems, &celtFetched)) != S_FALSE && celtFetched == 1) 
{
   hr = pPrinterFolder->GetDisplayNameOf (pidlItems, SHGDN_INFOLDER, &strDispName);
   if (FAILED (hr))
   {
      goto FreeInterfaces;
   }
   .
   .
}

After we have obtained the display name of the folder, we need to extract icons. Every shell object which has icon(s) associated with it, implements IExtractIcon interface. This can be obtained by using GetUIObjectOf method of IShellFolder interface. After getting the IExtractIcon interface pointer, use its two methods to get handles to small and large icons. This has been implemented in GetIconsForFolderNode function of CShellExt class.

IExtractIcon *pExtractIcon = NULL;

hr = pFolderNode->GetUIObjectOf (NULL, 1, const_cast<LPCITEMIDLIST *>(&pidlItems),
IID_IExtractIcon, NULL, reinterpret_cast<LPVOID *>(&pExtractIcon));
	
if (SUCCEEDED (hr)) {
	TCHAR str[MAX_PATH] = {0};
	int index;
	UINT flags;

	// Get the file location where the icons are stored.

	hr = pExtractIcon->GetIconLocation (0, str, MAX_PATH, &index, &flags);
	if (SUCCEEDED (hr)) {
		HICON hiconLarge = NULL;
		HICON hiconSmall = NULL;
		UINT nIconSize = MAKELONG (32, 16);
		LPCSTR pszFile = (LPCSTR)str;

		// Extract the icon handles from the location.

		hr = pExtractIcon->Extract (str, index, &hIconLg, &hIconSm, nIconSize);
		pExtractIcon->Release ();
	}
}

To show the use of this extension class, I have created a dialog-based application, which has a tool bar with 3 buttons for NetWork compuetrs, Printers, RecycleBin items. Click on one of them to see the results. The sample application also shows the usage of CTreeCtrl and how to implement CToolBar in dialog based applications.

Downloads

Download demo project - 28.3 Kb

History



Comments

  • Drag-Drop Across Virtual Folders and Windows File System in the Windows Explorer

    Posted by Legacy on 03/03/2000 12:00am

    Originally posted by: Suneel Kumar.P

    How to get the target folder PIDL? ( folder on which the user dorps the files being dragged ).

    Some body please help me as soon as possible.

    Reply
  • How to add stuff to my computer ?

    Posted by Legacy on 03/02/2000 12:00am

    Originally posted by: Matthew Campbell

    Does anyone know how to add icons to "My computer". For say a program.

    Reply
  • Failing when i try to use CSIDL_HISTORY !!!!?

    Posted by Legacy on 02/24/2000 12:00am

    Originally posted by: jabarooth

    This sample is failing at SHGetSpecialFolderLocation() function calling when i use CSIDL_HISTORY. Help me Pls...

    Reply
  • Can i Create Special Folders Or Virtual Folders

    Posted by Legacy on 01/25/2000 12:00am

    Originally posted by: Ashutosh

    I want an icon to be displayed in the tree view of the windows explorer. On clicking this icon , i want to launch an exe file. Can any one help me do it ? 
    
    thanks in anticipation.

    Reply
  • How to open Add Printers dialog programmatically

    Posted by Legacy on 09/21/1999 12:00am

    Originally posted by: Pramendra

    Does anybody know how to open the Add Printers Dialog Programmatically.


    My idea is :

    1. Get the PIDL of the 'Add Printer' folder.

    2. Fill Up a SHELLEXECUTEINFO Structure.

    3. Use ShellExecuteEx to open the dialog.

    has anybody done this before?


    best regards
    Pramendra Dadhwal

    Reply
  • Where's the Comment?

    Posted by Legacy on 08/11/1999 12:00am

    Originally posted by: Carsten Witte

    Hi Gurus,

    I'v done a similar shell-enum, getting all machines, every shared folder (I don't care for printers), entire network... so far so good, but I (or the function) fail miserably when it comes to the comments. Explorer is displaying those fine, so I guess it must be part of it.

    At the point, where I got a correct folder and item (must be correct since I get the correct name and icon, what is predicable, since lpItem came from lpFolder->EnumObjects) and tried a:

    NETRESOURCE nrc;
    ::ZeroMemory (&nrc, sizeof (nrc));
    hResult= SHGetDataFromIDList (lpFolder, lpItem, SHGDFIL_NETRESOURCE, (PVOID) &nrc, sizeof (nrc));

    It simply fails on all machines that are part of my workgroup and therefore childen of the CSIDL_NETWORK and works fine on anything under "Entire Network". But not even then it wouldn't fill *any* of the nrc.lp* entries.

    What's wrong?

    TIA, Carsten Witte

    Reply
  • Mapping an internet drive(using FTP) just like a native drive.

    Posted by Legacy on 08/11/1999 12:00am

    Originally posted by: Anand

    How can I map an internet drive using FTP, just like a native network drive. The mapped drive should be listed in the windows explorer just like any other logical drive and should provide all the functions e.g copying,renamin, etc.


    regards
    Anand

    Reply
  • ...

    Posted by Legacy on 07/21/1999 12:00am

    Originally posted by: Mihai

    Did you try the IShellFolder::CreateViewObject, IShellView::CreateWindow...?
    
    Sincerely, Mihai

    Reply
  • Code for getting icon for control pannel items ..

    Posted by Legacy on 07/16/1999 12:00am

    Originally posted by: Naveen Kohli

    //
    HRESULT
    CShellExt::GetIconsForControlPanel (LPCTSTR lpszFile, HICON &hIconSm, HICON &hIconLg)
    {
    HRESULT hr = S_OK;
    NEWCPLINFO ncpInfo;

    ZeroMemory (&ncpInfo, sizeof (ncpInfo));
    ncpInfo.dwSize = sizeof (ncpInfo);

    // Load the CPL for the control pannel applet.

    HINSTANCE hlibCPL = ::LoadLibrary (lpszFile);

    // Get the process address of the Applet's entry point DLL i.e. CPiApplet which all the
    // control panel applets are supposed to provide.

    APPLET_PROC fCPLApplet = (APPLET_PROC)GetProcAddress (hlibCPL, "CPlApplet");

    // Initialize the Applet.

    if (fCPLApplet (NULL, CPL_INIT, 0, 0)) {
    // Get the number of aplets supported by this control pannel object.

    LONG numApplets = fCPLApplet (NULL, CPL_GETCOUNT, 0, 0);

    // Inquire the applet.

    LONG retVal = fCPLApplet (NULL, CPL_NEWINQUIRE, 0, (LONG)&ncpInfo);
    HICON hSmIcon, hLgIcon;
    ExtractIconEx (lpszFile, 0, &hSmIcon, &hLgIcon, 2);

    hIconSm = ::CopyIcon (hSmIcon);
    hIconLg = ::CopyIcon (hLgIcon);

    if (hIconSm == NULL) {
    hIconSm = ::CopyIcon (hLgIcon);
    }
    }

    // Before we free the applet dll, notify it to exit.

    fCPLApplet (NULL, CPL_EXIT, 0, 0);

    // Free the loaded library

    FreeLibrary (hlibCPL);

    return hr;
    }

    // changes to be made in GetIconsForFolderNode function...


    if (m_bControlPanelSearch) {
    try {
    hr = GetIconsForControlPanel (pszFile, hIconSm, hIconLg);
    }
    catch (...) {
    TRACE (_T ("Exception thrown\n"));
    }
    }
    else {
    hr = pExtractIcon->Extract (str, index, &hIconLg, &hIconSm, nIconSize);
    pExtractIcon->Release ();
    }

    Reply
  • How about the control panel?

    Posted by Legacy on 06/02/1999 12:00am

    Originally posted by: Byron Montgomerie

    I know how to get the control panel labels using enum, but
    getting the icons for control panels with multiple entries
    seems to be a rather tricky task, any ideas? (Some control panels use several icons, descriptions etc when communicating with the control panel application, you can call them "manually" using various argument like 1, 2, @1, @2 etc using shell32.dll, but that is icky) Differentiating between mouse/keyboard/etc when they all resolve to one control panel is my problem, any clue? Is there a standard
    argument convention for this kind of thing? Looking for
    something that kind apply to control panels, Dialup networking entries etc.

    Thanks for any info

    Byron

    Reply
  • Loading, Please Wait ...

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds