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