1 /*
2  * ReactOS Device Manager Applet
3  * Copyright (C) 2004 - 2005 ReactOS Team
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18  */
19 /*
20  *
21  * PROJECT:         ReactOS devmgr.dll
22  * FILE:            lib/devmgr/advprop.c
23  * PURPOSE:         ReactOS Device Manager
24  * PROGRAMMER:      Thomas Weidenmueller <w3seek@reactos.com>
25  *                  Ged Murphy <gedmurphy@reactos.org>
26  * UPDATE HISTORY:
27  *      04-04-2004  Created
28  */
29 
30 #include "precomp.h"
31 #include "properties.h"
32 #include "resource.h"
33 
34 #include <winver.h>
35 
36 
37 static UINT WINAPI
38 EnumDeviceDriverFilesCallback(IN PVOID Context,
39                               IN UINT Notification,
40                               IN UINT_PTR Param1,
41                               IN UINT_PTR Param2)
42 {
43     LVITEM li;
44     PENUMDRIVERFILES_CONTEXT EnumDriverFilesContext = (PENUMDRIVERFILES_CONTEXT)Context;
45 
46     li.mask = LVIF_TEXT | LVIF_STATE;
47     li.iItem = EnumDriverFilesContext->nCount++;
48     li.iSubItem = 0;
49     li.state = (li.iItem == 0 ? LVIS_SELECTED : 0);
50     li.stateMask = LVIS_SELECTED;
51     li.pszText = (LPWSTR)Param1;
52     (void)ListView_InsertItem(EnumDriverFilesContext->hDriversListView,
53                               &li);
54     return NO_ERROR;
55 }
56 
57 
58 static VOID
59 UpdateDriverDetailsDlg(IN HWND hwndDlg,
60                        IN HWND hDriversListView,
61                        IN PDEVADVPROP_INFO dap)
62 {
63     HDEVINFO DeviceInfoSet;
64     PSP_DEVINFO_DATA DeviceInfoData;
65     SP_DRVINFO_DATA DriverInfoData;
66     ENUMDRIVERFILES_CONTEXT EnumDriverFilesContext;
67 
68     if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
69     {
70         DeviceInfoSet = dap->CurrentDeviceInfoSet;
71         DeviceInfoData = &dap->CurrentDeviceInfoData;
72     }
73     else
74     {
75         DeviceInfoSet = dap->DeviceInfoSet;
76         DeviceInfoData = &dap->DeviceInfoData;
77     }
78 
79     /* set the device image */
80     SendDlgItemMessage(hwndDlg,
81                        IDC_DEVICON,
82                        STM_SETICON,
83                        (WPARAM)dap->hDevIcon,
84                        0);
85 
86     /* set the device name edit control text */
87     SetDlgItemText(hwndDlg,
88                    IDC_DEVNAME,
89                    dap->szDevName);
90 
91     /* fill the driver files list view */
92     EnumDriverFilesContext.hDriversListView = hDriversListView;
93     EnumDriverFilesContext.nCount = 0;
94 
95     (void)ListView_DeleteAllItems(EnumDriverFilesContext.hDriversListView);
96     DriverInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
97     if (FindCurrentDriver(DeviceInfoSet,
98                           DeviceInfoData,
99                           &DriverInfoData) &&
100         SetupDiSetSelectedDriver(DeviceInfoSet,
101                                  DeviceInfoData,
102                                  &DriverInfoData))
103     {
104         HSPFILEQ queueHandle;
105 
106         queueHandle = SetupOpenFileQueue();
107         if (queueHandle != (HSPFILEQ)INVALID_HANDLE_VALUE)
108         {
109             SP_DEVINSTALL_PARAMS DeviceInstallParams = {0};
110             DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
111             if (SetupDiGetDeviceInstallParams(DeviceInfoSet,
112                                               DeviceInfoData,
113                                               &DeviceInstallParams))
114             {
115                 DeviceInstallParams.FileQueue = queueHandle;
116                 DeviceInstallParams.Flags |= DI_NOVCP;
117 
118                 if (SetupDiSetDeviceInstallParams(DeviceInfoSet,
119                                                   DeviceInfoData,
120                                                   &DeviceInstallParams) &&
121                     SetupDiCallClassInstaller(DIF_INSTALLDEVICEFILES,
122                                               DeviceInfoSet,
123                                               DeviceInfoData))
124                 {
125                     DWORD scanResult;
126                     RECT rcClient;
127                     LVCOLUMN lvc;
128 
129                     /* enumerate the driver files */
130                     SetupScanFileQueue(queueHandle,
131                                        SPQ_SCAN_USE_CALLBACK,
132                                        NULL,
133                                        EnumDeviceDriverFilesCallback,
134                                        &EnumDriverFilesContext,
135                                        &scanResult);
136 
137                     /* update the list view column width */
138                     GetClientRect(hDriversListView,
139                                   &rcClient);
140                     lvc.mask = LVCF_WIDTH;
141                     lvc.cx = rcClient.right;
142                     (void)ListView_SetColumn(hDriversListView,
143                                              0,
144                                              &lvc);
145 
146                     /* highlight the first item from list */
147                     if (ListView_GetSelectedCount(hDriversListView) != 0)
148                     {
149                         ListView_SetItemState(hDriversListView,
150                                               0,
151                                               LVIS_FOCUSED | LVIS_SELECTED,
152                                               LVIS_FOCUSED | LVIS_SELECTED);
153                     }
154                 }
155             }
156 
157             SetupCloseFileQueue(queueHandle);
158         }
159     }
160 }
161 
162 
163 static VOID
164 UpdateDriverVersionInfoDetails(IN HWND hwndDlg,
165                                IN LPCWSTR lpszDriverPath)
166 {
167     DWORD dwHandle;
168     DWORD dwVerInfoSize;
169     LPVOID lpData = NULL;
170     LPVOID lpInfo;
171     UINT uInfoLen;
172     DWORD dwLangId;
173     WCHAR szLangInfo[255];
174     WCHAR szLangPath[MAX_PATH];
175     LPWSTR lpCompanyName = NULL;
176     LPWSTR lpFileVersion = NULL;
177     LPWSTR lpLegalCopyright = NULL;
178     LPWSTR lpDigitalSigner = NULL;
179     UINT uBufLen;
180     WCHAR szNotAvailable[255];
181 
182     /* extract version info from selected file */
183     dwVerInfoSize = GetFileVersionInfoSize(lpszDriverPath,
184                                            &dwHandle);
185     if (!dwVerInfoSize)
186         goto done;
187 
188     lpData = HeapAlloc(GetProcessHeap(),
189                        HEAP_ZERO_MEMORY,
190                        dwVerInfoSize);
191     if (!lpData)
192         goto done;
193 
194     if (!GetFileVersionInfo(lpszDriverPath,
195                             dwHandle,
196                             dwVerInfoSize,
197                             lpData))
198         goto done;
199 
200     if (!VerQueryValue(lpData,
201                        L"\\VarFileInfo\\Translation",
202                        &lpInfo,
203                        &uInfoLen))
204         goto done;
205 
206     dwLangId = *(LPDWORD)lpInfo;
207     swprintf(szLangInfo, L"\\StringFileInfo\\%04x%04x\\",
208              LOWORD(dwLangId), HIWORD(dwLangId));
209 
210     /* read CompanyName */
211     wcscpy(szLangPath, szLangInfo);
212     wcscat(szLangPath, L"CompanyName");
213 
214     VerQueryValue(lpData,
215                   szLangPath,
216                   (void **)&lpCompanyName,
217                   (PUINT)&uBufLen);
218 
219     /* read FileVersion */
220     wcscpy(szLangPath, szLangInfo);
221     wcscat(szLangPath, L"FileVersion");
222 
223     VerQueryValue(lpData,
224                   szLangPath,
225                   (void **)&lpFileVersion,
226                   (PUINT)&uBufLen);
227 
228     /* read LegalTrademarks */
229     wcscpy(szLangPath, szLangInfo);
230     wcscat(szLangPath, L"LegalCopyright");
231 
232     VerQueryValue(lpData,
233                   szLangPath,
234                   (void **)&lpLegalCopyright,
235                   (PUINT)&uBufLen);
236 
237     /* TODO: read digital signer info */
238 
239 done:
240     if (!LoadString(hDllInstance,
241                     IDS_NOTAVAILABLE,
242                     szNotAvailable,
243                     sizeof(szNotAvailable) / sizeof(WCHAR)))
244     {
245         wcscpy(szNotAvailable, L"n/a");
246     }
247 
248     /* update labels */
249     if (!lpCompanyName)
250         lpCompanyName = szNotAvailable;
251     SetDlgItemText(hwndDlg,
252                    IDC_FILEPROVIDER,
253                    lpCompanyName);
254 
255     if (!lpFileVersion)
256         lpFileVersion = szNotAvailable;
257     SetDlgItemText(hwndDlg,
258                    IDC_FILEVERSION,
259                    lpFileVersion);
260 
261     if (!lpLegalCopyright)
262         lpLegalCopyright = szNotAvailable;
263     SetDlgItemText(hwndDlg,
264                    IDC_FILECOPYRIGHT,
265                    lpLegalCopyright);
266 
267     if (!lpDigitalSigner)
268         lpDigitalSigner = szNotAvailable;
269     SetDlgItemText(hwndDlg,
270                    IDC_DIGITALSIGNER,
271                    lpDigitalSigner);
272 
273     /* release version info */
274     if (lpData)
275         HeapFree(GetProcessHeap(),
276                  0,
277                  lpData);
278 }
279 
280 
281 static INT_PTR
282 CALLBACK
283 DriverDetailsDlgProc(IN HWND hwndDlg,
284                      IN UINT uMsg,
285                      IN WPARAM wParam,
286                      IN LPARAM lParam)
287 {
288     PDEVADVPROP_INFO dap;
289     INT_PTR Ret = FALSE;
290 
291     dap = (PDEVADVPROP_INFO)GetWindowLongPtr(hwndDlg,
292                                              DWL_USER);
293 
294     if (dap != NULL || uMsg == WM_INITDIALOG)
295     {
296         switch (uMsg)
297         {
298             case WM_COMMAND:
299             {
300                 switch (LOWORD(wParam))
301                 {
302                     case IDOK:
303                     case IDCANCEL:
304                     {
305                         EndDialog(hwndDlg,
306                                   IDOK);
307                         break;
308                     }
309                 }
310                 break;
311             }
312 
313             case WM_CLOSE:
314             {
315                 EndDialog(hwndDlg,
316                           IDCANCEL);
317                 break;
318             }
319 
320             case WM_INITDIALOG:
321             {
322                 LV_COLUMN lvc;
323                 HWND hDriversListView;
324                 WCHAR szBuffer[260];
325 
326                 dap = (PDEVADVPROP_INFO)lParam;
327                 if (dap != NULL)
328                 {
329                     SetWindowLongPtr(hwndDlg,
330                                      DWL_USER,
331                                      (DWORD_PTR)dap);
332 
333                     hDriversListView = GetDlgItem(hwndDlg,
334                                                   IDC_DRIVERFILES);
335 
336                     /* add a column to the list view control */
337                     lvc.mask = LVCF_FMT | LVCF_WIDTH;
338                     lvc.fmt = LVCFMT_LEFT;
339                     lvc.cx = 0;
340                     (void)ListView_InsertColumn(hDriversListView,
341                                                 0,
342                                                 &lvc);
343 
344                     UpdateDriverDetailsDlg(hwndDlg,
345                                            hDriversListView,
346                                            dap);
347 
348                     if (ListView_GetItemCount(hDriversListView) == 0)
349                     {
350                         if (LoadStringW(hDllInstance, IDS_NODRIVERS, szBuffer, _countof(szBuffer)))
351                             MessageBoxW(hwndDlg, szBuffer, dap->szDevName, MB_OK);
352                         EndDialog(hwndDlg, IDCANCEL);
353                     }
354                 }
355 
356                 Ret = TRUE;
357                 break;
358             }
359 
360             case WM_NOTIFY:
361             {
362                 LPNMHDR pnmhdr = (LPNMHDR)lParam;
363 
364                 switch (pnmhdr->code)
365                 {
366                 case LVN_ITEMCHANGED:
367                     {
368                         LPNMLISTVIEW pnmv = (LPNMLISTVIEW)lParam;
369                         HWND hDriversListView = GetDlgItem(hwndDlg,
370                                                            IDC_DRIVERFILES);
371 
372                         if (ListView_GetSelectedCount(hDriversListView) == 0)
373                         {
374                             /* nothing is selected - empty the labels */
375                             SetDlgItemText(hwndDlg,
376                                            IDC_FILEPROVIDER,
377                                            NULL);
378                             SetDlgItemText(hwndDlg,
379                                            IDC_FILEVERSION,
380                                            NULL);
381                             SetDlgItemText(hwndDlg,
382                                            IDC_FILECOPYRIGHT,
383                                            NULL);
384                             SetDlgItemText(hwndDlg,
385                                            IDC_DIGITALSIGNER,
386                                            NULL);
387                         }
388                         else if (pnmv->uNewState != 0)
389                         {
390                             /* extract version info and update the labels */
391                             WCHAR szDriverPath[MAX_PATH];
392 
393                             ListView_GetItemText(hDriversListView,
394                                                  pnmv->iItem,
395                                                  pnmv->iSubItem,
396                                                  szDriverPath,
397                                                  MAX_PATH);
398 
399                             UpdateDriverVersionInfoDetails(hwndDlg,
400                                                            szDriverPath);
401                         }
402                     }
403                 }
404                 break;
405             }
406         }
407     }
408 
409     return Ret;
410 }
411 
412 
413 static
414 VOID
415 UpdateDriver(
416     IN HWND hwndDlg,
417     IN PDEVADVPROP_INFO dap)
418 {
419     TOKEN_PRIVILEGES Privileges;
420     HANDLE hToken;
421     DWORD dwReboot;
422     BOOL NeedReboot = FALSE;
423 
424     // Better use InstallDevInst:
425     //     BOOL
426     //     WINAPI
427     //     InstallDevInst(
428     //         HWND hWnd,
429     //         LPWSTR wszDeviceId,
430     //         BOOL bUpdate,
431     //         DWORD *dwReboot);
432     // See: http://comp.os.ms-windows.programmer.win32.narkive.com/J8FTd4KK/signature-of-undocumented-installdevinstex
433 
434     if (!InstallDevInst(hwndDlg, dap->szDeviceID, TRUE, &dwReboot))
435         return;
436 
437     if (NeedReboot == FALSE)
438         return;
439 
440     //FIXME: load text from resource file
441     if (MessageBoxW(hwndDlg, L"Reboot now?", L"Reboot required", MB_YESNO | MB_ICONQUESTION) != IDYES)
442         return;
443 
444     if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
445     {
446         ERR("OpenProcessToken failed\n");
447         return;
448     }
449 
450     /* Get the LUID for the Shutdown privilege */
451     if (!LookupPrivilegeValueW(NULL, SE_SHUTDOWN_NAME, &Privileges.Privileges[0].Luid))
452     {
453         ERR("LookupPrivilegeValue failed\n");
454         CloseHandle(hToken);
455         return;
456     }
457 
458     /* Assign the Shutdown privilege to our process */
459     Privileges.PrivilegeCount = 1;
460     Privileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
461 
462     if (!AdjustTokenPrivileges(hToken, FALSE, &Privileges, 0, NULL, NULL))
463     {
464         ERR("AdjustTokenPrivileges failed\n");
465         CloseHandle(hToken);
466         return;
467     }
468 
469     /* Finally shut down the system */
470     if (!ExitWindowsEx(EWX_REBOOT, SHTDN_REASON_MAJOR_OTHER | SHTDN_REASON_MINOR_OTHER | SHTDN_REASON_FLAG_PLANNED))
471     {
472         ERR("ExitWindowsEx failed\n");
473         CloseHandle(hToken);
474     }
475 }
476 
477 
478 static VOID
479 UpdateDriverDlg(IN HWND hwndDlg,
480                 IN PDEVADVPROP_INFO dap)
481 {
482     HDEVINFO DeviceInfoSet;
483     PSP_DEVINFO_DATA DeviceInfoData;
484 
485     if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
486     {
487         DeviceInfoSet = dap->CurrentDeviceInfoSet;
488         DeviceInfoData = &dap->CurrentDeviceInfoData;
489     }
490     else
491     {
492         DeviceInfoSet = dap->DeviceInfoSet;
493         DeviceInfoData = &dap->DeviceInfoData;
494     }
495 
496     /* set the device image */
497     SendDlgItemMessage(hwndDlg,
498                        IDC_DEVICON,
499                        STM_SETICON,
500                        (WPARAM)dap->hDevIcon,
501                        0);
502 
503     /* set the device name edit control text */
504     SetDlgItemText(hwndDlg,
505                    IDC_DEVNAME,
506                    dap->szDevName);
507 
508     /* query the driver provider */
509     if (GetDriverProviderString(DeviceInfoSet,
510                                 DeviceInfoData,
511                                 dap->szTemp,
512                                 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
513     {
514         SetDlgItemText(hwndDlg,
515                        IDC_DRVPROVIDER,
516                        dap->szTemp);
517     }
518 
519     /* query the driver date */
520     if (GetDriverDateString(DeviceInfoSet,
521                             DeviceInfoData,
522                             dap->szTemp,
523                             sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
524     {
525         SetDlgItemText(hwndDlg,
526                        IDC_DRVDATE,
527                        dap->szTemp);
528     }
529 
530     /* query the driver version */
531     if (GetDriverVersionString(DeviceInfoSet,
532                                DeviceInfoData,
533                                dap->szTemp,
534                                sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
535     {
536         SetDlgItemText(hwndDlg,
537                        IDC_DRVVERSION,
538                        dap->szTemp);
539     }
540 }
541 
542 
543 static INT_PTR
544 CALLBACK
545 AdvProcDriverDlgProc(IN HWND hwndDlg,
546                      IN UINT uMsg,
547                      IN WPARAM wParam,
548                      IN LPARAM lParam)
549 {
550     PDEVADVPROP_INFO dap;
551     INT_PTR Ret = FALSE;
552 
553     dap = (PDEVADVPROP_INFO)GetWindowLongPtr(hwndDlg,
554                                              DWL_USER);
555 
556     if (dap != NULL || uMsg == WM_INITDIALOG)
557     {
558         switch (uMsg)
559         {
560             case WM_COMMAND:
561             {
562                 switch (LOWORD(wParam))
563                 {
564                     case IDC_DRIVERDETAILS:
565                         DialogBoxParam(hDllInstance,
566                                        MAKEINTRESOURCE(IDD_DRIVERDETAILS),
567                                        hwndDlg,
568                                        DriverDetailsDlgProc,
569                                        (ULONG_PTR)dap);
570                         break;
571 
572                     case IDC_UPDATEDRIVER:
573                         UpdateDriver(hwndDlg, dap);
574                         break;
575                 }
576                 break;
577             }
578 
579             case WM_NOTIFY:
580             {
581                 NMHDR *hdr = (NMHDR*)lParam;
582                 switch (hdr->code)
583                 {
584                     case PSN_APPLY:
585                         break;
586                 }
587                 break;
588             }
589 
590             case WM_INITDIALOG:
591             {
592                 dap = (PDEVADVPROP_INFO)((LPPROPSHEETPAGE)lParam)->lParam;
593                 if (dap != NULL)
594                 {
595                     SetWindowLongPtr(hwndDlg,
596                                      DWL_USER,
597                                      (DWORD_PTR)dap);
598 
599                     UpdateDriverDlg(hwndDlg,
600                                     dap);
601                 }
602                 Ret = TRUE;
603                 break;
604             }
605         }
606     }
607 
608     return Ret;
609 }
610 
611 
612 static VOID
613 SetListViewText(HWND hwnd,
614                 INT iItem,
615                 LPCWSTR lpText)
616 {
617     LVITEM li;
618 
619     li.mask = LVIF_TEXT | LVIF_STATE;
620     li.iItem = iItem;
621     li.iSubItem = 0;
622     li.state = 0; //(li.iItem == 0 ? LVIS_SELECTED : 0);
623     li.stateMask = LVIS_SELECTED;
624     li.pszText = (LPWSTR)lpText;
625     (void)ListView_InsertItem(hwnd,
626                               &li);
627 }
628 
629 
630 static VOID
631 UpdateDetailsDlg(IN HWND hwndDlg,
632                  IN PDEVADVPROP_INFO dap)
633 {
634     HWND hwndComboBox;
635     HWND hwndListView;
636     LV_COLUMN lvc;
637     RECT rcClient;
638 
639     UINT i;
640     UINT Properties[] =
641     {
642         IDS_PROP_DEVICEID,
643         IDS_PROP_HARDWAREIDS,
644         IDS_PROP_COMPATIBLEIDS,
645         IDS_PROP_MATCHINGDEVICEID,
646         IDS_PROP_SERVICE,
647         IDS_PROP_ENUMERATOR,
648         IDS_PROP_CAPABILITIES,
649         IDS_PROP_DEVNODEFLAGS,
650         IDS_PROP_CONFIGFLAGS,
651         IDS_PROP_CSCONFIGFLAGS,
652         IDS_PROP_EJECTIONRELATIONS,
653         IDS_PROP_REMOVALRELATIONS,
654         IDS_PROP_BUSRELATIONS,
655         IDS_PROP_DEVUPPERFILTERS,
656         IDS_PROP_DEVLOWERFILTERS,
657         IDS_PROP_CLASSUPPERFILTERS,
658         IDS_PROP_CLASSLOWERFILTERS,
659         IDS_PROP_CLASSINSTALLER,
660         IDS_PROP_CLASSCOINSTALLER,
661         IDS_PROP_DEVICECOINSTALLER,
662         IDS_PROP_FIRMWAREREVISION,
663         IDS_PROP_CURRENTPOWERSTATE,
664         IDS_PROP_POWERCAPABILITIES,
665         IDS_PROP_POWERSTATEMAPPINGS
666     };
667 
668 
669     /* set the device image */
670     SendDlgItemMessage(hwndDlg,
671                        IDC_DEVICON,
672                        STM_SETICON,
673                        (WPARAM)dap->hDevIcon,
674                        0);
675 
676     /* set the device name edit control text */
677     SetDlgItemText(hwndDlg,
678                    IDC_DEVNAME,
679                    dap->szDevName);
680 
681 
682     hwndComboBox = GetDlgItem(hwndDlg,
683                               IDC_DETAILSPROPNAME);
684 
685     hwndListView = GetDlgItem(hwndDlg,
686                               IDC_DETAILSPROPVALUE);
687 
688     for (i = 0; i != sizeof(Properties) / sizeof(Properties[0]); i++)
689     {
690         /* fill in the device usage combo box */
691         if (LoadString(hDllInstance,
692                        Properties[i],
693                        dap->szTemp,
694                        sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
695         {
696             SendMessage(hwndComboBox,
697                         CB_ADDSTRING,
698                         0,
699                         (LPARAM)dap->szTemp);
700         }
701     }
702 
703 
704     GetClientRect(hwndListView,
705                   &rcClient);
706 
707     /* add a column to the list view control */
708     lvc.mask = LVCF_FMT | LVCF_WIDTH;
709     lvc.fmt = LVCFMT_LEFT;
710     lvc.cx = rcClient.right;
711     (void)ListView_InsertColumn(hwndListView,
712                                 0,
713                                 &lvc);
714 
715     SendMessage(hwndComboBox,
716                 CB_SETCURSEL,
717                 0,
718                 0);
719 
720     SetListViewText(hwndListView, 0, dap->szDeviceID);
721 
722     SetFocus(hwndComboBox);
723 }
724 
725 
726 static VOID
727 DisplayDevicePropertyText(IN PDEVADVPROP_INFO dap,
728                           IN HWND hwndListView,
729                           IN DWORD dwProperty)
730 {
731     HDEVINFO DeviceInfoSet;
732     PSP_DEVINFO_DATA DeviceInfoData;
733     DWORD dwType;
734     DWORD dwSize;
735     DWORD dwValue;
736     LPBYTE lpBuffer;
737     LPWSTR lpStr;
738     INT len;
739     INT index;
740 
741     if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
742     {
743         DeviceInfoSet = dap->CurrentDeviceInfoSet;
744         DeviceInfoData = &dap->CurrentDeviceInfoData;
745     }
746     else
747     {
748         DeviceInfoSet = dap->DeviceInfoSet;
749         DeviceInfoData = &dap->DeviceInfoData;
750     }
751 
752     dwSize = 0;
753     SetupDiGetDeviceRegistryProperty(DeviceInfoSet,
754                                      DeviceInfoData,
755                                      dwProperty,
756                                      &dwType,
757                                      NULL,
758                                      0,
759                                      &dwSize);
760     if (dwSize == 0)
761     {
762         if (GetLastError() != ERROR_FILE_NOT_FOUND)
763         {
764             swprintf(dap->szTemp, L"Error: Getting the size failed! (Error: %ld)", GetLastError());
765             SetListViewText(hwndListView, 0, dap->szTemp);
766         }
767         return;
768     }
769 
770     if (dwType == REG_SZ)
771         dwSize += sizeof(WCHAR);
772 
773     lpBuffer = (LPBYTE)HeapAlloc(GetProcessHeap(),
774                                  HEAP_ZERO_MEMORY,
775                                  dwSize);
776     if (lpBuffer == NULL)
777     {
778         SetListViewText(hwndListView, 0, L"Error: Allocating the buffer failed!");
779         return;
780     }
781 
782     if (SetupDiGetDeviceRegistryProperty(DeviceInfoSet,
783                                          DeviceInfoData,
784                                          dwProperty,
785                                          &dwType,
786                                          lpBuffer,
787                                          dwSize,
788                                          &dwSize))
789     {
790         if (dwType == REG_SZ)
791         {
792             SetListViewText(hwndListView, 0, (LPWSTR)lpBuffer);
793         }
794         else if (dwType == REG_MULTI_SZ)
795         {
796             lpStr = (LPWSTR)lpBuffer;
797             index = 0;
798             while (*lpStr != 0)
799             {
800                 len = wcslen(lpStr) + 1;
801 
802                 SetListViewText(hwndListView, index, lpStr);
803 
804                 lpStr += len;
805                 index++;
806             }
807         }
808         else if (dwType == REG_DWORD)
809         {
810             dwValue = *(DWORD *) lpBuffer;
811 
812             switch (dwProperty)
813             {
814                 case SPDRP_CAPABILITIES:
815                     index = 0;
816                     if (dwValue & CM_DEVCAP_LOCKSUPPORTED)
817                         SetListViewText(hwndListView, index++, L"CM_DEVCAP_LOCKSUPPORTED");
818                     if (dwValue & CM_DEVCAP_EJECTSUPPORTED)
819                         SetListViewText(hwndListView, index++, L"CM_DEVCAP_EJECTSUPPORTED");
820                     if (dwValue & CM_DEVCAP_REMOVABLE)
821                         SetListViewText(hwndListView, index++, L"CM_DEVCAP_REMOVABLE");
822                     if (dwValue & CM_DEVCAP_DOCKDEVICE)
823                         SetListViewText(hwndListView, index++, L"CM_DEVCAP_DOCKDEVICE");
824                     if (dwValue & CM_DEVCAP_UNIQUEID)
825                         SetListViewText(hwndListView, index++, L"CM_DEVCAP_UNIQUEID");
826                     if (dwValue & CM_DEVCAP_SILENTINSTALL)
827                         SetListViewText(hwndListView, index++, L"CM_DEVCAP_SILENTINSTALL");
828                     if (dwValue & CM_DEVCAP_RAWDEVICEOK)
829                         SetListViewText(hwndListView, index++, L"CM_DEVCAP_RAWDEVICEOK");
830                     if (dwValue & CM_DEVCAP_SURPRISEREMOVALOK)
831                         SetListViewText(hwndListView, index++, L"CM_DEVCAP_SURPRISEREMOVALOK");
832                     if (dwValue & CM_DEVCAP_HARDWAREDISABLED)
833                         SetListViewText(hwndListView, index++, L"CM_DEVCAP_HARDWAREDISABLED");
834                     if (dwValue & CM_DEVCAP_NONDYNAMIC)
835                         SetListViewText(hwndListView, index++, L"CM_DEVCAP_NONDYNAMIC");
836                     break;
837 
838                 case SPDRP_CONFIGFLAGS:
839                     index = 0;
840                     if (dwValue & CONFIGFLAG_DISABLED)
841                         SetListViewText(hwndListView, index++, L"CONFIGFLAG_DISABLED");
842                     if (dwValue & CONFIGFLAG_REMOVED)
843                         SetListViewText(hwndListView, index++, L"CONFIGFLAG_REMOVED");
844                     if (dwValue & CONFIGFLAG_MANUAL_INSTALL)
845                         SetListViewText(hwndListView, index++, L"CONFIGFLAG_MANUAL_INSTALL");
846                     if (dwValue & CONFIGFLAG_IGNORE_BOOT_LC)
847                         SetListViewText(hwndListView, index++, L"CONFIGFLAG_IGNORE_BOOT_LC");
848                     if (dwValue & CONFIGFLAG_NET_BOOT)
849                         SetListViewText(hwndListView, index++, L"CONFIGFLAG_NET_BOOT");
850                     if (dwValue & CONFIGFLAG_REINSTALL)
851                         SetListViewText(hwndListView, index++, L"CONFIGFLAG_REINSTALL");
852                     if (dwValue & CONFIGFLAG_FAILEDINSTALL)
853                         SetListViewText(hwndListView, index++, L"CONFIGFLAG_FAILEDINSTALL");
854                     if (dwValue & CONFIGFLAG_CANTSTOPACHILD)
855                         SetListViewText(hwndListView, index++, L"CONFIGFLAG_CANTSTOPACHILD");
856                     if (dwValue & CONFIGFLAG_OKREMOVEROM)
857                         SetListViewText(hwndListView, index++, L"CONFIGFLAG_OKREMOVEROM");
858                     if (dwValue & CONFIGFLAG_NOREMOVEEXIT)
859                         SetListViewText(hwndListView, index++, L"CONFIGFLAG_NOREMOVEEXIT");
860                     break;
861 
862                 default:
863                     swprintf(dap->szTemp, L"0x%08lx", dwValue);
864                     SetListViewText(hwndListView, 0, dap->szTemp);
865                     break;
866             }
867         }
868         else
869         {
870             SetListViewText(hwndListView, 0, L"Error: Unsupported value type!");
871 
872         }
873     }
874     else
875     {
876         SetListViewText(hwndListView, 0, L"Error: Retrieving the value failed!");
877     }
878 
879     HeapFree(GetProcessHeap(),
880              0,
881              lpBuffer);
882 }
883 
884 static VOID
885 DisplayDevNodeFlags(IN PDEVADVPROP_INFO dap,
886                     IN HWND hwndListView)
887 {
888     DWORD dwStatus = 0;
889     DWORD dwProblem = 0;
890     INT index;
891 
892     CM_Get_DevNode_Status_Ex(&dwStatus,
893                              &dwProblem,
894                              dap->DeviceInfoData.DevInst,
895                              0,
896                              dap->hMachine);
897 
898     index = 0;
899     if (dwStatus & DN_ROOT_ENUMERATED)
900         SetListViewText(hwndListView, index++, L"DN_ROOT_ENUMERATED");
901     if (dwStatus & DN_DRIVER_LOADED)
902         SetListViewText(hwndListView, index++, L"DN_DRIVER_LOADED");
903     if (dwStatus & DN_ENUM_LOADED)
904         SetListViewText(hwndListView, index++, L"DN_ENUM_LOADED");
905     if (dwStatus & DN_STARTED)
906         SetListViewText(hwndListView, index++, L"DN_STARTED");
907     if (dwStatus & DN_MANUAL)
908         SetListViewText(hwndListView, index++, L"DN_MANUAL");
909     if (dwStatus & DN_NEED_TO_ENUM)
910         SetListViewText(hwndListView, index++, L"DN_NEED_TO_ENUM");
911     if (dwStatus & DN_DRIVER_BLOCKED)
912         SetListViewText(hwndListView, index++, L"DN_DRIVER_BLOCKED");
913     if (dwStatus & DN_HARDWARE_ENUM)
914         SetListViewText(hwndListView, index++, L"DN_HARDWARE_ENUM");
915     if (dwStatus & DN_NEED_RESTART)
916         SetListViewText(hwndListView, index++, L"DN_NEED_RESTART");
917     if (dwStatus & DN_CHILD_WITH_INVALID_ID)
918         SetListViewText(hwndListView, index++, L"DN_CHILD_WITH_INVALID_ID");
919     if (dwStatus & DN_HAS_PROBLEM)
920         SetListViewText(hwndListView, index++, L"DN_HAS_PROBLEM");
921     if (dwStatus & DN_FILTERED)
922         SetListViewText(hwndListView, index++, L"DN_FILTERED");
923     if (dwStatus & DN_LEGACY_DRIVER)
924         SetListViewText(hwndListView, index++, L"DN_LEGACY_DRIVER");
925     if (dwStatus & DN_DISABLEABLE)
926         SetListViewText(hwndListView, index++, L"DN_DISABLEABLE");
927     if (dwStatus & DN_REMOVABLE)
928         SetListViewText(hwndListView, index++, L"DN_REMOVABLE");
929     if (dwStatus & DN_PRIVATE_PROBLEM)
930         SetListViewText(hwndListView, index++, L"DN_PRIVATE_PROBLEM");
931     if (dwStatus & DN_MF_PARENT)
932         SetListViewText(hwndListView, index++, L"DN_MF_PARENT");
933     if (dwStatus & DN_MF_CHILD)
934         SetListViewText(hwndListView, index++, L"DN_MF_CHILD");
935     if (dwStatus & DN_WILL_BE_REMOVED)
936         SetListViewText(hwndListView, index++, L"DN_WILL_BE_REMOVED");
937 
938     if (dwStatus & DN_NOT_FIRST_TIMEE)
939         SetListViewText(hwndListView, index++, L"DN_NOT_FIRST_TIMEE");
940     if (dwStatus & DN_STOP_FREE_RES)
941         SetListViewText(hwndListView, index++, L"DN_STOP_FREE_RES");
942     if (dwStatus & DN_REBAL_CANDIDATE)
943         SetListViewText(hwndListView, index++, L"DN_REBAL_CANDIDATE");
944     if (dwStatus & DN_BAD_PARTIAL)
945         SetListViewText(hwndListView, index++, L"DN_BAD_PARTIAL");
946     if (dwStatus & DN_NT_ENUMERATOR)
947         SetListViewText(hwndListView, index++, L"DN_NT_ENUMERATOR");
948     if (dwStatus & DN_NT_DRIVER)
949         SetListViewText(hwndListView, index++, L"DN_NT_DRIVER");
950 
951     if (dwStatus & DN_NEEDS_LOCKING)
952         SetListViewText(hwndListView, index++, L"DN_NEEDS_LOCKING");
953     if (dwStatus & DN_ARM_WAKEUP)
954         SetListViewText(hwndListView, index++, L"DN_ARM_WAKEUP");
955     if (dwStatus & DN_APM_ENUMERATOR)
956         SetListViewText(hwndListView, index++, L"DN_APM_ENUMERATOR");
957     if (dwStatus & DN_APM_DRIVER)
958         SetListViewText(hwndListView, index++, L"DN_APM_DRIVER");
959     if (dwStatus & DN_SILENT_INSTALL)
960         SetListViewText(hwndListView, index++, L"DN_SILENT_INSTALL");
961     if (dwStatus & DN_NO_SHOW_IN_DM)
962         SetListViewText(hwndListView, index++, L"DN_NO_SHOW_IN_DM");
963     if (dwStatus & DN_BOOT_LOG_PROB)
964         SetListViewText(hwndListView, index++, L"DN_BOOT_LOG_PROB");
965 
966 //    swprintf(dap->szTemp, L"0x%08x", dwStatus);
967 //    SetListViewText(hwndListView, 0, dap->szTemp);
968 }
969 
970 
971 static VOID
972 DisplayDevNodeEnumerator(IN PDEVADVPROP_INFO dap,
973                          IN HWND hwndListView)
974 {
975     PSP_DEVINFO_DATA DeviceInfoData;
976 
977     DWORD dwType = 0;
978     WCHAR szBuffer[256];
979     DWORD dwSize = 256 * sizeof(WCHAR);
980 
981     if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
982     {
983         DeviceInfoData = &dap->CurrentDeviceInfoData;
984     }
985     else
986     {
987         DeviceInfoData = &dap->DeviceInfoData;
988     }
989 
990     CM_Get_DevNode_Registry_Property_ExW(DeviceInfoData->DevInst,
991                                          CM_DRP_ENUMERATOR_NAME,
992                                          &dwType,
993                                          &szBuffer,
994                                          &dwSize,
995                                          0,
996                                          dap->hMachine);
997 
998     SetListViewText(hwndListView, 0, szBuffer);
999 }
1000 
1001 
1002 static VOID
1003 DisplayCsFlags(IN PDEVADVPROP_INFO dap,
1004                IN HWND hwndListView)
1005 {
1006     DWORD dwValue = 0;
1007     INT index;
1008 
1009     CM_Get_HW_Prof_Flags_Ex(dap->szDevName,
1010                             0, /* current hardware profile */
1011                             &dwValue,
1012                             0,
1013                             dap->hMachine);
1014 
1015     index = 0;
1016     if (dwValue & CSCONFIGFLAG_DISABLED)
1017         SetListViewText(hwndListView, index++, L"CSCONFIGFLAG_DISABLED");
1018 
1019     if (dwValue & CSCONFIGFLAG_DO_NOT_CREATE)
1020         SetListViewText(hwndListView, index++, L"CSCONFIGFLAG_DO_NOT_CREATE");
1021 
1022     if (dwValue & CSCONFIGFLAG_DO_NOT_START)
1023         SetListViewText(hwndListView, index++, L"CSCONFIGFLAG_DO_NOT_START");
1024 }
1025 
1026 
1027 static VOID
1028 DisplayMatchingDeviceId(IN PDEVADVPROP_INFO dap,
1029                         IN HWND hwndListView)
1030 {
1031     HDEVINFO DeviceInfoSet;
1032     PSP_DEVINFO_DATA DeviceInfoData;
1033     WCHAR szBuffer[256];
1034     HKEY hKey;
1035     DWORD dwSize;
1036     DWORD dwType;
1037 
1038     if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
1039     {
1040         DeviceInfoSet = dap->CurrentDeviceInfoSet;
1041         DeviceInfoData = &dap->CurrentDeviceInfoData;
1042     }
1043     else
1044     {
1045         DeviceInfoSet = dap->DeviceInfoSet;
1046         DeviceInfoData = &dap->DeviceInfoData;
1047     }
1048 
1049     hKey = SetupDiOpenDevRegKey(DeviceInfoSet,
1050                                 DeviceInfoData,
1051                                 DICS_FLAG_GLOBAL,
1052                                 0,
1053                                 DIREG_DRV,
1054                                 KEY_QUERY_VALUE);
1055     if (hKey != INVALID_HANDLE_VALUE)
1056     {
1057         dwSize = 256 * sizeof(WCHAR);
1058         if (RegQueryValueEx(hKey,
1059                             L"MatchingDeviceId",
1060                             NULL,
1061                             &dwType,
1062                             (LPBYTE)szBuffer,
1063                             &dwSize) == ERROR_SUCCESS)
1064         {
1065             SetListViewText(hwndListView, 0, szBuffer);
1066         }
1067 
1068         RegCloseKey(hKey);
1069     }
1070 }
1071 
1072 
1073 static VOID
1074 DisplayClassCoinstallers(IN PDEVADVPROP_INFO dap,
1075                           IN HWND hwndListView)
1076 {
1077     HDEVINFO DeviceInfoSet;
1078     PSP_DEVINFO_DATA DeviceInfoData;
1079     WCHAR szClassGuid[45];
1080     HKEY hKey = (HKEY)INVALID_HANDLE_VALUE;
1081     DWORD dwSize;
1082     DWORD dwType;
1083     LPBYTE lpBuffer = NULL;
1084     LPWSTR lpStr;
1085     INT index;
1086     INT len;
1087     LONG lError;
1088 
1089     if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
1090     {
1091         DeviceInfoSet = dap->CurrentDeviceInfoSet;
1092         DeviceInfoData = &dap->CurrentDeviceInfoData;
1093     }
1094     else
1095     {
1096         DeviceInfoSet = dap->DeviceInfoSet;
1097         DeviceInfoData = &dap->DeviceInfoData;
1098     }
1099 
1100     dwSize = 45 * sizeof(WCHAR);
1101     if (!SetupDiGetDeviceRegistryProperty(DeviceInfoSet,
1102                                           DeviceInfoData,
1103                                           SPDRP_CLASSGUID,
1104                                           &dwType,
1105                                           (LPBYTE)szClassGuid,
1106                                           dwSize,
1107                                           &dwSize))
1108         return;
1109 
1110     lError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1111                            L"SYSTEM\\CurrentControlSet\\Control\\CoDeviceInstallers",
1112                            0,
1113                            GENERIC_READ,
1114                            &hKey);
1115     if (lError != ERROR_SUCCESS)
1116         return;
1117 
1118     dwSize = 0;
1119     lError = RegQueryValueEx(hKey,
1120                              szClassGuid,
1121                              NULL,
1122                              &dwType,
1123                              NULL,
1124                              &dwSize);
1125     if (lError != ERROR_SUCCESS)
1126         goto done;
1127 
1128     if (dwSize == 0)
1129         goto done;
1130 
1131     lpBuffer = (LPBYTE)HeapAlloc(GetProcessHeap(),
1132                                  HEAP_ZERO_MEMORY,
1133                                  dwSize);
1134 
1135     RegQueryValueEx(hKey,
1136                     szClassGuid,
1137                     NULL,
1138                     &dwType,
1139                     lpBuffer,
1140                     &dwSize);
1141 
1142     lpStr = (LPWSTR)lpBuffer;
1143     index = 0;
1144     while (*lpStr != 0)
1145     {
1146         len = wcslen(lpStr) + 1;
1147 
1148         SetListViewText(hwndListView, index, lpStr);
1149 
1150         lpStr += len;
1151         index++;
1152     }
1153 
1154 done:
1155     if (lpBuffer != NULL)
1156         HeapFree(GetProcessHeap(), 0, lpBuffer);
1157 
1158     if (hKey != INVALID_HANDLE_VALUE)
1159         RegCloseKey(hKey);
1160 }
1161 
1162 
1163 static VOID
1164 DisplayDeviceCoinstallers(IN PDEVADVPROP_INFO dap,
1165                           IN HWND hwndListView)
1166 {
1167     HDEVINFO DeviceInfoSet;
1168     PSP_DEVINFO_DATA DeviceInfoData;
1169     HKEY hKey;
1170     DWORD dwSize;
1171     DWORD dwType;
1172     LPBYTE lpBuffer;
1173     LPWSTR lpStr;
1174     INT index;
1175     INT len;
1176 
1177     if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
1178     {
1179         DeviceInfoSet = dap->CurrentDeviceInfoSet;
1180         DeviceInfoData = &dap->CurrentDeviceInfoData;
1181     }
1182     else
1183     {
1184         DeviceInfoSet = dap->DeviceInfoSet;
1185         DeviceInfoData = &dap->DeviceInfoData;
1186     }
1187 
1188     hKey = SetupDiOpenDevRegKey(DeviceInfoSet,
1189                                 DeviceInfoData,
1190                                 DICS_FLAG_GLOBAL,
1191                                 0,
1192                                 DIREG_DRV,
1193                                 KEY_QUERY_VALUE);
1194     if (hKey != INVALID_HANDLE_VALUE)
1195     {
1196         dwSize = 0;
1197         if (RegQueryValueEx(hKey,
1198                             L"CoInstallers32",
1199                             NULL,
1200                             &dwType,
1201                             NULL,
1202                             &dwSize) == ERROR_SUCCESS &&
1203             dwSize > 0)
1204         {
1205 
1206             lpBuffer = (LPBYTE)HeapAlloc(GetProcessHeap(),
1207                                          HEAP_ZERO_MEMORY,
1208                                          dwSize);
1209 
1210             RegQueryValueEx(hKey,
1211                             L"CoInstallers32",
1212                             NULL,
1213                             &dwType,
1214                             lpBuffer,
1215                             &dwSize);
1216 
1217             lpStr = (LPWSTR)lpBuffer;
1218             index = 0;
1219             while (*lpStr != 0)
1220             {
1221                 len = wcslen(lpStr) + 1;
1222 
1223                 SetListViewText(hwndListView, index, lpStr);
1224 
1225                 lpStr += len;
1226                 index++;
1227             }
1228 
1229             HeapFree(GetProcessHeap(),
1230                      0,
1231                      lpBuffer);
1232         }
1233 
1234         RegCloseKey(hKey);
1235     }
1236 }
1237 
1238 
1239 static VOID
1240 DisplayClassProperties(IN PDEVADVPROP_INFO dap,
1241                        IN HWND hwndListView,
1242                        IN LPCWSTR lpProperty)
1243 {
1244     HDEVINFO DeviceInfoSet;
1245     PSP_DEVINFO_DATA DeviceInfoData;
1246     WCHAR szClassGuid[45];
1247     DWORD dwSize;
1248     DWORD dwType;
1249     HKEY hKey;
1250     GUID ClassGuid;
1251     LPBYTE lpBuffer;
1252     LPWSTR lpStr;
1253     INT index = 0;
1254     INT len;
1255 
1256     if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
1257     {
1258         DeviceInfoSet = dap->CurrentDeviceInfoSet;
1259         DeviceInfoData = &dap->CurrentDeviceInfoData;
1260     }
1261     else
1262     {
1263         DeviceInfoSet = dap->DeviceInfoSet;
1264         DeviceInfoData = &dap->DeviceInfoData;
1265     }
1266 
1267     dwSize = 45 * sizeof(WCHAR);
1268     if (!SetupDiGetDeviceRegistryProperty(DeviceInfoSet,
1269                                           DeviceInfoData,
1270                                           SPDRP_CLASSGUID,
1271                                           &dwType,
1272                                           (LPBYTE)szClassGuid,
1273                                           dwSize,
1274                                           &dwSize))
1275         return;
1276 
1277     pSetupGuidFromString(szClassGuid,
1278                          &ClassGuid);
1279 
1280     hKey = SetupDiOpenClassRegKey(&ClassGuid,
1281                                   KEY_QUERY_VALUE);
1282     if (hKey != INVALID_HANDLE_VALUE)
1283     {
1284         dwSize = 0;
1285         if (RegQueryValueEx(hKey,
1286                             lpProperty,
1287                             NULL,
1288                             &dwType,
1289                             NULL,
1290                             &dwSize) == ERROR_SUCCESS &&
1291             dwSize > 0)
1292         {
1293             lpBuffer = (LPBYTE)HeapAlloc(GetProcessHeap(),
1294                                          HEAP_ZERO_MEMORY,
1295                                          dwSize);
1296 
1297             RegQueryValueEx(hKey,
1298                             lpProperty,
1299                             NULL,
1300                             &dwType,
1301                             lpBuffer,
1302                             &dwSize);
1303 
1304             if (dwType == REG_SZ)
1305             {
1306                 SetListViewText(hwndListView, 0, (LPWSTR)lpBuffer);
1307             }
1308             else if (dwType == REG_MULTI_SZ)
1309             {
1310                 lpStr = (LPWSTR)lpBuffer;
1311                 index = 0;
1312                 while (*lpStr != 0)
1313                 {
1314                     len = wcslen(lpStr) + 1;
1315 
1316                     SetListViewText(hwndListView, index, lpStr);
1317 
1318                     lpStr += len;
1319                     index++;
1320                 }
1321             }
1322 
1323             HeapFree(GetProcessHeap(),
1324                      0,
1325                      lpBuffer);
1326         }
1327 
1328         RegCloseKey(hKey);
1329     }
1330 }
1331 
1332 
1333 static VOID
1334 DisplayDeviceRelations(
1335     IN PDEVADVPROP_INFO dap,
1336     IN HWND hwndListView,
1337     IN ULONG ulFlags)
1338 {
1339     ULONG ulLength = 0;
1340     LPWSTR pszBuffer = NULL, pszStr;
1341     INT index = 0, len;
1342     CONFIGRET ret;
1343 
1344     ret = CM_Get_Device_ID_List_Size_ExW(&ulLength,
1345                                          dap->szDeviceID,
1346                                          ulFlags,
1347                                          NULL);
1348     if (ret != CR_SUCCESS)
1349         return;
1350 
1351     pszBuffer = (LPWSTR)HeapAlloc(GetProcessHeap(),
1352                                   HEAP_ZERO_MEMORY,
1353                                   ulLength * sizeof(WCHAR));
1354     if (pszBuffer == NULL)
1355         return;
1356 
1357     ret = CM_Get_Device_ID_List_ExW(dap->szDeviceID,
1358                                     pszBuffer,
1359                                     ulLength,
1360                                     ulFlags,
1361                                     NULL);
1362     if (ret != CR_SUCCESS)
1363     {
1364         HeapFree(GetProcessHeap(), 0, pszBuffer);
1365         return;
1366     }
1367 
1368     pszStr = pszBuffer;
1369     index = 0;
1370     while (*pszStr != 0)
1371     {
1372         len = wcslen(pszStr) + 1;
1373 
1374         SetListViewText(hwndListView, index, pszStr);
1375 
1376         pszStr += len;
1377         index++;
1378     }
1379 
1380     HeapFree(GetProcessHeap(), 0, pszBuffer);
1381 }
1382 
1383 
1384 static VOID
1385 DisplayDeviceProperties(IN PDEVADVPROP_INFO dap,
1386                         IN HWND hwndComboBox,
1387                         IN HWND hwndListView)
1388 {
1389     INT Index;
1390 
1391     Index = (INT)SendMessage(hwndComboBox,
1392                              CB_GETCURSEL,
1393                              0,
1394                              0);
1395     if (Index == CB_ERR)
1396         return;
1397 
1398     (void)ListView_DeleteAllItems(hwndListView);
1399 
1400     switch (Index)
1401     {
1402         case 0:
1403             SetListViewText(hwndListView, 0, dap->szDeviceID);
1404             break;
1405 
1406         case 1: /* Hardware ID */
1407             DisplayDevicePropertyText(dap,
1408                                       hwndListView,
1409                                       SPDRP_HARDWAREID);
1410             break;
1411 
1412         case 2: /* Compatible IDs */
1413             DisplayDevicePropertyText(dap,
1414                                       hwndListView,
1415                                       SPDRP_COMPATIBLEIDS);
1416             break;
1417 
1418         case 3: /* Matching ID */
1419             DisplayMatchingDeviceId(dap,
1420                                     hwndListView);
1421             break;
1422 
1423         case 4: /* Service */
1424             DisplayDevicePropertyText(dap,
1425                                       hwndListView,
1426                                       SPDRP_SERVICE);
1427             break;
1428 
1429         case 5: /* Enumerator */
1430             DisplayDevNodeEnumerator(dap,
1431                                      hwndListView);
1432             break;
1433 
1434         case 6: /* Capabilities */
1435             DisplayDevicePropertyText(dap,
1436                                       hwndListView,
1437                                       SPDRP_CAPABILITIES);
1438             break;
1439 
1440         case 7: /* Devnode Flags */
1441             DisplayDevNodeFlags(dap,
1442                                 hwndListView);
1443             break;
1444 
1445         case 8: /* Config Flags */
1446             DisplayDevicePropertyText(dap,
1447                                       hwndListView,
1448                                       SPDRP_CONFIGFLAGS);
1449             break;
1450 
1451         case 9: /* CSConfig Flags */
1452             DisplayCsFlags(dap,
1453                            hwndListView);
1454             break;
1455 
1456         case 10: /* Ejection relation */
1457             DisplayDeviceRelations(dap,
1458                                    hwndListView,
1459                                    CM_GETIDLIST_FILTER_EJECTRELATIONS);
1460             break;
1461 
1462         case 11: /* Removal relations */
1463             DisplayDeviceRelations(dap,
1464                                    hwndListView,
1465                                    CM_GETIDLIST_FILTER_REMOVALRELATIONS);
1466             break;
1467 
1468         case 12: /* Bus relation */
1469             DisplayDeviceRelations(dap,
1470                                    hwndListView,
1471                                    CM_GETIDLIST_FILTER_BUSRELATIONS);
1472             break;
1473 
1474         case 13: /* Device Upper Filters */
1475             DisplayDevicePropertyText(dap,
1476                                       hwndListView,
1477                                       SPDRP_UPPERFILTERS);
1478             break;
1479 
1480         case 14: /* Device Lower Filters */
1481             DisplayDevicePropertyText(dap,
1482                                       hwndListView,
1483                                       SPDRP_LOWERFILTERS);
1484             break;
1485 
1486         case 15: /* Class Upper Filters */
1487             DisplayClassProperties(dap,
1488                                    hwndListView,
1489                                    L"UpperFilters");
1490             break;
1491 
1492         case 16: /* Class Lower Filters */
1493             DisplayClassProperties(dap,
1494                                    hwndListView,
1495                                    L"LowerFilters");
1496             break;
1497 
1498         case 17: /* Class Installer */
1499             DisplayClassProperties(dap,
1500                                    hwndListView,
1501                                    L"Installer32");
1502             break;
1503 
1504         case 18: /* Class Coinstaller */
1505             DisplayClassCoinstallers(dap,
1506                                      hwndListView);
1507             break;
1508 
1509         case 19: /* Device Coinstaller */
1510             DisplayDeviceCoinstallers(dap,
1511                                       hwndListView);
1512             break;
1513 
1514 #if 0
1515         case 20: /* Firmware Revision */
1516             break;
1517 
1518         case 21: /* Current Power State */
1519             break;
1520 
1521         case 20: /* Power Capabilities */
1522             break;
1523 
1524         case 21: /* Power State Mappings */
1525             break;
1526 #endif
1527 
1528         default:
1529             SetListViewText(hwndListView, 0, L"<Not implemented yet>");
1530             break;
1531     }
1532 }
1533 
1534 
1535 static INT_PTR
1536 CALLBACK
1537 AdvProcDetailsDlgProc(IN HWND hwndDlg,
1538                       IN UINT uMsg,
1539                       IN WPARAM wParam,
1540                       IN LPARAM lParam)
1541 {
1542     PDEVADVPROP_INFO dap;
1543     INT_PTR Ret = FALSE;
1544 
1545     dap = (PDEVADVPROP_INFO)GetWindowLongPtr(hwndDlg,
1546                                              DWL_USER);
1547 
1548     if (dap != NULL || uMsg == WM_INITDIALOG)
1549     {
1550         switch (uMsg)
1551         {
1552             case WM_COMMAND:
1553             {
1554                 switch (LOWORD(wParam))
1555                 {
1556                     case IDC_DETAILSPROPNAME:
1557                         if (HIWORD(wParam) == CBN_SELCHANGE)
1558                         {
1559                             DisplayDeviceProperties(dap,
1560                                                     GetDlgItem(hwndDlg, IDC_DETAILSPROPNAME),
1561                                                     GetDlgItem(hwndDlg, IDC_DETAILSPROPVALUE));
1562                         }
1563                         break;
1564                 }
1565                 break;
1566             }
1567 
1568             case WM_NOTIFY:
1569             {
1570                 NMHDR *hdr = (NMHDR*)lParam;
1571                 switch (hdr->code)
1572                 {
1573                     case PSN_APPLY:
1574                         break;
1575                 }
1576                 break;
1577             }
1578 
1579             case WM_INITDIALOG:
1580             {
1581                 dap = (PDEVADVPROP_INFO)((LPPROPSHEETPAGE)lParam)->lParam;
1582                 if (dap != NULL)
1583                 {
1584                     SetWindowLongPtr(hwndDlg,
1585                                      DWL_USER,
1586                                      (DWORD_PTR)dap);
1587 
1588                     UpdateDetailsDlg(hwndDlg,
1589                                      dap);
1590                 }
1591                 Ret = TRUE;
1592                 break;
1593             }
1594         }
1595     }
1596 
1597     return Ret;
1598 }
1599 
1600 
1601 static VOID
1602 InitDevUsageActions(IN HWND hwndDlg,
1603                     IN HWND hComboBox,
1604                     IN PDEVADVPROP_INFO dap)
1605 {
1606     INT Index;
1607     UINT i;
1608     UINT Actions[] =
1609     {
1610         IDS_ENABLEDEVICE,
1611         IDS_DISABLEDEVICE,
1612     };
1613 
1614     for (i = 0;
1615          i != sizeof(Actions) / sizeof(Actions[0]);
1616          i++)
1617     {
1618         /* fill in the device usage combo box */
1619         if (LoadString(hDllInstance,
1620                        Actions[i],
1621                        dap->szTemp,
1622                        sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
1623         {
1624             Index = (INT)SendMessage(hComboBox,
1625                                      CB_ADDSTRING,
1626                                      0,
1627                                      (LPARAM)dap->szTemp);
1628             if (Index != CB_ERR)
1629             {
1630                 SendMessage(hComboBox,
1631                             CB_SETITEMDATA,
1632                             (WPARAM)Index,
1633                             (LPARAM)Actions[i]);
1634 
1635                 switch (Actions[i])
1636                 {
1637                     case IDS_ENABLEDEVICE:
1638                         if (dap->DeviceStarted)
1639                         {
1640                             SendMessage(hComboBox,
1641                                         CB_SETCURSEL,
1642                                         (WPARAM)Index,
1643                                         0);
1644                         }
1645                         break;
1646 
1647                     case IDS_DISABLEDEVICE:
1648                         if (!dap->DeviceStarted)
1649                         {
1650                             SendMessage(hComboBox,
1651                                         CB_SETCURSEL,
1652                                         (WPARAM)Index,
1653                                         0);
1654                         }
1655                         break;
1656 
1657                     default:
1658                         break;
1659                 }
1660             }
1661         }
1662     }
1663 }
1664 
1665 
1666 static UINT
1667 GetSelectedUsageAction(IN HWND hComboBox)
1668 {
1669     INT Index;
1670     UINT Ret = 0;
1671 
1672     Index = (INT)SendMessage(hComboBox,
1673                              CB_GETCURSEL,
1674                              0,
1675                              0);
1676     if (Index != CB_ERR)
1677     {
1678         INT iRet = (INT) SendMessage(hComboBox,
1679                                CB_GETITEMDATA,
1680                                (WPARAM)Index,
1681                                0);
1682         if (iRet != CB_ERR)
1683         {
1684             Ret = (UINT)iRet;
1685         }
1686     }
1687 
1688     return Ret;
1689 }
1690 
1691 
1692 static BOOL
1693 ApplyGeneralSettings(IN HWND hwndDlg,
1694                      IN PDEVADVPROP_INFO dap)
1695 {
1696     BOOL Ret = FALSE;
1697 
1698     if (dap->DeviceUsageChanged && dap->IsAdmin && dap->CanDisable)
1699     {
1700         UINT SelectedUsageAction;
1701         BOOL NeedReboot = FALSE;
1702 
1703         SelectedUsageAction = GetSelectedUsageAction(GetDlgItem(hwndDlg,
1704                                                                 IDC_DEVUSAGE));
1705         switch (SelectedUsageAction)
1706         {
1707             case IDS_ENABLEDEVICE:
1708                 if (!dap->DeviceStarted)
1709                 {
1710                     Ret = EnableDevice(dap->DeviceInfoSet,
1711                                        &dap->DeviceInfoData,
1712                                        TRUE,
1713                                        0,
1714                                        &NeedReboot);
1715                 }
1716                 break;
1717 
1718             case IDS_DISABLEDEVICE:
1719                 if (dap->DeviceStarted)
1720                 {
1721                     Ret = EnableDevice(dap->DeviceInfoSet,
1722                                        &dap->DeviceInfoData,
1723                                        FALSE,
1724                                        0,
1725                                        &NeedReboot);
1726                 }
1727                 break;
1728 
1729             default:
1730                 break;
1731         }
1732 
1733         if (Ret)
1734         {
1735             if (NeedReboot)
1736             {
1737                 /* make PropertySheet() return PSM_REBOOTSYSTEM */
1738                 PropSheet_RebootSystem(hwndDlg);
1739             }
1740         }
1741         else
1742         {
1743             /* FIXME - display an error message */
1744             FIXME("Failed to enable/disable device! LastError: %d\n",
1745                   GetLastError());
1746         }
1747     }
1748     else
1749         Ret = !dap->DeviceUsageChanged;
1750 
1751     /* disable the apply button */
1752     PropSheet_UnChanged(GetParent(hwndDlg),
1753                         hwndDlg);
1754     dap->DeviceUsageChanged = FALSE;
1755     return Ret;
1756 }
1757 
1758 
1759 static VOID
1760 UpdateDevInfo(IN HWND hwndDlg,
1761               IN PDEVADVPROP_INFO dap,
1762               IN BOOL ReOpen)
1763 {
1764     HWND hDevUsage, hPropSheetDlg, hDevProbBtn;
1765     CONFIGRET cr;
1766     ULONG Status, ProblemNumber;
1767     SP_DEVINSTALL_PARAMS_W InstallParams;
1768     UINT TroubleShootStrId = IDS_TROUBLESHOOTDEV;
1769     BOOL bFlag, bDevActionAvailable = TRUE;
1770     BOOL bDrvInstalled = FALSE;
1771     DWORD iPage;
1772     HDEVINFO DeviceInfoSet = NULL;
1773     PSP_DEVINFO_DATA DeviceInfoData = NULL;
1774     PROPSHEETHEADER psh;
1775     DWORD nDriverPages = 0;
1776     BOOL RecalcPages = FALSE;
1777 
1778     hPropSheetDlg = GetParent(hwndDlg);
1779 
1780     if (dap->PageInitialized)
1781     {
1782         /* switch to the General page */
1783         PropSheet_SetCurSelByID(hPropSheetDlg,
1784                                 IDD_DEVICEGENERAL);
1785 
1786         /* remove and destroy the existing device property sheet pages */
1787         if (dap->DevPropSheets != NULL)
1788         {
1789             for (iPage = 0;
1790                  iPage != dap->nDevPropSheets;
1791                  iPage++)
1792             {
1793                 if (dap->DevPropSheets[iPage] != NULL)
1794                 {
1795                     PropSheet_RemovePage(hPropSheetDlg,
1796                                          (WPARAM) -1,
1797                                          dap->DevPropSheets[iPage]);
1798                     RecalcPages = TRUE;
1799                 }
1800             }
1801         }
1802     }
1803 
1804     iPage = 0;
1805 
1806     if (dap->FreeDevPropSheets)
1807     {
1808         /* don't free the array if it's the one allocated in
1809            DisplayDeviceAdvancedProperties */
1810         HeapFree(GetProcessHeap(),
1811                  0,
1812                  dap->DevPropSheets);
1813 
1814         dap->FreeDevPropSheets = FALSE;
1815     }
1816 
1817     dap->DevPropSheets = NULL;
1818     dap->nDevPropSheets = 0;
1819 
1820     if (ReOpen)
1821     {
1822         /* create a new device info set and re-open the device */
1823         if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
1824         {
1825             SetupDiDestroyDeviceInfoList(dap->CurrentDeviceInfoSet);
1826         }
1827 
1828         dap->ParentDevInst = 0;
1829         dap->CurrentDeviceInfoSet = SetupDiCreateDeviceInfoListEx(NULL,
1830                                                                   hwndDlg,
1831                                                                   dap->lpMachineName,
1832                                                                   NULL);
1833         if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
1834         {
1835             if (SetupDiOpenDeviceInfo(dap->CurrentDeviceInfoSet,
1836                                       dap->szDeviceID,
1837                                       hwndDlg,
1838                                       0,
1839                                       &dap->CurrentDeviceInfoData))
1840             {
1841                 if (dap->CloseDevInst)
1842                 {
1843                     SetupDiDestroyDeviceInfoList(dap->DeviceInfoSet);
1844                 }
1845 
1846                 dap->CloseDevInst = TRUE;
1847                 dap->DeviceInfoSet = dap->CurrentDeviceInfoSet;
1848                 dap->DeviceInfoData = dap->CurrentDeviceInfoData;
1849                 dap->CurrentDeviceInfoSet = INVALID_HANDLE_VALUE;
1850             }
1851             else
1852                 goto GetParentNode;
1853         }
1854         else
1855         {
1856 GetParentNode:
1857             /* get the parent node from the initial devinst */
1858             CM_Get_Parent_Ex(&dap->ParentDevInst,
1859                              dap->DeviceInfoData.DevInst,
1860                              0,
1861                              dap->hMachine);
1862         }
1863 
1864         if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
1865         {
1866             DeviceInfoSet = dap->CurrentDeviceInfoSet;
1867             DeviceInfoData = &dap->CurrentDeviceInfoData;
1868         }
1869         else
1870         {
1871             DeviceInfoSet = dap->DeviceInfoSet;
1872             DeviceInfoData = &dap->DeviceInfoData;
1873         }
1874     }
1875     else
1876     {
1877         DeviceInfoSet = dap->DeviceInfoSet;
1878         DeviceInfoData = &dap->DeviceInfoData;
1879     }
1880 
1881     dap->HasDriverPage = FALSE;
1882     dap->HasResourcePage = FALSE;
1883     dap->HasPowerPage = FALSE;
1884     if (IsDriverInstalled(DeviceInfoData->DevInst,
1885                           dap->hMachine,
1886                           &bDrvInstalled) &&
1887         bDrvInstalled)
1888     {
1889         if (SetupDiCallClassInstaller((dap->ShowRemotePages ?
1890                                            DIF_ADDREMOTEPROPERTYPAGE_ADVANCED :
1891                                            DIF_ADDPROPERTYPAGE_ADVANCED),
1892                                       DeviceInfoSet,
1893                                       DeviceInfoData))
1894         {
1895             /* get install params */
1896             InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
1897             if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet,
1898                                                 DeviceInfoData,
1899                                                 &InstallParams))
1900             {
1901                 /* zero the flags */
1902                 InstallParams.Flags = 0;
1903             }
1904 
1905             dap->HasDriverPage = !(InstallParams.Flags & DI_DRIVERPAGE_ADDED);
1906             dap->HasResourcePage = !(InstallParams.Flags & DI_RESOURCEPAGE_ADDED);
1907             dap->HasPowerPage = !(InstallParams.Flags & DI_FLAGSEX_POWERPAGE_ADDED);
1908         }
1909     }
1910 
1911     /* get the device icon */
1912     if (dap->hDevIcon != NULL)
1913     {
1914         DestroyIcon(dap->hDevIcon);
1915         dap->hDevIcon = NULL;
1916     }
1917     if (!SetupDiLoadClassIcon(&DeviceInfoData->ClassGuid,
1918                               &dap->hDevIcon,
1919                               NULL))
1920     {
1921         dap->hDevIcon = NULL;
1922     }
1923 
1924     /* get the device name */
1925     if (GetDeviceDescriptionString(DeviceInfoSet,
1926                                    DeviceInfoData,
1927                                    dap->szDevName,
1928                                    sizeof(dap->szDevName) / sizeof(dap->szDevName[0])))
1929     {
1930         PropSheet_SetTitle(hPropSheetDlg,
1931                            PSH_PROPTITLE,
1932                            dap->szDevName);
1933     }
1934 
1935     /* set the device image */
1936     SendDlgItemMessage(hwndDlg,
1937                        IDC_DEVICON,
1938                        STM_SETICON,
1939                        (WPARAM)dap->hDevIcon,
1940                        0);
1941 
1942     /* set the device name edit control text */
1943     SetDlgItemText(hwndDlg,
1944                    IDC_DEVNAME,
1945                    dap->szDevName);
1946 
1947     /* set the device type edit control text */
1948     if (GetDeviceTypeString(DeviceInfoData,
1949                             dap->szTemp,
1950                             sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
1951     {
1952         SetDlgItemText(hwndDlg,
1953                        IDC_DEVTYPE,
1954                        dap->szTemp);
1955     }
1956 
1957     /* set the device manufacturer edit control text */
1958     if (GetDeviceManufacturerString(DeviceInfoSet,
1959                                     DeviceInfoData,
1960                                     dap->szTemp,
1961                                     sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
1962     {
1963         SetDlgItemText(hwndDlg,
1964                        IDC_DEVMANUFACTURER,
1965                        dap->szTemp);
1966     }
1967 
1968     /* set the device location edit control text */
1969     if (GetDeviceLocationString(DeviceInfoSet,
1970                                 DeviceInfoData,
1971                                 dap->ParentDevInst,
1972                                 dap->szTemp,
1973                                 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
1974     {
1975         SetDlgItemText(hwndDlg,
1976                        IDC_DEVLOCATION,
1977                        dap->szTemp);
1978     }
1979 
1980     /* set the device status edit control text */
1981     if (GetDeviceStatusString(DeviceInfoData->DevInst,
1982                               dap->hMachine,
1983                               dap->szTemp,
1984                               sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
1985     {
1986         SetDlgItemText(hwndDlg,
1987                        IDC_DEVSTATUS,
1988                        dap->szTemp);
1989     }
1990 
1991     /* set the device troubleshoot button text and disable it if necessary */
1992     hDevProbBtn = GetDlgItem(hwndDlg,
1993                              IDC_DEVPROBLEM);
1994     cr = CM_Get_DevNode_Status_Ex(&Status,
1995                                   &ProblemNumber,
1996                                   DeviceInfoData->DevInst,
1997                                   0,
1998                                   dap->hMachine);
1999     if (cr == CR_SUCCESS && (Status & DN_HAS_PROBLEM))
2000     {
2001         switch (ProblemNumber)
2002         {
2003             case CM_PROB_DEVLOADER_FAILED:
2004             {
2005                 /* FIXME - only if it's not a root bus devloader,
2006                            disable the button otherwise */
2007                 TroubleShootStrId = IDS_UPDATEDRV;
2008                 break;
2009             }
2010 
2011             case CM_PROB_OUT_OF_MEMORY:
2012             case CM_PROB_ENTRY_IS_WRONG_TYPE:
2013             case CM_PROB_LACKED_ARBITRATOR:
2014             case CM_PROB_FAILED_START:
2015             case CM_PROB_LIAR:
2016             case CM_PROB_UNKNOWN_RESOURCE:
2017             {
2018                 TroubleShootStrId = IDS_UPDATEDRV;
2019                 break;
2020             }
2021 
2022             case CM_PROB_BOOT_CONFIG_CONFLICT:
2023             case CM_PROB_NORMAL_CONFLICT:
2024             case CM_PROB_REENUMERATION:
2025             {
2026                 /* FIXME - Troubleshoot conflict */
2027                 break;
2028             }
2029 
2030             case CM_PROB_FAILED_FILTER:
2031             case CM_PROB_REINSTALL:
2032             case CM_PROB_FAILED_INSTALL:
2033             {
2034                 TroubleShootStrId = IDS_REINSTALLDRV;
2035                 break;
2036             }
2037 
2038             case CM_PROB_DEVLOADER_NOT_FOUND:
2039             {
2040                 /* FIXME - 4 cases:
2041                    1) if it's a missing system devloader:
2042                       - disable the button (Reinstall Driver)
2043                    2) if it's not a system devloader but still missing:
2044                       - Reinstall Driver
2045                    3) if it's not a system devloader but the file can be found:
2046                       - Update Driver
2047                    4) if it's a missing or empty software key
2048                       - Update Driver
2049                  */
2050                 break;
2051             }
2052 
2053             case CM_PROB_INVALID_DATA:
2054             case CM_PROB_PARTIAL_LOG_CONF:
2055             case CM_PROB_NO_VALID_LOG_CONF:
2056             case CM_PROB_HARDWARE_DISABLED:
2057             case CM_PROB_CANT_SHARE_IRQ:
2058             case CM_PROB_TRANSLATION_FAILED:
2059             case CM_PROB_SYSTEM_SHUTDOWN:
2060             case CM_PROB_PHANTOM:
2061                 bDevActionAvailable = FALSE;
2062                 break;
2063 
2064             case CM_PROB_NOT_VERIFIED:
2065             case CM_PROB_DEVICE_NOT_THERE:
2066                 /* FIXME - search hardware */
2067                 break;
2068 
2069             case CM_PROB_NEED_RESTART:
2070             case CM_PROB_WILL_BE_REMOVED:
2071             case CM_PROB_MOVED:
2072             case CM_PROB_TOO_EARLY:
2073             case CM_PROB_DISABLED_SERVICE:
2074                 TroubleShootStrId = IDS_REBOOT;
2075                 break;
2076 
2077             case CM_PROB_REGISTRY:
2078                 /* FIXME - check registry? */
2079                 break;
2080 
2081             case CM_PROB_DISABLED:
2082                 /* if device was disabled by the user: */
2083                 TroubleShootStrId = IDS_ENABLEDEV;
2084                 /* FIXME - otherwise disable button because the device was
2085                            disabled by the system*/
2086                 break;
2087 
2088             case CM_PROB_DEVLOADER_NOT_READY:
2089                 /* FIXME - if it's a graphics adapter:
2090                            - if it's a a secondary adapter and the main adapter
2091                              couldn't be found
2092                              - disable  button
2093                            - else
2094                              - Properties
2095                          - else
2096                            - Update driver
2097                  */
2098                 break;
2099 
2100             case CM_PROB_FAILED_ADD:
2101                 TroubleShootStrId = IDS_PROPERTIES;
2102                 break;
2103         }
2104     }
2105 
2106     if (LoadString(hDllInstance,
2107                    TroubleShootStrId,
2108                    dap->szTemp,
2109                    sizeof(dap->szTemp) / sizeof(dap->szTemp[0])) != 0)
2110     {
2111         SetWindowText(hDevProbBtn,
2112                       dap->szTemp);
2113     }
2114     EnableWindow(hDevProbBtn,
2115                  dap->IsAdmin && bDevActionAvailable);
2116 
2117     /* check if the device can be enabled/disabled */
2118     hDevUsage = GetDlgItem(hwndDlg,
2119                            IDC_DEVUSAGE);
2120 
2121     dap->CanDisable = FALSE;
2122     dap->DeviceStarted = FALSE;
2123 
2124     if (CanDisableDevice(DeviceInfoData->DevInst,
2125                          dap->hMachine,
2126                          &bFlag))
2127     {
2128         dap->CanDisable = bFlag;
2129     }
2130 
2131     if (IsDeviceStarted(DeviceInfoData->DevInst,
2132                         dap->hMachine,
2133                         &bFlag))
2134     {
2135         dap->DeviceStarted = bFlag;
2136     }
2137 
2138     /* enable/disable the device usage controls */
2139     EnableWindow(GetDlgItem(hwndDlg,
2140                             IDC_DEVUSAGELABEL),
2141                  dap->CanDisable && dap->IsAdmin);
2142     EnableWindow(hDevUsage,
2143                  dap->CanDisable && dap->IsAdmin);
2144 
2145     /* clear the combobox */
2146     SendMessage(hDevUsage,
2147                 CB_RESETCONTENT,
2148                 0,
2149                 0);
2150     if (dap->CanDisable)
2151     {
2152         InitDevUsageActions(hwndDlg,
2153                             hDevUsage,
2154                             dap);
2155     }
2156 
2157     /* find out how many new device property sheets to add.
2158        fake a PROPSHEETHEADER structure, we don't plan to
2159        call PropertySheet again!*/
2160     psh.dwSize = sizeof(PROPSHEETHEADER);
2161     psh.dwFlags = 0;
2162     psh.nPages = 0;
2163 
2164     /* get the number of device property sheets for the device */
2165     if (!SetupDiGetClassDevPropertySheets(DeviceInfoSet,
2166                                           DeviceInfoData,
2167                                           &psh,
2168                                           0,
2169                                           &nDriverPages,
2170                                           dap->PropertySheetType) &&
2171         nDriverPages != 0 && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
2172     {
2173         dap->nDevPropSheets += nDriverPages;
2174     }
2175     else
2176     {
2177         nDriverPages = 0;
2178     }
2179 
2180     /* include the driver page */
2181     if (dap->HasDriverPage)
2182         dap->nDevPropSheets++;
2183 
2184     /* include the details page */
2185     if (dap->Extended)
2186         dap->nDevPropSheets++;
2187 
2188     if (dap->HasResourcePage)
2189         dap->nDevPropSheets++;
2190 
2191     /* add the device property sheets */
2192     if (dap->nDevPropSheets != 0)
2193     {
2194         dap->DevPropSheets = (HPROPSHEETPAGE *)HeapAlloc(GetProcessHeap(),
2195                                                          HEAP_ZERO_MEMORY,
2196                                                          dap->nDevPropSheets * sizeof(HPROPSHEETPAGE));
2197         if (dap->DevPropSheets != NULL)
2198         {
2199             if (nDriverPages != 0)
2200             {
2201                 psh.phpage = dap->DevPropSheets;
2202 
2203                 /* query the device property sheet pages to add */
2204                 if (SetupDiGetClassDevPropertySheets(DeviceInfoSet,
2205                                                      DeviceInfoData,
2206                                                      &psh,
2207                                                      dap->nDevPropSheets,
2208                                                      NULL,
2209                                                      dap->PropertySheetType))
2210                 {
2211                     /* add the property sheets */
2212                     for (iPage = 0;
2213                          iPage < nDriverPages;
2214                          iPage++)
2215                     {
2216                         if (PropSheet_AddPage(hPropSheetDlg,
2217                                               dap->DevPropSheets[iPage]))
2218                         {
2219                             RecalcPages = TRUE;
2220                         }
2221                     }
2222 
2223                     dap->FreeDevPropSheets = TRUE;
2224                 }
2225                 else
2226                 {
2227                     /* cleanup, we were unable to get the device property sheets */
2228                     iPage = nDriverPages;
2229                     dap->nDevPropSheets -= nDriverPages;
2230                     nDriverPages = 0;
2231                 }
2232             }
2233             else
2234                 iPage = 0;
2235 
2236             /* add the driver page if necessary */
2237             if (dap->HasDriverPage)
2238             {
2239                 PROPSHEETPAGE pspDriver = {0};
2240                 pspDriver.dwSize = sizeof(PROPSHEETPAGE);
2241                 pspDriver.dwFlags = PSP_DEFAULT;
2242                 pspDriver.hInstance = hDllInstance;
2243                 pspDriver.pszTemplate = (LPCWSTR)MAKEINTRESOURCE(IDD_DEVICEDRIVER);
2244                 pspDriver.pfnDlgProc = AdvProcDriverDlgProc;
2245                 pspDriver.lParam = (LPARAM)dap;
2246                 dap->DevPropSheets[iPage] = dap->pCreatePropertySheetPageW(&pspDriver);
2247                 if (dap->DevPropSheets[iPage] != NULL)
2248                 {
2249                     if (PropSheet_AddPage(hPropSheetDlg,
2250                                           dap->DevPropSheets[iPage]))
2251                     {
2252                         iPage++;
2253                         RecalcPages = TRUE;
2254                     }
2255                     else
2256                     {
2257                         dap->pDestroyPropertySheetPage(dap->DevPropSheets[iPage]);
2258                         dap->DevPropSheets[iPage] = NULL;
2259                     }
2260                 }
2261             }
2262 
2263             if (dap->Extended)
2264             {
2265                 /* Add the details page */
2266                 PROPSHEETPAGE pspDetails = {0};
2267                 pspDetails.dwSize = sizeof(PROPSHEETPAGE);
2268                 pspDetails.dwFlags = PSP_DEFAULT;
2269                 pspDetails.hInstance = hDllInstance;
2270                 pspDetails.pszTemplate = (LPCWSTR)MAKEINTRESOURCE(IDD_DEVICEDETAILS);
2271                 pspDetails.pfnDlgProc = AdvProcDetailsDlgProc;
2272                 pspDetails.lParam = (LPARAM)dap;
2273                 dap->DevPropSheets[iPage] = dap->pCreatePropertySheetPageW(&pspDetails);
2274                 if (dap->DevPropSheets[iPage] != NULL)
2275                 {
2276                     if (PropSheet_AddPage(hPropSheetDlg,
2277                                           dap->DevPropSheets[iPage]))
2278                     {
2279                         iPage++;
2280                         RecalcPages = TRUE;
2281                     }
2282                     else
2283                     {
2284                         dap->pDestroyPropertySheetPage(dap->DevPropSheets[iPage]);
2285                         dap->DevPropSheets[iPage] = NULL;
2286                     }
2287                 }
2288             }
2289 
2290             if (dap->HasResourcePage)
2291             {
2292                 PROPSHEETPAGE pspDriver = {0};
2293                 pspDriver.dwSize = sizeof(PROPSHEETPAGE);
2294                 pspDriver.dwFlags = PSP_DEFAULT;
2295                 pspDriver.hInstance = hDllInstance;
2296                 pspDriver.pszTemplate = (LPCWSTR)MAKEINTRESOURCE(IDD_DEVICERESOURCES);
2297                 pspDriver.pfnDlgProc = ResourcesProcDriverDlgProc;
2298                 pspDriver.lParam = (LPARAM)dap;
2299                 dap->DevPropSheets[iPage] = dap->pCreatePropertySheetPageW(&pspDriver);
2300                 if (dap->DevPropSheets[iPage] != NULL)
2301                 {
2302                     if (PropSheet_AddPage(hPropSheetDlg,
2303                                           dap->DevPropSheets[iPage]))
2304                     {
2305                         iPage++;
2306                         RecalcPages = TRUE;
2307                     }
2308                     else
2309                     {
2310                         dap->pDestroyPropertySheetPage(dap->DevPropSheets[iPage]);
2311                         dap->DevPropSheets[iPage] = NULL;
2312                     }
2313                 }
2314             }
2315             /* FIXME: Add the power page */
2316         }
2317         else
2318             dap->nDevPropSheets = 0;
2319     }
2320 
2321     if (RecalcPages)
2322     {
2323         PropSheet_RecalcPageSizes(hPropSheetDlg);
2324     }
2325 
2326     /* finally, disable the apply button */
2327     PropSheet_UnChanged(hPropSheetDlg,
2328                         hwndDlg);
2329     dap->DeviceUsageChanged = FALSE;
2330 }
2331 
2332 
2333 static LRESULT
2334 CALLBACK
2335 DlgParentSubWndProc(IN HWND hwnd,
2336                     IN UINT uMsg,
2337                     IN WPARAM wParam,
2338                     IN LPARAM lParam)
2339 {
2340     PDEVADVPROP_INFO dap;
2341 
2342     dap = (PDEVADVPROP_INFO)GetProp(hwnd,
2343                                     L"DevMgrDevChangeSub");
2344     if (dap != NULL)
2345     {
2346         if (uMsg == WM_DEVICECHANGE && !IsWindowVisible(dap->hWndGeneralPage))
2347         {
2348             SendMessage(dap->hWndGeneralPage,
2349                         WM_DEVICECHANGE,
2350                         wParam,
2351                         lParam);
2352         }
2353 
2354         /* pass the message the the old window proc */
2355         return CallWindowProc(dap->ParentOldWndProc,
2356                               hwnd,
2357                               uMsg,
2358                               wParam,
2359                               lParam);
2360     }
2361     else
2362     {
2363         /* this is not a good idea if the subclassed window was an ansi
2364            window, but we failed finding out the previous window proc
2365            so we can't use CallWindowProc. This should rarely - if ever -
2366            happen. */
2367 
2368         return DefWindowProc(hwnd,
2369                              uMsg,
2370                              wParam,
2371                              lParam);
2372     }
2373 }
2374 
2375 
2376 static INT_PTR
2377 CALLBACK
2378 AdvPropGeneralDlgProc(IN HWND hwndDlg,
2379                       IN UINT uMsg,
2380                       IN WPARAM wParam,
2381                       IN LPARAM lParam)
2382 {
2383     PDEVADVPROP_INFO dap;
2384     INT_PTR Ret = FALSE;
2385 
2386     dap = (PDEVADVPROP_INFO)GetWindowLongPtr(hwndDlg,
2387                                              DWL_USER);
2388 
2389     if (dap != NULL || uMsg == WM_INITDIALOG)
2390     {
2391         switch (uMsg)
2392         {
2393             case WM_COMMAND:
2394             {
2395                 switch (LOWORD(wParam))
2396                 {
2397                     case IDC_DEVUSAGE:
2398                     {
2399                         if (HIWORD(wParam) == CBN_SELCHANGE)
2400                         {
2401                             PropSheet_Changed(GetParent(hwndDlg),
2402                                               hwndDlg);
2403                             dap->DeviceUsageChanged = TRUE;
2404                         }
2405                         break;
2406                     }
2407 
2408                     case IDC_DEVPROBLEM:
2409                     {
2410                         if (dap->IsAdmin)
2411                         {
2412                             /* display the device problem wizard */
2413                             ShowDeviceProblemWizard(hwndDlg,
2414                                                     dap->DeviceInfoSet,
2415                                                     &dap->DeviceInfoData,
2416                                                     dap->hMachine);
2417                         }
2418                         break;
2419                     }
2420                 }
2421                 break;
2422             }
2423 
2424             case WM_NOTIFY:
2425             {
2426                 NMHDR *hdr = (NMHDR*)lParam;
2427                 switch (hdr->code)
2428                 {
2429                     case PSN_APPLY:
2430                         ApplyGeneralSettings(hwndDlg,
2431                                              dap);
2432                         break;
2433                 }
2434                 break;
2435             }
2436 
2437             case WM_INITDIALOG:
2438             {
2439                 dap = (PDEVADVPROP_INFO)((LPPROPSHEETPAGE)lParam)->lParam;
2440                 if (dap != NULL)
2441                 {
2442                     HWND hWndParent;
2443 
2444                     dap->hWndGeneralPage = hwndDlg;
2445 
2446                     SetWindowLongPtr(hwndDlg,
2447                                      DWL_USER,
2448                                      (DWORD_PTR)dap);
2449 
2450                     /* subclass the parent window to always receive
2451                        WM_DEVICECHANGE messages */
2452                     hWndParent = GetParent(hwndDlg);
2453                     if (hWndParent != NULL)
2454                     {
2455                         /* subclass the parent window. This is not safe
2456                            if the parent window belongs to another thread! */
2457                         dap->ParentOldWndProc = (WNDPROC)SetWindowLongPtr(hWndParent,
2458                                                                           GWLP_WNDPROC,
2459                                                                           (LONG_PTR)DlgParentSubWndProc);
2460 
2461                         if (dap->ParentOldWndProc != NULL &&
2462                             SetProp(hWndParent,
2463                                     L"DevMgrDevChangeSub",
2464                                     (HANDLE)dap))
2465                         {
2466                             dap->hWndParent = hWndParent;
2467                         }
2468                     }
2469 
2470                     /* do not call UpdateDevInfo directly in here because it modifies
2471                        the pages of the property sheet! */
2472                     PostMessage(hwndDlg,
2473                                 PM_INITIALIZE,
2474                                 0,
2475                                 0);
2476                 }
2477                 Ret = TRUE;
2478                 break;
2479             }
2480 
2481             case WM_DEVICECHANGE:
2482             {
2483                 /* FIXME - don't call UpdateDevInfo for all events */
2484                 UpdateDevInfo(hwndDlg,
2485                               dap,
2486                               TRUE);
2487                 Ret = TRUE;
2488                 break;
2489             }
2490 
2491             case PM_INITIALIZE:
2492             {
2493                 UpdateDevInfo(hwndDlg,
2494                               dap,
2495                               FALSE);
2496                 dap->PageInitialized = TRUE;
2497                 break;
2498             }
2499 
2500             case WM_DESTROY:
2501             {
2502                 /* restore the old window proc of the subclassed parent window */
2503                 if (dap->hWndParent != NULL && dap->ParentOldWndProc != NULL)
2504                 {
2505                     if (SetWindowLongPtr(dap->hWndParent,
2506                                          GWLP_WNDPROC,
2507                                          (LONG_PTR)dap->ParentOldWndProc) == (LONG_PTR)DlgParentSubWndProc)
2508                     {
2509                         RemoveProp(dap->hWndParent,
2510                                    L"DevMgrDevChangeSub");
2511                     }
2512                 }
2513                 break;
2514             }
2515         }
2516     }
2517 
2518     return Ret;
2519 }
2520 
2521 
2522 INT_PTR
2523 DisplayDeviceAdvancedProperties(IN HWND hWndParent,
2524                                 IN LPCWSTR lpDeviceID  OPTIONAL,
2525                                 IN HDEVINFO DeviceInfoSet,
2526                                 IN PSP_DEVINFO_DATA DeviceInfoData,
2527                                 IN HINSTANCE hComCtl32,
2528                                 IN LPCWSTR lpMachineName,
2529                                 IN DWORD dwFlags)
2530 {
2531     PROPSHEETHEADER psh = {0};
2532     PROPSHEETPAGE pspGeneral = {0};
2533     PPROPERTYSHEETW pPropertySheetW;
2534     PCREATEPROPERTYSHEETPAGEW pCreatePropertySheetPageW;
2535     PDESTROYPROPERTYSHEETPAGE pDestroyPropertySheetPage;
2536     PDEVADVPROP_INFO DevAdvPropInfo;
2537     HMACHINE hMachine = NULL;
2538     DWORD DevIdSize = 0;
2539     INT_PTR Ret = -1;
2540 
2541     /* we don't want to statically link against comctl32, so find the
2542        functions we need dynamically */
2543     pPropertySheetW =
2544         (PPROPERTYSHEETW)GetProcAddress(hComCtl32,
2545                                         "PropertySheetW");
2546     pCreatePropertySheetPageW =
2547         (PCREATEPROPERTYSHEETPAGEW)GetProcAddress(hComCtl32,
2548                                                   "CreatePropertySheetPageW");
2549     pDestroyPropertySheetPage =
2550         (PDESTROYPROPERTYSHEETPAGE)GetProcAddress(hComCtl32,
2551                                                   "DestroyPropertySheetPage");
2552     if (pPropertySheetW == NULL ||
2553         pCreatePropertySheetPageW == NULL ||
2554         pDestroyPropertySheetPage == NULL)
2555     {
2556         return -1;
2557     }
2558 
2559     if (lpDeviceID == NULL)
2560     {
2561         /* find out how much size is needed for the device id */
2562         if (SetupDiGetDeviceInstanceId(DeviceInfoSet,
2563                                        DeviceInfoData,
2564                                        NULL,
2565                                        0,
2566                                        &DevIdSize))
2567         {
2568             ERR("SetupDiGetDeviceInstanceId unexpectedly returned TRUE!\n");
2569             return -1;
2570         }
2571 
2572         if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
2573         {
2574             return -1;
2575         }
2576     }
2577     else
2578     {
2579         DevIdSize = (DWORD)wcslen(lpDeviceID) + 1;
2580     }
2581 
2582     if (lpMachineName != NULL && lpMachineName[0] != L'\0')
2583     {
2584         CONFIGRET cr = CM_Connect_Machine(lpMachineName,
2585                                           &hMachine);
2586         if (cr != CR_SUCCESS)
2587         {
2588             return -1;
2589         }
2590     }
2591 
2592     /* create the internal structure associated with the "General",
2593        "Driver", ... pages */
2594     DevAdvPropInfo = (PDEVADVPROP_INFO)HeapAlloc(GetProcessHeap(),
2595                                                  HEAP_ZERO_MEMORY,
2596                                                  FIELD_OFFSET(DEVADVPROP_INFO,
2597                                                               szDeviceID) +
2598                                                      (DevIdSize * sizeof(WCHAR)));
2599     if (DevAdvPropInfo == NULL)
2600     {
2601         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2602         goto Cleanup;
2603     }
2604 
2605     if (lpDeviceID == NULL)
2606     {
2607         /* read the device instance id */
2608         if (!SetupDiGetDeviceInstanceId(DeviceInfoSet,
2609                                         DeviceInfoData,
2610                                         DevAdvPropInfo->szDeviceID,
2611                                         DevIdSize,
2612                                         NULL))
2613         {
2614             goto Cleanup;
2615         }
2616     }
2617     else
2618     {
2619         /* copy the device instance id supplied by the caller */
2620         wcscpy(DevAdvPropInfo->szDeviceID,
2621                lpDeviceID);
2622     }
2623 
2624     DevAdvPropInfo->DeviceInfoSet = DeviceInfoSet;
2625     DevAdvPropInfo->DeviceInfoData = *DeviceInfoData;
2626     DevAdvPropInfo->CurrentDeviceInfoSet = INVALID_HANDLE_VALUE;
2627     DevAdvPropInfo->CurrentDeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
2628 
2629     DevAdvPropInfo->ShowRemotePages = (lpMachineName != NULL && lpMachineName[0] != L'\0');
2630     DevAdvPropInfo->hMachine = hMachine;
2631     DevAdvPropInfo->lpMachineName = lpMachineName;
2632     DevAdvPropInfo->szDevName[0] = L'\0';
2633     DevAdvPropInfo->hComCtl32 = hComCtl32;
2634     DevAdvPropInfo->pCreatePropertySheetPageW = pCreatePropertySheetPageW;
2635     DevAdvPropInfo->pDestroyPropertySheetPage = pDestroyPropertySheetPage;
2636 
2637     DevAdvPropInfo->IsAdmin = TRUE;// IsUserAdmin();
2638     DevAdvPropInfo->DoDefaultDevAction = ((dwFlags & DPF_DEVICE_STATUS_ACTION) != 0);
2639     DevAdvPropInfo->Extended = ((dwFlags & DPF_EXTENDED) != 0);
2640 
2641     psh.dwSize = sizeof(PROPSHEETHEADER);
2642     psh.dwFlags = PSH_PROPTITLE | PSH_NOAPPLYNOW;
2643     psh.hwndParent = hWndParent;
2644     psh.pszCaption = DevAdvPropInfo->szDevName;
2645 
2646     DevAdvPropInfo->PropertySheetType = DevAdvPropInfo->ShowRemotePages ?
2647                                             DIGCDP_FLAG_REMOTE_ADVANCED :
2648                                             DIGCDP_FLAG_ADVANCED;
2649 
2650     psh.phpage = (HPROPSHEETPAGE *)HeapAlloc(GetProcessHeap(),
2651                                              HEAP_ZERO_MEMORY,
2652                                              1 * sizeof(HPROPSHEETPAGE));
2653     if (psh.phpage == NULL)
2654     {
2655         goto Cleanup;
2656     }
2657 
2658     /* add the "General" property sheet */
2659     pspGeneral.dwSize = sizeof(PROPSHEETPAGE);
2660     pspGeneral.dwFlags = PSP_DEFAULT;
2661     pspGeneral.hInstance = hDllInstance;
2662     pspGeneral.pszTemplate = (LPCWSTR)MAKEINTRESOURCE(IDD_DEVICEGENERAL);
2663     pspGeneral.pfnDlgProc = AdvPropGeneralDlgProc;
2664     pspGeneral.lParam = (LPARAM)DevAdvPropInfo;
2665     psh.phpage[psh.nPages] = pCreatePropertySheetPageW(&pspGeneral);
2666     if (psh.phpage[psh.nPages] != NULL)
2667     {
2668         psh.nPages++;
2669     }
2670 
2671     DevAdvPropInfo->nDevPropSheets = psh.nPages;
2672 
2673     if (psh.nPages != 0)
2674     {
2675         Ret = pPropertySheetW(&psh);
2676 
2677         /* NOTE: no need to destroy the property sheets anymore! */
2678     }
2679     else
2680     {
2681         UINT i;
2682 
2683 Cleanup:
2684         /* in case of failure the property sheets must be destroyed */
2685         if (psh.phpage != NULL)
2686         {
2687             for (i = 0;
2688                  i < psh.nPages;
2689                  i++)
2690             {
2691                 if (psh.phpage[i] != NULL)
2692                 {
2693                     pDestroyPropertySheetPage(psh.phpage[i]);
2694                 }
2695             }
2696         }
2697     }
2698 
2699     if (DevAdvPropInfo != NULL)
2700     {
2701         if (DevAdvPropInfo->FreeDevPropSheets)
2702         {
2703             /* don't free the array if it's the one allocated in
2704                DisplayDeviceAdvancedProperties */
2705             HeapFree(GetProcessHeap(),
2706                      0,
2707                      DevAdvPropInfo->DevPropSheets);
2708         }
2709 
2710         if (DevAdvPropInfo->CloseDevInst)
2711         {
2712             /* close the device info set in case a new one was created */
2713             SetupDiDestroyDeviceInfoList(DevAdvPropInfo->DeviceInfoSet);
2714         }
2715 
2716         if (DevAdvPropInfo->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
2717         {
2718             SetupDiDestroyDeviceInfoList(DevAdvPropInfo->CurrentDeviceInfoSet);
2719         }
2720 
2721         if (DevAdvPropInfo->hDevIcon != NULL)
2722         {
2723             DestroyIcon(DevAdvPropInfo->hDevIcon);
2724         }
2725 
2726         HeapFree(GetProcessHeap(),
2727                  0,
2728                  DevAdvPropInfo);
2729     }
2730 
2731     if (psh.phpage != NULL)
2732     {
2733         HeapFree(GetProcessHeap(),
2734                  0,
2735                  psh.phpage);
2736     }
2737 
2738     if (hMachine != NULL)
2739     {
2740         CM_Disconnect_Machine(hMachine);
2741     }
2742 
2743     return Ret;
2744 }
2745