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