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
EnumDeviceDriverFilesCallback(IN PVOID Context,IN UINT Notification,IN UINT_PTR Param1,IN UINT_PTR Param2)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
UpdateDriverDetailsDlg(IN HWND hwndDlg,IN HWND hDriversListView,IN PDEVADVPROP_INFO dap)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
UpdateDriverVersionInfoDetails(IN HWND hwndDlg,IN LPCWSTR lpszDriverPath)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
DriverDetailsDlgProc(IN HWND hwndDlg,IN UINT uMsg,IN WPARAM wParam,IN LPARAM lParam)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                                                  _countof(szDriverPath));
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
UninstallDriverDlgProc(IN HWND hwndDlg,IN UINT uMsg,IN WPARAM wParam,IN LPARAM lParam)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
UninstallDriver(_In_ HWND hwndDlg,_In_ PDEVADVPROP_INFO dap)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
UpdateDriver(IN HWND hwndDlg,IN PDEVADVPROP_INFO dap)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
UpdateDriverDlg(IN HWND hwndDlg,IN PDEVADVPROP_INFO dap)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
AdvProcDriverDlgProc(IN HWND hwndDlg,IN UINT uMsg,IN WPARAM wParam,IN LPARAM lParam)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
SetListViewText(HWND hwnd,INT iItem,LPCWSTR lpText)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
UpdateDetailsDlg(IN HWND hwndDlg,IN PDEVADVPROP_INFO dap)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
DisplayDevicePropertyText(IN PDEVADVPROP_INFO dap,IN HWND hwndListView,IN DWORD dwProperty)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                     swprintf(dap->szTemp, L"%08lx", dwValue);
956                     SetListViewText(hwndListView, index++, dap->szTemp);
957                     if (dwValue & CM_DEVCAP_LOCKSUPPORTED)
958                         SetListViewText(hwndListView, index++, L"CM_DEVCAP_LOCKSUPPORTED");
959                     if (dwValue & CM_DEVCAP_EJECTSUPPORTED)
960                         SetListViewText(hwndListView, index++, L"CM_DEVCAP_EJECTSUPPORTED");
961                     if (dwValue & CM_DEVCAP_REMOVABLE)
962                         SetListViewText(hwndListView, index++, L"CM_DEVCAP_REMOVABLE");
963                     if (dwValue & CM_DEVCAP_DOCKDEVICE)
964                         SetListViewText(hwndListView, index++, L"CM_DEVCAP_DOCKDEVICE");
965                     if (dwValue & CM_DEVCAP_UNIQUEID)
966                         SetListViewText(hwndListView, index++, L"CM_DEVCAP_UNIQUEID");
967                     if (dwValue & CM_DEVCAP_SILENTINSTALL)
968                         SetListViewText(hwndListView, index++, L"CM_DEVCAP_SILENTINSTALL");
969                     if (dwValue & CM_DEVCAP_RAWDEVICEOK)
970                         SetListViewText(hwndListView, index++, L"CM_DEVCAP_RAWDEVICEOK");
971                     if (dwValue & CM_DEVCAP_SURPRISEREMOVALOK)
972                         SetListViewText(hwndListView, index++, L"CM_DEVCAP_SURPRISEREMOVALOK");
973                     if (dwValue & CM_DEVCAP_HARDWAREDISABLED)
974                         SetListViewText(hwndListView, index++, L"CM_DEVCAP_HARDWAREDISABLED");
975                     if (dwValue & CM_DEVCAP_NONDYNAMIC)
976                         SetListViewText(hwndListView, index++, L"CM_DEVCAP_NONDYNAMIC");
977                     break;
978 
979                 case SPDRP_CONFIGFLAGS:
980                     index = 0;
981                     swprintf(dap->szTemp, L"%08lx", dwValue);
982                     SetListViewText(hwndListView, index++, dap->szTemp);
983                     if (dwValue & CONFIGFLAG_DISABLED)
984                         SetListViewText(hwndListView, index++, L"CONFIGFLAG_DISABLED");
985                     if (dwValue & CONFIGFLAG_REMOVED)
986                         SetListViewText(hwndListView, index++, L"CONFIGFLAG_REMOVED");
987                     if (dwValue & CONFIGFLAG_MANUAL_INSTALL)
988                         SetListViewText(hwndListView, index++, L"CONFIGFLAG_MANUAL_INSTALL");
989                     if (dwValue & CONFIGFLAG_IGNORE_BOOT_LC)
990                         SetListViewText(hwndListView, index++, L"CONFIGFLAG_IGNORE_BOOT_LC");
991                     if (dwValue & CONFIGFLAG_NET_BOOT)
992                         SetListViewText(hwndListView, index++, L"CONFIGFLAG_NET_BOOT");
993                     if (dwValue & CONFIGFLAG_REINSTALL)
994                         SetListViewText(hwndListView, index++, L"CONFIGFLAG_REINSTALL");
995                     if (dwValue & CONFIGFLAG_FAILEDINSTALL)
996                         SetListViewText(hwndListView, index++, L"CONFIGFLAG_FAILEDINSTALL");
997                     if (dwValue & CONFIGFLAG_CANTSTOPACHILD)
998                         SetListViewText(hwndListView, index++, L"CONFIGFLAG_CANTSTOPACHILD");
999                     if (dwValue & CONFIGFLAG_OKREMOVEROM)
1000                         SetListViewText(hwndListView, index++, L"CONFIGFLAG_OKREMOVEROM");
1001                     if (dwValue & CONFIGFLAG_NOREMOVEEXIT)
1002                         SetListViewText(hwndListView, index++, L"CONFIGFLAG_NOREMOVEEXIT");
1003                     break;
1004 
1005                 default:
1006                     swprintf(dap->szTemp, L"0x%08lx", dwValue);
1007                     SetListViewText(hwndListView, 0, dap->szTemp);
1008                     break;
1009             }
1010         }
1011         else
1012         {
1013             SetListViewText(hwndListView, 0, L"Error: Unsupported value type!");
1014 
1015         }
1016     }
1017     else
1018     {
1019         SetListViewText(hwndListView, 0, L"Error: Retrieving the value failed!");
1020     }
1021 
1022     HeapFree(GetProcessHeap(),
1023              0,
1024              lpBuffer);
1025 }
1026 
1027 static VOID
DisplayDevNodeFlags(IN PDEVADVPROP_INFO dap,IN HWND hwndListView)1028 DisplayDevNodeFlags(IN PDEVADVPROP_INFO dap,
1029                     IN HWND hwndListView)
1030 {
1031     DWORD dwStatus = 0;
1032     DWORD dwProblem = 0;
1033     INT index;
1034 
1035     CM_Get_DevNode_Status_Ex(&dwStatus,
1036                              &dwProblem,
1037                              dap->DeviceInfoData.DevInst,
1038                              0,
1039                              dap->hMachine);
1040 
1041     index = 0;
1042     swprintf(dap->szTemp, L"%08lx", dwStatus);
1043     SetListViewText(hwndListView, index++, dap->szTemp);
1044     if (dwStatus & DN_ROOT_ENUMERATED)
1045         SetListViewText(hwndListView, index++, L"DN_ROOT_ENUMERATED");
1046     if (dwStatus & DN_DRIVER_LOADED)
1047         SetListViewText(hwndListView, index++, L"DN_DRIVER_LOADED");
1048     if (dwStatus & DN_ENUM_LOADED)
1049         SetListViewText(hwndListView, index++, L"DN_ENUM_LOADED");
1050     if (dwStatus & DN_STARTED)
1051         SetListViewText(hwndListView, index++, L"DN_STARTED");
1052     if (dwStatus & DN_MANUAL)
1053         SetListViewText(hwndListView, index++, L"DN_MANUAL");
1054     if (dwStatus & DN_NEED_TO_ENUM)
1055         SetListViewText(hwndListView, index++, L"DN_NEED_TO_ENUM");
1056     if (dwStatus & DN_DRIVER_BLOCKED)
1057         SetListViewText(hwndListView, index++, L"DN_DRIVER_BLOCKED");
1058     if (dwStatus & DN_HARDWARE_ENUM)
1059         SetListViewText(hwndListView, index++, L"DN_HARDWARE_ENUM");
1060     if (dwStatus & DN_NEED_RESTART)
1061         SetListViewText(hwndListView, index++, L"DN_NEED_RESTART");
1062     if (dwStatus & DN_CHILD_WITH_INVALID_ID)
1063         SetListViewText(hwndListView, index++, L"DN_CHILD_WITH_INVALID_ID");
1064     if (dwStatus & DN_HAS_PROBLEM)
1065         SetListViewText(hwndListView, index++, L"DN_HAS_PROBLEM");
1066     if (dwStatus & DN_FILTERED)
1067         SetListViewText(hwndListView, index++, L"DN_FILTERED");
1068     if (dwStatus & DN_LEGACY_DRIVER)
1069         SetListViewText(hwndListView, index++, L"DN_LEGACY_DRIVER");
1070     if (dwStatus & DN_DISABLEABLE)
1071         SetListViewText(hwndListView, index++, L"DN_DISABLEABLE");
1072     if (dwStatus & DN_REMOVABLE)
1073         SetListViewText(hwndListView, index++, L"DN_REMOVABLE");
1074     if (dwStatus & DN_PRIVATE_PROBLEM)
1075         SetListViewText(hwndListView, index++, L"DN_PRIVATE_PROBLEM");
1076     if (dwStatus & DN_MF_PARENT)
1077         SetListViewText(hwndListView, index++, L"DN_MF_PARENT");
1078     if (dwStatus & DN_MF_CHILD)
1079         SetListViewText(hwndListView, index++, L"DN_MF_CHILD");
1080     if (dwStatus & DN_WILL_BE_REMOVED)
1081         SetListViewText(hwndListView, index++, L"DN_WILL_BE_REMOVED");
1082 
1083     if (dwStatus & DN_NOT_FIRST_TIMEE)
1084         SetListViewText(hwndListView, index++, L"DN_NOT_FIRST_TIMEE");
1085     if (dwStatus & DN_STOP_FREE_RES)
1086         SetListViewText(hwndListView, index++, L"DN_STOP_FREE_RES");
1087     if (dwStatus & DN_REBAL_CANDIDATE)
1088         SetListViewText(hwndListView, index++, L"DN_REBAL_CANDIDATE");
1089     if (dwStatus & DN_BAD_PARTIAL)
1090         SetListViewText(hwndListView, index++, L"DN_BAD_PARTIAL");
1091     if (dwStatus & DN_NT_ENUMERATOR)
1092         SetListViewText(hwndListView, index++, L"DN_NT_ENUMERATOR");
1093     if (dwStatus & DN_NT_DRIVER)
1094         SetListViewText(hwndListView, index++, L"DN_NT_DRIVER");
1095 
1096     if (dwStatus & DN_NEEDS_LOCKING)
1097         SetListViewText(hwndListView, index++, L"DN_NEEDS_LOCKING");
1098     if (dwStatus & DN_ARM_WAKEUP)
1099         SetListViewText(hwndListView, index++, L"DN_ARM_WAKEUP");
1100     if (dwStatus & DN_APM_ENUMERATOR)
1101         SetListViewText(hwndListView, index++, L"DN_APM_ENUMERATOR");
1102     if (dwStatus & DN_APM_DRIVER)
1103         SetListViewText(hwndListView, index++, L"DN_APM_DRIVER");
1104     if (dwStatus & DN_SILENT_INSTALL)
1105         SetListViewText(hwndListView, index++, L"DN_SILENT_INSTALL");
1106     if (dwStatus & DN_NO_SHOW_IN_DM)
1107         SetListViewText(hwndListView, index++, L"DN_NO_SHOW_IN_DM");
1108     if (dwStatus & DN_BOOT_LOG_PROB)
1109         SetListViewText(hwndListView, index++, L"DN_BOOT_LOG_PROB");
1110 }
1111 
1112 
1113 static VOID
DisplayDevNodeEnumerator(IN PDEVADVPROP_INFO dap,IN HWND hwndListView)1114 DisplayDevNodeEnumerator(IN PDEVADVPROP_INFO dap,
1115                          IN HWND hwndListView)
1116 {
1117     PSP_DEVINFO_DATA DeviceInfoData;
1118 
1119     DWORD dwType = 0;
1120     WCHAR szBuffer[256];
1121     DWORD dwSize = 256 * sizeof(WCHAR);
1122 
1123     if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
1124     {
1125         DeviceInfoData = &dap->CurrentDeviceInfoData;
1126     }
1127     else
1128     {
1129         DeviceInfoData = &dap->DeviceInfoData;
1130     }
1131 
1132     CM_Get_DevNode_Registry_Property_ExW(DeviceInfoData->DevInst,
1133                                          CM_DRP_ENUMERATOR_NAME,
1134                                          &dwType,
1135                                          &szBuffer,
1136                                          &dwSize,
1137                                          0,
1138                                          dap->hMachine);
1139 
1140     SetListViewText(hwndListView, 0, szBuffer);
1141 }
1142 
1143 
1144 static VOID
DisplayCsFlags(IN PDEVADVPROP_INFO dap,IN HWND hwndListView)1145 DisplayCsFlags(IN PDEVADVPROP_INFO dap,
1146                IN HWND hwndListView)
1147 {
1148     DWORD dwValue = 0;
1149     INT index;
1150 
1151     CM_Get_HW_Prof_Flags_Ex(dap->szDevName,
1152                             0, /* current hardware profile */
1153                             &dwValue,
1154                             0,
1155                             dap->hMachine);
1156 
1157     index = 0;
1158     swprintf(dap->szTemp, L"%08lx", dwValue);
1159     SetListViewText(hwndListView, index++, dap->szTemp);
1160 
1161     if (dwValue & CSCONFIGFLAG_DISABLED)
1162         SetListViewText(hwndListView, index++, L"CSCONFIGFLAG_DISABLED");
1163 
1164     if (dwValue & CSCONFIGFLAG_DO_NOT_CREATE)
1165         SetListViewText(hwndListView, index++, L"CSCONFIGFLAG_DO_NOT_CREATE");
1166 
1167     if (dwValue & CSCONFIGFLAG_DO_NOT_START)
1168         SetListViewText(hwndListView, index++, L"CSCONFIGFLAG_DO_NOT_START");
1169 }
1170 
1171 
1172 static VOID
DisplayMatchingDeviceId(IN PDEVADVPROP_INFO dap,IN HWND hwndListView)1173 DisplayMatchingDeviceId(IN PDEVADVPROP_INFO dap,
1174                         IN HWND hwndListView)
1175 {
1176     HDEVINFO DeviceInfoSet;
1177     PSP_DEVINFO_DATA DeviceInfoData;
1178     WCHAR szBuffer[256];
1179     HKEY hKey;
1180     DWORD dwSize;
1181     DWORD dwType;
1182 
1183     if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
1184     {
1185         DeviceInfoSet = dap->CurrentDeviceInfoSet;
1186         DeviceInfoData = &dap->CurrentDeviceInfoData;
1187     }
1188     else
1189     {
1190         DeviceInfoSet = dap->DeviceInfoSet;
1191         DeviceInfoData = &dap->DeviceInfoData;
1192     }
1193 
1194     hKey = SetupDiOpenDevRegKey(DeviceInfoSet,
1195                                 DeviceInfoData,
1196                                 DICS_FLAG_GLOBAL,
1197                                 0,
1198                                 DIREG_DRV,
1199                                 KEY_QUERY_VALUE);
1200     if (hKey != INVALID_HANDLE_VALUE)
1201     {
1202         dwSize = 256 * sizeof(WCHAR);
1203         if (RegQueryValueEx(hKey,
1204                             L"MatchingDeviceId",
1205                             NULL,
1206                             &dwType,
1207                             (LPBYTE)szBuffer,
1208                             &dwSize) == ERROR_SUCCESS)
1209         {
1210             SetListViewText(hwndListView, 0, szBuffer);
1211         }
1212 
1213         RegCloseKey(hKey);
1214     }
1215 }
1216 
1217 
1218 static VOID
DisplayClassCoinstallers(IN PDEVADVPROP_INFO dap,IN HWND hwndListView)1219 DisplayClassCoinstallers(IN PDEVADVPROP_INFO dap,
1220                           IN HWND hwndListView)
1221 {
1222     HDEVINFO DeviceInfoSet;
1223     PSP_DEVINFO_DATA DeviceInfoData;
1224     WCHAR szClassGuid[45];
1225     HKEY hKey = (HKEY)INVALID_HANDLE_VALUE;
1226     DWORD dwSize;
1227     DWORD dwType;
1228     LPBYTE lpBuffer = NULL;
1229     LPWSTR lpStr;
1230     INT index;
1231     INT len;
1232     LONG lError;
1233 
1234     if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
1235     {
1236         DeviceInfoSet = dap->CurrentDeviceInfoSet;
1237         DeviceInfoData = &dap->CurrentDeviceInfoData;
1238     }
1239     else
1240     {
1241         DeviceInfoSet = dap->DeviceInfoSet;
1242         DeviceInfoData = &dap->DeviceInfoData;
1243     }
1244 
1245     dwSize = 45 * sizeof(WCHAR);
1246     if (!SetupDiGetDeviceRegistryProperty(DeviceInfoSet,
1247                                           DeviceInfoData,
1248                                           SPDRP_CLASSGUID,
1249                                           &dwType,
1250                                           (LPBYTE)szClassGuid,
1251                                           dwSize,
1252                                           &dwSize))
1253         return;
1254 
1255     lError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1256                            L"SYSTEM\\CurrentControlSet\\Control\\CoDeviceInstallers",
1257                            0,
1258                            GENERIC_READ,
1259                            &hKey);
1260     if (lError != ERROR_SUCCESS)
1261         return;
1262 
1263     dwSize = 0;
1264     lError = RegQueryValueEx(hKey,
1265                              szClassGuid,
1266                              NULL,
1267                              &dwType,
1268                              NULL,
1269                              &dwSize);
1270     if (lError != ERROR_SUCCESS)
1271         goto done;
1272 
1273     if (dwSize == 0)
1274         goto done;
1275 
1276     lpBuffer = (LPBYTE)HeapAlloc(GetProcessHeap(),
1277                                  HEAP_ZERO_MEMORY,
1278                                  dwSize);
1279 
1280     RegQueryValueEx(hKey,
1281                     szClassGuid,
1282                     NULL,
1283                     &dwType,
1284                     lpBuffer,
1285                     &dwSize);
1286 
1287     lpStr = (LPWSTR)lpBuffer;
1288     index = 0;
1289     while (*lpStr != 0)
1290     {
1291         len = wcslen(lpStr) + 1;
1292 
1293         SetListViewText(hwndListView, index, lpStr);
1294 
1295         lpStr += len;
1296         index++;
1297     }
1298 
1299 done:
1300     if (lpBuffer != NULL)
1301         HeapFree(GetProcessHeap(), 0, lpBuffer);
1302 
1303     if (hKey != INVALID_HANDLE_VALUE)
1304         RegCloseKey(hKey);
1305 }
1306 
1307 
1308 static VOID
DisplayDeviceCoinstallers(IN PDEVADVPROP_INFO dap,IN HWND hwndListView)1309 DisplayDeviceCoinstallers(IN PDEVADVPROP_INFO dap,
1310                           IN HWND hwndListView)
1311 {
1312     HDEVINFO DeviceInfoSet;
1313     PSP_DEVINFO_DATA DeviceInfoData;
1314     HKEY hKey;
1315     DWORD dwSize;
1316     DWORD dwType;
1317     LPBYTE lpBuffer;
1318     LPWSTR lpStr;
1319     INT index;
1320     INT len;
1321 
1322     if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
1323     {
1324         DeviceInfoSet = dap->CurrentDeviceInfoSet;
1325         DeviceInfoData = &dap->CurrentDeviceInfoData;
1326     }
1327     else
1328     {
1329         DeviceInfoSet = dap->DeviceInfoSet;
1330         DeviceInfoData = &dap->DeviceInfoData;
1331     }
1332 
1333     hKey = SetupDiOpenDevRegKey(DeviceInfoSet,
1334                                 DeviceInfoData,
1335                                 DICS_FLAG_GLOBAL,
1336                                 0,
1337                                 DIREG_DRV,
1338                                 KEY_QUERY_VALUE);
1339     if (hKey != INVALID_HANDLE_VALUE)
1340     {
1341         dwSize = 0;
1342         if (RegQueryValueEx(hKey,
1343                             L"CoInstallers32",
1344                             NULL,
1345                             &dwType,
1346                             NULL,
1347                             &dwSize) == ERROR_SUCCESS &&
1348             dwSize > 0)
1349         {
1350 
1351             lpBuffer = (LPBYTE)HeapAlloc(GetProcessHeap(),
1352                                          HEAP_ZERO_MEMORY,
1353                                          dwSize);
1354 
1355             RegQueryValueEx(hKey,
1356                             L"CoInstallers32",
1357                             NULL,
1358                             &dwType,
1359                             lpBuffer,
1360                             &dwSize);
1361 
1362             lpStr = (LPWSTR)lpBuffer;
1363             index = 0;
1364             while (*lpStr != 0)
1365             {
1366                 len = wcslen(lpStr) + 1;
1367 
1368                 SetListViewText(hwndListView, index, lpStr);
1369 
1370                 lpStr += len;
1371                 index++;
1372             }
1373 
1374             HeapFree(GetProcessHeap(),
1375                      0,
1376                      lpBuffer);
1377         }
1378 
1379         RegCloseKey(hKey);
1380     }
1381 }
1382 
1383 
1384 static VOID
DisplayClassProperties(IN PDEVADVPROP_INFO dap,IN HWND hwndListView,IN LPCWSTR lpProperty)1385 DisplayClassProperties(IN PDEVADVPROP_INFO dap,
1386                        IN HWND hwndListView,
1387                        IN LPCWSTR lpProperty)
1388 {
1389     HDEVINFO DeviceInfoSet;
1390     PSP_DEVINFO_DATA DeviceInfoData;
1391     WCHAR szClassGuid[45];
1392     DWORD dwSize;
1393     DWORD dwType;
1394     HKEY hKey;
1395     GUID ClassGuid;
1396     LPBYTE lpBuffer;
1397     LPWSTR lpStr;
1398     INT index = 0;
1399     INT len;
1400 
1401     if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
1402     {
1403         DeviceInfoSet = dap->CurrentDeviceInfoSet;
1404         DeviceInfoData = &dap->CurrentDeviceInfoData;
1405     }
1406     else
1407     {
1408         DeviceInfoSet = dap->DeviceInfoSet;
1409         DeviceInfoData = &dap->DeviceInfoData;
1410     }
1411 
1412     dwSize = 45 * sizeof(WCHAR);
1413     if (!SetupDiGetDeviceRegistryProperty(DeviceInfoSet,
1414                                           DeviceInfoData,
1415                                           SPDRP_CLASSGUID,
1416                                           &dwType,
1417                                           (LPBYTE)szClassGuid,
1418                                           dwSize,
1419                                           &dwSize))
1420         return;
1421 
1422     pSetupGuidFromString(szClassGuid,
1423                          &ClassGuid);
1424 
1425     hKey = SetupDiOpenClassRegKey(&ClassGuid,
1426                                   KEY_QUERY_VALUE);
1427     if (hKey != INVALID_HANDLE_VALUE)
1428     {
1429         dwSize = 0;
1430         if (RegQueryValueEx(hKey,
1431                             lpProperty,
1432                             NULL,
1433                             &dwType,
1434                             NULL,
1435                             &dwSize) == ERROR_SUCCESS &&
1436             dwSize > 0)
1437         {
1438             lpBuffer = (LPBYTE)HeapAlloc(GetProcessHeap(),
1439                                          HEAP_ZERO_MEMORY,
1440                                          dwSize);
1441 
1442             RegQueryValueEx(hKey,
1443                             lpProperty,
1444                             NULL,
1445                             &dwType,
1446                             lpBuffer,
1447                             &dwSize);
1448 
1449             if (dwType == REG_SZ)
1450             {
1451                 SetListViewText(hwndListView, 0, (LPWSTR)lpBuffer);
1452             }
1453             else if (dwType == REG_MULTI_SZ)
1454             {
1455                 lpStr = (LPWSTR)lpBuffer;
1456                 index = 0;
1457                 while (*lpStr != 0)
1458                 {
1459                     len = wcslen(lpStr) + 1;
1460 
1461                     SetListViewText(hwndListView, index, lpStr);
1462 
1463                     lpStr += len;
1464                     index++;
1465                 }
1466             }
1467 
1468             HeapFree(GetProcessHeap(),
1469                      0,
1470                      lpBuffer);
1471         }
1472 
1473         RegCloseKey(hKey);
1474     }
1475 }
1476 
1477 
1478 static VOID
DisplayDeviceRelations(IN PDEVADVPROP_INFO dap,IN HWND hwndListView,IN ULONG ulFlags)1479 DisplayDeviceRelations(
1480     IN PDEVADVPROP_INFO dap,
1481     IN HWND hwndListView,
1482     IN ULONG ulFlags)
1483 {
1484     ULONG ulLength = 0;
1485     LPWSTR pszBuffer = NULL, pszStr;
1486     INT index = 0, len;
1487     CONFIGRET ret;
1488 
1489     ret = CM_Get_Device_ID_List_Size_ExW(&ulLength,
1490                                          dap->szDeviceID,
1491                                          ulFlags,
1492                                          NULL);
1493     if (ret != CR_SUCCESS)
1494         return;
1495 
1496     pszBuffer = (LPWSTR)HeapAlloc(GetProcessHeap(),
1497                                   HEAP_ZERO_MEMORY,
1498                                   ulLength * sizeof(WCHAR));
1499     if (pszBuffer == NULL)
1500         return;
1501 
1502     ret = CM_Get_Device_ID_List_ExW(dap->szDeviceID,
1503                                     pszBuffer,
1504                                     ulLength,
1505                                     ulFlags,
1506                                     NULL);
1507     if (ret != CR_SUCCESS)
1508     {
1509         HeapFree(GetProcessHeap(), 0, pszBuffer);
1510         return;
1511     }
1512 
1513     pszStr = pszBuffer;
1514     index = 0;
1515     while (*pszStr != 0)
1516     {
1517         len = wcslen(pszStr) + 1;
1518 
1519         SetListViewText(hwndListView, index, pszStr);
1520 
1521         pszStr += len;
1522         index++;
1523     }
1524 
1525     HeapFree(GetProcessHeap(), 0, pszBuffer);
1526 }
1527 
1528 
1529 static VOID
DisplayCurrentPowerState(IN PDEVADVPROP_INFO dap,IN HWND hwndListView)1530 DisplayCurrentPowerState(
1531     IN PDEVADVPROP_INFO dap,
1532     IN HWND hwndListView)
1533 {
1534     HDEVINFO DeviceInfoSet;
1535     PSP_DEVINFO_DATA DeviceInfoData;
1536     CM_POWER_DATA PowerData;
1537     DWORD dwSize, dwType;
1538     PCWSTR lpText = NULL;
1539 
1540     if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
1541     {
1542         DeviceInfoSet = dap->CurrentDeviceInfoSet;
1543         DeviceInfoData = &dap->CurrentDeviceInfoData;
1544     }
1545     else
1546     {
1547         DeviceInfoSet = dap->DeviceInfoSet;
1548         DeviceInfoData = &dap->DeviceInfoData;
1549     }
1550 
1551     dwSize = sizeof(CM_POWER_DATA);
1552     if (!SetupDiGetDeviceRegistryProperty(DeviceInfoSet,
1553                                           DeviceInfoData,
1554                                           SPDRP_DEVICE_POWER_DATA,
1555                                           &dwType,
1556                                           (LPBYTE)&PowerData,
1557                                           dwSize,
1558                                           &dwSize))
1559         return;
1560 
1561     switch (PowerData.PD_MostRecentPowerState)
1562     {
1563 //        case PowerDeviceUnspecified:
1564 
1565         case PowerDeviceD0:
1566             lpText = L"D0";
1567             break;
1568 
1569         case PowerDeviceD1:
1570             lpText = L"D1";
1571             break;
1572 
1573         case PowerDeviceD2:
1574             lpText = L"D2";
1575             break;
1576 
1577         case PowerDeviceD3:
1578             lpText = L"D3";
1579             break;
1580 
1581         default:
1582             break;
1583     }
1584 
1585     if (lpText != NULL)
1586         SetListViewText(hwndListView, 0, lpText);
1587 }
1588 
1589 
1590 static VOID
DisplayPowerCapabilities(IN PDEVADVPROP_INFO dap,IN HWND hwndListView)1591 DisplayPowerCapabilities(
1592     IN PDEVADVPROP_INFO dap,
1593     IN HWND hwndListView)
1594 {
1595     HDEVINFO DeviceInfoSet;
1596     PSP_DEVINFO_DATA DeviceInfoData;
1597     CM_POWER_DATA PowerData;
1598     DWORD dwSize, dwType;
1599     INT index = 0;
1600 
1601     if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
1602     {
1603         DeviceInfoSet = dap->CurrentDeviceInfoSet;
1604         DeviceInfoData = &dap->CurrentDeviceInfoData;
1605     }
1606     else
1607     {
1608         DeviceInfoSet = dap->DeviceInfoSet;
1609         DeviceInfoData = &dap->DeviceInfoData;
1610     }
1611 
1612     dwSize = sizeof(CM_POWER_DATA);
1613     if (!SetupDiGetDeviceRegistryProperty(DeviceInfoSet,
1614                                           DeviceInfoData,
1615                                           SPDRP_DEVICE_POWER_DATA,
1616                                           &dwType,
1617                                           (LPBYTE)&PowerData,
1618                                           dwSize,
1619                                           &dwSize))
1620         return;
1621 
1622     if (PowerData.PD_Capabilities & PDCAP_D0_SUPPORTED)
1623         SetListViewText(hwndListView, index++, L"PDCAP_D0_SUPPORTED");
1624 
1625     if (PowerData.PD_Capabilities & PDCAP_D1_SUPPORTED)
1626         SetListViewText(hwndListView, index++, L"PDCAP_D1_SUPPORTED");
1627 
1628     if (PowerData.PD_Capabilities & PDCAP_D2_SUPPORTED)
1629         SetListViewText(hwndListView, index++, L"PDCAP_D2_SUPPORTED");
1630 
1631     if (PowerData.PD_Capabilities & PDCAP_D3_SUPPORTED)
1632         SetListViewText(hwndListView, index++, L"PDCAP_D3_SUPPORTED");
1633 
1634     if (PowerData.PD_Capabilities & PDCAP_WAKE_FROM_D0_SUPPORTED)
1635         SetListViewText(hwndListView, index++, L"PDCAP_WAKE_FROM_D0_SUPPORTED");
1636 
1637     if (PowerData.PD_Capabilities & PDCAP_WAKE_FROM_D1_SUPPORTED)
1638         SetListViewText(hwndListView, index++, L"PDCAP_WAKE_FROM_D1_SUPPORTED");
1639 
1640     if (PowerData.PD_Capabilities & PDCAP_WAKE_FROM_D2_SUPPORTED)
1641         SetListViewText(hwndListView, index++, L"PDCAP_WAKE_FROM_D2_SUPPORTED");
1642 
1643     if (PowerData.PD_Capabilities & PDCAP_WAKE_FROM_D3_SUPPORTED)
1644         SetListViewText(hwndListView, index++, L"PDCAP_WAKE_FROM_D3_SUPPORTED");
1645 
1646     if (PowerData.PD_Capabilities & PDCAP_WARM_EJECT_SUPPORTED)
1647         SetListViewText(hwndListView, index++, L"PDCAP_WARM_EJECT_SUPPORTED");
1648 }
1649 
1650 
1651 static VOID
DisplayPowerStateMappings(IN PDEVADVPROP_INFO dap,IN HWND hwndListView)1652 DisplayPowerStateMappings(
1653     IN PDEVADVPROP_INFO dap,
1654     IN HWND hwndListView)
1655 {
1656     HDEVINFO DeviceInfoSet;
1657     PSP_DEVINFO_DATA DeviceInfoData;
1658     CM_POWER_DATA PowerData;
1659     DWORD dwSize, dwType;
1660     INT i;
1661     DEVICE_POWER_STATE PowerState;
1662     WCHAR szSystemStateBuffer[40];
1663     WCHAR szDeviceStateBuffer[40];
1664     WCHAR szOutBuffer[100];
1665 
1666     if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
1667     {
1668         DeviceInfoSet = dap->CurrentDeviceInfoSet;
1669         DeviceInfoData = &dap->CurrentDeviceInfoData;
1670     }
1671     else
1672     {
1673         DeviceInfoSet = dap->DeviceInfoSet;
1674         DeviceInfoData = &dap->DeviceInfoData;
1675     }
1676 
1677     dwSize = sizeof(CM_POWER_DATA);
1678     if (!SetupDiGetDeviceRegistryProperty(DeviceInfoSet,
1679                                           DeviceInfoData,
1680                                           SPDRP_DEVICE_POWER_DATA,
1681                                           &dwType,
1682                                           (LPBYTE)&PowerData,
1683                                           dwSize,
1684                                           &dwSize))
1685         return;
1686 
1687     for (i = PowerSystemWorking; i < PowerSystemMaximum; i++)
1688     {
1689         PowerState = PowerData.PD_PowerStateMapping[i];
1690         if ((PowerState >= PowerDeviceUnspecified) && (PowerState <= PowerDeviceD3))
1691         {
1692             swprintf(szSystemStateBuffer, L"S%u", i - 1);
1693 
1694             switch (PowerState)
1695             {
1696                 case PowerDeviceUnspecified:
1697                     wcscpy(szDeviceStateBuffer, L"Not specified");
1698                     break;
1699 
1700                 case PowerDeviceD0:
1701                     wcscpy(szDeviceStateBuffer, L"D0");
1702                     break;
1703 
1704                 case PowerDeviceD1:
1705                     wcscpy(szDeviceStateBuffer, L"D1");
1706                     break;
1707 
1708                 case PowerDeviceD2:
1709                     wcscpy(szDeviceStateBuffer, L"D2");
1710                     break;
1711 
1712                 case PowerDeviceD3:
1713                     wcscpy(szDeviceStateBuffer, L"D3");
1714                     break;
1715 
1716                 default:
1717                     break;
1718             }
1719 
1720             swprintf(szOutBuffer, L"%s -> %s", szSystemStateBuffer, szDeviceStateBuffer);
1721             SetListViewText(hwndListView, i, szOutBuffer);
1722         }
1723     }
1724 }
1725 
1726 
1727 static VOID
DisplayDeviceProperties(IN PDEVADVPROP_INFO dap,IN HWND hwndComboBox,IN HWND hwndListView)1728 DisplayDeviceProperties(IN PDEVADVPROP_INFO dap,
1729                         IN HWND hwndComboBox,
1730                         IN HWND hwndListView)
1731 {
1732     INT Index;
1733 
1734     Index = (INT)SendMessage(hwndComboBox,
1735                              CB_GETCURSEL,
1736                              0,
1737                              0);
1738     if (Index == CB_ERR)
1739         return;
1740 
1741     (void)ListView_DeleteAllItems(hwndListView);
1742 
1743     switch (Index)
1744     {
1745         case 0: /* Device ID */
1746             SetListViewText(hwndListView, 0, dap->szDeviceID);
1747             break;
1748 
1749         case 1: /* Hardware ID */
1750             DisplayDevicePropertyText(dap,
1751                                       hwndListView,
1752                                       SPDRP_HARDWAREID);
1753             break;
1754 
1755         case 2: /* Compatible IDs */
1756             DisplayDevicePropertyText(dap,
1757                                       hwndListView,
1758                                       SPDRP_COMPATIBLEIDS);
1759             break;
1760 
1761         case 3: /* Matching ID */
1762             DisplayMatchingDeviceId(dap,
1763                                     hwndListView);
1764             break;
1765 
1766         case 4: /* Service */
1767             DisplayDevicePropertyText(dap,
1768                                       hwndListView,
1769                                       SPDRP_SERVICE);
1770             break;
1771 
1772         case 5: /* Enumerator */
1773             DisplayDevNodeEnumerator(dap,
1774                                      hwndListView);
1775             break;
1776 
1777         case 6: /* Capabilities */
1778             DisplayDevicePropertyText(dap,
1779                                       hwndListView,
1780                                       SPDRP_CAPABILITIES);
1781             break;
1782 
1783         case 7: /* Devnode Flags */
1784             DisplayDevNodeFlags(dap,
1785                                 hwndListView);
1786             break;
1787 
1788         case 8: /* Config Flags */
1789             DisplayDevicePropertyText(dap,
1790                                       hwndListView,
1791                                       SPDRP_CONFIGFLAGS);
1792             break;
1793 
1794         case 9: /* CSConfig Flags */
1795             DisplayCsFlags(dap,
1796                            hwndListView);
1797             break;
1798 
1799         case 10: /* Ejection relation */
1800             DisplayDeviceRelations(dap,
1801                                    hwndListView,
1802                                    CM_GETIDLIST_FILTER_EJECTRELATIONS);
1803             break;
1804 
1805         case 11: /* Removal relations */
1806             DisplayDeviceRelations(dap,
1807                                    hwndListView,
1808                                    CM_GETIDLIST_FILTER_REMOVALRELATIONS);
1809             break;
1810 
1811         case 12: /* Bus relation */
1812             DisplayDeviceRelations(dap,
1813                                    hwndListView,
1814                                    CM_GETIDLIST_FILTER_BUSRELATIONS);
1815             break;
1816 
1817         case 13: /* Device Upper Filters */
1818             DisplayDevicePropertyText(dap,
1819                                       hwndListView,
1820                                       SPDRP_UPPERFILTERS);
1821             break;
1822 
1823         case 14: /* Device Lower Filters */
1824             DisplayDevicePropertyText(dap,
1825                                       hwndListView,
1826                                       SPDRP_LOWERFILTERS);
1827             break;
1828 
1829         case 15: /* Class Upper Filters */
1830             DisplayClassProperties(dap,
1831                                    hwndListView,
1832                                    L"UpperFilters");
1833             break;
1834 
1835         case 16: /* Class Lower Filters */
1836             DisplayClassProperties(dap,
1837                                    hwndListView,
1838                                    L"LowerFilters");
1839             break;
1840 
1841         case 17: /* Class Installer */
1842             DisplayClassProperties(dap,
1843                                    hwndListView,
1844                                    L"Installer32");
1845             break;
1846 
1847         case 18: /* Class Coinstaller */
1848             DisplayClassCoinstallers(dap,
1849                                      hwndListView);
1850             break;
1851 
1852         case 19: /* Device Coinstaller */
1853             DisplayDeviceCoinstallers(dap,
1854                                       hwndListView);
1855             break;
1856 
1857 #if 0
1858         case 20: /* Firmware Revision */
1859             break;
1860 #endif
1861 
1862         case 21: /* Current Power State */
1863             DisplayCurrentPowerState(dap,
1864                                      hwndListView);
1865             break;
1866 
1867         case 22: /* Power Capabilities */
1868             DisplayPowerCapabilities(dap,
1869                                      hwndListView);
1870             break;
1871 
1872         case 23: /* Power State Mappings */
1873             DisplayPowerStateMappings(dap,
1874                                       hwndListView);
1875             break;
1876 
1877         default:
1878             SetListViewText(hwndListView, 0, L"<Not implemented yet>");
1879             break;
1880     }
1881 }
1882 
1883 
1884 static INT_PTR
1885 CALLBACK
AdvProcDetailsDlgProc(IN HWND hwndDlg,IN UINT uMsg,IN WPARAM wParam,IN LPARAM lParam)1886 AdvProcDetailsDlgProc(IN HWND hwndDlg,
1887                       IN UINT uMsg,
1888                       IN WPARAM wParam,
1889                       IN LPARAM lParam)
1890 {
1891     PDEVADVPROP_INFO dap;
1892     INT_PTR Ret = FALSE;
1893 
1894     dap = (PDEVADVPROP_INFO)GetWindowLongPtr(hwndDlg, DWLP_USER);
1895 
1896     if (dap != NULL || uMsg == WM_INITDIALOG)
1897     {
1898         switch (uMsg)
1899         {
1900             case WM_CONTEXTMENU:
1901             {
1902                 if ((HWND)wParam == GetDlgItem(hwndDlg, IDC_DETAILSPROPVALUE))
1903                 {
1904                     WCHAR szColName[255];
1905 
1906                     if (!LoadStringW(hDllInstance, IDS_COPY, szColName, _countof(szColName)))
1907                         break;
1908 
1909                     INT nSelectedItems = ListView_GetSelectedCount((HWND)wParam);
1910                     POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
1911                     HMENU hPopup = CreatePopupMenu();
1912 
1913                     AppendMenuW(hPopup, MF_STRING, IDS_MENU_COPY, szColName);
1914 
1915                     if (nSelectedItems <= 0)
1916                         EnableMenuItem(hPopup, IDS_MENU_COPY, MF_BYCOMMAND | MF_GRAYED);
1917 
1918                     TrackPopupMenu(hPopup, TPM_LEFTALIGN, pt.x, pt.y, 0, hwndDlg, NULL);
1919                     DestroyMenu(hPopup);
1920                     Ret = TRUE;
1921                 }
1922                 break;
1923             }
1924 
1925             case WM_COMMAND:
1926             {
1927                 switch (LOWORD(wParam))
1928                 {
1929                     case IDC_DETAILSPROPNAME:
1930                         if (HIWORD(wParam) == CBN_SELCHANGE)
1931                         {
1932                             DisplayDeviceProperties(dap,
1933                                                     GetDlgItem(hwndDlg, IDC_DETAILSPROPNAME),
1934                                                     GetDlgItem(hwndDlg, IDC_DETAILSPROPVALUE));
1935                         }
1936                         break;
1937 
1938                     case IDS_MENU_COPY:
1939                     {
1940                         HWND hwndListView = GetDlgItem(hwndDlg, IDC_DETAILSPROPVALUE);
1941                         INT nSelectedItems = ListView_GetSelectedCount(hwndListView);
1942                         INT nSelectedId = ListView_GetSelectionMark(hwndListView);
1943 
1944                         if (nSelectedId < 0 || nSelectedItems <= 0)
1945                             break;
1946 
1947                         HGLOBAL hGlobal;
1948                         LPWSTR pszBuffer;
1949                         SIZE_T cchSize = MAX_PATH + 1;
1950 
1951                         hGlobal = GlobalAlloc(GHND, cchSize * sizeof(WCHAR));
1952                         if (!hGlobal)
1953                             break;
1954                         pszBuffer = (LPWSTR)GlobalLock(hGlobal);
1955                         if (!pszBuffer)
1956                         {
1957                             GlobalFree(hGlobal);
1958                             break;
1959                         }
1960 
1961                         ListView_GetItemText(hwndListView,
1962                                              nSelectedId, 0,
1963                                              pszBuffer,
1964                                              cchSize);
1965                         /* Ensure NULL-termination */
1966                         pszBuffer[cchSize - 1] = UNICODE_NULL;
1967 
1968                         GlobalUnlock(hGlobal);
1969 
1970                         if (OpenClipboard(NULL))
1971                         {
1972                             EmptyClipboard();
1973                             SetClipboardData(CF_UNICODETEXT, hGlobal);
1974                             CloseClipboard();
1975                             Ret = TRUE;
1976                         }
1977                         else
1978                         {
1979                             GlobalFree(hGlobal);
1980                         }
1981                         break;
1982                     }
1983                 }
1984                 break;
1985             }
1986 
1987             case WM_NOTIFY:
1988             {
1989                 NMHDR *hdr = (NMHDR*)lParam;
1990                 switch (hdr->code)
1991                 {
1992                     case PSN_APPLY:
1993                         break;
1994                 }
1995                 break;
1996             }
1997 
1998             case WM_INITDIALOG:
1999             {
2000                 dap = (PDEVADVPROP_INFO)((LPPROPSHEETPAGE)lParam)->lParam;
2001                 if (dap != NULL)
2002                 {
2003                     SetWindowLongPtr(hwndDlg, DWLP_USER, (DWORD_PTR)dap);
2004 
2005                     UpdateDetailsDlg(hwndDlg,
2006                                      dap);
2007                 }
2008                 Ret = TRUE;
2009                 break;
2010             }
2011         }
2012     }
2013 
2014     return Ret;
2015 }
2016 
2017 
2018 static VOID
InitDevUsageActions(IN HWND hwndDlg,IN HWND hComboBox,IN PDEVADVPROP_INFO dap)2019 InitDevUsageActions(IN HWND hwndDlg,
2020                     IN HWND hComboBox,
2021                     IN PDEVADVPROP_INFO dap)
2022 {
2023     INT Index;
2024     UINT i;
2025     UINT Actions[] =
2026     {
2027         IDS_ENABLEDEVICE,
2028         IDS_DISABLEDEVICE,
2029     };
2030 
2031     for (i = 0;
2032          i != sizeof(Actions) / sizeof(Actions[0]);
2033          i++)
2034     {
2035         /* fill in the device usage combo box */
2036         if (LoadString(hDllInstance,
2037                        Actions[i],
2038                        dap->szTemp,
2039                        sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
2040         {
2041             Index = (INT)SendMessage(hComboBox,
2042                                      CB_ADDSTRING,
2043                                      0,
2044                                      (LPARAM)dap->szTemp);
2045             if (Index != CB_ERR)
2046             {
2047                 SendMessage(hComboBox,
2048                             CB_SETITEMDATA,
2049                             (WPARAM)Index,
2050                             (LPARAM)Actions[i]);
2051 
2052                 switch (Actions[i])
2053                 {
2054                     case IDS_ENABLEDEVICE:
2055                         if (dap->DeviceStarted)
2056                         {
2057                             SendMessage(hComboBox,
2058                                         CB_SETCURSEL,
2059                                         (WPARAM)Index,
2060                                         0);
2061                         }
2062                         break;
2063 
2064                     case IDS_DISABLEDEVICE:
2065                         if (!dap->DeviceStarted)
2066                         {
2067                             SendMessage(hComboBox,
2068                                         CB_SETCURSEL,
2069                                         (WPARAM)Index,
2070                                         0);
2071                         }
2072                         break;
2073 
2074                     default:
2075                         break;
2076                 }
2077             }
2078         }
2079     }
2080 }
2081 
2082 
2083 static UINT
GetSelectedUsageAction(IN HWND hComboBox)2084 GetSelectedUsageAction(IN HWND hComboBox)
2085 {
2086     INT Index;
2087     UINT Ret = 0;
2088 
2089     Index = (INT)SendMessage(hComboBox,
2090                              CB_GETCURSEL,
2091                              0,
2092                              0);
2093     if (Index != CB_ERR)
2094     {
2095         INT iRet = (INT) SendMessage(hComboBox,
2096                                CB_GETITEMDATA,
2097                                (WPARAM)Index,
2098                                0);
2099         if (iRet != CB_ERR)
2100         {
2101             Ret = (UINT)iRet;
2102         }
2103     }
2104 
2105     return Ret;
2106 }
2107 
2108 
2109 static BOOL
ApplyGeneralSettings(IN HWND hwndDlg,IN PDEVADVPROP_INFO dap)2110 ApplyGeneralSettings(IN HWND hwndDlg,
2111                      IN PDEVADVPROP_INFO dap)
2112 {
2113     BOOL Ret = FALSE;
2114 
2115     if (dap->DeviceUsageChanged && dap->IsAdmin && dap->CanDisable)
2116     {
2117         UINT SelectedUsageAction;
2118         BOOL NeedReboot = FALSE;
2119 
2120         SelectedUsageAction = GetSelectedUsageAction(GetDlgItem(hwndDlg,
2121                                                                 IDC_DEVUSAGE));
2122         switch (SelectedUsageAction)
2123         {
2124             case IDS_ENABLEDEVICE:
2125                 if (!dap->DeviceStarted)
2126                 {
2127                     Ret = EnableDevice(dap->DeviceInfoSet,
2128                                        &dap->DeviceInfoData,
2129                                        TRUE,
2130                                        0,
2131                                        &NeedReboot);
2132                 }
2133                 break;
2134 
2135             case IDS_DISABLEDEVICE:
2136                 if (dap->DeviceStarted)
2137                 {
2138                     Ret = EnableDevice(dap->DeviceInfoSet,
2139                                        &dap->DeviceInfoData,
2140                                        FALSE,
2141                                        0,
2142                                        &NeedReboot);
2143                 }
2144                 break;
2145 
2146             default:
2147                 break;
2148         }
2149 
2150         if (Ret)
2151         {
2152             if (NeedReboot)
2153             {
2154                 /* make PropertySheet() return PSM_REBOOTSYSTEM */
2155                 PropSheet_RebootSystem(hwndDlg);
2156             }
2157         }
2158         else
2159         {
2160             /* FIXME - display an error message */
2161             FIXME("Failed to enable/disable device! LastError: %d\n",
2162                   GetLastError());
2163         }
2164     }
2165     else
2166         Ret = !dap->DeviceUsageChanged;
2167 
2168     /* disable the apply button */
2169     PropSheet_UnChanged(GetParent(hwndDlg),
2170                         hwndDlg);
2171     dap->DeviceUsageChanged = FALSE;
2172     return Ret;
2173 }
2174 
2175 
2176 static VOID
UpdateDevInfo(IN HWND hwndDlg,IN PDEVADVPROP_INFO dap,IN BOOL ReOpen)2177 UpdateDevInfo(IN HWND hwndDlg,
2178               IN PDEVADVPROP_INFO dap,
2179               IN BOOL ReOpen)
2180 {
2181     HWND hDevUsage, hPropSheetDlg, hDevProbBtn;
2182     CONFIGRET cr;
2183     ULONG Status, ProblemNumber;
2184     SP_DEVINSTALL_PARAMS_W InstallParams;
2185     UINT TroubleShootStrId = IDS_TROUBLESHOOTDEV;
2186     BOOL bFlag, bDevActionAvailable = TRUE;
2187     BOOL bDrvInstalled = FALSE;
2188     DWORD iPage;
2189     HDEVINFO DeviceInfoSet = NULL;
2190     PSP_DEVINFO_DATA DeviceInfoData = NULL;
2191     PROPSHEETHEADER psh;
2192     DWORD nDriverPages = 0;
2193     BOOL RecalcPages = FALSE;
2194 
2195     hPropSheetDlg = GetParent(hwndDlg);
2196 
2197     if (dap->PageInitialized)
2198     {
2199         /* switch to the General page */
2200         PropSheet_SetCurSelByID(hPropSheetDlg,
2201                                 IDD_DEVICEGENERAL);
2202 
2203         /* remove and destroy the existing device property sheet pages */
2204         if (dap->DevPropSheets != NULL)
2205         {
2206             for (iPage = 0;
2207                  iPage != dap->nDevPropSheets;
2208                  iPage++)
2209             {
2210                 if (dap->DevPropSheets[iPage] != NULL)
2211                 {
2212                     PropSheet_RemovePage(hPropSheetDlg,
2213                                          (WPARAM) -1,
2214                                          dap->DevPropSheets[iPage]);
2215                     RecalcPages = TRUE;
2216                 }
2217             }
2218         }
2219     }
2220 
2221     iPage = 0;
2222 
2223     if (dap->FreeDevPropSheets)
2224     {
2225         /* don't free the array if it's the one allocated in
2226            DisplayDeviceAdvancedProperties */
2227         HeapFree(GetProcessHeap(),
2228                  0,
2229                  dap->DevPropSheets);
2230 
2231         dap->FreeDevPropSheets = FALSE;
2232     }
2233 
2234     dap->DevPropSheets = NULL;
2235     dap->nDevPropSheets = 0;
2236 
2237     if (ReOpen)
2238     {
2239         /* create a new device info set and re-open the device */
2240         if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
2241         {
2242             SetupDiDestroyDeviceInfoList(dap->CurrentDeviceInfoSet);
2243         }
2244 
2245         dap->ParentDevInst = 0;
2246         dap->CurrentDeviceInfoSet = SetupDiCreateDeviceInfoListEx(NULL,
2247                                                                   hwndDlg,
2248                                                                   dap->lpMachineName,
2249                                                                   NULL);
2250         if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
2251         {
2252             if (SetupDiOpenDeviceInfo(dap->CurrentDeviceInfoSet,
2253                                       dap->szDeviceID,
2254                                       hwndDlg,
2255                                       0,
2256                                       &dap->CurrentDeviceInfoData))
2257             {
2258                 if (dap->CloseDevInst)
2259                 {
2260                     SetupDiDestroyDeviceInfoList(dap->DeviceInfoSet);
2261                 }
2262 
2263                 dap->CloseDevInst = TRUE;
2264                 dap->DeviceInfoSet = dap->CurrentDeviceInfoSet;
2265                 dap->DeviceInfoData = dap->CurrentDeviceInfoData;
2266                 dap->CurrentDeviceInfoSet = INVALID_HANDLE_VALUE;
2267             }
2268             else
2269                 goto GetParentNode;
2270         }
2271         else
2272         {
2273 GetParentNode:
2274             /* get the parent node from the initial devinst */
2275             CM_Get_Parent_Ex(&dap->ParentDevInst,
2276                              dap->DeviceInfoData.DevInst,
2277                              0,
2278                              dap->hMachine);
2279         }
2280 
2281         if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
2282         {
2283             DeviceInfoSet = dap->CurrentDeviceInfoSet;
2284             DeviceInfoData = &dap->CurrentDeviceInfoData;
2285         }
2286         else
2287         {
2288             DeviceInfoSet = dap->DeviceInfoSet;
2289             DeviceInfoData = &dap->DeviceInfoData;
2290         }
2291     }
2292     else
2293     {
2294         DeviceInfoSet = dap->DeviceInfoSet;
2295         DeviceInfoData = &dap->DeviceInfoData;
2296     }
2297 
2298     dap->HasDriverPage = TRUE;
2299     dap->HasResourcePage = TRUE;
2300     dap->HasPowerPage = TRUE;
2301     if (IsDriverInstalled(DeviceInfoData->DevInst,
2302                           dap->hMachine,
2303                           &bDrvInstalled) &&
2304         bDrvInstalled)
2305     {
2306         if (SetupDiCallClassInstaller((dap->ShowRemotePages ?
2307                                            DIF_ADDREMOTEPROPERTYPAGE_ADVANCED :
2308                                            DIF_ADDPROPERTYPAGE_ADVANCED),
2309                                       DeviceInfoSet,
2310                                       DeviceInfoData))
2311         {
2312             /* get install params */
2313             InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
2314             if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet,
2315                                                 DeviceInfoData,
2316                                                 &InstallParams))
2317             {
2318                 /* zero the flags */
2319                 InstallParams.Flags = 0;
2320                 InstallParams.FlagsEx = 0;
2321             }
2322 
2323             dap->HasDriverPage = !(InstallParams.Flags & DI_DRIVERPAGE_ADDED);
2324             dap->HasResourcePage = !(InstallParams.Flags & DI_RESOURCEPAGE_ADDED);
2325             dap->HasPowerPage = !(InstallParams.FlagsEx & DI_FLAGSEX_POWERPAGE_ADDED);
2326         }
2327     }
2328 
2329     /* get the device icon */
2330     if (dap->hDevIcon != NULL)
2331     {
2332         DestroyIcon(dap->hDevIcon);
2333         dap->hDevIcon = NULL;
2334     }
2335     if (!SetupDiLoadClassIcon(&DeviceInfoData->ClassGuid,
2336                               &dap->hDevIcon,
2337                               NULL))
2338     {
2339         dap->hDevIcon = NULL;
2340     }
2341 
2342     /* get the device name */
2343     if (GetDeviceDescriptionString(DeviceInfoSet,
2344                                    DeviceInfoData,
2345                                    dap->szDevName,
2346                                    sizeof(dap->szDevName) / sizeof(dap->szDevName[0])))
2347     {
2348         PropSheet_SetTitle(hPropSheetDlg,
2349                            PSH_PROPTITLE,
2350                            dap->szDevName);
2351     }
2352 
2353     /* set the device image */
2354     SendDlgItemMessage(hwndDlg,
2355                        IDC_DEVICON,
2356                        STM_SETICON,
2357                        (WPARAM)dap->hDevIcon,
2358                        0);
2359 
2360     /* set the device name edit control text */
2361     SetDlgItemText(hwndDlg,
2362                    IDC_DEVNAME,
2363                    dap->szDevName);
2364 
2365     /* set the device type edit control text */
2366     if (GetDeviceTypeString(DeviceInfoData,
2367                             dap->szTemp,
2368                             sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
2369     {
2370         SetDlgItemText(hwndDlg,
2371                        IDC_DEVTYPE,
2372                        dap->szTemp);
2373     }
2374 
2375     /* set the device manufacturer edit control text */
2376     if (GetDeviceManufacturerString(DeviceInfoSet,
2377                                     DeviceInfoData,
2378                                     dap->szTemp,
2379                                     sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
2380     {
2381         SetDlgItemText(hwndDlg,
2382                        IDC_DEVMANUFACTURER,
2383                        dap->szTemp);
2384     }
2385 
2386     /* set the device location edit control text */
2387     if (GetDeviceLocationString(DeviceInfoSet,
2388                                 DeviceInfoData,
2389                                 dap->ParentDevInst,
2390                                 dap->szTemp,
2391                                 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
2392     {
2393         SetDlgItemText(hwndDlg,
2394                        IDC_DEVLOCATION,
2395                        dap->szTemp);
2396     }
2397 
2398     /* set the device status edit control text */
2399     if (GetDeviceStatusString(DeviceInfoData->DevInst,
2400                               dap->hMachine,
2401                               dap->szTemp,
2402                               sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
2403     {
2404         SetDlgItemText(hwndDlg,
2405                        IDC_DEVSTATUS,
2406                        dap->szTemp);
2407     }
2408 
2409     /* set the device troubleshoot button text and disable it if necessary */
2410     hDevProbBtn = GetDlgItem(hwndDlg,
2411                              IDC_DEVPROBLEM);
2412     cr = CM_Get_DevNode_Status_Ex(&Status,
2413                                   &ProblemNumber,
2414                                   DeviceInfoData->DevInst,
2415                                   0,
2416                                   dap->hMachine);
2417     if (cr == CR_SUCCESS && (Status & DN_HAS_PROBLEM))
2418     {
2419         switch (ProblemNumber)
2420         {
2421             case CM_PROB_DEVLOADER_FAILED:
2422             {
2423                 /* FIXME - only if it's not a root bus devloader,
2424                            disable the button otherwise */
2425                 TroubleShootStrId = IDS_UPDATEDRV;
2426                 break;
2427             }
2428 
2429             case CM_PROB_OUT_OF_MEMORY:
2430             case CM_PROB_ENTRY_IS_WRONG_TYPE:
2431             case CM_PROB_LACKED_ARBITRATOR:
2432             case CM_PROB_FAILED_START:
2433             case CM_PROB_LIAR:
2434             case CM_PROB_UNKNOWN_RESOURCE:
2435             {
2436                 TroubleShootStrId = IDS_UPDATEDRV;
2437                 break;
2438             }
2439 
2440             case CM_PROB_BOOT_CONFIG_CONFLICT:
2441             case CM_PROB_NORMAL_CONFLICT:
2442             case CM_PROB_REENUMERATION:
2443             {
2444                 /* FIXME - Troubleshoot conflict */
2445                 break;
2446             }
2447 
2448             case CM_PROB_FAILED_FILTER:
2449             case CM_PROB_REINSTALL:
2450             case CM_PROB_FAILED_INSTALL:
2451             {
2452                 TroubleShootStrId = IDS_REINSTALLDRV;
2453                 break;
2454             }
2455 
2456             case CM_PROB_DEVLOADER_NOT_FOUND:
2457             {
2458                 /* FIXME - 4 cases:
2459                    1) if it's a missing system devloader:
2460                       - disable the button (Reinstall Driver)
2461                    2) if it's not a system devloader but still missing:
2462                       - Reinstall Driver
2463                    3) if it's not a system devloader but the file can be found:
2464                       - Update Driver
2465                    4) if it's a missing or empty software key
2466                       - Update Driver
2467                  */
2468                 break;
2469             }
2470 
2471             case CM_PROB_INVALID_DATA:
2472             case CM_PROB_PARTIAL_LOG_CONF:
2473             case CM_PROB_NO_VALID_LOG_CONF:
2474             case CM_PROB_HARDWARE_DISABLED:
2475             case CM_PROB_CANT_SHARE_IRQ:
2476             case CM_PROB_TRANSLATION_FAILED:
2477             case CM_PROB_SYSTEM_SHUTDOWN:
2478             case CM_PROB_PHANTOM:
2479                 bDevActionAvailable = FALSE;
2480                 break;
2481 
2482             case CM_PROB_NOT_VERIFIED:
2483             case CM_PROB_DEVICE_NOT_THERE:
2484                 /* FIXME - search hardware */
2485                 break;
2486 
2487             case CM_PROB_NEED_RESTART:
2488             case CM_PROB_WILL_BE_REMOVED:
2489             case CM_PROB_MOVED:
2490             case CM_PROB_TOO_EARLY:
2491             case CM_PROB_DISABLED_SERVICE:
2492                 TroubleShootStrId = IDS_REBOOT;
2493                 break;
2494 
2495             case CM_PROB_REGISTRY:
2496                 /* FIXME - check registry? */
2497                 break;
2498 
2499             case CM_PROB_DISABLED:
2500                 /* if device was disabled by the user: */
2501                 TroubleShootStrId = IDS_ENABLEDEV;
2502                 /* FIXME - otherwise disable button because the device was
2503                            disabled by the system*/
2504                 break;
2505 
2506             case CM_PROB_DEVLOADER_NOT_READY:
2507                 /* FIXME - if it's a graphics adapter:
2508                            - if it's a a secondary adapter and the main adapter
2509                              couldn't be found
2510                              - disable  button
2511                            - else
2512                              - Properties
2513                          - else
2514                            - Update driver
2515                  */
2516                 break;
2517 
2518             case CM_PROB_FAILED_ADD:
2519                 TroubleShootStrId = IDS_PROPERTIES;
2520                 break;
2521         }
2522     }
2523 
2524     if (LoadString(hDllInstance,
2525                    TroubleShootStrId,
2526                    dap->szTemp,
2527                    sizeof(dap->szTemp) / sizeof(dap->szTemp[0])) != 0)
2528     {
2529         SetWindowText(hDevProbBtn,
2530                       dap->szTemp);
2531     }
2532     EnableWindow(hDevProbBtn,
2533                  dap->IsAdmin && bDevActionAvailable);
2534 
2535     /* check if the device can be enabled/disabled */
2536     hDevUsage = GetDlgItem(hwndDlg,
2537                            IDC_DEVUSAGE);
2538 
2539     dap->CanDisable = FALSE;
2540     dap->DeviceStarted = FALSE;
2541 
2542     if (CanDisableDevice(DeviceInfoData->DevInst,
2543                          dap->hMachine,
2544                          &bFlag))
2545     {
2546         dap->CanDisable = bFlag;
2547     }
2548 
2549     if (IsDeviceStarted(DeviceInfoData->DevInst,
2550                         dap->hMachine,
2551                         &bFlag))
2552     {
2553         dap->DeviceStarted = bFlag;
2554     }
2555 
2556     /* enable/disable the device usage controls */
2557     EnableWindow(GetDlgItem(hwndDlg,
2558                             IDC_DEVUSAGELABEL),
2559                  dap->CanDisable && dap->IsAdmin);
2560     EnableWindow(hDevUsage,
2561                  dap->CanDisable && dap->IsAdmin);
2562 
2563     /* clear the combobox */
2564     SendMessage(hDevUsage,
2565                 CB_RESETCONTENT,
2566                 0,
2567                 0);
2568     if (dap->CanDisable)
2569     {
2570         InitDevUsageActions(hwndDlg,
2571                             hDevUsage,
2572                             dap);
2573     }
2574 
2575     /* find out how many new device property sheets to add.
2576        fake a PROPSHEETHEADER structure, we don't plan to
2577        call PropertySheet again!*/
2578     psh.dwSize = sizeof(PROPSHEETHEADER);
2579     psh.dwFlags = 0;
2580     psh.nPages = 0;
2581 
2582     /* get the number of device property sheets for the device */
2583     if (!SetupDiGetClassDevPropertySheets(DeviceInfoSet,
2584                                           DeviceInfoData,
2585                                           &psh,
2586                                           0,
2587                                           &nDriverPages,
2588                                           dap->PropertySheetType) &&
2589         nDriverPages != 0 && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
2590     {
2591         dap->nDevPropSheets += nDriverPages;
2592     }
2593     else
2594     {
2595         nDriverPages = 0;
2596     }
2597 
2598     dap->pResourceList = GetResourceList(dap->szDeviceID);
2599 
2600     /* include the driver page */
2601     if (dap->HasDriverPage)
2602         dap->nDevPropSheets++;
2603 
2604     /* include the details page */
2605     if (dap->Extended)
2606         dap->nDevPropSheets++;
2607 
2608     if (dap->HasResourcePage && dap->pResourceList != NULL)
2609         dap->nDevPropSheets++;
2610 
2611     /* add the device property sheets */
2612     if (dap->nDevPropSheets != 0)
2613     {
2614         dap->DevPropSheets = (HPROPSHEETPAGE *)HeapAlloc(GetProcessHeap(),
2615                                                          HEAP_ZERO_MEMORY,
2616                                                          dap->nDevPropSheets * sizeof(HPROPSHEETPAGE));
2617         if (dap->DevPropSheets != NULL)
2618         {
2619             if (nDriverPages != 0)
2620             {
2621                 psh.phpage = dap->DevPropSheets;
2622 
2623                 /* query the device property sheet pages to add */
2624                 if (SetupDiGetClassDevPropertySheets(DeviceInfoSet,
2625                                                      DeviceInfoData,
2626                                                      &psh,
2627                                                      dap->nDevPropSheets,
2628                                                      NULL,
2629                                                      dap->PropertySheetType))
2630                 {
2631                     /* add the property sheets */
2632                     for (iPage = 0;
2633                          iPage < nDriverPages;
2634                          iPage++)
2635                     {
2636                         if (PropSheet_AddPage(hPropSheetDlg,
2637                                               dap->DevPropSheets[iPage]))
2638                         {
2639                             RecalcPages = TRUE;
2640                         }
2641                     }
2642 
2643                     dap->FreeDevPropSheets = TRUE;
2644                 }
2645                 else
2646                 {
2647                     /* cleanup, we were unable to get the device property sheets */
2648                     iPage = nDriverPages;
2649                     dap->nDevPropSheets -= nDriverPages;
2650                     nDriverPages = 0;
2651                 }
2652             }
2653             else
2654                 iPage = 0;
2655 
2656             /* add the driver page if necessary */
2657             if (dap->HasDriverPage)
2658             {
2659                 PROPSHEETPAGE pspDriver = {0};
2660                 pspDriver.dwSize = sizeof(PROPSHEETPAGE);
2661                 pspDriver.dwFlags = PSP_DEFAULT;
2662                 pspDriver.hInstance = hDllInstance;
2663                 pspDriver.pszTemplate = (LPCWSTR)MAKEINTRESOURCE(IDD_DEVICEDRIVER);
2664                 pspDriver.pfnDlgProc = AdvProcDriverDlgProc;
2665                 pspDriver.lParam = (LPARAM)dap;
2666                 dap->DevPropSheets[iPage] = dap->pCreatePropertySheetPageW(&pspDriver);
2667                 if (dap->DevPropSheets[iPage] != NULL)
2668                 {
2669                     if (PropSheet_AddPage(hPropSheetDlg,
2670                                           dap->DevPropSheets[iPage]))
2671                     {
2672                         iPage++;
2673                         RecalcPages = TRUE;
2674                     }
2675                     else
2676                     {
2677                         dap->pDestroyPropertySheetPage(dap->DevPropSheets[iPage]);
2678                         dap->DevPropSheets[iPage] = NULL;
2679                     }
2680                 }
2681             }
2682 
2683             if (dap->Extended)
2684             {
2685                 /* Add the details page */
2686                 PROPSHEETPAGE pspDetails = {0};
2687                 pspDetails.dwSize = sizeof(PROPSHEETPAGE);
2688                 pspDetails.dwFlags = PSP_DEFAULT;
2689                 pspDetails.hInstance = hDllInstance;
2690                 pspDetails.pszTemplate = (LPCWSTR)MAKEINTRESOURCE(IDD_DEVICEDETAILS);
2691                 pspDetails.pfnDlgProc = AdvProcDetailsDlgProc;
2692                 pspDetails.lParam = (LPARAM)dap;
2693                 dap->DevPropSheets[iPage] = dap->pCreatePropertySheetPageW(&pspDetails);
2694                 if (dap->DevPropSheets[iPage] != NULL)
2695                 {
2696                     if (PropSheet_AddPage(hPropSheetDlg,
2697                                           dap->DevPropSheets[iPage]))
2698                     {
2699                         iPage++;
2700                         RecalcPages = TRUE;
2701                     }
2702                     else
2703                     {
2704                         dap->pDestroyPropertySheetPage(dap->DevPropSheets[iPage]);
2705                         dap->DevPropSheets[iPage] = NULL;
2706                     }
2707                 }
2708             }
2709 
2710             if (dap->HasResourcePage && dap->pResourceList)
2711             {
2712                 PROPSHEETPAGE pspDriver = {0};
2713                 pspDriver.dwSize = sizeof(PROPSHEETPAGE);
2714                 pspDriver.dwFlags = PSP_DEFAULT;
2715                 pspDriver.hInstance = hDllInstance;
2716                 pspDriver.pszTemplate = (LPCWSTR)MAKEINTRESOURCE(IDD_DEVICERESOURCES);
2717                 pspDriver.pfnDlgProc = ResourcesProcDriverDlgProc;
2718                 pspDriver.lParam = (LPARAM)dap;
2719                 dap->DevPropSheets[iPage] = dap->pCreatePropertySheetPageW(&pspDriver);
2720                 if (dap->DevPropSheets[iPage] != NULL)
2721                 {
2722                     if (PropSheet_AddPage(hPropSheetDlg,
2723                                           dap->DevPropSheets[iPage]))
2724                     {
2725                         iPage++;
2726                         RecalcPages = TRUE;
2727                     }
2728                     else
2729                     {
2730                         dap->pDestroyPropertySheetPage(dap->DevPropSheets[iPage]);
2731                         dap->DevPropSheets[iPage] = NULL;
2732                     }
2733                 }
2734             }
2735             /* FIXME: Add the power page */
2736         }
2737         else
2738             dap->nDevPropSheets = 0;
2739     }
2740 
2741     if (RecalcPages)
2742     {
2743         PropSheet_RecalcPageSizes(hPropSheetDlg);
2744     }
2745 
2746     /* finally, disable the apply button */
2747     PropSheet_UnChanged(hPropSheetDlg,
2748                         hwndDlg);
2749     dap->DeviceUsageChanged = FALSE;
2750 }
2751 
2752 
2753 static LRESULT
2754 CALLBACK
DlgParentSubWndProc(IN HWND hwnd,IN UINT uMsg,IN WPARAM wParam,IN LPARAM lParam)2755 DlgParentSubWndProc(IN HWND hwnd,
2756                     IN UINT uMsg,
2757                     IN WPARAM wParam,
2758                     IN LPARAM lParam)
2759 {
2760     PDEVADVPROP_INFO dap;
2761 
2762     dap = (PDEVADVPROP_INFO)GetProp(hwnd,
2763                                     L"DevMgrDevChangeSub");
2764     if (dap != NULL)
2765     {
2766         if (uMsg == WM_DEVICECHANGE && !IsWindowVisible(dap->hWndGeneralPage))
2767         {
2768             SendMessage(dap->hWndGeneralPage,
2769                         WM_DEVICECHANGE,
2770                         wParam,
2771                         lParam);
2772         }
2773 
2774         /* pass the message the the old window proc */
2775         return CallWindowProc(dap->ParentOldWndProc,
2776                               hwnd,
2777                               uMsg,
2778                               wParam,
2779                               lParam);
2780     }
2781     else
2782     {
2783         /* this is not a good idea if the subclassed window was an ansi
2784            window, but we failed finding out the previous window proc
2785            so we can't use CallWindowProc. This should rarely - if ever -
2786            happen. */
2787 
2788         return DefWindowProc(hwnd,
2789                              uMsg,
2790                              wParam,
2791                              lParam);
2792     }
2793 }
2794 
2795 
2796 static INT_PTR
2797 CALLBACK
AdvPropGeneralDlgProc(IN HWND hwndDlg,IN UINT uMsg,IN WPARAM wParam,IN LPARAM lParam)2798 AdvPropGeneralDlgProc(IN HWND hwndDlg,
2799                       IN UINT uMsg,
2800                       IN WPARAM wParam,
2801                       IN LPARAM lParam)
2802 {
2803     PDEVADVPROP_INFO dap;
2804     INT_PTR Ret = FALSE;
2805 
2806     dap = (PDEVADVPROP_INFO)GetWindowLongPtr(hwndDlg, DWLP_USER);
2807 
2808     if (dap != NULL || uMsg == WM_INITDIALOG)
2809     {
2810         switch (uMsg)
2811         {
2812             case WM_COMMAND:
2813             {
2814                 switch (LOWORD(wParam))
2815                 {
2816                     case IDC_DEVUSAGE:
2817                     {
2818                         if (HIWORD(wParam) == CBN_SELCHANGE)
2819                         {
2820                             PropSheet_Changed(GetParent(hwndDlg),
2821                                               hwndDlg);
2822                             dap->DeviceUsageChanged = TRUE;
2823                         }
2824                         break;
2825                     }
2826 
2827                     case IDC_DEVPROBLEM:
2828                     {
2829                         if (dap->IsAdmin)
2830                         {
2831                             /* display the device problem wizard */
2832                             ShowDeviceProblemWizard(hwndDlg,
2833                                                     dap->DeviceInfoSet,
2834                                                     &dap->DeviceInfoData,
2835                                                     dap->hMachine);
2836                         }
2837                         break;
2838                     }
2839                 }
2840                 break;
2841             }
2842 
2843             case WM_NOTIFY:
2844             {
2845                 NMHDR *hdr = (NMHDR*)lParam;
2846                 switch (hdr->code)
2847                 {
2848                     case PSN_APPLY:
2849                         ApplyGeneralSettings(hwndDlg,
2850                                              dap);
2851                         break;
2852                 }
2853                 break;
2854             }
2855 
2856             case WM_INITDIALOG:
2857             {
2858                 dap = (PDEVADVPROP_INFO)((LPPROPSHEETPAGE)lParam)->lParam;
2859                 if (dap != NULL)
2860                 {
2861                     HWND hWndParent;
2862 
2863                     dap->hWndGeneralPage = hwndDlg;
2864 
2865                     SetWindowLongPtr(hwndDlg, DWLP_USER, (DWORD_PTR)dap);
2866 
2867                     /* subclass the parent window to always receive
2868                        WM_DEVICECHANGE messages */
2869                     hWndParent = GetParent(hwndDlg);
2870                     if (hWndParent != NULL)
2871                     {
2872                         /* subclass the parent window. This is not safe
2873                            if the parent window belongs to another thread! */
2874                         dap->ParentOldWndProc = (WNDPROC)SetWindowLongPtr(hWndParent,
2875                                                                           GWLP_WNDPROC,
2876                                                                           (LONG_PTR)DlgParentSubWndProc);
2877 
2878                         if (dap->ParentOldWndProc != NULL &&
2879                             SetProp(hWndParent,
2880                                     L"DevMgrDevChangeSub",
2881                                     (HANDLE)dap))
2882                         {
2883                             dap->hWndParent = hWndParent;
2884                         }
2885                     }
2886 
2887                     /* do not call UpdateDevInfo directly in here because it modifies
2888                        the pages of the property sheet! */
2889                     PostMessage(hwndDlg,
2890                                 PM_INITIALIZE,
2891                                 0,
2892                                 0);
2893                 }
2894                 Ret = TRUE;
2895                 break;
2896             }
2897 
2898             case WM_DEVICECHANGE:
2899             {
2900                 /* FIXME - don't call UpdateDevInfo for all events */
2901                 UpdateDevInfo(hwndDlg,
2902                               dap,
2903                               TRUE);
2904                 Ret = TRUE;
2905                 break;
2906             }
2907 
2908             case PM_INITIALIZE:
2909             {
2910                 UpdateDevInfo(hwndDlg,
2911                               dap,
2912                               FALSE);
2913                 dap->PageInitialized = TRUE;
2914                 break;
2915             }
2916 
2917             case WM_DESTROY:
2918             {
2919                 /* restore the old window proc of the subclassed parent window */
2920                 if (dap->hWndParent != NULL && dap->ParentOldWndProc != NULL)
2921                 {
2922                     if (SetWindowLongPtr(dap->hWndParent,
2923                                          GWLP_WNDPROC,
2924                                          (LONG_PTR)dap->ParentOldWndProc) == (LONG_PTR)DlgParentSubWndProc)
2925                     {
2926                         RemoveProp(dap->hWndParent,
2927                                    L"DevMgrDevChangeSub");
2928                     }
2929                 }
2930                 break;
2931             }
2932         }
2933     }
2934 
2935     return Ret;
2936 }
2937 
2938 
2939 INT_PTR
DisplayDeviceAdvancedProperties(IN HWND hWndParent,IN LPCWSTR lpDeviceID OPTIONAL,IN HDEVINFO DeviceInfoSet,IN PSP_DEVINFO_DATA DeviceInfoData,IN HINSTANCE hComCtl32,IN LPCWSTR lpMachineName,IN DWORD dwFlags)2940 DisplayDeviceAdvancedProperties(IN HWND hWndParent,
2941                                 IN LPCWSTR lpDeviceID  OPTIONAL,
2942                                 IN HDEVINFO DeviceInfoSet,
2943                                 IN PSP_DEVINFO_DATA DeviceInfoData,
2944                                 IN HINSTANCE hComCtl32,
2945                                 IN LPCWSTR lpMachineName,
2946                                 IN DWORD dwFlags)
2947 {
2948     PROPSHEETHEADER psh = {0};
2949     PROPSHEETPAGE pspGeneral = {0};
2950     PPROPERTYSHEETW pPropertySheetW;
2951     PCREATEPROPERTYSHEETPAGEW pCreatePropertySheetPageW;
2952     PDESTROYPROPERTYSHEETPAGE pDestroyPropertySheetPage;
2953     PDEVADVPROP_INFO DevAdvPropInfo;
2954     HMACHINE hMachine = NULL;
2955     DWORD DevIdSize = 0;
2956     INT_PTR Ret = -1;
2957 
2958     /* we don't want to statically link against comctl32, so find the
2959        functions we need dynamically */
2960     pPropertySheetW =
2961         (PPROPERTYSHEETW)GetProcAddress(hComCtl32,
2962                                         "PropertySheetW");
2963     pCreatePropertySheetPageW =
2964         (PCREATEPROPERTYSHEETPAGEW)GetProcAddress(hComCtl32,
2965                                                   "CreatePropertySheetPageW");
2966     pDestroyPropertySheetPage =
2967         (PDESTROYPROPERTYSHEETPAGE)GetProcAddress(hComCtl32,
2968                                                   "DestroyPropertySheetPage");
2969     if (pPropertySheetW == NULL ||
2970         pCreatePropertySheetPageW == NULL ||
2971         pDestroyPropertySheetPage == NULL)
2972     {
2973         return -1;
2974     }
2975 
2976     if (lpDeviceID == NULL)
2977     {
2978         /* find out how much size is needed for the device id */
2979         if (SetupDiGetDeviceInstanceId(DeviceInfoSet,
2980                                        DeviceInfoData,
2981                                        NULL,
2982                                        0,
2983                                        &DevIdSize))
2984         {
2985             ERR("SetupDiGetDeviceInstanceId unexpectedly returned TRUE!\n");
2986             return -1;
2987         }
2988 
2989         if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
2990         {
2991             return -1;
2992         }
2993     }
2994     else
2995     {
2996         DevIdSize = (DWORD)wcslen(lpDeviceID) + 1;
2997     }
2998 
2999     if (lpMachineName != NULL && lpMachineName[0] != L'\0')
3000     {
3001         CONFIGRET cr = CM_Connect_Machine(lpMachineName,
3002                                           &hMachine);
3003         if (cr != CR_SUCCESS)
3004         {
3005             return -1;
3006         }
3007     }
3008 
3009     /* create the internal structure associated with the "General",
3010        "Driver", ... pages */
3011     DevAdvPropInfo = (PDEVADVPROP_INFO)HeapAlloc(GetProcessHeap(),
3012                                                  HEAP_ZERO_MEMORY,
3013                                                  FIELD_OFFSET(DEVADVPROP_INFO,
3014                                                               szDeviceID) +
3015                                                      (DevIdSize * sizeof(WCHAR)));
3016     if (DevAdvPropInfo == NULL)
3017     {
3018         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3019         goto Cleanup;
3020     }
3021 
3022     if (lpDeviceID == NULL)
3023     {
3024         /* read the device instance id */
3025         if (!SetupDiGetDeviceInstanceId(DeviceInfoSet,
3026                                         DeviceInfoData,
3027                                         DevAdvPropInfo->szDeviceID,
3028                                         DevIdSize,
3029                                         NULL))
3030         {
3031             goto Cleanup;
3032         }
3033     }
3034     else
3035     {
3036         /* copy the device instance id supplied by the caller */
3037         wcscpy(DevAdvPropInfo->szDeviceID,
3038                lpDeviceID);
3039     }
3040 
3041     DevAdvPropInfo->DeviceInfoSet = DeviceInfoSet;
3042     DevAdvPropInfo->DeviceInfoData = *DeviceInfoData;
3043     DevAdvPropInfo->CurrentDeviceInfoSet = INVALID_HANDLE_VALUE;
3044     DevAdvPropInfo->CurrentDeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
3045 
3046     DevAdvPropInfo->ShowRemotePages = (lpMachineName != NULL && lpMachineName[0] != L'\0');
3047     DevAdvPropInfo->hMachine = hMachine;
3048     DevAdvPropInfo->lpMachineName = lpMachineName;
3049     DevAdvPropInfo->szDevName[0] = L'\0';
3050     DevAdvPropInfo->hComCtl32 = hComCtl32;
3051     DevAdvPropInfo->pCreatePropertySheetPageW = pCreatePropertySheetPageW;
3052     DevAdvPropInfo->pDestroyPropertySheetPage = pDestroyPropertySheetPage;
3053 
3054     DevAdvPropInfo->IsAdmin = TRUE;// IsUserAdmin();
3055     DevAdvPropInfo->DoDefaultDevAction = ((dwFlags & DPF_DEVICE_STATUS_ACTION) != 0);
3056     DevAdvPropInfo->Extended = ((dwFlags & DPF_EXTENDED) != 0);
3057 
3058     psh.dwSize = sizeof(PROPSHEETHEADER);
3059     psh.dwFlags = PSH_PROPTITLE | PSH_NOAPPLYNOW;
3060     psh.hwndParent = hWndParent;
3061     psh.pszCaption = DevAdvPropInfo->szDevName;
3062 
3063     DevAdvPropInfo->PropertySheetType = DevAdvPropInfo->ShowRemotePages ?
3064                                             DIGCDP_FLAG_REMOTE_ADVANCED :
3065                                             DIGCDP_FLAG_ADVANCED;
3066 
3067     psh.phpage = (HPROPSHEETPAGE *)HeapAlloc(GetProcessHeap(),
3068                                              HEAP_ZERO_MEMORY,
3069                                              1 * sizeof(HPROPSHEETPAGE));
3070     if (psh.phpage == NULL)
3071     {
3072         goto Cleanup;
3073     }
3074 
3075     /* add the "General" property sheet */
3076     pspGeneral.dwSize = sizeof(PROPSHEETPAGE);
3077     pspGeneral.dwFlags = PSP_DEFAULT;
3078     pspGeneral.hInstance = hDllInstance;
3079     pspGeneral.pszTemplate = (LPCWSTR)MAKEINTRESOURCE(IDD_DEVICEGENERAL);
3080     pspGeneral.pfnDlgProc = AdvPropGeneralDlgProc;
3081     pspGeneral.lParam = (LPARAM)DevAdvPropInfo;
3082     psh.phpage[psh.nPages] = pCreatePropertySheetPageW(&pspGeneral);
3083     if (psh.phpage[psh.nPages] != NULL)
3084     {
3085         psh.nPages++;
3086     }
3087 
3088     DevAdvPropInfo->nDevPropSheets = psh.nPages;
3089 
3090     if (psh.nPages != 0)
3091     {
3092         Ret = pPropertySheetW(&psh);
3093 
3094         /* NOTE: no need to destroy the property sheets anymore! */
3095     }
3096     else
3097     {
3098         UINT i;
3099 
3100 Cleanup:
3101         /* in case of failure the property sheets must be destroyed */
3102         if (psh.phpage != NULL)
3103         {
3104             for (i = 0;
3105                  i < psh.nPages;
3106                  i++)
3107             {
3108                 if (psh.phpage[i] != NULL)
3109                 {
3110                     pDestroyPropertySheetPage(psh.phpage[i]);
3111                 }
3112             }
3113         }
3114     }
3115 
3116     if (Ret != 1)
3117     {
3118         SP_DEVINSTALL_PARAMS_W DeviceInstallParams;
3119 
3120         DeviceInstallParams.cbSize = sizeof(DeviceInstallParams);
3121         if (SetupDiGetDeviceInstallParamsW(DeviceInfoSet,
3122                                            DeviceInfoData,
3123                                            &DeviceInstallParams))
3124         {
3125             SP_PROPCHANGE_PARAMS PropChangeParams;
3126             PropChangeParams.ClassInstallHeader.cbSize = sizeof(PropChangeParams.ClassInstallHeader);
3127             PropChangeParams.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
3128             PropChangeParams.Scope = DICS_FLAG_GLOBAL;
3129             PropChangeParams.StateChange = DICS_PROPCHANGE;
3130 
3131             SetupDiSetClassInstallParamsW(DeviceInfoSet,
3132                                           DeviceInfoData,
3133                                           (PSP_CLASSINSTALL_HEADER)&PropChangeParams,
3134                                           sizeof(PropChangeParams));
3135 
3136             SetupDiCallClassInstaller(DIF_PROPERTYCHANGE,
3137                                       DeviceInfoSet,
3138                                       DeviceInfoData);
3139 
3140             DeviceInstallParams.FlagsEx &= ~DI_FLAGSEX_PROPCHANGE_PENDING;
3141             SetupDiSetDeviceInstallParamsW(DeviceInfoSet,
3142                                            DeviceInfoData,
3143                                            &DeviceInstallParams);
3144         }
3145     }
3146 
3147     if (DevAdvPropInfo != NULL)
3148     {
3149         if (DevAdvPropInfo->FreeDevPropSheets)
3150         {
3151             /* don't free the array if it's the one allocated in
3152                DisplayDeviceAdvancedProperties */
3153             HeapFree(GetProcessHeap(),
3154                      0,
3155                      DevAdvPropInfo->DevPropSheets);
3156         }
3157 
3158         if (DevAdvPropInfo->CloseDevInst)
3159         {
3160             /* close the device info set in case a new one was created */
3161             SetupDiDestroyDeviceInfoList(DevAdvPropInfo->DeviceInfoSet);
3162         }
3163 
3164         if (DevAdvPropInfo->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
3165         {
3166             SetupDiDestroyDeviceInfoList(DevAdvPropInfo->CurrentDeviceInfoSet);
3167         }
3168 
3169         if (DevAdvPropInfo->hDevIcon != NULL)
3170         {
3171             DestroyIcon(DevAdvPropInfo->hDevIcon);
3172         }
3173 
3174         if (DevAdvPropInfo->pResourceList != NULL)
3175             HeapFree(GetProcessHeap(), 0, DevAdvPropInfo->pResourceList);
3176 
3177         HeapFree(GetProcessHeap(),
3178                  0,
3179                  DevAdvPropInfo);
3180     }
3181 
3182     if (psh.phpage != NULL)
3183     {
3184         HeapFree(GetProcessHeap(),
3185                  0,
3186                  psh.phpage);
3187     }
3188 
3189     if (hMachine != NULL)
3190     {
3191         CM_Disconnect_Machine(hMachine);
3192     }
3193 
3194     return Ret;
3195 }
3196