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