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