c9b6a6bdabfdb10427a028e87404c87cec435845
[reactos.git] / reactos / lib / newdev / newdev.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS New devices installation
4 * FILE: lib/newdev/newdev.c
5 * PURPOSE: New devices installation
6 *
7 * PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.org)
8 */
9
10 //#define NDEBUG
11 #include <debug.h>
12
13 #include "newdev.h"
14
15 static BOOL SearchDriver ( PDEVINSTDATA DevInstData, LPCTSTR Path );
16 static BOOL InstallDriver ( PDEVINSTDATA DevInstData );
17 static DWORD WINAPI FindDriverProc( LPVOID lpParam );
18 static BOOL FindDriver ( PDEVINSTDATA DevInstData );
19
20 static DEVINSTDATA DevInstData;
21 HINSTANCE hDllInstance;
22 HANDLE hThread;
23
24 static HFONT
25 CreateTitleFont(VOID)
26 {
27 NONCLIENTMETRICS ncm;
28 LOGFONT LogFont;
29 HDC hdc;
30 INT FontSize;
31 HFONT hFont;
32
33 ncm.cbSize = sizeof(NONCLIENTMETRICS);
34 SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
35
36 LogFont = ncm.lfMessageFont;
37 LogFont.lfWeight = FW_BOLD;
38 _tcscpy(LogFont.lfFaceName, _T("MS Shell Dlg"));
39
40 hdc = GetDC(NULL);
41 FontSize = 12;
42 LogFont.lfHeight = 0 - GetDeviceCaps (hdc, LOGPIXELSY) * FontSize / 72;
43 hFont = CreateFontIndirect(&LogFont);
44 ReleaseDC(NULL, hdc);
45
46 return hFont;
47 }
48
49 static VOID
50 CenterWindow(HWND hWnd)
51 {
52 HWND hWndParent;
53 RECT rcParent;
54 RECT rcWindow;
55
56 hWndParent = GetParent(hWnd);
57 if (hWndParent == NULL)
58 hWndParent = GetDesktopWindow();
59
60 GetWindowRect(hWndParent, &rcParent);
61 GetWindowRect(hWnd, &rcWindow);
62
63 SetWindowPos(hWnd,
64 HWND_TOP,
65 ((rcParent.right - rcParent.left) - (rcWindow.right - rcWindow.left)) / 2,
66 ((rcParent.bottom - rcParent.top) - (rcWindow.bottom - rcWindow.top)) / 2,
67 0,
68 0,
69 SWP_NOSIZE);
70 }
71
72 static INT_PTR CALLBACK
73 WelcomeDlgProc(
74 IN HWND hwndDlg,
75 IN UINT uMsg,
76 IN WPARAM wParam,
77 IN LPARAM lParam)
78 {
79
80 PDEVINSTDATA DevInstData;
81
82 /* Retrieve pointer to the global setup data */
83 DevInstData = (PDEVINSTDATA)GetWindowLongPtr (hwndDlg, GWL_USERDATA);
84
85 switch (uMsg)
86 {
87 case WM_INITDIALOG:
88 {
89 HWND hwndControl;
90 DWORD dwStyle;
91
92 /* Get pointer to the global setup data */
93 DevInstData = (PDEVINSTDATA)((LPPROPSHEETPAGE)lParam)->lParam;
94 SetWindowLongPtr(hwndDlg, GWL_USERDATA, (DWORD_PTR)DevInstData);
95
96 hwndControl = GetParent(hwndDlg);
97
98 /* Center the wizard window */
99 CenterWindow (hwndControl);
100
101 /* Hide the system menu */
102 dwStyle = GetWindowLong(hwndControl, GWL_STYLE);
103 SetWindowLong(hwndControl, GWL_STYLE, dwStyle & ~WS_SYSMENU);
104
105 /* Set title font */
106 SendDlgItemMessage(hwndDlg,
107 IDC_WELCOMETITLE,
108 WM_SETFONT,
109 (WPARAM)DevInstData->hTitleFont,
110 (LPARAM)TRUE);
111
112 SendDlgItemMessage(hwndDlg,
113 IDC_DEVICE,
114 WM_SETTEXT,
115 0,
116 (LPARAM) DevInstData->buffer);
117
118 SendDlgItemMessage(hwndDlg,
119 IDC_RADIO_AUTO,
120 BM_SETCHECK,
121 (WPARAM) TRUE,
122 (LPARAM) 0);
123
124
125 }
126 break;
127
128
129 case WM_NOTIFY:
130 {
131 LPNMHDR lpnm = (LPNMHDR)lParam;
132
133 switch (lpnm->code)
134 {
135 case PSN_SETACTIVE:
136 /* Enable the Next button */
137 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT);
138 break;
139
140 case PSN_WIZNEXT:
141 /* Handle a Next button click, if necessary */
142
143 if (SendDlgItemMessage(hwndDlg, IDC_RADIO_AUTO, BM_GETCHECK, (WPARAM) 0, (LPARAM) 0) == BST_CHECKED)
144 PropSheet_SetCurSel(GetParent(hwndDlg), 0, IDD_SEARCHDRV);
145
146 break;
147
148 default:
149 break;
150 }
151 }
152 break;
153
154 default:
155 break;
156 }
157
158 return FALSE;
159 }
160
161 static INT_PTR CALLBACK
162 CHSourceDlgProc(
163 IN HWND hwndDlg,
164 IN UINT uMsg,
165 IN WPARAM wParam,
166 IN LPARAM lParam)
167 {
168
169 PDEVINSTDATA DevInstData;
170
171 /* Retrieve pointer to the global setup data */
172 DevInstData = (PDEVINSTDATA)GetWindowLongPtr (hwndDlg, GWL_USERDATA);
173
174 switch (uMsg)
175 {
176 case WM_INITDIALOG:
177 {
178 HWND hwndControl;
179 DWORD dwStyle;
180
181 /* Get pointer to the global setup data */
182 DevInstData = (PDEVINSTDATA)((LPPROPSHEETPAGE)lParam)->lParam;
183 SetWindowLongPtr(hwndDlg, GWL_USERDATA, (DWORD_PTR)DevInstData);
184
185 hwndControl = GetParent(hwndDlg);
186
187 /* Center the wizard window */
188 CenterWindow (hwndControl);
189
190 /* Hide the system menu */
191 dwStyle = GetWindowLong(hwndControl, GWL_STYLE);
192 SetWindowLong(hwndControl, GWL_STYLE, dwStyle & ~WS_SYSMENU);
193
194 SendDlgItemMessage(hwndDlg,
195 IDC_RADIO_SEARCHHERE,
196 BM_SETCHECK,
197 (WPARAM) TRUE,
198 (LPARAM) 0);
199
200 }
201 break;
202
203
204 case WM_NOTIFY:
205 {
206 LPNMHDR lpnm = (LPNMHDR)lParam;
207
208 switch (lpnm->code)
209 {
210 case PSN_SETACTIVE:
211 /* Enable the Next and Back buttons */
212 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT | PSWIZB_BACK);
213 break;
214
215 case PSN_WIZNEXT:
216 /* Handle a Next button click, if necessary */
217 PropSheet_SetCurSel(GetParent(hwndDlg), 0, 4);
218 break;
219
220 default:
221 break;
222 }
223 }
224 break;
225
226 default:
227 break;
228 }
229
230 return FALSE;
231 }
232
233 static INT_PTR CALLBACK
234 SearchDrvDlgProc(
235 IN HWND hwndDlg,
236 IN UINT uMsg,
237 IN WPARAM wParam,
238 IN LPARAM lParam)
239 {
240
241 PDEVINSTDATA DevInstData;
242 DWORD dwThreadId;
243
244 /* Retrieve pointer to the global setup data */
245 DevInstData = (PDEVINSTDATA)GetWindowLongPtr (hwndDlg, GWL_USERDATA);
246
247 switch (uMsg)
248 {
249 case WM_INITDIALOG:
250 {
251 HWND hwndControl;
252 DWORD dwStyle;
253
254 /* Get pointer to the global setup data */
255 DevInstData = (PDEVINSTDATA)((LPPROPSHEETPAGE)lParam)->lParam;
256 SetWindowLongPtr(hwndDlg, GWL_USERDATA, (DWORD_PTR)DevInstData);
257
258 DevInstData->hDialog = hwndDlg;
259 hwndControl = GetParent(hwndDlg);
260
261 /* Center the wizard window */
262 CenterWindow (hwndControl);
263
264 SendDlgItemMessage(hwndDlg,
265 IDC_DEVICE,
266 WM_SETTEXT,
267 0,
268 (LPARAM) DevInstData->buffer);
269
270 /* Hide the system menu */
271 dwStyle = GetWindowLong(hwndControl, GWL_STYLE);
272 SetWindowLong(hwndControl, GWL_STYLE, dwStyle & ~WS_SYSMENU);
273 }
274 break;
275
276 case WM_SEARCH_FINISHED:
277 {
278 CloseHandle(hThread);
279 hThread = 0;
280 if (wParam == 0)
281 PropSheet_SetCurSel(GetParent(hwndDlg), 0, IDD_NODRIVER);
282 else
283 PropSheet_SetCurSel(GetParent(hwndDlg), 0, IDD_FINISHPAGE);
284 break;
285 }
286 case WM_NOTIFY:
287 {
288 LPNMHDR lpnm = (LPNMHDR)lParam;
289
290 switch (lpnm->code)
291 {
292 case PSN_SETACTIVE:
293 PropSheet_SetWizButtons(GetParent(hwndDlg), !PSWIZB_NEXT | !PSWIZB_BACK);
294 hThread = CreateThread( NULL, 0, FindDriverProc, DevInstData, 0, &dwThreadId);
295 break;
296
297 case PSN_KILLACTIVE:
298 if (hThread != 0)
299 {
300 SetWindowLong ( hwndDlg, DWL_MSGRESULT, TRUE);
301 return TRUE;
302 }
303 break;
304 case PSN_WIZNEXT:
305 /* Handle a Next button click, if necessary */
306 break;
307
308 default:
309 break;
310 }
311 }
312 break;
313
314 default:
315 break;
316 }
317
318 return FALSE;
319 }
320
321 static DWORD WINAPI
322 FindDriverProc(
323 IN LPVOID lpParam)
324 {
325 TCHAR drive[] = {'?',':',0};
326 size_t nType;
327 DWORD dwDrives;
328 PDEVINSTDATA DevInstData;
329 UINT i = 1;
330
331 DevInstData = (PDEVINSTDATA)lpParam;
332
333 dwDrives = GetLogicalDrives();
334 for (drive[0] = 'A'; drive[0] <= 'Z'; drive[0]++)
335 {
336 if (dwDrives & i)
337 {
338 nType = GetDriveType( drive );
339 if ((nType == DRIVE_CDROM) || (nType == DRIVE_FIXED))
340 {
341 /* search for inf file */
342 if (SearchDriver ( DevInstData, drive ))
343 {
344 /* if we found a valid driver inf... */
345 if (FindDriver ( DevInstData ))
346 {
347 InstallDriver ( DevInstData );
348 PostMessage(DevInstData->hDialog, WM_SEARCH_FINISHED, 1, 0);
349 return 0;
350 }
351 }
352 }
353 }
354 i <<= 1;
355 }
356
357 PostMessage(DevInstData->hDialog, WM_SEARCH_FINISHED, 0, 0);
358 return 0;
359 }
360
361 static INT_PTR CALLBACK
362 FinishDlgProc(
363 IN HWND hwndDlg,
364 IN UINT uMsg,
365 IN WPARAM wParam,
366 IN LPARAM lParam)
367 {
368
369 PDEVINSTDATA DevInstData;
370
371 /* Retrieve pointer to the global setup data */
372 DevInstData = (PDEVINSTDATA)GetWindowLongPtr (hwndDlg, GWL_USERDATA);
373
374 switch (uMsg)
375 {
376 case WM_INITDIALOG:
377 {
378 HWND hwndControl;
379
380 /* Get pointer to the global setup data */
381 DevInstData = (PDEVINSTDATA)((LPPROPSHEETPAGE)lParam)->lParam;
382 SetWindowLongPtr(hwndDlg, GWL_USERDATA, (DWORD_PTR)DevInstData);
383
384 hwndControl = GetDlgItem(GetParent(hwndDlg), IDCANCEL);
385 ShowWindow (hwndControl, SW_HIDE);
386 EnableWindow (hwndControl, FALSE);
387
388 SendDlgItemMessage(hwndDlg,
389 IDC_DEVICE,
390 WM_SETTEXT,
391 0,
392 (LPARAM) DevInstData->drvInfoData.Description);
393
394 /* Set title font */
395 SendDlgItemMessage(hwndDlg,
396 IDC_FINISHTITLE,
397 WM_SETFONT,
398 (WPARAM)DevInstData->hTitleFont,
399 (LPARAM)TRUE);
400 }
401 break;
402
403 case WM_NOTIFY:
404 {
405 LPNMHDR lpnm = (LPNMHDR)lParam;
406
407 switch (lpnm->code)
408 {
409 case PSN_SETACTIVE:
410 /* Enable the correct buttons on for the active page */
411 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_FINISH);
412 break;
413
414 case PSN_WIZBACK:
415 /* Handle a Back button click, if necessary */
416 break;
417
418 case PSN_WIZFINISH:
419 /* Handle a Finish button click, if necessary */
420 break;
421
422 default:
423 break;
424 }
425 }
426 break;
427
428 default:
429 break;
430 }
431
432 return FALSE;
433 }
434
435 static INT_PTR CALLBACK
436 InstFailDlgProc(
437 IN HWND hwndDlg,
438 IN UINT uMsg,
439 IN WPARAM wParam,
440 IN LPARAM lParam)
441 {
442
443 PDEVINSTDATA DevInstData;
444
445 /* Get pointer to the global setup data */
446 DevInstData = (PDEVINSTDATA)GetWindowLongPtr (hwndDlg, GWL_USERDATA);
447
448 switch (uMsg)
449 {
450 case WM_INITDIALOG:
451 {
452 HWND hwndControl;
453
454 DevInstData = (PDEVINSTDATA)((LPPROPSHEETPAGE)lParam)->lParam;
455 SetWindowLongPtr(hwndDlg, GWL_USERDATA, (DWORD_PTR)DevInstData);
456
457 hwndControl = GetDlgItem(GetParent(hwndDlg), IDCANCEL);
458 ShowWindow (hwndControl, SW_HIDE);
459 EnableWindow (hwndControl, FALSE);
460
461 /* Set title font */
462 SendDlgItemMessage(hwndDlg,
463 IDC_FINISHTITLE,
464 WM_SETFONT,
465 (WPARAM)DevInstData->hTitleFont,
466 (LPARAM)TRUE);
467 }
468 break;
469
470 case WM_NOTIFY:
471 {
472 LPNMHDR lpnm = (LPNMHDR)lParam;
473 DWORD config_flags;
474 BOOL ret;
475
476 switch (lpnm->code)
477 {
478 case PSN_SETACTIVE:
479 /* Enable the correct buttons on for the active page */
480 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_FINISH);
481 break;
482
483 case PSN_WIZBACK:
484 PropSheet_SetCurSel(GetParent(hwndDlg), 0, IDD_WELCOMEPAGE);
485 /* Handle a Back button click, if necessary */
486 break;
487
488 case PSN_WIZFINISH:
489 /* Handle a Finish button click, if necessary */
490 if (SendDlgItemMessage(hwndDlg, IDC_DONOTSHOWDLG, BM_GETCHECK, (WPARAM) 0, (LPARAM) 0) == BST_CHECKED)
491 {
492
493 if(SetupDiGetDeviceRegistryProperty(DevInstData->hDevInfo,
494 &DevInstData->devInfoData,
495 SPDRP_CONFIGFLAGS,
496 NULL,
497 (BYTE *)&config_flags,
498 sizeof(config_flags),
499 NULL))
500 {
501 config_flags |= CONFIGFLAG_FAILEDINSTALL;
502 ret = SetupDiSetDeviceRegistryProperty(
503 DevInstData->hDevInfo,
504 &DevInstData->devInfoData,
505 SPDRP_CONFIGFLAGS,
506 NULL, 0 );
507 }
508
509 }
510 break;
511
512 default:
513 break;
514 }
515 }
516 break;
517
518 default:
519 break;
520 }
521
522 return FALSE;
523 }
524
525
526 static BOOL
527 FindDriver(
528 IN PDEVINSTDATA DevInstData)
529 {
530
531 BOOL ret;
532
533 ret = SetupDiBuildDriverInfoList(DevInstData->hDevInfo, &DevInstData->devInfoData, SPDIT_COMPATDRIVER);
534 if (!ret)
535 {
536 DPRINT("SetupDiBuildDriverInfoList() failed with error 0x%lx\n", GetLastError());
537 return FALSE;
538 }
539
540 DevInstData->drvInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
541 ret = SetupDiEnumDriverInfo(
542 DevInstData->hDevInfo,
543 &DevInstData->devInfoData,
544 SPDIT_COMPATDRIVER,
545 0,
546 &DevInstData->drvInfoData);
547 if (!ret)
548 {
549 if (GetLastError() == ERROR_NO_MORE_ITEMS)
550 return FALSE;
551 DPRINT("SetupDiEnumDriverInfo() failed with error 0x%lx\n", GetLastError());
552 return FALSE;
553 }
554 DPRINT("Installing driver %S: %S\n", DevInstData->drvInfoData.MfgName, DevInstData->drvInfoData.Description);
555
556 return TRUE;
557 }
558
559
560 static BOOL
561 IsDots(IN LPCTSTR str)
562 {
563 if(_tcscmp(str, _T(".")) && _tcscmp(str, _T(".."))) return FALSE;
564 return TRUE;
565 }
566
567 static LPTSTR
568 GetFileExt(IN LPTSTR FileName)
569 {
570 if (FileName == 0)
571 return _T("");
572
573 int i = _tcsclen(FileName);
574 while ((i >= 0) && (FileName[i] != _T('.')))
575 i--;
576
577 FileName = _tcslwr(FileName);
578
579 if (i >= 0)
580 return &FileName[i];
581 else
582 return _T("");
583 }
584
585 static BOOL
586 SearchDriver(
587 IN PDEVINSTDATA DevInstData,
588 IN LPCTSTR Path)
589 {
590 WIN32_FIND_DATA wfd;
591 SP_DEVINSTALL_PARAMS DevInstallParams;
592 TCHAR DirPath[MAX_PATH];
593 TCHAR FileName[MAX_PATH];
594 TCHAR FullPath[MAX_PATH];
595 TCHAR LastDirPath[MAX_PATH] = _T("");
596 TCHAR PathWithPattern[MAX_PATH];
597 BOOL ok = TRUE;
598 BOOL ret;
599 HANDLE hFindFile;
600
601 _tcscpy(DirPath, Path);
602
603 if (DirPath[_tcsclen(DirPath) - 1] != '\\')
604 _tcscat(DirPath, _T("\\"));
605
606 _tcscpy(PathWithPattern, DirPath);
607 _tcscat(PathWithPattern, _T("\\*"));
608
609 for (hFindFile = FindFirstFile(PathWithPattern, &wfd); ((hFindFile != INVALID_HANDLE_VALUE) && ok); ok = FindNextFile(hFindFile, &wfd))
610 {
611
612 _tcscpy(FileName, wfd.cFileName);
613 if (IsDots(FileName)) continue;
614
615 if((wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
616 {
617 _tcscpy(FullPath, DirPath);
618 _tcscat(FullPath, FileName);
619 if(SearchDriver(DevInstData, FullPath))
620 break;
621 }
622 else
623 {
624 LPCTSTR pszExtension = GetFileExt(FileName);
625
626 if ((_tcscmp(pszExtension, _T(".inf")) == 0) && (_tcscmp(LastDirPath, DirPath) != 0))
627 {
628 _tcscpy(LastDirPath, DirPath);
629 ZeroMemory (&DevInstallParams, sizeof(SP_DEVINSTALL_PARAMS));
630 DevInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
631
632 ret = SetupDiGetDeviceInstallParams(
633 DevInstData->hDevInfo,
634 &DevInstData->devInfoData,
635 &DevInstallParams);
636
637 if (_tcsclen(DirPath) <= MAX_PATH)
638 {
639 memcpy(DevInstallParams.DriverPath, DirPath, (_tcsclen(DirPath) + 1) * sizeof(TCHAR));
640 }
641
642 ret = SetupDiSetDeviceInstallParams(
643 DevInstData->hDevInfo,
644 &DevInstData->devInfoData,
645 &DevInstallParams);
646
647 if ( FindDriver ( DevInstData ) )
648 {
649 if (hFindFile != INVALID_HANDLE_VALUE)
650 FindClose(hFindFile);
651 return TRUE;
652 }
653
654 }
655 }
656 }
657
658 if (hFindFile != INVALID_HANDLE_VALUE)
659 FindClose(hFindFile);
660
661 return FALSE;
662 }
663
664 static BOOL
665 InstallDriver(
666 IN PDEVINSTDATA DevInstData)
667 {
668
669 BOOL ret;
670
671 ret = SetupDiCallClassInstaller(
672 DIF_SELECTBESTCOMPATDRV,
673 DevInstData->hDevInfo,
674 &DevInstData->devInfoData);
675 if (!ret)
676 {
677 DPRINT("SetupDiCallClassInstaller(DIF_SELECTBESTCOMPATDRV) failed with error 0x%lx\n", GetLastError());
678 return FALSE;
679 }
680
681 ret = SetupDiCallClassInstaller(
682 DIF_ALLOW_INSTALL,
683 DevInstData->hDevInfo,
684 &DevInstData->devInfoData);
685 if (!ret)
686 {
687 DPRINT("SetupDiCallClassInstaller(DIF_ALLOW_INSTALL) failed with error 0x%lx\n", GetLastError());
688 return FALSE;
689 }
690
691 ret = SetupDiCallClassInstaller(
692 DIF_NEWDEVICEWIZARD_PREANALYZE,
693 DevInstData->hDevInfo,
694 &DevInstData->devInfoData);
695 if (!ret)
696 {
697 DPRINT("SetupDiCallClassInstaller(DIF_NEWDEVICEWIZARD_PREANALYZE) failed with error 0x%lx\n", GetLastError());
698 return FALSE;
699 }
700
701 ret = SetupDiCallClassInstaller(
702 DIF_NEWDEVICEWIZARD_POSTANALYZE,
703 DevInstData->hDevInfo,
704 &DevInstData->devInfoData);
705 if (!ret)
706 {
707 DPRINT("SetupDiCallClassInstaller(DIF_NEWDEVICEWIZARD_POSTANALYZE) failed with error 0x%lx\n", GetLastError());
708 return FALSE;
709 }
710
711 ret = SetupDiCallClassInstaller(
712 DIF_INSTALLDEVICEFILES,
713 DevInstData->hDevInfo,
714 &DevInstData->devInfoData);
715 if (!ret)
716 {
717 DPRINT("SetupDiCallClassInstaller(DIF_INSTALLDEVICEFILES) failed with error 0x%lx\n", GetLastError());
718 return FALSE;
719 }
720
721 ret = SetupDiCallClassInstaller(
722 DIF_REGISTER_COINSTALLERS,
723 DevInstData->hDevInfo,
724 &DevInstData->devInfoData);
725 if (!ret)
726 {
727 DPRINT("SetupDiCallClassInstaller(DIF_REGISTER_COINSTALLERS) failed with error 0x%lx\n", GetLastError());
728 return FALSE;
729 }
730
731 ret = SetupDiCallClassInstaller(
732 DIF_INSTALLINTERFACES,
733 DevInstData->hDevInfo,
734 &DevInstData->devInfoData);
735 if (!ret)
736 {
737 DPRINT("SetupDiCallClassInstaller(DIF_INSTALLINTERFACES) failed with error 0x%lx\n", GetLastError());
738 return FALSE;
739 }
740
741 ret = SetupDiCallClassInstaller(
742 DIF_INSTALLDEVICE,
743 DevInstData->hDevInfo,
744 &DevInstData->devInfoData);
745 if (!ret)
746 {
747 DPRINT("SetupDiCallClassInstaller(DIF_INSTALLDEVICE) failed with error 0x%lx\n", GetLastError());
748 return FALSE;
749 }
750
751 ret = SetupDiCallClassInstaller(
752 DIF_NEWDEVICEWIZARD_FINISHINSTALL,
753 DevInstData->hDevInfo,
754 &DevInstData->devInfoData);
755 if (!ret)
756 {
757 DPRINT("SetupDiCallClassInstaller(DIF_NEWDEVICEWIZARD_FINISHINSTALL) failed with error 0x%lx\n", GetLastError());
758 return FALSE;
759 }
760
761 ret = SetupDiCallClassInstaller(
762 DIF_DESTROYPRIVATEDATA,
763 DevInstData->hDevInfo,
764 &DevInstData->devInfoData);
765 if (!ret)
766 {
767 DPRINT("SetupDiCallClassInstaller(DIF_DESTROYPRIVATEDATA) failed with error 0x%lx\n", GetLastError());
768 return FALSE;
769 }
770
771 return TRUE;
772
773 }
774
775 static VOID
776 CleanUp(VOID)
777 {
778
779 if (DevInstData.devInfoData.cbSize != 0)
780 {
781 if (!SetupDiDestroyDriverInfoList(DevInstData.hDevInfo, &DevInstData.devInfoData, SPDIT_COMPATDRIVER))
782 DPRINT("SetupDiDestroyDriverInfoList() failed with error 0x%lx\n", GetLastError());
783 }
784
785 if (DevInstData.hDevInfo != INVALID_HANDLE_VALUE)
786 {
787 if (!SetupDiDestroyDeviceInfoList(DevInstData.hDevInfo))
788 DPRINT("SetupDiDestroyDeviceInfoList() failed with error 0x%lx\n", GetLastError());
789 }
790
791 if (DevInstData.buffer)
792 HeapFree(GetProcessHeap(), 0, DevInstData.buffer);
793
794 }
795
796 BOOL WINAPI
797 DevInstallW(
798 IN HWND hWndParent,
799 IN HINSTANCE hInstance,
800 IN LPCWSTR InstanceId,
801 IN INT Show)
802 {
803
804 PROPSHEETHEADER psh;
805 HPROPSHEETPAGE ahpsp[5];
806 PROPSHEETPAGE psp;
807 BOOL ret;
808
809 /* Clear devinst data */
810 ZeroMemory(&DevInstData, sizeof(DEVINSTDATA));
811 DevInstData.devInfoData.cbSize = 0; /* Tell if the devInfoData is valid */
812
813
814 DevInstData.hDevInfo = SetupDiCreateDeviceInfoListExW(NULL, NULL, NULL, NULL);
815 if (DevInstData.hDevInfo == INVALID_HANDLE_VALUE)
816 {
817 DPRINT("SetupDiCreateDeviceInfoListExW() failed with error 0x%lx\n", GetLastError());
818 CleanUp();
819 return FALSE;
820 }
821
822 DevInstData.devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
823 ret = SetupDiOpenDeviceInfoW(
824 DevInstData.hDevInfo,
825 InstanceId,
826 NULL,
827 0, /* Open flags */
828 &DevInstData.devInfoData);
829 if (!ret)
830 {
831 DPRINT("SetupDiOpenDeviceInfoW() failed with error 0x%lx (InstanceId %S)\n", GetLastError(), InstanceId);
832 DevInstData.devInfoData.cbSize = 0;
833 CleanUp();
834 return FALSE;
835 }
836
837 SetLastError(ERROR_GEN_FAILURE);
838 ret = SetupDiGetDeviceRegistryProperty(
839 DevInstData.hDevInfo,
840 &DevInstData.devInfoData,
841 SPDRP_DEVICEDESC,
842 &DevInstData.regDataType,
843 NULL, 0,
844 &DevInstData.requiredSize);
845
846 if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER && DevInstData.regDataType == REG_SZ)
847 {
848 DevInstData.buffer = HeapAlloc(GetProcessHeap(), 0, DevInstData.requiredSize);
849 if (!DevInstData.buffer)
850 {
851 DPRINT("HeapAlloc() failed\n");
852 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
853 }
854 else
855 {
856 ret = SetupDiGetDeviceRegistryProperty(
857 DevInstData.hDevInfo,
858 &DevInstData.devInfoData,
859 SPDRP_DEVICEDESC,
860 &DevInstData.regDataType,
861 DevInstData.buffer, DevInstData.requiredSize,
862 &DevInstData.requiredSize);
863 }
864 }
865 if (!ret)
866 {
867 DPRINT("SetupDiGetDeviceRegistryProperty() failed with error 0x%lx (InstanceId %S)\n", GetLastError(), InstanceId);
868 CleanUp();
869 return FALSE;
870 }
871
872 DPRINT("Installing %S (%S)\n", DevInstData.buffer, InstanceId);
873
874 if ((!FindDriver(&DevInstData)) && (Show != SW_HIDE))
875 {
876
877 /* Create the Welcome page */
878 ZeroMemory (&psp, sizeof(PROPSHEETPAGE));
879 psp.dwSize = sizeof(PROPSHEETPAGE);
880 psp.dwFlags = PSP_DEFAULT | PSP_HIDEHEADER;
881 psp.hInstance = hDllInstance;
882 psp.lParam = (LPARAM)&DevInstData;
883 psp.pfnDlgProc = WelcomeDlgProc;
884 psp.pszTemplate = MAKEINTRESOURCE(IDD_WELCOMEPAGE);
885 ahpsp[IDD_WELCOMEPAGE] = CreatePropertySheetPage(&psp);
886
887 /* Create the Select Source page */
888 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
889 psp.pfnDlgProc = CHSourceDlgProc;
890 psp.pszTemplate = MAKEINTRESOURCE(IDD_CHSOURCE);
891 ahpsp[IDD_CHSOURCE] = CreatePropertySheetPage(&psp);
892
893 /* Create the Search driver page */
894 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
895 psp.pfnDlgProc = SearchDrvDlgProc;
896 psp.pszTemplate = MAKEINTRESOURCE(IDD_SEARCHDRV);
897 ahpsp[IDD_SEARCHDRV] = CreatePropertySheetPage(&psp);
898
899 /* Create the Finish page */
900 psp.dwFlags = PSP_DEFAULT | PSP_HIDEHEADER;
901 psp.pfnDlgProc = FinishDlgProc;
902 psp.pszTemplate = MAKEINTRESOURCE(IDD_FINISHPAGE);
903 ahpsp[IDD_FINISHPAGE] = CreatePropertySheetPage(&psp);
904
905 /* Create the Install failed page */
906 psp.dwFlags = PSP_DEFAULT | PSP_HIDEHEADER;
907 psp.pfnDlgProc = InstFailDlgProc;
908 psp.pszTemplate = MAKEINTRESOURCE(IDD_NODRIVER);
909 ahpsp[IDD_NODRIVER] = CreatePropertySheetPage(&psp);
910
911 /* Create the property sheet */
912 psh.dwSize = sizeof(PROPSHEETHEADER);
913 psh.dwFlags = PSH_WIZARD97 | PSH_WATERMARK | PSH_HEADER;
914 psh.hInstance = hDllInstance;
915 psh.hwndParent = NULL;
916 psh.nPages = 5;
917 psh.nStartPage = 0;
918 psh.phpage = ahpsp;
919 psh.pszbmWatermark = MAKEINTRESOURCE(IDB_WATERMARK);
920 psh.pszbmHeader = MAKEINTRESOURCE(IDB_HEADER);
921
922 /* Create title font */
923 DevInstData.hTitleFont = CreateTitleFont();
924
925 /* Display the wizard */
926 PropertySheet(&psh);
927
928 DeleteObject(DevInstData.hTitleFont);
929
930 }
931 else
932 {
933 InstallDriver ( &DevInstData );
934 }
935
936 CleanUp();
937 return TRUE;
938 }
939
940 BOOL WINAPI
941 DllMain(
942 IN HINSTANCE hInstance,
943 IN DWORD dwReason,
944 IN LPVOID lpReserved)
945 {
946 if (dwReason == DLL_PROCESS_ATTACH)
947 {
948 INITCOMMONCONTROLSEX InitControls;
949
950 InitControls.dwSize = sizeof(INITCOMMONCONTROLSEX);
951 InitControls.dwICC = ICC_PROGRESS_CLASS;
952 InitCommonControlsEx(&InitControls);
953 hDllInstance = hInstance;
954 }
955
956 return TRUE;
957 }