xref: /reactos/dll/cpl/hdwwiz/hdwwiz.c (revision cc439606)
1 /*
2  * ReactOS New devices installation
3  * Copyright (C) 2005, 2008 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  * PROJECT:         ReactOS Add hardware control panel
21  * FILE:            dll/cpl/hdwwiz/hdwwiz.c
22  * PURPOSE:         ReactOS Add hardware control panel
23  * PROGRAMMER:      Herv� Poussineau (hpoussin@reactos.org)
24  *                  Dmitry Chapyshev (dmitry@reactos.org)
25  */
26 
27 #include "resource.h"
28 #include "hdwwiz.h"
29 
30 /* GLOBALS ******************************************************************/
31 
32 HINSTANCE hApplet = NULL;
33 HFONT hTitleFont;
34 SP_CLASSIMAGELIST_DATA ImageListData;
35 PWSTR pDeviceStatusText;
36 HANDLE hProcessHeap;
37 HDEVINFO hDevInfoTypes;
38 
39 typedef BOOL (WINAPI *PINSTALL_NEW_DEVICE)(HWND, LPGUID, PDWORD);
40 
41 
42 /* STATIC FUNCTIONS *********************************************************/
43 
44 static HFONT
45 CreateTitleFont(VOID)
46 {
47     NONCLIENTMETRICS ncm;
48     LOGFONT LogFont;
49     HDC hdc;
50     INT FontSize;
51     HFONT hFont;
52 
53     ncm.cbSize = sizeof(NONCLIENTMETRICS);
54     SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
55 
56     LogFont = ncm.lfMessageFont;
57     LogFont.lfWeight = FW_BOLD;
58     wcscpy(LogFont.lfFaceName, L"MS Shell Dlg");
59 
60     hdc = GetDC(NULL);
61     FontSize = 12;
62     LogFont.lfHeight = 0 - GetDeviceCaps (hdc, LOGPIXELSY) * FontSize / 72;
63     hFont = CreateFontIndirect(&LogFont);
64     ReleaseDC(NULL, hdc);
65 
66     return hFont;
67 }
68 
69 static INT_PTR CALLBACK
70 StartPageDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
71 {
72     switch (uMsg)
73     {
74         case WM_INITDIALOG:
75         {
76             /* Set title font */
77             SendDlgItemMessage(hwndDlg, IDC_FINISHTITLE, WM_SETFONT, (WPARAM)hTitleFont, (LPARAM)TRUE);
78         }
79         break;
80 
81         case WM_NOTIFY:
82         {
83             LPNMHDR lpnm = (LPNMHDR)lParam;
84 
85             switch (lpnm->code)
86             {
87                 case PSN_SETACTIVE:
88                 {
89                     PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT);
90                 }
91                 break;
92             }
93         }
94         break;
95     }
96 
97     return FALSE;
98 }
99 
100 static INT_PTR CALLBACK
101 SearchPageDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
102 {
103     switch (uMsg)
104     {
105         case WM_INITDIALOG:
106         {
107             /* TODO: PnP devices search */
108         }
109         break;
110 
111         case WM_NOTIFY:
112         {
113             LPNMHDR lpnm = (LPNMHDR)lParam;
114 
115             switch (lpnm->code)
116             {
117                 case PSN_SETACTIVE:
118                 {
119                     PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT | PSWIZB_BACK);
120                 }
121                 break;
122             }
123         }
124         break;
125     }
126 
127     return FALSE;
128 }
129 
130 static INT_PTR CALLBACK
131 IsConnectedPageDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
132 {
133     switch (uMsg)
134     {
135         case WM_COMMAND:
136         {
137             if(HIWORD(wParam) == BN_CLICKED)
138             {
139                 if ((SendDlgItemMessage(hwndDlg, IDC_CONNECTED, BM_GETCHECK, 0, 0) == BST_CHECKED) ||
140                     (SendDlgItemMessage(hwndDlg, IDC_NOTCONNECTED, BM_GETCHECK, 0, 0) == BST_CHECKED))
141                 {
142                     PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT | PSWIZB_BACK);
143                 }
144                 else
145                 {
146                     PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK);
147                 }
148             }
149         }
150         break;
151 
152         case WM_NOTIFY:
153         {
154             LPNMHDR lpnm = (LPNMHDR)lParam;
155 
156             switch (lpnm->code)
157             {
158                 case PSN_SETACTIVE:
159                 {
160                     if ((SendDlgItemMessage(hwndDlg, IDC_CONNECTED, BM_GETCHECK, 0, 0) == BST_CHECKED) ||
161                         (SendDlgItemMessage(hwndDlg, IDC_NOTCONNECTED, BM_GETCHECK, 0, 0) == BST_CHECKED))
162                     {
163                         PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT | PSWIZB_BACK);
164                     }
165                     else
166                     {
167                         PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK);
168                     }
169                 }
170                 break;
171 
172                 case PSN_WIZNEXT:
173                 {
174                     if (SendDlgItemMessage(hwndDlg, IDC_NOTCONNECTED, BM_GETCHECK, 0, 0) == BST_CHECKED)
175                         SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, IDD_NOTCONNECTEDPAGE);
176                     else
177                         SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, IDD_PROBELISTPAGE);
178 
179                     return TRUE;
180                 }
181             }
182         }
183         break;
184     }
185 
186     return FALSE;
187 }
188 
189 static INT_PTR CALLBACK
190 FinishPageDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
191 {
192     switch (uMsg)
193     {
194         case WM_INITDIALOG:
195         {
196             /* Set title font */
197             SendDlgItemMessage(hwndDlg, IDC_FINISHTITLE, WM_SETFONT, (WPARAM)hTitleFont, (LPARAM)TRUE);
198         }
199         break;
200 
201         case WM_NOTIFY:
202         {
203             LPNMHDR lpnm = (LPNMHDR)lParam;
204 
205             switch (lpnm->code)
206             {
207                 case PSN_SETACTIVE:
208                 {
209                     /* Only "Finish" button */
210                     PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_FINISH);
211                 }
212                 break;
213             }
214         }
215         break;
216     }
217 
218     return FALSE;
219 }
220 
221 static INT_PTR CALLBACK
222 NotConnectedPageDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
223 {
224     switch (uMsg)
225     {
226         case WM_INITDIALOG:
227         {
228             /* Set title font */
229             SendDlgItemMessage(hwndDlg, IDC_FINISHTITLE, WM_SETFONT, (WPARAM)hTitleFont, (LPARAM)TRUE);
230         }
231         break;
232 
233         case WM_NOTIFY:
234         {
235             LPNMHDR lpnm = (LPNMHDR)lParam;
236 
237             switch (lpnm->code)
238             {
239                 case PSN_SETACTIVE:
240                 {
241                     PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_FINISH | PSWIZB_BACK);
242                 }
243                 break;
244 
245                 case PSN_WIZBACK:
246                 {
247                     SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, IDD_ISCONNECTEDPAGE);
248                     return TRUE;
249                 }
250             }
251         }
252         break;
253     }
254 
255     return FALSE;
256 }
257 
258 static VOID
259 TrimGuidString(LPWSTR szString, LPWSTR szNewString)
260 {
261     WCHAR szBuffer[39];
262     INT Index;
263 
264     if (wcslen(szString) == 38)
265     {
266         if ((szString[0] == L'{') && (szString[37] == L'}'))
267         {
268             for (Index = 0; Index < wcslen(szString); Index++)
269                 szBuffer[Index] = szString[Index + 1];
270 
271             szBuffer[36] = L'\0';
272             wcscpy(szNewString, szBuffer);
273             return;
274         }
275     }
276     wcscpy(szNewString, L"\0");
277 }
278 
279 static VOID
280 InitProbeListPage(HWND hwndDlg)
281 {
282     LV_COLUMN Column;
283     LV_ITEM Item;
284     WCHAR szBuffer[MAX_STR_SIZE], szGuid[MAX_STR_SIZE],
285           szTrimGuid[MAX_STR_SIZE], szStatusText[MAX_STR_SIZE];
286     HWND hList = GetDlgItem(hwndDlg, IDC_PROBELIST);
287     PWSTR pstrStatusText;
288     HDEVINFO hDevInfo;
289     SP_DEVINFO_DATA DevInfoData;
290     ULONG ulStatus, ulProblemNumber;
291     GUID ClassGuid;
292     RECT Rect;
293     DWORD Index;
294 
295     if (!hList) return;
296 
297     ZeroMemory(&Column, sizeof(LV_COLUMN));
298 
299     GetClientRect(hList, &Rect);
300 
301     Column.mask         = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
302     Column.fmt          = LVCFMT_LEFT;
303     Column.iSubItem     = 0;
304     Column.pszText      = NULL;
305     Column.cx           = Rect.right - GetSystemMetrics(SM_CXVSCROLL);
306     (VOID) ListView_InsertColumn(hList, 0, &Column);
307 
308     ZeroMemory(&Item, sizeof(LV_ITEM));
309 
310     LoadString(hApplet, IDS_ADDNEWDEVICE, szBuffer, sizeof(szBuffer) / sizeof(WCHAR));
311 
312     Item.mask       = LVIF_TEXT | LVIF_PARAM | LVIF_STATE | LVIF_IMAGE;
313     Item.pszText    = (LPWSTR) szBuffer;
314     Item.iItem      = (INT) ListView_GetItemCount(hList);
315     Item.iImage     = -1;
316     (VOID) ListView_InsertItem(hList, &Item);
317 
318     hDevInfo = SetupDiGetClassDevsEx(NULL, NULL, NULL, DIGCF_ALLCLASSES | DIGCF_PRESENT, NULL, NULL, 0);
319 
320     if (hDevInfo == INVALID_HANDLE_VALUE) return;
321 
322     /* Get the device image List */
323     ImageListData.cbSize = sizeof(ImageListData);
324     SetupDiGetClassImageList(&ImageListData);
325 
326     DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
327     for (Index = 0; TRUE; Index++)
328     {
329         szBuffer[0] = L'\0';
330 
331         if (!SetupDiEnumDeviceInfo(hDevInfo, Index, &DevInfoData)) break;
332 
333         if (CM_Get_DevNode_Status_Ex(&ulStatus, &ulProblemNumber, DevInfoData.DevInst, 0, NULL) == CR_SUCCESS)
334         {
335             if (ulStatus & DN_NO_SHOW_IN_DM) continue;
336         }
337 
338         /* Get the device's friendly name */
339         if (!SetupDiGetDeviceRegistryProperty(hDevInfo,
340                                               &DevInfoData,
341                                               SPDRP_FRIENDLYNAME,
342                                               0,
343                                               (BYTE*)szBuffer,
344                                               MAX_STR_SIZE,
345                                               NULL))
346         {
347             /* If the friendly name fails, try the description instead */
348             SetupDiGetDeviceRegistryProperty(hDevInfo,
349                                              &DevInfoData,
350                                              SPDRP_DEVICEDESC,
351                                              0,
352                                              (BYTE*)szBuffer,
353                                              MAX_STR_SIZE,
354                                              NULL);
355         }
356 
357         SetupDiGetDeviceRegistryProperty(hDevInfo,
358                                          &DevInfoData,
359                                          SPDRP_CLASSGUID,
360                                          0,
361                                          (BYTE*)szGuid,
362                                          MAX_STR_SIZE,
363                                          NULL);
364 
365         TrimGuidString(szGuid, szTrimGuid);
366         UuidFromStringW(szTrimGuid, &ClassGuid);
367 
368         SetupDiGetClassImageIndex(&ImageListData,
369                                   &ClassGuid,
370                                   &Item.iImage);
371 
372         DeviceProblemTextW(NULL,
373                            DevInfoData.DevInst,
374                            ulProblemNumber,
375                            szStatusText,
376                            sizeof(szStatusText) / sizeof(WCHAR));
377 
378         pstrStatusText = (PWSTR)HeapAlloc(hProcessHeap, 0, sizeof(szStatusText));
379         lstrcpy(pstrStatusText, szStatusText);
380 
381         if (szBuffer[0] != L'\0')
382         {
383             /* Set device name */
384             Item.pszText = (LPWSTR) szBuffer;
385             Item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE | LVIF_IMAGE;
386             Item.lParam = (LPARAM) pstrStatusText;
387             Item.iItem = (INT) ListView_GetItemCount(hList);
388             (VOID) ListView_InsertItem(hList, &Item);
389         }
390 
391         DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
392     }
393 
394     (VOID) ListView_SetImageList(hList, ImageListData.ImageList, LVSIL_SMALL);
395     (VOID) ListView_SetExtendedListViewStyle(hList, LVS_EX_FULLROWSELECT);
396     SetupDiDestroyDeviceInfoList(hDevInfo);
397 }
398 
399 static INT_PTR CALLBACK
400 ProbeListPageDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
401 {
402     INT Index;
403 
404     switch (uMsg)
405     {
406         case WM_INITDIALOG:
407         {
408             pDeviceStatusText = (PWSTR)HeapAlloc(hProcessHeap, 0, MAX_STR_SIZE);
409             InitProbeListPage(hwndDlg);
410         }
411         break;
412 
413         case WM_NOTIFY:
414         {
415             LPNMHDR lpnm = (LPNMHDR)lParam;
416 
417             switch (lpnm->code)
418             {
419                 case PSN_SETACTIVE:
420                 {
421                     PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_NEXT);
422                 }
423                 break;
424 
425                 case PSN_WIZNEXT:
426                 {
427                     Index = (INT) SendMessage(GetDlgItem(hwndDlg, IDC_PROBELIST), LVM_GETNEXTITEM, -1, LVNI_FOCUSED);
428                     if (Index == -1) Index = 0;
429 
430                     if (Index == 0)
431                     {
432                         SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, IDD_SELECTWAYPAGE);
433                     }
434                     else
435                     {
436                         LVITEM Item;
437                         PWSTR pts;
438 
439                         ZeroMemory(&Item, sizeof(LV_ITEM));
440                         Item.mask = LVIF_PARAM;
441                         Item.iItem = Index;
442                         (VOID) ListView_GetItem(GetDlgItem(hwndDlg, IDC_PROBELIST), &Item);
443                         pts = (PWSTR) Item.lParam;
444                         wcscpy(pDeviceStatusText, pts);
445 
446                         SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, IDD_HWSTATUSPAGE);
447                     }
448                     return TRUE;
449                 }
450             }
451         }
452         break;
453 
454         case WM_DESTROY:
455         {
456             INT Index;
457             LVITEM Item;
458 
459             for (Index = ListView_GetItemCount(GetDlgItem(hwndDlg, IDC_PROBELIST)); --Index > 0;)
460             {
461                 ZeroMemory(&Item, sizeof(LV_ITEM));
462                 Item.mask = LVIF_PARAM;
463                 Item.iItem = Index;
464                 (VOID) ListView_GetItem(GetDlgItem(hwndDlg, IDC_PROBELIST), &Item);
465                 HeapFree(hProcessHeap, 0, (LPVOID) Item.lParam);
466             }
467             HeapFree(hProcessHeap, 0, (LPVOID) pDeviceStatusText);
468         }
469         break;
470     }
471 
472     return FALSE;
473 }
474 
475 static INT_PTR CALLBACK
476 SelectWayPageDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
477 {
478     switch (uMsg)
479     {
480         case WM_NOTIFY:
481         {
482             LPNMHDR lpnm = (LPNMHDR)lParam;
483 
484             switch (lpnm->code)
485             {
486                 case PSN_SETACTIVE:
487                 {
488                     PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT | PSWIZB_BACK);
489                     if (SendDlgItemMessage(hwndDlg, IDC_AUTOINSTALL, BM_GETCHECK, 0, 0) == BST_CHECKED)
490                         SendDlgItemMessage(hwndDlg, IDC_MANUALLYINST, BM_SETCHECK, 0, 0);
491                     else
492                     {
493                         SendDlgItemMessage(hwndDlg, IDC_AUTOINSTALL, BM_SETCHECK, 1, 1);
494                         SendDlgItemMessage(hwndDlg, IDC_MANUALLYINST, BM_SETCHECK, 0, 0);
495                     }
496                 }
497                 break;
498 
499                 case PSN_WIZNEXT:
500                 {
501                     if (SendDlgItemMessage(hwndDlg, IDC_AUTOINSTALL, BM_GETCHECK, 0, 0) == BST_CHECKED)
502                         SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, IDD_PROGRESSPAGE);
503                     else
504                         SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, IDD_HWTYPESPAGE);
505 
506                     return TRUE;
507                 }
508             }
509         }
510         break;
511     }
512 
513     return FALSE;
514 }
515 
516 static INT_PTR CALLBACK
517 DevStatusPageDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
518 {
519     switch (uMsg)
520     {
521         case WM_INITDIALOG:
522         {
523             /* Set title font */
524             SendDlgItemMessage(hwndDlg, IDC_FINISHTITLE, WM_SETFONT, (WPARAM)hTitleFont, (LPARAM)TRUE);
525         }
526         break;
527 
528         case WM_NOTIFY:
529         {
530             LPNMHDR lpnm = (LPNMHDR)lParam;
531 
532             switch (lpnm->code)
533             {
534                 case PSN_SETACTIVE:
535                 {
536                     /* Set status text */
537                     SetWindowText(GetDlgItem(hwndDlg, IDC_HWSTATUSEDIT), pDeviceStatusText);
538 
539                     PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_FINISH | PSWIZB_BACK);
540                 }
541                 break;
542 
543                 case PSN_WIZBACK:
544                 {
545                     SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, IDD_PROBELISTPAGE);
546                     return TRUE;
547                 }
548             }
549         }
550         break;
551     }
552 
553     return FALSE;
554 }
555 
556 static INT
557 EnumDeviceClasses(INT ClassIndex,
558                   LPWSTR DevClassName,
559                   LPWSTR DevClassDesc,
560                   BOOL *DevPresent,
561                   INT *ClassImage)
562 {
563     GUID ClassGuid;
564     HKEY KeyClass;
565     WCHAR ClassName[MAX_STR_SIZE];
566     DWORD RequiredSize = MAX_STR_SIZE;
567     UINT Ret;
568 
569     *DevPresent = FALSE;
570     *DevClassName = L'\0';
571 
572     Ret = CM_Enumerate_Classes(ClassIndex,
573                                &ClassGuid,
574                                0);
575     if (Ret != CR_SUCCESS)
576     {
577         /* All classes enumerated */
578         if(Ret == CR_NO_SUCH_VALUE)
579         {
580             hDevInfoTypes = NULL;
581             return -1;
582         }
583 
584         if (Ret == CR_INVALID_DATA)
585         {
586             ; /* FIXME: What should we do here? */
587         }
588 
589         /* Handle other errors... */
590     }
591 
592     if (SetupDiClassNameFromGuid(&ClassGuid,
593                                  ClassName,
594                                  RequiredSize,
595                                  &RequiredSize))
596     {
597         lstrcpy(DevClassName, ClassName);
598     }
599 
600     if (!SetupDiGetClassImageIndex(&ImageListData,
601                                    &ClassGuid,
602                                    ClassImage))
603     {
604         /* FIXME: Can we do this?
605          * Set the blank icon: IDI_SETUPAPI_BLANK = 41
606          * It'll be image 24 in the imagelist */
607         *ClassImage = 24;
608     }
609 
610     /* Get device info for all devices of a particular class */
611     hDevInfoTypes = SetupDiGetClassDevs(&ClassGuid,
612                                    NULL,
613                                    NULL,
614                                    DIGCF_PRESENT);
615     if (hDevInfoTypes == INVALID_HANDLE_VALUE)
616     {
617         hDevInfoTypes = NULL;
618         return 0;
619     }
620 
621     KeyClass = SetupDiOpenClassRegKeyEx(&ClassGuid,
622                                         MAXIMUM_ALLOWED,
623                                         DIOCR_INSTALLER,
624                                         NULL,
625                                         0);
626     if (KeyClass != INVALID_HANDLE_VALUE)
627     {
628 
629         LONG dwSize = MAX_STR_SIZE;
630 
631         if (RegQueryValue(KeyClass,
632                           NULL,
633                           DevClassDesc,
634                           &dwSize) != ERROR_SUCCESS)
635         {
636             *DevClassDesc = L'\0';
637         }
638     }
639     else
640     {
641         return -3;
642     }
643 
644     *DevPresent = TRUE;
645 
646     RegCloseKey(KeyClass);
647 
648     return 0;
649 }
650 
651 static VOID
652 InitHardWareTypesPage(HWND hwndDlg)
653 {
654     HWND hList = GetDlgItem(hwndDlg, IDC_HWTYPESLIST);
655     WCHAR DevName[MAX_STR_SIZE];
656     WCHAR DevDesc[MAX_STR_SIZE];
657     BOOL DevExist = FALSE;
658     INT ClassRet, DevImage, Index = 0;
659     LV_COLUMN Column;
660     LV_ITEM Item;
661     RECT Rect;
662 
663     if (!hList) return;
664 
665     ZeroMemory(&Column, sizeof(LV_COLUMN));
666 
667     GetClientRect(hList, &Rect);
668 
669     Column.mask         = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
670     Column.fmt          = LVCFMT_LEFT;
671     Column.iSubItem     = 0;
672     Column.pszText      = NULL;
673     Column.cx           = Rect.right - GetSystemMetrics(SM_CXVSCROLL);
674     (VOID) ListView_InsertColumn(hList, 0, &Column);
675 
676     ZeroMemory(&Item, sizeof(LV_ITEM));
677 
678     do
679     {
680         ClassRet = EnumDeviceClasses(Index,
681                                      DevName,
682                                      DevDesc,
683                                      &DevExist,
684                                      &DevImage);
685 
686         if ((ClassRet != -1) && (DevExist))
687         {
688             Item.mask   = LVIF_TEXT | LVIF_PARAM | LVIF_STATE | LVIF_IMAGE;
689             Item.iItem  = Index;
690             Item.iImage = DevImage;
691 
692             if (DevDesc[0] != L'\0')
693                 Item.pszText = (LPWSTR) DevDesc;
694             else
695                 Item.pszText = (LPWSTR) DevName;
696 
697             (VOID) ListView_InsertItem(hList, &Item);
698 
699             /* Kill InfoList initialized in EnumDeviceClasses */
700             if (hDevInfoTypes)
701             {
702                 SetupDiDestroyDeviceInfoList(hDevInfoTypes);
703                 hDevInfoTypes = NULL;
704             }
705         }
706         Index++;
707     }
708     while (ClassRet != -1);
709 
710     (VOID) ListView_SetImageList(hList, ImageListData.ImageList, LVSIL_SMALL);
711 }
712 
713 static INT_PTR CALLBACK
714 HdTypesPageDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
715 {
716     switch (uMsg)
717     {
718         case WM_INITDIALOG:
719         {
720             InitHardWareTypesPage(hwndDlg);
721         }
722         break;
723 
724         case WM_NOTIFY:
725         {
726             LPNMHDR lpnm = (LPNMHDR)lParam;
727 
728             switch (lpnm->code)
729             {
730                 case PSN_SETACTIVE:
731                 {
732                     PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK);
733                 }
734                 break;
735 
736                 case PSN_WIZBACK:
737                 {
738                     SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, IDD_SELECTWAYPAGE);
739                     return TRUE;
740                 }
741             }
742         }
743         break;
744     }
745 
746     return FALSE;
747 }
748 
749 static INT_PTR CALLBACK
750 ProgressPageDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
751 {
752     switch (uMsg)
753     {
754         case WM_NOTIFY:
755         {
756             LPNMHDR lpnm = (LPNMHDR)lParam;
757 
758             switch (lpnm->code)
759             {
760                 case PSN_SETACTIVE:
761                 {
762                     PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK);
763                 }
764                 break;
765 
766                 case PSN_WIZBACK:
767                 {
768                     SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, IDD_SELECTWAYPAGE);
769                     return TRUE;
770                 }
771             }
772         }
773         break;
774     }
775 
776     return FALSE;
777 }
778 
779 static VOID
780 HardwareWizardInit(HWND hwnd)
781 {
782     HPROPSHEETPAGE ahpsp[10];
783     PROPSHEETPAGE psp = {0};
784     PROPSHEETHEADER psh;
785     UINT nPages = 0;
786 
787     /* Create the Start page, until setup is working */
788     psp.dwSize = sizeof(PROPSHEETPAGE);
789     psp.dwFlags = PSP_DEFAULT | PSP_HIDEHEADER;
790     psp.hInstance = hApplet;
791     psp.lParam = 0;
792     psp.pfnDlgProc = StartPageDlgProc;
793     psp.pszTemplate = MAKEINTRESOURCE(IDD_STARTPAGE);
794     ahpsp[nPages++] = CreatePropertySheetPage(&psp);
795 
796     /* Create search page */
797     psp.dwSize = sizeof(PROPSHEETPAGE);
798     psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
799     psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_SEARCHTITLE);
800     psp.pszHeaderSubTitle = NULL;
801     psp.hInstance = hApplet;
802     psp.lParam = 0;
803     psp.pfnDlgProc = SearchPageDlgProc;
804     psp.pszTemplate = MAKEINTRESOURCE(IDD_SEARCHPAGE);
805     ahpsp[nPages++] = CreatePropertySheetPage(&psp);
806 
807     /* Create is connected page */
808     psp.dwSize = sizeof(PROPSHEETPAGE);
809     psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
810     psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_ISCONNECTED);
811     psp.pszHeaderSubTitle = NULL;
812     psp.hInstance = hApplet;
813     psp.lParam = 0;
814     psp.pfnDlgProc = IsConnectedPageDlgProc;
815     psp.pszTemplate = MAKEINTRESOURCE(IDD_ISCONNECTEDPAGE);
816     ahpsp[nPages++] = CreatePropertySheetPage(&psp);
817 
818     /* Create probe list page */
819     psp.dwSize = sizeof(PROPSHEETPAGE);
820     psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
821     psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_PROBELISTTITLE);
822     psp.pszHeaderSubTitle = NULL;
823     psp.hInstance = hApplet;
824     psp.lParam = 0;
825     psp.pfnDlgProc = ProbeListPageDlgProc;
826     psp.pszTemplate = MAKEINTRESOURCE(IDD_PROBELISTPAGE);
827     ahpsp[nPages++] = CreatePropertySheetPage(&psp);
828 
829     /* Create select search way page */
830     psp.dwSize = sizeof(PROPSHEETPAGE);
831     psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
832     psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_SELECTWAYTITLE);
833     psp.pszHeaderSubTitle = NULL;
834     psp.hInstance = hApplet;
835     psp.lParam = 0;
836     psp.pfnDlgProc = SelectWayPageDlgProc;
837     psp.pszTemplate = MAKEINTRESOURCE(IDD_SELECTWAYPAGE);
838     ahpsp[nPages++] = CreatePropertySheetPage(&psp);
839 
840     /* Create device status page */
841     psp.dwSize = sizeof(PROPSHEETPAGE);
842     psp.dwFlags = PSP_DEFAULT | PSP_HIDEHEADER;
843     psp.hInstance = hApplet;
844     psp.lParam = 0;
845     psp.pfnDlgProc = DevStatusPageDlgProc;
846     psp.pszTemplate = MAKEINTRESOURCE(IDD_HWSTATUSPAGE);
847     ahpsp[nPages++] = CreatePropertySheetPage(&psp);
848 
849     /* Create hardware types page */
850     psp.dwSize = sizeof(PROPSHEETPAGE);
851     psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
852     psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_HDTYPESTITLE);
853     psp.pszHeaderSubTitle = NULL;
854     psp.hInstance = hApplet;
855     psp.lParam = 0;
856     psp.pfnDlgProc = HdTypesPageDlgProc;
857     psp.pszTemplate = MAKEINTRESOURCE(IDD_HWTYPESPAGE);
858     ahpsp[nPages++] = CreatePropertySheetPage(&psp);
859 
860     /* Create progress page */
861     psp.dwSize = sizeof(PROPSHEETPAGE);
862     psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
863     psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_SEARCHTITLE);
864     psp.pszHeaderSubTitle = NULL;
865     psp.hInstance = hApplet;
866     psp.lParam = 0;
867     psp.pfnDlgProc = ProgressPageDlgProc;
868     psp.pszTemplate = MAKEINTRESOURCE(IDD_PROGRESSPAGE);
869     ahpsp[nPages++] = CreatePropertySheetPage(&psp);
870 
871     /* Create finish page */
872     psp.dwSize = sizeof(PROPSHEETPAGE);
873     psp.dwFlags = PSP_DEFAULT | PSP_HIDEHEADER;
874     psp.hInstance = hApplet;
875     psp.lParam = 0;
876     psp.pfnDlgProc = FinishPageDlgProc;
877     psp.pszTemplate = MAKEINTRESOURCE(IDD_FINISHPAGE);
878     ahpsp[nPages++] = CreatePropertySheetPage(&psp);
879 
880     /* Create not connected page */
881     psp.dwSize = sizeof(PROPSHEETPAGE);
882     psp.dwFlags = PSP_DEFAULT | PSP_HIDEHEADER;
883     psp.hInstance = hApplet;
884     psp.lParam = 0;
885     psp.pfnDlgProc = NotConnectedPageDlgProc;
886     psp.pszTemplate = MAKEINTRESOURCE(IDD_NOTCONNECTEDPAGE);
887     ahpsp[nPages++] = CreatePropertySheetPage(&psp);
888 
889     /* Create the property sheet */
890     psh.dwSize = sizeof(PROPSHEETHEADER);
891     psh.dwFlags = PSH_WIZARD97 | PSH_WATERMARK | PSH_HEADER;
892     psh.hInstance = hApplet;
893     psh.hwndParent = hwnd;
894     psh.nPages = nPages;
895     psh.nStartPage = 0;
896     psh.phpage = ahpsp;
897     psh.pszbmWatermark = MAKEINTRESOURCE(IDB_WATERMARK);
898     psh.pszbmHeader = MAKEINTRESOURCE(IDB_HEADER);
899 
900     /* Create title font */
901     hTitleFont = CreateTitleFont();
902 
903     /* Display the wizard */
904     PropertySheet(&psh);
905 
906     DeleteObject(hTitleFont);
907 }
908 
909 /* FUNCTIONS ****************************************************************/
910 
911 BOOL WINAPI
912 InstallNewDevice(HWND hwndParent, LPGUID ClassGuid, PDWORD pReboot)
913 {
914     return FALSE;
915 }
916 
917 VOID WINAPI
918 AddHardwareWizard(HWND hwnd, LPWSTR lpName)
919 {
920     if (lpName != NULL)
921     {
922         DPRINT1("No support of remote installation yet!\n");
923         return;
924     }
925 
926     HardwareWizardInit(hwnd);
927 }
928 
929 /* Control Panel Callback */
930 LONG CALLBACK
931 CPlApplet(HWND hwndCpl, UINT uMsg, LPARAM lParam1, LPARAM lParam2)
932 {
933     switch (uMsg)
934     {
935         case CPL_INIT:
936             return TRUE;
937 
938         case CPL_GETCOUNT:
939             return 1;
940 
941         case CPL_INQUIRE:
942             {
943                 CPLINFO *CPlInfo = (CPLINFO*)lParam2;
944                 CPlInfo->lData = 0;
945                 CPlInfo->idIcon = IDI_CPLICON;
946                 CPlInfo->idName = IDS_CPLNAME;
947                 CPlInfo->idInfo = IDS_CPLDESCRIPTION;
948             }
949             break;
950 
951         case CPL_DBLCLK:
952             AddHardwareWizard(hwndCpl, NULL);
953             break;
954     }
955 
956     return FALSE;
957 }
958 
959 BOOL WINAPI
960 DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpvReserved)
961 {
962     UNREFERENCED_PARAMETER(lpvReserved);
963 
964     switch (dwReason)
965     {
966         case DLL_PROCESS_ATTACH:
967             hApplet = hinstDLL;
968             hProcessHeap = GetProcessHeap();
969             DisableThreadLibraryCalls(hinstDLL);
970             break;
971     }
972 
973     return TRUE;
974 }
975