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