- Partly implement of installed hardware page
[reactos.git] / reactos / dll / cpl / hdwwiz / hdwwiz.c
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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
36 typedef BOOL (WINAPI *PINSTALL_NEW_DEVICE)(HWND, LPGUID, PDWORD);
37
38
39 /* STATIC FUNCTIONS *********************************************************/
40
41 static HFONT
42 CreateTitleFont(VOID)
43 {
44 NONCLIENTMETRICS ncm;
45 LOGFONT LogFont;
46 HDC hdc;
47 INT FontSize;
48 HFONT hFont;
49
50 ncm.cbSize = sizeof(NONCLIENTMETRICS);
51 SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
52
53 LogFont = ncm.lfMessageFont;
54 LogFont.lfWeight = FW_BOLD;
55 _tcscpy(LogFont.lfFaceName, _T("MS Shell Dlg"));
56
57 hdc = GetDC(NULL);
58 FontSize = 12;
59 LogFont.lfHeight = 0 - GetDeviceCaps (hdc, LOGPIXELSY) * FontSize / 72;
60 hFont = CreateFontIndirect(&LogFont);
61 ReleaseDC(NULL, hdc);
62
63 return hFont;
64 }
65
66 static INT_PTR CALLBACK
67 StartPageDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
68 {
69 switch (uMsg)
70 {
71 case WM_INITDIALOG:
72 {
73 /* Set title font */
74 SendDlgItemMessage(hwndDlg, IDC_FINISHTITLE, WM_SETFONT, (WPARAM)hTitleFont, (LPARAM)TRUE);
75 }
76 break;
77 }
78
79 return FALSE;
80 }
81
82 static INT_PTR CALLBACK
83 SearchPageDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
84 {
85 return FALSE;
86 }
87
88 static INT_PTR CALLBACK
89 IsConnctedPageDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
90 {
91 switch (uMsg)
92 {
93 case WM_COMMAND:
94 {
95 if(HIWORD(wParam) == BN_CLICKED)
96 {
97 if ((SendDlgItemMessage(hwndDlg, IDC_CONNECTED, BM_GETCHECK, 0, 0) == BST_CHECKED) ||
98 (SendDlgItemMessage(hwndDlg, IDC_NOTCONNECTED, BM_GETCHECK, 0, 0) == BST_CHECKED))
99 {
100 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT | PSWIZB_BACK);
101 }
102 else
103 {
104 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK);
105 }
106 }
107 }
108 break;
109
110 case WM_NOTIFY:
111 {
112 LPNMHDR lpnm = (LPNMHDR)lParam;
113
114 switch (lpnm->code)
115 {
116 case PSN_SETACTIVE:
117 {
118 if ((SendDlgItemMessage(hwndDlg, IDC_CONNECTED, BM_GETCHECK, 0, 0) == BST_CHECKED) ||
119 (SendDlgItemMessage(hwndDlg, IDC_NOTCONNECTED, BM_GETCHECK, 0, 0) == BST_CHECKED))
120 {
121 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT | PSWIZB_BACK);
122 }
123 else
124 {
125 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK);
126 }
127 }
128 break;
129
130 case PSN_WIZNEXT:
131 {
132 if (SendDlgItemMessage(hwndDlg, IDC_NOTCONNECTED, BM_GETCHECK, 0, 0) == BST_CHECKED)
133 SetWindowLong(hwndDlg, DWL_MSGRESULT, IDD_NOTCONNECTEDPAGE);
134 else
135 SetWindowLong(hwndDlg, DWL_MSGRESULT, IDD_PROBELISTPAGE);
136
137 return TRUE;
138 }
139 }
140 }
141 break;
142 }
143
144 return FALSE;
145 }
146
147 static INT_PTR CALLBACK
148 FinishPageDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
149 {
150 switch (uMsg)
151 {
152 case WM_INITDIALOG:
153 {
154 /* Set title font */
155 SendDlgItemMessage(hwndDlg, IDC_FINISHTITLE, WM_SETFONT, (WPARAM)hTitleFont, (LPARAM)TRUE);
156 }
157 break;
158
159 case WM_NOTIFY:
160 {
161 LPNMHDR lpnm = (LPNMHDR)lParam;
162
163 switch (lpnm->code)
164 {
165 case PSN_SETACTIVE:
166 {
167 /* Only "Finish" button */
168 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_FINISH);
169 }
170 break;
171 }
172 }
173 break;
174 }
175
176 return FALSE;
177 }
178
179 static INT_PTR CALLBACK
180 NotConnectedPageDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
181 {
182 switch (uMsg)
183 {
184 case WM_INITDIALOG:
185 {
186 /* Set title font */
187 SendDlgItemMessage(hwndDlg, IDC_FINISHTITLE, WM_SETFONT, (WPARAM)hTitleFont, (LPARAM)TRUE);
188 }
189 break;
190
191 case WM_NOTIFY:
192 {
193 LPNMHDR lpnm = (LPNMHDR)lParam;
194
195 switch (lpnm->code)
196 {
197 case PSN_SETACTIVE:
198 {
199 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_FINISH | PSWIZB_BACK);
200 }
201 break;
202
203 case PSN_WIZBACK:
204 {
205 SetWindowLong(hwndDlg, DWL_MSGRESULT, IDD_ISCONNECTEDPAGE);
206 return TRUE;
207 }
208 }
209 }
210 break;
211 }
212
213 return FALSE;
214 }
215
216 static VOID
217 TrimGuidString(LPWSTR szString, LPWSTR szNewString)
218 {
219 WCHAR szBuffer[39];
220 INT Index;
221
222 if (wcslen(szString) == 38)
223 {
224 if ((szString[0] == L'{') && (szString[37] == L'}'))
225 {
226 for (Index = 0; Index < wcslen(szString); Index++)
227 szBuffer[Index] = szString[Index + 1];
228
229 szBuffer[36] = L'\0';
230 wcscpy(szNewString, szBuffer);
231 return;
232 }
233 }
234 wcscpy(szNewString, L"\0");
235 }
236
237 static VOID
238 InitProbeListPage(HWND hwndDlg)
239 {
240 LV_COLUMN Column;
241 LV_ITEM Item;
242 WCHAR szBuffer[MAX_STR_SIZE], szGuid[MAX_STR_SIZE], szTrimGuid[MAX_STR_SIZE];
243 HWND hList = GetDlgItem(hwndDlg, IDC_PROBELIST);
244 HDEVINFO hDevInfo;
245 SP_DEVINFO_DATA DevInfoData;
246 ULONG ulStatus, ulProblemNumber;
247 GUID ClassGuid;
248 RECT Rect;
249 DWORD Index;
250
251 if (!hList) return;
252
253 ZeroMemory(&Column, sizeof(LV_COLUMN));
254
255 GetClientRect(hList, &Rect);
256
257 Column.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
258 Column.fmt = LVCFMT_LEFT;
259 Column.iSubItem = 0;
260 Column.pszText = NULL;
261 Column.cx = Rect.right - GetSystemMetrics(SM_CXVSCROLL);
262 (VOID) ListView_InsertColumn(hList, 0, &Column);
263
264 ZeroMemory(&Item, sizeof(LV_ITEM));
265
266 LoadString(hApplet, IDS_ADDNEWDEVICE, szBuffer, sizeof(szBuffer) / sizeof(WCHAR));
267
268 Item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE | LVIF_IMAGE;
269 Item.pszText = (LPTSTR) szBuffer;
270 Item.iItem = 0;
271 Item.iImage = -1;
272 (VOID) ListView_InsertItem(hList, &Item);
273
274 (VOID) ListView_SetExtendedListViewStyle(hList, LVS_EX_FULLROWSELECT);
275
276 hDevInfo = SetupDiGetClassDevsEx(NULL, NULL, NULL, DIGCF_ALLCLASSES | DIGCF_PRESENT, NULL, NULL, 0);
277
278 if (hDevInfo == INVALID_HANDLE_VALUE) return;
279
280 /* get the device image List */
281 ImageListData.cbSize = sizeof(ImageListData);
282 SetupDiGetClassImageList(&ImageListData);
283
284 DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
285 for (Index = 0; TRUE; Index++)
286 {
287 if (!SetupDiEnumDeviceInfo(hDevInfo, Index, &DevInfoData)) break;
288
289 if (CM_Get_DevNode_Status_Ex(&ulStatus, &ulProblemNumber, DevInfoData.DevInst, 0, NULL) == CR_SUCCESS)
290 {
291 if (ulStatus & DN_NO_SHOW_IN_DM) continue;
292 }
293
294 /* get the device's friendly name */
295 if (!SetupDiGetDeviceRegistryProperty(hDevInfo,
296 &DevInfoData,
297 SPDRP_FRIENDLYNAME,
298 0,
299 (BYTE*)szBuffer,
300 MAX_STR_SIZE,
301 NULL))
302 {
303 /* if the friendly name fails, try the description instead */
304 SetupDiGetDeviceRegistryProperty(hDevInfo,
305 &DevInfoData,
306 SPDRP_DEVICEDESC,
307 0,
308 (BYTE*)szBuffer,
309 MAX_STR_SIZE,
310 NULL);
311 }
312
313 SetupDiGetDeviceRegistryProperty(hDevInfo,
314 &DevInfoData,
315 SPDRP_CLASSGUID,
316 0,
317 (BYTE*)szGuid,
318 MAX_STR_SIZE,
319 NULL);
320
321 TrimGuidString(szGuid, szTrimGuid);
322 UuidFromStringW(szTrimGuid, &ClassGuid);
323
324 SetupDiGetClassImageIndex(&ImageListData,
325 &ClassGuid,
326 &Item.iImage);
327
328 /* Set device name */
329 Item.pszText = (LPTSTR) szBuffer;
330 Item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
331 Item.iItem = (INT) ListView_GetItemCount(hList);
332 (VOID) ListView_InsertItem(hList, &Item);
333
334 DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
335 }
336
337 (VOID) ListView_SetImageList(hList, ImageListData.ImageList, LVSIL_SMALL);
338 SetupDiDestroyDeviceInfoList(hDevInfo);
339 }
340
341 static INT_PTR CALLBACK
342 ProbeListPageDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
343 {
344 switch (uMsg)
345 {
346 case WM_INITDIALOG:
347 {
348 InitProbeListPage(hwndDlg);
349 }
350 break;
351
352 case WM_COMMAND:
353 {
354
355 }
356 break;
357
358 case WM_NOTIFY:
359 {
360 LPNMHDR lpnm = (LPNMHDR)lParam;
361
362 switch (lpnm->code)
363 {
364 case PSN_SETACTIVE:
365 {
366 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK);
367 }
368 break;
369
370 case PSN_WIZNEXT:
371 {
372 SetWindowLong(hwndDlg, DWL_MSGRESULT, IDD_FINISHPAGE);
373 return TRUE;
374 }
375 }
376 }
377 break;
378 }
379
380 return FALSE;
381 }
382
383 static VOID
384 HardwareWizardInit(HWND hwnd)
385 {
386 HPROPSHEETPAGE ahpsp[5];
387 PROPSHEETPAGE psp = {0};
388 PROPSHEETHEADER psh;
389 UINT nPages = 0;
390
391 /* Create the Start page, until setup is working */
392 psp.dwSize = sizeof(PROPSHEETPAGE);
393 psp.dwFlags = PSP_DEFAULT | PSP_HIDEHEADER;
394 psp.hInstance = hApplet;
395 psp.lParam = 0;
396 psp.pfnDlgProc = StartPageDlgProc;
397 psp.pszTemplate = MAKEINTRESOURCE(IDD_STARTPAGE);
398 ahpsp[nPages++] = CreatePropertySheetPage(&psp);
399
400 /* Create search page */
401 psp.dwSize = sizeof(PROPSHEETPAGE);
402 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
403 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_SEARCHTITLE);
404 psp.pszHeaderSubTitle = NULL;
405 psp.hInstance = hApplet;
406 psp.lParam = 0;
407 psp.pfnDlgProc = SearchPageDlgProc;
408 psp.pszTemplate = MAKEINTRESOURCE(IDD_SEARCHPAGE);
409 ahpsp[nPages++] = CreatePropertySheetPage(&psp);
410
411 /* Create is connected page */
412 psp.dwSize = sizeof(PROPSHEETPAGE);
413 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
414 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_ISCONNECTED);
415 psp.pszHeaderSubTitle = NULL;
416 psp.hInstance = hApplet;
417 psp.lParam = 0;
418 psp.pfnDlgProc = IsConnctedPageDlgProc;
419 psp.pszTemplate = MAKEINTRESOURCE(IDD_ISCONNECTEDPAGE);
420 ahpsp[nPages++] = CreatePropertySheetPage(&psp);
421
422 /* Create probe list page */
423 psp.dwSize = sizeof(PROPSHEETPAGE);
424 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
425 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_PROBELISTTITLE);
426 psp.pszHeaderSubTitle = NULL;
427 psp.hInstance = hApplet;
428 psp.lParam = 0;
429 psp.pfnDlgProc = ProbeListPageDlgProc;
430 psp.pszTemplate = MAKEINTRESOURCE(IDD_PROBELISTPAGE);
431 ahpsp[nPages++] = CreatePropertySheetPage(&psp);
432
433 /* Create finish page */
434 psp.dwSize = sizeof(PROPSHEETPAGE);
435 psp.dwFlags = PSP_DEFAULT | PSP_HIDEHEADER;
436 psp.hInstance = hApplet;
437 psp.lParam = 0;
438 psp.pfnDlgProc = FinishPageDlgProc;
439 psp.pszTemplate = MAKEINTRESOURCE(IDD_FINISHPAGE);
440 ahpsp[nPages++] = CreatePropertySheetPage(&psp);
441
442 /* Create not connected page */
443 psp.dwSize = sizeof(PROPSHEETPAGE);
444 psp.dwFlags = PSP_DEFAULT | PSP_HIDEHEADER;
445 psp.hInstance = hApplet;
446 psp.lParam = 0;
447 psp.pfnDlgProc = NotConnectedPageDlgProc;
448 psp.pszTemplate = MAKEINTRESOURCE(IDD_NOTCONNECTEDPAGE);
449 ahpsp[nPages++] = CreatePropertySheetPage(&psp);
450
451 /* Create the property sheet */
452 psh.dwSize = sizeof(PROPSHEETHEADER);
453 psh.dwFlags = PSH_WIZARD97 | PSH_WATERMARK | PSH_HEADER;
454 psh.hInstance = hApplet;
455 psh.hwndParent = hwnd;
456 psh.nPages = nPages;
457 psh.nStartPage = 0;
458 psh.phpage = ahpsp;
459 psh.pszbmWatermark = MAKEINTRESOURCE(IDB_WATERMARK);
460 psh.pszbmHeader = MAKEINTRESOURCE(IDB_HEADER);
461
462 /* Create title font */
463 hTitleFont = CreateTitleFont();
464
465 /* Display the wizard */
466 PropertySheet(&psh);
467
468 DeleteObject(hTitleFont);
469 }
470
471 /* FUNCTIONS ****************************************************************/
472
473 BOOL WINAPI
474 InstallNewDevice(HWND hwndParent, LPGUID ClassGuid, PDWORD pReboot)
475 {
476 return FALSE;
477 }
478
479 VOID WINAPI
480 AddHardwareWizard(HWND hwnd, LPWSTR lpName)
481 {
482 if (lpName != NULL)
483 {
484 DPRINT1("No support of remote installation yet!\n");
485 return;
486 }
487
488 HardwareWizardInit(hwnd);
489 }
490
491 /* Control Panel Callback */
492 LONG CALLBACK
493 CPlApplet(HWND hwndCpl, UINT uMsg, LPARAM lParam1, LPARAM lParam2)
494 {
495 switch (uMsg)
496 {
497 case CPL_INIT:
498 return TRUE;
499
500 case CPL_GETCOUNT:
501 return 1;
502
503 case CPL_INQUIRE:
504 {
505 CPLINFO *CPlInfo = (CPLINFO*)lParam2;
506 CPlInfo->lData = 0;
507 CPlInfo->idIcon = IDI_CPLICON;
508 CPlInfo->idName = IDS_CPLNAME;
509 CPlInfo->idInfo = IDS_CPLDESCRIPTION;
510 }
511 break;
512
513 case CPL_DBLCLK:
514 AddHardwareWizard(hwndCpl, NULL);
515 break;
516 }
517
518 return FALSE;
519 }
520
521 BOOL WINAPI
522 DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpvReserved)
523 {
524 UNREFERENCED_PARAMETER(lpvReserved);
525
526 switch (dwReason)
527 {
528 case DLL_PROCESS_ATTACH:
529 hApplet = hinstDLL;
530 DisableThreadLibraryCalls(hinstDLL);
531 break;
532 }
533
534 return TRUE;
535 }