Click here to Skip to main content
Click here to Skip to main content

Device Property Sheet Dialog

By , 12 Aug 2004
 

Sample Image - DevicePropertySheet.jpg

Introduction

In my last article (Enumerate Properties of an Installed Device), I used Setup APIs to enumerate all of the properties of an installed device. But these properties are common for all devices and there were no specific properties that differ with other devices' properties. For example, a sound card has some properties that are different with properties of a network adapter.

Also, during these months, several developers asked me for device specific properties and how can one change them programmatically. I searched over the net but I could not find any related article. Now, this article is my effort to solving the problem.

Reverse Engineering The Device Manager

The first step is searching the MSDN. I searched the MSDN to find any API related to Device Manager; for example, an API that gets some information about a device (e.g., DevNode, Device GUID or etc.) and shows a dialog (may be Device Property Sheet) of properties. But there is no such API. At least, I can't find any, if anyone knows such an API, I would be glad to be informed.

The second step is to study more about the Device Manager. The Device Manager is a DLL (DevMgr.dll) that is used in MMC as a snap-in. Figure 2 shows it:

Device Manager

I used PE File Explorer (a free utility with source code) for exploring PE (Portable Executable) files like *.exe, *.dll, *.ocx, and etc.

With this utility, I found exported functions. That made an idea for me. How can other programs call these exported (and also undocumented) functions to show device property sheets?

Figure 3 shows PEFileExplorer that opens DevMgr.dll.

Sample screenshot

A big step was done with PEFileExplorer. Now I know which functions are exported by the DLL, and this makes me to search about exported functions.

From MSDN, I found that Rundll.exe and Rundll32.exe allow to invoke a function exported from a DLL. However, Rundll and Rundll32 programs do not allow you to call any exported function from any DLL. For example, you can not use these utility programs to call the Win32 API (Application Programming Interface) calls exported from the system DLLs. The programs only allow you to call functions from a DLL that are explicitly written to be called by them.

The command line for Rundll32.exe is as follows:

Rundll32.exe <name of dll> 
       <entry point function> <arguments>

With a deep look on the list of exported functions, everyone can understand that the entry point of DevMgr.dll is DeviceProperties_RunDLLA (ANSI version) and DeviceProperties_RunDLLW (UNICODE version). As Microsoft Knowledge Base Article - 164787 suggests, Rundll32.exe can handle the entry point function without using A or W. In other words, we are required to call the entry point as follows:

Rundll32.exe devmgr.dll DeviceProperties_RunDLL /DeviceID 
                                            root\system\0000

The above syntax means Rundll32.exe should call DeviceProperties_RunDll (as an entry point of DevMgr.dll) and pass /DeviceID root\system\0000 as argument of the function.

Solution

In the previous article, I showed you how we can obtain DeviceID of an installed device. Then by calling Rundll32.exe with proper arguments, the property sheet of an installed device will appear.

The following code shows an example:

void CDevicePropertySheetDialogDlg::OnDeviceProperty() 
{
    DEVNODE dn;
    
    for (int i=0; i<m_Devices.GetItemCount(); i++)
    {
        if (m_Devices.GetItemState(i, LVIS_SELECTED)) //item was selected
        {
            dn=(DEVNODE) m_Devices.GetItemData(i);
            break;
        }
    }
    
    CString CommandLine;

    //Enumerate properties
    for (int j=0; j<DeviceProperty.size(); j++)
    {
        if (DeviceProperty[j].dn==dn)
        {
            CommandLine.Format(_T("DevMgr.dll 
                  DeviceProperties_RunDLL /DeviceID \"%s\""),
                  DeviceProperty[j].Properties[ID_DEVICEID].PropertyValue);
            break;
        }
    }
    
    ShellExecute(m_hWnd, _T("open"), _T("Rundll32.exe"), 
                                CommandLine, NULL, SW_SHOW);
}

I assume that all of the devices listed in a list view control (m_Devices) and properties of the device (including DeviceID) are saved in DevicePropert vector.

Alternative Way

An alternative way is to load DevMgr.dll dynamically with LoadLibrary API. Here is the changed code to load the device property sheet with LoadLibrary API:

void CDevicePropertySheetDialogDlg::OnDeviceProperty() 
{
    DEVNODE dn;

    for (int i=0; i<m_Devices.GetItemCount(); i++)
    {
        if (m_Devices.GetItemState(i, LVIS_SELECTED)) //item was selected
        {
            //AfxMessageBox(m_Devices.GetItemText(i, 0));
            dn=(DEVNODE) m_Devices.GetItemData(i);
            break;
        }
    }

    CString CommandLine;

    //Enumerate properties
    for (int j=0; j<DeviceProperty.size(); j++)
    {
        if (DeviceProperty[j].dn==dn)
        {
            CommandLine.Format(_T("/MachineName \"\" /DeviceID %s"),
                        DeviceProperty[j].Properties[ID_DEVICEID].PropertyValue);

            break;
        }
    }

    PDEVICEPROPERTIES pDeviceProperties;
    HINSTANCE hInst=AfxGetInstanceHandle();
    HINSTANCE  hDevMgr = LoadLibrary(_TEXT("devmgr.dll"));
    if (hDevMgr) 
    {
        pDeviceProperties = (PDEVICEPROPERTIES) GetProcAddress((HMODULE) hDevMgr, 
            DeviceProperties_RunDLL);
    }

    if (pDeviceProperties)
    {
        pDeviceProperties(m_hWnd, hInst, CommandLine.GetBuffer(0), SW_SHOW);
    }

}

It should be noticed that DeviceProperties_RunDLL is defined as below:

#ifdef _UNICODE 
#define DeviceProperties_RunDLL  "DeviceProperties_RunDLLW"
typedef void (_stdcall *PDEVICEPROPERTIES)(
                   HWND hwndStub,
                   HINSTANCE hAppInstance,
                   LPWSTR lpCmdLine,
                   int    nCmdShow
                   );

#else
#define DeviceProperties_RunDLL  "DeviceProperties_RunDLLA"
typedef void (_stdcall *PDEVICEPROPERTIES)(
                   HWND hwndStub,
                   HINSTANCE hAppInstance,
                   LPSTR lpCmdLine,
                   int    nCmdShow
                   );
#endif

Thanks to Martin Rubas for his comment.

Enjoy!

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

A. Riazi
Iran (Islamic Republic Of) Iran (Islamic Republic Of)
Member
I was born in Shiraz, a very beautiful famous city in Iran. I started programming when I was 12 years old with GWBASIC. Since now, I worked with various programming languages from Basic, Foxpro, C/C++, Visual Basic, Pascal to MATLAB and now Visual C++.
I graduated from Iran University of Science & Technology in Communication Eng., and now work as a system programmer for a telecommunication industry.
I wrote several programs and drivers for Synthesizers, Power Amplifiers, GPIB, GPS devices, Radio cards, Data Acqusition cards and so many related devices.
I'm author of several books like Learning C (primary and advanced), Learning Visual Basic, API application for VB, Teach Yourself Object Oriented Programming (OOP) and etc.
I'm winner of January, May, August 2003 and April 2005 best article of month competetion, my articles are:

You can see list of my articles, by clicking here


Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralMy vote of 5membermanoj kumar choubey26 Feb '12 - 19:56 
Nice
GeneralAdd an extra device property tab into device Propertiesmembercharle_hsin8 Jul '09 - 10:57 
Hi Riazi, did you ever try to add an extra device property tab into device Properties window? I am trying to do this, but haven't be able to do it yet in Windows 7.
GeneralMoshkel dar tashkhiseh Cart Seda (Sound Cards)memberkoorosh4 Jan '07 - 7:27 
salam ostad
bebakhshid keh farsi minevisam
man koorosh nosrati hastam .raies edarehyeh internet irankhodro.
moshkeli too kar ba cart seda daram keh beh noyee marboot beh in projehyee keh shoma inja matrah kardid misheh.
agar baratoon emkan dareh Emailetoon ro bedid ta dar soorateh emkan komakam konid.
besyar khoshhal misham betoonam az shoma chizi yad begiram.
va vaghan mayehyeh eftekhareh ma hastid.
moteshakeram
koorosh nosrati
k.nosrati@ikco.com
koorosh_nosrati@yahoo.com
 
Koorosh Nosrati
0098 - 912 - 2582914

QuestionUninstall device from the Device Managermemberararavikar27 Apr '06 - 9:32 
I need to uninstall "Windows portable device" from the device manager programatically.
 
Are there any APIs to uninstall the device from Device manager?
 
Let me know.

AnswerRe: Uninstall device from the Device ManagermemberA. Riazi28 Apr '06 - 0:59 
Use SetupDiRemoveDevice() Setup API for uninstalling devices.
 
Best regards,
A. Riazi
GeneralRe: Uninstall device from the Device Managermemberararavikar28 Apr '06 - 11:46 
Thanks for the help.
I tried using this function.
I tried to use this function to get all the USB device names.
devInfoSet = SetupDiGetClassDevs(GUID_DEVCLASS_USB,NULL,NULL,DIGCF_PRESENT);
 
This returns me all the entries in USB from the device manager.
 
I am specifically looking for Windows portable devices entry in the device manager and not able to find out that entry with this function.
There is no GUID defined for Windows portable devices in devguid.h.
 
How do I get the information about WPD devices?
 
Please let me know.

AnswerRe: Uninstall device from the Device ManagermemberA. Riazi28 Apr '06 - 14:48 
Try this:
devInfoSet = SetupDiGetClassDevs(GUID_DEVCLASS_USB,NULL,NULL,DIGCF_ALL);
 
Best regards,
A. Riazi
QuestionHow to open COM Port Advanced Settingsmemberquantum197615 Feb '06 - 19:32 
I would like to programmatically (VB6) bring up the Advanced Settings window under the Device Manager for the serial port. I can get to the COM Port Properties window by using:
 
rundll32.exe devmgr.dll,DeviceProperties_RunDLL /DeviceID acpi\pnp0501\1
 
But I still have to click on the Port Settings tab followed by the Advanced button. Does anyone know of another way to get to the Advanced Settings window automatically?
 

Thanks,
quantum1976
GeneralRetrieve USB InfomemberLiYS28 Oct '05 - 6:18 
Hey Riazi
Greet article again!
Can I call One of the exported funtion in devmgr.dll
through which I can get the USB drive's Vender IDentifier(I do it this way because I want to make it both workable on Win98 and Windows NT). In addition, Can I receive something from
calling the devmgr.dll's function? Like a string represents USB VID it returns.
 



GeneralRe: Retrieve USB InfomemberA. Riazi28 Oct '05 - 21:23 
Thanks for your comment. You can call exported functions of Device Manager dll (DevMgr.dll) directly or using device manager property sheet for every device as described in my other article System Dialogs[^].
 
I'm not sure that is it possible to get a string from devmgr.dll or not. But may be you can do it by calling functions provided by your USB driver.
 
Best regards,
A. Riazi

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130523.1 | Last Updated 13 Aug 2004
Article Copyright 2004 by A. Riazi
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid