2 * New device installer (newdev.dll)
4 * Copyright 2005-2006 Hervé Poussineau (hpoussin@reactos.org)
5 * 2005 Christoph von Wittich (Christoph@ActiveVB.de)
6 * 2009 Colin Finck (colin@reactos.org)
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 #include "newdev_private.h"
28 /* Global variables */
29 HINSTANCE hDllInstance
;
33 IN PDEVINSTDATA DevInstData
,
34 IN LPCWSTR Directory OPTIONAL
,
35 IN LPCWSTR InfFile OPTIONAL
);
41 UpdateDriverForPlugAndPlayDevicesW(
43 IN LPCWSTR HardwareId
,
44 IN LPCWSTR FullInfPath
,
45 IN DWORD InstallFlags
,
46 OUT PBOOL bRebootRequired OPTIONAL
)
48 DEVINSTDATA DevInstData
;
52 LPCWSTR CurrentHardwareId
; /* Pointer into Buffer */
53 BOOL FoundHardwareId
, FoundAtLeastOneDevice
= FALSE
;
56 DevInstData
.hDevInfo
= INVALID_HANDLE_VALUE
;
58 TRACE("UpdateDriverForPlugAndPlayDevicesW(%p %s %s 0x%x %p)\n",
59 hwndParent
, debugstr_w(HardwareId
), debugstr_w(FullInfPath
), InstallFlags
, bRebootRequired
);
61 /* FIXME: InstallFlags bRebootRequired ignored! */
64 if (InstallFlags
& ~(INSTALLFLAG_FORCE
| INSTALLFLAG_READONLY
| INSTALLFLAG_NONINTERACTIVE
))
66 TRACE("Unknown flags: 0x%08lx\n", InstallFlags
& ~(INSTALLFLAG_FORCE
| INSTALLFLAG_READONLY
| INSTALLFLAG_NONINTERACTIVE
));
67 SetLastError(ERROR_INVALID_FLAGS
);
71 /* Enumerate all devices of the system */
72 DevInstData
.hDevInfo
= SetupDiGetClassDevsW(NULL
, NULL
, hwndParent
, DIGCF_ALLCLASSES
| DIGCF_PRESENT
);
73 if (DevInstData
.hDevInfo
== INVALID_HANDLE_VALUE
)
75 DevInstData
.devInfoData
.cbSize
= sizeof(SP_DEVINFO_DATA
);
78 if (!SetupDiEnumDeviceInfo(DevInstData
.hDevInfo
, i
, &DevInstData
.devInfoData
))
80 if (GetLastError() != ERROR_NO_MORE_ITEMS
)
82 TRACE("SetupDiEnumDeviceInfo() failed with error 0x%x\n", GetLastError());
85 /* This error was expected */
90 HeapFree(GetProcessHeap(), 0, Buffer
);
93 while (!SetupDiGetDeviceRegistryPropertyW(
95 &DevInstData
.devInfoData
,
102 if (GetLastError() == ERROR_FILE_NOT_FOUND
)
107 else if (GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
109 TRACE("SetupDiGetDeviceRegistryPropertyW() failed with error 0x%x\n", GetLastError());
112 /* This error was expected */
113 HeapFree(GetProcessHeap(), 0, Buffer
);
114 Buffer
= HeapAlloc(GetProcessHeap(), 0, BufferSize
);
117 TRACE("HeapAlloc() failed\n", GetLastError());
118 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
125 /* Check if we match the given hardware ID */
126 FoundHardwareId
= FALSE
;
127 for (CurrentHardwareId
= Buffer
; *CurrentHardwareId
!= UNICODE_NULL
; CurrentHardwareId
+= wcslen(CurrentHardwareId
) + 1)
129 if (wcscmp(CurrentHardwareId
, HardwareId
) == 0)
131 FoundHardwareId
= TRUE
;
135 if (!FoundHardwareId
)
138 /* We need to try to update the driver of this device */
140 /* Get Instance ID */
141 HeapFree(GetProcessHeap(), 0, Buffer
);
143 if (SetupDiGetDeviceInstanceIdW(DevInstData
.hDevInfo
, &DevInstData
.devInfoData
, NULL
, 0, &BufferSize
))
145 /* Error, as the output buffer should be too small */
146 SetLastError(ERROR_GEN_FAILURE
);
149 else if (GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
151 TRACE("SetupDiGetDeviceInstanceIdW() failed with error 0x%x\n", GetLastError());
154 else if ((Buffer
= HeapAlloc(GetProcessHeap(), 0, BufferSize
* sizeof(WCHAR
))) == NULL
)
156 TRACE("HeapAlloc() failed\n", GetLastError());
157 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
160 else if (!SetupDiGetDeviceInstanceIdW(DevInstData
.hDevInfo
, &DevInstData
.devInfoData
, Buffer
, BufferSize
, NULL
))
162 TRACE("SetupDiGetDeviceInstanceIdW() failed with error 0x%x\n", GetLastError());
165 TRACE("Trying to update the driver of %s\n", debugstr_w(Buffer
));
167 /* Search driver in the specified .inf file */
168 if (!SearchDriver(&DevInstData
, NULL
, FullInfPath
))
170 TRACE("SearchDriver() failed with error 0x%x\n", GetLastError());
174 /* FIXME: HACK! We shouldn't check of ERROR_PRIVILEGE_NOT_HELD */
175 //if (!InstallCurrentDriver(&DevInstData))
176 if (!InstallCurrentDriver(&DevInstData
) && GetLastError() != ERROR_PRIVILEGE_NOT_HELD
)
178 TRACE("InstallCurrentDriver() failed with error 0x%x\n", GetLastError());
182 FoundAtLeastOneDevice
= TRUE
;
185 if (FoundAtLeastOneDevice
)
187 SetLastError(NO_ERROR
);
192 TRACE("No device found with HardwareID %s\n", debugstr_w(HardwareId
));
193 SetLastError(ERROR_NO_SUCH_DEVINST
);
197 if (DevInstData
.hDevInfo
!= INVALID_HANDLE_VALUE
)
198 SetupDiDestroyDeviceInfoList(DevInstData
.hDevInfo
);
199 HeapFree(GetProcessHeap(), 0, Buffer
);
207 UpdateDriverForPlugAndPlayDevicesA(
209 IN LPCSTR HardwareId
,
210 IN LPCSTR FullInfPath
,
211 IN DWORD InstallFlags
,
212 OUT PBOOL bRebootRequired OPTIONAL
)
215 LPWSTR HardwareIdW
= NULL
;
216 LPWSTR FullInfPathW
= NULL
;
218 int len
= MultiByteToWideChar(CP_ACP
, 0, HardwareId
, -1, NULL
, 0);
219 HardwareIdW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
222 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
225 MultiByteToWideChar(CP_ACP
, 0, HardwareId
, -1, HardwareIdW
, len
);
227 len
= MultiByteToWideChar(CP_ACP
, 0, FullInfPath
, -1, NULL
, 0);
228 FullInfPathW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
231 HeapFree(GetProcessHeap(), 0, HardwareIdW
);
232 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
235 MultiByteToWideChar(CP_ACP
, 0, FullInfPath
, -1, FullInfPathW
, len
);
237 Result
= UpdateDriverForPlugAndPlayDevicesW(
244 HeapFree(GetProcessHeap(), 0, HardwareIdW
);
245 HeapFree(GetProcessHeap(), 0, FullInfPathW
);
250 /* Directory and InfFile MUST NOT be specified simultaneously */
253 IN PDEVINSTDATA DevInstData
,
254 IN LPCWSTR Directory OPTIONAL
,
255 IN LPCWSTR InfFile OPTIONAL
)
257 SP_DEVINSTALL_PARAMS_W DevInstallParams
= {0,};
260 DevInstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
261 if (!SetupDiGetDeviceInstallParamsW(DevInstData
->hDevInfo
, &DevInstData
->devInfoData
, &DevInstallParams
))
263 TRACE("SetupDiGetDeviceInstallParams() failed with error 0x%x\n", GetLastError());
266 DevInstallParams
.FlagsEx
|= DI_FLAGSEX_ALLOWEXCLUDEDDRVS
;
270 DevInstallParams
.Flags
|= DI_ENUMSINGLEINF
;
271 wcsncpy(DevInstallParams
.DriverPath
, InfFile
, MAX_PATH
);
275 DevInstallParams
.Flags
&= ~DI_ENUMSINGLEINF
;
276 wcsncpy(DevInstallParams
.DriverPath
, Directory
, MAX_PATH
);
280 DevInstallParams
.Flags
&= ~DI_ENUMSINGLEINF
;
281 *DevInstallParams
.DriverPath
= '\0';
284 ret
= SetupDiSetDeviceInstallParamsW(
285 DevInstData
->hDevInfo
,
286 &DevInstData
->devInfoData
,
290 TRACE("SetupDiSetDeviceInstallParams() failed with error 0x%x\n", GetLastError());
294 ret
= SetupDiBuildDriverInfoList(
295 DevInstData
->hDevInfo
,
296 &DevInstData
->devInfoData
,
300 TRACE("SetupDiBuildDriverInfoList() failed with error 0x%x\n", GetLastError());
304 DevInstData
->drvInfoData
.cbSize
= sizeof(SP_DRVINFO_DATA
);
305 ret
= SetupDiEnumDriverInfoW(
306 DevInstData
->hDevInfo
,
307 &DevInstData
->devInfoData
,
310 &DevInstData
->drvInfoData
);
313 if (GetLastError() == ERROR_NO_MORE_ITEMS
)
315 TRACE("SetupDiEnumDriverInfo() failed with error 0x%x\n", GetLastError());
323 IsDots(IN LPCWSTR str
)
325 if(wcscmp(str
, L
".") && wcscmp(str
, L
"..")) return FALSE
;
330 GetFileExt(IN LPWSTR FileName
)
334 Dot
= wcsrchr(FileName
, '.');
342 SearchDriverRecursive(
343 IN PDEVINSTDATA DevInstData
,
346 WIN32_FIND_DATAW wfd
;
347 WCHAR DirPath
[MAX_PATH
];
348 WCHAR FileName
[MAX_PATH
];
349 WCHAR FullPath
[MAX_PATH
];
350 WCHAR LastDirPath
[MAX_PATH
] = L
"";
351 WCHAR PathWithPattern
[MAX_PATH
];
354 HANDLE hFindFile
= INVALID_HANDLE_VALUE
;
356 wcscpy(DirPath
, Path
);
358 if (DirPath
[wcslen(DirPath
) - 1] != '\\')
359 wcscat(DirPath
, L
"\\");
361 wcscpy(PathWithPattern
, DirPath
);
362 wcscat(PathWithPattern
, L
"\\*");
364 for (hFindFile
= FindFirstFileW(PathWithPattern
, &wfd
);
365 ok
&& hFindFile
!= INVALID_HANDLE_VALUE
;
366 ok
= FindNextFileW(hFindFile
, &wfd
))
369 wcscpy(FileName
, wfd
.cFileName
);
370 if (IsDots(FileName
))
373 if (wfd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
375 /* Recursive search */
376 wcscpy(FullPath
, DirPath
);
377 wcscat(FullPath
, FileName
);
378 if (SearchDriverRecursive(DevInstData
, FullPath
))
381 /* We continue the search for a better driver */
386 LPCWSTR pszExtension
= GetFileExt(FileName
);
388 if ((_wcsicmp(pszExtension
, L
".inf") == 0) && (wcscmp(LastDirPath
, DirPath
) != 0))
390 wcscpy(LastDirPath
, DirPath
);
392 if (wcslen(DirPath
) > MAX_PATH
)
393 /* Path is too long to be searched */
396 if (SearchDriver(DevInstData
, DirPath
, NULL
))
399 /* We continue the search for a better driver */
406 if (hFindFile
!= INVALID_HANDLE_VALUE
)
407 FindClose(hFindFile
);
412 ScanFoldersForDriver(
413 IN PDEVINSTDATA DevInstData
)
417 /* Search in default location */
418 result
= SearchDriver(DevInstData
, NULL
, NULL
);
420 if (DevInstData
->CustomSearchPath
)
422 /* Search only in specified paths */
423 /* We need to check all specified directories to be
424 * sure to find the best driver for the device.
427 for (Path
= DevInstData
->CustomSearchPath
; *Path
!= '\0'; Path
+= wcslen(Path
) + 1)
429 TRACE("Search driver in %s\n", debugstr_w(Path
));
430 if (wcslen(Path
) == 2 && Path
[1] == ':')
432 if (SearchDriverRecursive(DevInstData
, Path
))
437 if (SearchDriver(DevInstData
, Path
, NULL
))
447 PrepareFoldersToScan(
448 IN PDEVINSTDATA DevInstData
,
449 IN BOOL IncludeRemovableDevices
,
450 IN BOOL IncludeCustomPath
,
451 IN HWND hwndCombo OPTIONAL
)
453 WCHAR drive
[] = {'?',':',0};
457 DWORD CustomTextLength
= 0;
458 DWORD LengthNeeded
= 0;
461 /* Calculate length needed to store the search paths */
462 if (IncludeRemovableDevices
)
464 dwDrives
= GetLogicalDrives();
465 for (drive
[0] = 'A', i
= 1; drive
[0] <= 'Z'; drive
[0]++, i
<<= 1)
469 nType
= GetDriveTypeW(drive
);
470 if (nType
== DRIVE_REMOVABLE
|| nType
== DRIVE_CDROM
)
477 if (IncludeCustomPath
)
479 CustomTextLength
= 1 + ComboBox_GetTextLength(hwndCombo
);
480 LengthNeeded
+= CustomTextLength
;
483 /* Allocate space for search paths */
484 HeapFree(GetProcessHeap(), 0, DevInstData
->CustomSearchPath
);
485 DevInstData
->CustomSearchPath
= Buffer
= HeapAlloc(
488 (LengthNeeded
+ 1) * sizeof(WCHAR
));
491 TRACE("HeapAlloc() failed\n");
492 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
496 /* Fill search paths */
497 if (IncludeRemovableDevices
)
499 for (drive
[0] = 'A', i
= 1; drive
[0] <= 'Z'; drive
[0]++, i
<<= 1)
503 nType
= GetDriveTypeW(drive
);
504 if (nType
== DRIVE_REMOVABLE
|| nType
== DRIVE_CDROM
)
506 Buffer
+= 1 + swprintf(Buffer
, drive
);
511 if (IncludeCustomPath
)
513 Buffer
+= 1 + GetWindowTextW(hwndCombo
, Buffer
, CustomTextLength
);
521 InstallCurrentDriver(
522 IN PDEVINSTDATA DevInstData
)
526 TRACE("Installing driver %s: %s\n",
527 debugstr_w(DevInstData
->drvInfoData
.MfgName
),
528 debugstr_w(DevInstData
->drvInfoData
.Description
));
530 ret
= SetupDiCallClassInstaller(
531 DIF_SELECTBESTCOMPATDRV
,
532 DevInstData
->hDevInfo
,
533 &DevInstData
->devInfoData
);
536 TRACE("SetupDiCallClassInstaller(DIF_SELECTBESTCOMPATDRV) failed with error 0x%x\n", GetLastError());
540 ret
= SetupDiCallClassInstaller(
542 DevInstData
->hDevInfo
,
543 &DevInstData
->devInfoData
);
546 TRACE("SetupDiCallClassInstaller(DIF_ALLOW_INSTALL) failed with error 0x%x\n", GetLastError());
550 ret
= SetupDiCallClassInstaller(
551 DIF_NEWDEVICEWIZARD_PREANALYZE
,
552 DevInstData
->hDevInfo
,
553 &DevInstData
->devInfoData
);
556 TRACE("SetupDiCallClassInstaller(DIF_NEWDEVICEWIZARD_PREANALYZE) failed with error 0x%x\n", GetLastError());
560 ret
= SetupDiCallClassInstaller(
561 DIF_NEWDEVICEWIZARD_POSTANALYZE
,
562 DevInstData
->hDevInfo
,
563 &DevInstData
->devInfoData
);
566 TRACE("SetupDiCallClassInstaller(DIF_NEWDEVICEWIZARD_POSTANALYZE) failed with error 0x%x\n", GetLastError());
570 ret
= SetupDiCallClassInstaller(
571 DIF_INSTALLDEVICEFILES
,
572 DevInstData
->hDevInfo
,
573 &DevInstData
->devInfoData
);
576 TRACE("SetupDiCallClassInstaller(DIF_INSTALLDEVICEFILES) failed with error 0x%x\n", GetLastError());
580 ret
= SetupDiCallClassInstaller(
581 DIF_REGISTER_COINSTALLERS
,
582 DevInstData
->hDevInfo
,
583 &DevInstData
->devInfoData
);
586 TRACE("SetupDiCallClassInstaller(DIF_REGISTER_COINSTALLERS) failed with error 0x%x\n", GetLastError());
590 ret
= SetupDiCallClassInstaller(
591 DIF_INSTALLINTERFACES
,
592 DevInstData
->hDevInfo
,
593 &DevInstData
->devInfoData
);
596 TRACE("SetupDiCallClassInstaller(DIF_INSTALLINTERFACES) failed with error 0x%x\n", GetLastError());
600 ret
= SetupDiCallClassInstaller(
602 DevInstData
->hDevInfo
,
603 &DevInstData
->devInfoData
);
606 TRACE("SetupDiCallClassInstaller(DIF_INSTALLDEVICE) failed with error 0x%x\n", GetLastError());
610 ret
= SetupDiCallClassInstaller(
611 DIF_NEWDEVICEWIZARD_FINISHINSTALL
,
612 DevInstData
->hDevInfo
,
613 &DevInstData
->devInfoData
);
616 TRACE("SetupDiCallClassInstaller(DIF_NEWDEVICEWIZARD_FINISHINSTALL) failed with error 0x%x\n", GetLastError());
620 ret
= SetupDiCallClassInstaller(
621 DIF_DESTROYPRIVATEDATA
,
622 DevInstData
->hDevInfo
,
623 &DevInstData
->devInfoData
);
626 TRACE("SetupDiCallClassInstaller(DIF_DESTROYPRIVATEDATA) failed with error 0x%x\n", GetLastError());
639 IN HINSTANCE hInstance
,
640 IN LPCWSTR InstanceId
,
643 PDEVINSTDATA DevInstData
= NULL
;
648 TRACE("(%p, %p, %s, %d)\n", hWndParent
, hInstance
, debugstr_w(InstanceId
), Show
);
652 /* XP kills the process... */
653 ExitProcess(ERROR_ACCESS_DENIED
);
656 DevInstData
= HeapAlloc(GetProcessHeap(), 0, sizeof(DEVINSTDATA
));
659 TRACE("HeapAlloc() failed\n");
660 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
664 /* Clear devinst data */
665 ZeroMemory(DevInstData
, sizeof(DEVINSTDATA
));
666 DevInstData
->devInfoData
.cbSize
= 0; /* Tell if the devInfoData is valid */
668 /* Fill devinst data */
669 DevInstData
->hDevInfo
= SetupDiCreateDeviceInfoListExW(NULL
, NULL
, NULL
, NULL
);
670 if (DevInstData
->hDevInfo
== INVALID_HANDLE_VALUE
)
672 TRACE("SetupDiCreateDeviceInfoListExW() failed with error 0x%x\n", GetLastError());
676 DevInstData
->devInfoData
.cbSize
= sizeof(SP_DEVINFO_DATA
);
677 ret
= SetupDiOpenDeviceInfoW(
678 DevInstData
->hDevInfo
,
682 &DevInstData
->devInfoData
);
685 TRACE("SetupDiOpenDeviceInfoW() failed with error 0x%x (InstanceId %s)\n",
686 GetLastError(), debugstr_w(InstanceId
));
687 DevInstData
->devInfoData
.cbSize
= 0;
691 SetLastError(ERROR_GEN_FAILURE
);
692 ret
= SetupDiGetDeviceRegistryProperty(
693 DevInstData
->hDevInfo
,
694 &DevInstData
->devInfoData
,
696 &DevInstData
->regDataType
,
698 &DevInstData
->requiredSize
);
700 if (!ret
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
&& DevInstData
->regDataType
== REG_SZ
)
702 DevInstData
->buffer
= HeapAlloc(GetProcessHeap(), 0, DevInstData
->requiredSize
);
703 if (!DevInstData
->buffer
)
705 TRACE("HeapAlloc() failed\n");
706 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
710 ret
= SetupDiGetDeviceRegistryPropertyW(
711 DevInstData
->hDevInfo
,
712 &DevInstData
->devInfoData
,
714 &DevInstData
->regDataType
,
715 DevInstData
->buffer
, DevInstData
->requiredSize
,
716 &DevInstData
->requiredSize
);
721 TRACE("SetupDiGetDeviceRegistryProperty() failed with error 0x%x (InstanceId %s)\n",
722 GetLastError(), debugstr_w(InstanceId
));
726 if (SetupDiGetDeviceRegistryPropertyW(
727 DevInstData
->hDevInfo
,
728 &DevInstData
->devInfoData
,
731 (BYTE
*)&config_flags
,
732 sizeof(config_flags
),
735 if (config_flags
& CONFIGFLAG_FAILEDINSTALL
)
737 /* The device is disabled */
738 TRACE("Device is disabled\n");
744 TRACE("Installing %s (%s)\n", debugstr_w((PCWSTR
)DevInstData
->buffer
), debugstr_w(InstanceId
));
746 /* Search driver in default location and removable devices */
747 if (!PrepareFoldersToScan(DevInstData
, FALSE
, FALSE
, NULL
))
749 TRACE("PrepareFoldersToScan() failed with error 0x%lx\n", GetLastError());
752 if (ScanFoldersForDriver(DevInstData
))
754 /* Driver found ; install it */
755 retval
= InstallCurrentDriver(DevInstData
);
756 TRACE("InstallCurrentDriver() returned %d\n", retval
);
757 if (retval
&& Show
!= SW_HIDE
)
759 /* Should we display the 'Need to reboot' page? */
760 SP_DEVINSTALL_PARAMS installParams
;
761 installParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
762 if (SetupDiGetDeviceInstallParams(
763 DevInstData
->hDevInfo
,
764 &DevInstData
->devInfoData
,
767 if (installParams
.Flags
& (DI_NEEDRESTART
| DI_NEEDREBOOT
))
769 TRACE("Displaying 'Reboot' wizard page\n");
770 retval
= DisplayWizard(DevInstData
, hWndParent
, IDD_NEEDREBOOT
);
776 else if (Show
== SW_HIDE
)
778 /* We can't show the wizard. Fail the install */
779 TRACE("No wizard\n");
783 /* Prepare the wizard, and display it */
784 TRACE("Need to show install wizard\n");
785 retval
= DisplayWizard(DevInstData
, hWndParent
, IDD_WELCOMEPAGE
);
790 if (DevInstData
->devInfoData
.cbSize
!= 0)
792 if (!SetupDiDestroyDriverInfoList(DevInstData
->hDevInfo
, &DevInstData
->devInfoData
, SPDIT_COMPATDRIVER
))
793 TRACE("SetupDiDestroyDriverInfoList() failed with error 0x%lx\n", GetLastError());
795 if (DevInstData
->hDevInfo
!= INVALID_HANDLE_VALUE
)
797 if (!SetupDiDestroyDeviceInfoList(DevInstData
->hDevInfo
))
798 TRACE("SetupDiDestroyDeviceInfoList() failed with error 0x%lx\n", GetLastError());
800 HeapFree(GetProcessHeap(), 0, DevInstData
->buffer
);
801 HeapFree(GetProcessHeap(), 0, DevInstData
);
812 IN LPCWSTR InstanceId
,
814 OUT LPDWORD lpReboot
)
816 PDEVINSTDATA DevInstData
= NULL
;
820 TRACE("InstllDevInst(%p, %s, %d, %p)\n", hWndParent
, debugstr_w(InstanceId
), bUpdate
, lpReboot
);
822 DevInstData
= HeapAlloc(GetProcessHeap(), 0, sizeof(DEVINSTDATA
));
825 TRACE("HeapAlloc() failed\n");
826 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
830 /* Clear devinst data */
831 ZeroMemory(DevInstData
, sizeof(DEVINSTDATA
));
832 DevInstData
->devInfoData
.cbSize
= 0; /* Tell if the devInfoData is valid */
833 DevInstData
->bUpdate
= bUpdate
;
835 /* Fill devinst data */
836 DevInstData
->hDevInfo
= SetupDiCreateDeviceInfoListExW(NULL
, NULL
, NULL
, NULL
);
837 if (DevInstData
->hDevInfo
== INVALID_HANDLE_VALUE
)
839 TRACE("SetupDiCreateDeviceInfoListExW() failed with error 0x%x\n", GetLastError());
843 DevInstData
->devInfoData
.cbSize
= sizeof(SP_DEVINFO_DATA
);
844 ret
= SetupDiOpenDeviceInfoW(
845 DevInstData
->hDevInfo
,
849 &DevInstData
->devInfoData
);
852 TRACE("SetupDiOpenDeviceInfoW() failed with error 0x%x (InstanceId %s)\n",
853 GetLastError(), debugstr_w(InstanceId
));
854 DevInstData
->devInfoData
.cbSize
= 0;
858 SetLastError(ERROR_GEN_FAILURE
);
859 ret
= SetupDiGetDeviceRegistryProperty(
860 DevInstData
->hDevInfo
,
861 &DevInstData
->devInfoData
,
863 &DevInstData
->regDataType
,
865 &DevInstData
->requiredSize
);
867 if (!ret
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
&& DevInstData
->regDataType
== REG_SZ
)
869 DevInstData
->buffer
= HeapAlloc(GetProcessHeap(), 0, DevInstData
->requiredSize
);
870 if (!DevInstData
->buffer
)
872 TRACE("HeapAlloc() failed\n");
873 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
877 ret
= SetupDiGetDeviceRegistryPropertyW(
878 DevInstData
->hDevInfo
,
879 &DevInstData
->devInfoData
,
881 &DevInstData
->regDataType
,
882 DevInstData
->buffer
, DevInstData
->requiredSize
,
883 &DevInstData
->requiredSize
);
889 TRACE("SetupDiGetDeviceRegistryProperty() failed with error 0x%x (InstanceId %s)\n",
890 GetLastError(), debugstr_w(InstanceId
));
894 /* Prepare the wizard, and display it */
895 TRACE("Need to show install wizard\n");
896 retval
= DisplayWizard(DevInstData
, hWndParent
, IDD_WELCOMEPAGE
);
901 if (DevInstData
->devInfoData
.cbSize
!= 0)
903 if (!SetupDiDestroyDriverInfoList(DevInstData
->hDevInfo
, &DevInstData
->devInfoData
, SPDIT_COMPATDRIVER
))
904 TRACE("SetupDiDestroyDriverInfoList() failed with error 0x%lx\n", GetLastError());
906 if (DevInstData
->hDevInfo
!= INVALID_HANDLE_VALUE
)
908 if (!SetupDiDestroyDeviceInfoList(DevInstData
->hDevInfo
))
909 TRACE("SetupDiDestroyDeviceInfoList() failed with error 0x%lx\n", GetLastError());
911 HeapFree(GetProcessHeap(), 0, DevInstData
->buffer
);
912 HeapFree(GetProcessHeap(), 0, DevInstData
);
925 IN HINSTANCE hInstance
,
926 IN LPWSTR lpNamedPipeName
,
929 BOOL ReturnValue
= FALSE
;
933 HANDLE hPipe
= INVALID_HANDLE_VALUE
;
934 PWSTR DeviceInstance
= NULL
;
935 PWSTR InstallEventName
= NULL
;
938 hPipe
= CreateFileW(lpNamedPipeName
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
940 if(hPipe
== INVALID_HANDLE_VALUE
)
942 ERR("CreateFileW failed with error %u\n", GetLastError());
946 /* Read the data. Some is just included for compatibility with Windows right now and not yet used by ReactOS.
947 See umpnpmgr for more details. */
948 if(!ReadFile(hPipe
, &Value
, sizeof(Value
), &BytesRead
, NULL
))
950 ERR("ReadFile failed with error %u\n", GetLastError());
954 InstallEventName
= (PWSTR
)HeapAlloc(GetProcessHeap(), 0, Value
);
956 if(!ReadFile(hPipe
, InstallEventName
, Value
, &BytesRead
, NULL
))
958 ERR("ReadFile failed with error %u\n", GetLastError());
962 /* I couldn't figure out what the following value means under Windows XP.
963 Therefore I used it in umpnpmgr to pass the ShowWizard variable. */
964 if(!ReadFile(hPipe
, &ShowWizard
, sizeof(ShowWizard
), &BytesRead
, NULL
))
966 ERR("ReadFile failed with error %u\n", GetLastError());
970 /* Next one is again size in bytes of the following string */
971 if(!ReadFile(hPipe
, &Value
, sizeof(Value
), &BytesRead
, NULL
))
973 ERR("ReadFile failed with error %u\n", GetLastError());
977 DeviceInstance
= (PWSTR
)HeapAlloc(GetProcessHeap(), 0, Value
);
979 if(!ReadFile(hPipe
, DeviceInstance
, Value
, &BytesRead
, NULL
))
981 ERR("ReadFile failed with error %u\n", GetLastError());
985 ReturnValue
= DevInstallW(NULL
, NULL
, DeviceInstance
, ShowWizard
? SW_SHOWNOACTIVATE
: SW_HIDE
);
988 if(hPipe
!= INVALID_HANDLE_VALUE
)
992 HeapFree(GetProcessHeap(), 0, InstallEventName
);
995 HeapFree(GetProcessHeap(), 0, DeviceInstance
);
1002 IN HINSTANCE hInstance
,
1004 IN LPVOID lpReserved
)
1006 if (dwReason
== DLL_PROCESS_ATTACH
)
1008 INITCOMMONCONTROLSEX InitControls
;
1010 DisableThreadLibraryCalls(hInstance
);
1012 InitControls
.dwSize
= sizeof(INITCOMMONCONTROLSEX
);
1013 InitControls
.dwICC
= ICC_PROGRESS_CLASS
;
1014 InitCommonControlsEx(&InitControls
);
1015 hDllInstance
= hInstance
;