Something went wrong. Try again.
Reactos
Something went wrong. Try again.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073/* * New device installer (newdev.dll) * * Copyright 2005-2006 Hervé Poussineau (hpoussin@reactos.org) * 2005 Christoph von Wittich (Christoph@ActiveVB.de) * 2009 Colin Finck (colin@reactos.org) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
#include "newdev_private.h"
#include <stdio.h>#include <winnls.h>
/* Global variables */HINSTANCE hDllInstance;
static BOOLSearchDriver( IN PDEVINSTDATA DevInstData, IN LPCWSTR Directory OPTIONAL, IN LPCWSTR InfFile OPTIONAL);
/** @implemented*/BOOL WINAPIUpdateDriverForPlugAndPlayDevicesW( IN HWND hwndParent, IN LPCWSTR HardwareId, IN LPCWSTR FullInfPath, IN DWORD InstallFlags, OUT PBOOL bRebootRequired OPTIONAL){ DEVINSTDATA DevInstData; DWORD i; LPWSTR Buffer = NULL; DWORD BufferSize; LPCWSTR CurrentHardwareId; /* Pointer into Buffer */ DWORD Property; BOOL FoundHardwareId, FoundAtLeastOneDevice = FALSE; BOOL ret = FALSE;
DevInstData.hDevInfo = INVALID_HANDLE_VALUE;
TRACE("UpdateDriverForPlugAndPlayDevicesW(%p %s %s 0x%x %p)\n", hwndParent, debugstr_w(HardwareId), debugstr_w(FullInfPath), InstallFlags, bRebootRequired);
/* FIXME: InstallFlags bRebootRequired ignored! */
/* Check flags */ if (InstallFlags & ~(INSTALLFLAG_FORCE | INSTALLFLAG_READONLY | INSTALLFLAG_NONINTERACTIVE)) { TRACE("Unknown flags: 0x%08lx\n", InstallFlags & ~(INSTALLFLAG_FORCE | INSTALLFLAG_READONLY | INSTALLFLAG_NONINTERACTIVE)); SetLastError(ERROR_INVALID_FLAGS); goto cleanup; }
/* Enumerate all devices of the system */ DevInstData.hDevInfo = SetupDiGetClassDevsW(NULL, NULL, hwndParent, DIGCF_ALLCLASSES | DIGCF_PRESENT); if (DevInstData.hDevInfo == INVALID_HANDLE_VALUE) goto cleanup; DevInstData.devInfoData.cbSize = sizeof(SP_DEVINFO_DATA); for (i = 0; ; i++) { if (!SetupDiEnumDeviceInfo(DevInstData.hDevInfo, i, &DevInstData.devInfoData)) { if (GetLastError() != ERROR_NO_MORE_ITEMS) { TRACE("SetupDiEnumDeviceInfo() failed with error 0x%x\n", GetLastError()); goto cleanup; } /* This error was expected */ break; }
/* Match Hardware ID */ FoundHardwareId = FALSE; Property = SPDRP_HARDWAREID; while (TRUE) { /* Get IDs data */ Buffer = NULL; BufferSize = 0; while (!SetupDiGetDeviceRegistryPropertyW(DevInstData.hDevInfo, &DevInstData.devInfoData, Property, NULL, (PBYTE)Buffer, BufferSize, &BufferSize)) { if (GetLastError() == ERROR_FILE_NOT_FOUND) { break; } else if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { TRACE("SetupDiGetDeviceRegistryPropertyW() failed with error 0x%x\n", GetLastError()); goto cleanup; } /* This error was expected */ HeapFree(GetProcessHeap(), 0, Buffer); Buffer = HeapAlloc(GetProcessHeap(), 0, BufferSize); if (!Buffer) { TRACE("HeapAlloc() failed\n", GetLastError()); SetLastError(ERROR_NOT_ENOUGH_MEMORY); goto cleanup; } } if (Buffer) { /* Check if we match the given hardware ID */ for (CurrentHardwareId = Buffer; *CurrentHardwareId != UNICODE_NULL; CurrentHardwareId += wcslen(CurrentHardwareId) + 1) { if (_wcsicmp(CurrentHardwareId, HardwareId) == 0) { FoundHardwareId = TRUE; break; } } } if (FoundHardwareId || Property == SPDRP_COMPATIBLEIDS) { break; } Property = SPDRP_COMPATIBLEIDS; } if (!FoundHardwareId) continue;
/* We need to try to update the driver of this device */
/* Get Instance ID */ HeapFree(GetProcessHeap(), 0, Buffer); Buffer = NULL; if (SetupDiGetDeviceInstanceIdW(DevInstData.hDevInfo, &DevInstData.devInfoData, NULL, 0, &BufferSize)) { /* Error, as the output buffer should be too small */ SetLastError(ERROR_GEN_FAILURE); goto cleanup; } else if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { TRACE("SetupDiGetDeviceInstanceIdW() failed with error 0x%x\n", GetLastError()); goto cleanup; } else if ((Buffer = HeapAlloc(GetProcessHeap(), 0, BufferSize * sizeof(WCHAR))) == NULL) { TRACE("HeapAlloc() failed\n", GetLastError()); SetLastError(ERROR_NOT_ENOUGH_MEMORY); goto cleanup; } else if (!SetupDiGetDeviceInstanceIdW(DevInstData.hDevInfo, &DevInstData.devInfoData, Buffer, BufferSize, NULL)) { TRACE("SetupDiGetDeviceInstanceIdW() failed with error 0x%x\n", GetLastError()); goto cleanup; } TRACE("Trying to update the driver of %s\n", debugstr_w(Buffer));
/* Search driver in the specified .inf file */ if (!SearchDriver(&DevInstData, NULL, FullInfPath)) { TRACE("SearchDriver() failed with error 0x%x\n", GetLastError()); continue; }
/* FIXME: HACK! We shouldn't check of ERROR_PRIVILEGE_NOT_HELD */ //if (!InstallCurrentDriver(&DevInstData)) if (!InstallCurrentDriver(&DevInstData) && GetLastError() != ERROR_PRIVILEGE_NOT_HELD) { TRACE("InstallCurrentDriver() failed with error 0x%x\n", GetLastError()); continue; }
FoundAtLeastOneDevice = TRUE; }
if (FoundAtLeastOneDevice) { SetLastError(NO_ERROR); ret = TRUE; } else { TRACE("No device found with HardwareID %s\n", debugstr_w(HardwareId)); SetLastError(ERROR_NO_SUCH_DEVINST); }
cleanup: if (DevInstData.hDevInfo != INVALID_HANDLE_VALUE) SetupDiDestroyDeviceInfoList(DevInstData.hDevInfo); HeapFree(GetProcessHeap(), 0, Buffer); return ret;}
/** @implemented*/BOOL WINAPIUpdateDriverForPlugAndPlayDevicesA( IN HWND hwndParent, IN LPCSTR HardwareId, IN LPCSTR FullInfPath, IN DWORD InstallFlags, OUT PBOOL bRebootRequired OPTIONAL){ BOOL Result; LPWSTR HardwareIdW = NULL; LPWSTR FullInfPathW = NULL;
int len = MultiByteToWideChar(CP_ACP, 0, HardwareId, -1, NULL, 0); HardwareIdW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); if (!HardwareIdW) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); return FALSE; } MultiByteToWideChar(CP_ACP, 0, HardwareId, -1, HardwareIdW, len);
len = MultiByteToWideChar(CP_ACP, 0, FullInfPath, -1, NULL, 0); FullInfPathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); if (!FullInfPathW) { HeapFree(GetProcessHeap(), 0, HardwareIdW); SetLastError(ERROR_NOT_ENOUGH_MEMORY); return FALSE; } MultiByteToWideChar(CP_ACP, 0, FullInfPath, -1, FullInfPathW, len);
Result = UpdateDriverForPlugAndPlayDevicesW( hwndParent, HardwareIdW, FullInfPathW, InstallFlags, bRebootRequired);
HeapFree(GetProcessHeap(), 0, HardwareIdW); HeapFree(GetProcessHeap(), 0, FullInfPathW);
return Result;}
/* Directory and InfFile MUST NOT be specified simultaneously */static BOOLSearchDriver( IN PDEVINSTDATA DevInstData, IN LPCWSTR Directory OPTIONAL, IN LPCWSTR InfFile OPTIONAL){ SP_DEVINSTALL_PARAMS_W DevInstallParams = {0,}; BOOL ret;
DevInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); if (!SetupDiGetDeviceInstallParamsW(DevInstData->hDevInfo, &DevInstData->devInfoData, &DevInstallParams)) { TRACE("SetupDiGetDeviceInstallParams() failed with error 0x%x\n", GetLastError()); return FALSE; } DevInstallParams.FlagsEx |= DI_FLAGSEX_ALLOWEXCLUDEDDRVS;
if (InfFile) { DevInstallParams.Flags |= DI_ENUMSINGLEINF; wcsncpy(DevInstallParams.DriverPath, InfFile, MAX_PATH); } else if (Directory) { DevInstallParams.Flags &= ~DI_ENUMSINGLEINF; wcsncpy(DevInstallParams.DriverPath, Directory, MAX_PATH); } else { DevInstallParams.Flags &= ~DI_ENUMSINGLEINF; *DevInstallParams.DriverPath = '\0'; }
ret = SetupDiSetDeviceInstallParamsW( DevInstData->hDevInfo, &DevInstData->devInfoData, &DevInstallParams); if (!ret) { TRACE("SetupDiSetDeviceInstallParams() failed with error 0x%x\n", GetLastError()); return FALSE; }
ret = SetupDiBuildDriverInfoList( DevInstData->hDevInfo, &DevInstData->devInfoData, SPDIT_COMPATDRIVER); if (!ret) { TRACE("SetupDiBuildDriverInfoList() failed with error 0x%x\n", GetLastError()); return FALSE; }
DevInstData->drvInfoData.cbSize = sizeof(SP_DRVINFO_DATA); ret = SetupDiEnumDriverInfoW( DevInstData->hDevInfo, &DevInstData->devInfoData, SPDIT_COMPATDRIVER, 0, &DevInstData->drvInfoData); if (!ret) { if (GetLastError() == ERROR_NO_MORE_ITEMS) return FALSE; TRACE("SetupDiEnumDriverInfo() failed with error 0x%x\n", GetLastError()); return FALSE; }
return TRUE;}
static BOOLIsDots(IN LPCWSTR str){ if(wcscmp(str, L".") && wcscmp(str, L"..")) return FALSE; return TRUE;}
static LPCWSTRGetFileExt(IN LPWSTR FileName){ LPCWSTR Dot;
Dot = wcsrchr(FileName, '.'); if (!Dot) return L"";
return Dot;}
static BOOLSearchDriverRecursive( IN PDEVINSTDATA DevInstData, IN LPCWSTR Path){ WIN32_FIND_DATAW wfd; WCHAR DirPath[MAX_PATH]; WCHAR FileName[MAX_PATH]; WCHAR FullPath[MAX_PATH]; WCHAR LastDirPath[MAX_PATH] = L""; WCHAR PathWithPattern[MAX_PATH]; BOOL ok = TRUE; BOOL retval = FALSE; HANDLE hFindFile = INVALID_HANDLE_VALUE;
wcscpy(DirPath, Path);
if (DirPath[wcslen(DirPath) - 1] != '\\') wcscat(DirPath, L"\\");
wcscpy(PathWithPattern, DirPath); wcscat(PathWithPattern, L"*");
for (hFindFile = FindFirstFileW(PathWithPattern, &wfd); ok && hFindFile != INVALID_HANDLE_VALUE; ok = FindNextFileW(hFindFile, &wfd)) {
wcscpy(FileName, wfd.cFileName); if (IsDots(FileName)) continue;
if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { /* Recursive search */ wcscpy(FullPath, DirPath); wcscat(FullPath, FileName); if (SearchDriverRecursive(DevInstData, FullPath)) { retval = TRUE; /* We continue the search for a better driver */ } } else { LPCWSTR pszExtension = GetFileExt(FileName);
if ((_wcsicmp(pszExtension, L".inf") == 0) && (wcscmp(LastDirPath, DirPath) != 0)) { wcscpy(LastDirPath, DirPath);
if (wcslen(DirPath) > MAX_PATH) /* Path is too long to be searched */ continue;
if (SearchDriver(DevInstData, DirPath, NULL)) { retval = TRUE; /* We continue the search for a better driver */ }
} } }
if (hFindFile != INVALID_HANDLE_VALUE) FindClose(hFindFile); return retval;}
BOOLCheckBestDriver( _In_ PDEVINSTDATA DevInstData, _In_ PCWSTR pszDir){ return SearchDriverRecursive(DevInstData, pszDir);}
BOOLScanFoldersForDriver( IN PDEVINSTDATA DevInstData){ BOOL result;
/* Search in default location */ result = SearchDriver(DevInstData, NULL, NULL);
if (DevInstData->CustomSearchPath) { /* Search only in specified paths */ /* We need to check all specified directories to be * sure to find the best driver for the device. */ LPCWSTR Path; for (Path = DevInstData->CustomSearchPath; *Path != '\0'; Path += wcslen(Path) + 1) { TRACE("Search driver in %s\n", debugstr_w(Path)); if (wcslen(Path) == 2 && Path[1] == ':') { if (SearchDriverRecursive(DevInstData, Path)) result = TRUE; } else { if (SearchDriver(DevInstData, Path, NULL)) result = TRUE; } } }
return result;}
BOOLPrepareFoldersToScan( IN PDEVINSTDATA DevInstData, IN BOOL IncludeRemovableDevices, IN BOOL IncludeCustomPath, IN HWND hwndCombo OPTIONAL){ WCHAR drive[] = {'?',':',0}; DWORD dwDrives = 0; DWORD i; UINT nType; DWORD CustomTextLength = 0; DWORD LengthNeeded = 0; LPWSTR Buffer; INT idx = (INT)SendMessageW(hwndCombo, CB_GETCURSEL, 0, 0);
/* Calculate length needed to store the search paths */ if (IncludeRemovableDevices) { dwDrives = GetLogicalDrives(); for (drive[0] = 'A', i = 1; drive[0] <= 'Z'; drive[0]++, i <<= 1) { if (dwDrives & i) { nType = GetDriveTypeW(drive); if (nType == DRIVE_REMOVABLE || nType == DRIVE_CDROM) { LengthNeeded += 3; } } } } if (IncludeCustomPath) { CustomTextLength = 1 + ((idx != CB_ERR) ? (INT)SendMessageW(hwndCombo, CB_GETLBTEXTLEN, idx, 0) : ComboBox_GetTextLength(hwndCombo)); LengthNeeded += CustomTextLength; }
/* Allocate space for search paths */ HeapFree(GetProcessHeap(), 0, DevInstData->CustomSearchPath); DevInstData->CustomSearchPath = Buffer = HeapAlloc( GetProcessHeap(), 0, (LengthNeeded + 1) * sizeof(WCHAR)); if (!Buffer) { TRACE("HeapAlloc() failed\n"); SetLastError(ERROR_NOT_ENOUGH_MEMORY); return FALSE; }
/* Fill search paths */ if (IncludeRemovableDevices) { for (drive[0] = 'A', i = 1; drive[0] <= 'Z'; drive[0]++, i <<= 1) { if (dwDrives & i) { nType = GetDriveTypeW(drive); if (nType == DRIVE_REMOVABLE || nType == DRIVE_CDROM) { Buffer += 1 + swprintf(Buffer, drive); } } } } if (IncludeCustomPath) { Buffer += 1 + ((idx != CB_ERR) ? SendMessageW(hwndCombo, CB_GETLBTEXT, idx, (LPARAM)Buffer) : GetWindowTextW(hwndCombo, Buffer, CustomTextLength)); } *Buffer = '\0';
return TRUE;}
BOOLInstallCurrentDriver( IN PDEVINSTDATA DevInstData){ BOOL ret;
TRACE("Installing driver %s: %s\n", debugstr_w(DevInstData->drvInfoData.MfgName), debugstr_w(DevInstData->drvInfoData.Description));
ret = SetupDiCallClassInstaller( DIF_SELECTBESTCOMPATDRV, DevInstData->hDevInfo, &DevInstData->devInfoData); if (!ret) { TRACE("SetupDiCallClassInstaller(DIF_SELECTBESTCOMPATDRV) failed with error 0x%x\n", GetLastError()); return FALSE; }
ret = SetupDiCallClassInstaller( DIF_ALLOW_INSTALL, DevInstData->hDevInfo, &DevInstData->devInfoData); if (!ret) { TRACE("SetupDiCallClassInstaller(DIF_ALLOW_INSTALL) failed with error 0x%x\n", GetLastError()); return FALSE; }
ret = SetupDiCallClassInstaller( DIF_NEWDEVICEWIZARD_PREANALYZE, DevInstData->hDevInfo, &DevInstData->devInfoData); if (!ret) { TRACE("SetupDiCallClassInstaller(DIF_NEWDEVICEWIZARD_PREANALYZE) failed with error 0x%x\n", GetLastError()); return FALSE; }
ret = SetupDiCallClassInstaller( DIF_NEWDEVICEWIZARD_POSTANALYZE, DevInstData->hDevInfo, &DevInstData->devInfoData); if (!ret) { TRACE("SetupDiCallClassInstaller(DIF_NEWDEVICEWIZARD_POSTANALYZE) failed with error 0x%x\n", GetLastError()); return FALSE; }
ret = SetupDiCallClassInstaller( DIF_INSTALLDEVICEFILES, DevInstData->hDevInfo, &DevInstData->devInfoData); if (!ret) { TRACE("SetupDiCallClassInstaller(DIF_INSTALLDEVICEFILES) failed with error 0x%x\n", GetLastError()); return FALSE; }
ret = SetupDiCallClassInstaller( DIF_REGISTER_COINSTALLERS, DevInstData->hDevInfo, &DevInstData->devInfoData); if (!ret) { TRACE("SetupDiCallClassInstaller(DIF_REGISTER_COINSTALLERS) failed with error 0x%x\n", GetLastError()); return FALSE; }
ret = SetupDiCallClassInstaller( DIF_INSTALLINTERFACES, DevInstData->hDevInfo, &DevInstData->devInfoData); if (!ret) { TRACE("SetupDiCallClassInstaller(DIF_INSTALLINTERFACES) failed with error 0x%x\n", GetLastError()); return FALSE; }
ret = SetupDiCallClassInstaller( DIF_INSTALLDEVICE, DevInstData->hDevInfo, &DevInstData->devInfoData); if (!ret) { TRACE("SetupDiCallClassInstaller(DIF_INSTALLDEVICE) failed with error 0x%x\n", GetLastError()); return FALSE; }
ret = SetupDiCallClassInstaller( DIF_NEWDEVICEWIZARD_FINISHINSTALL, DevInstData->hDevInfo, &DevInstData->devInfoData); if (!ret) { TRACE("SetupDiCallClassInstaller(DIF_NEWDEVICEWIZARD_FINISHINSTALL) failed with error 0x%x\n", GetLastError()); return FALSE; }
ret = SetupDiCallClassInstaller( DIF_DESTROYPRIVATEDATA, DevInstData->hDevInfo, &DevInstData->devInfoData); if (!ret) { TRACE("SetupDiCallClassInstaller(DIF_DESTROYPRIVATEDATA) failed with error 0x%x\n", GetLastError()); return FALSE; }
return TRUE;}
/** @implemented*/BOOL WINAPIDevInstallW( IN HWND hWndParent, IN HINSTANCE hInstance, IN LPCWSTR InstanceId, IN INT Show){ PDEVINSTDATA DevInstData = NULL; BOOL ret; DWORD config_flags; BOOL retval = FALSE;
TRACE("(%p, %p, %s, %d)\n", hWndParent, hInstance, debugstr_w(InstanceId), Show);
if (!IsUserAdmin()) { /* XP kills the process... */ ExitProcess(ERROR_ACCESS_DENIED); }
DevInstData = HeapAlloc(GetProcessHeap(), 0, sizeof(DEVINSTDATA)); if (!DevInstData) { TRACE("HeapAlloc() failed\n"); SetLastError(ERROR_NOT_ENOUGH_MEMORY); goto cleanup; }
/* Clear devinst data */ ZeroMemory(DevInstData, sizeof(DEVINSTDATA)); DevInstData->devInfoData.cbSize = 0; /* Tell if the devInfoData is valid */
/* Fill devinst data */ DevInstData->hDevInfo = SetupDiCreateDeviceInfoListExW(NULL, NULL, NULL, NULL); if (DevInstData->hDevInfo == INVALID_HANDLE_VALUE) { TRACE("SetupDiCreateDeviceInfoListExW() failed with error 0x%x\n", GetLastError()); goto cleanup; }
DevInstData->devInfoData.cbSize = sizeof(SP_DEVINFO_DATA); ret = SetupDiOpenDeviceInfoW( DevInstData->hDevInfo, InstanceId, NULL, 0, /* Open flags */ &DevInstData->devInfoData); if (!ret) { TRACE("SetupDiOpenDeviceInfoW() failed with error 0x%x (InstanceId %s)\n", GetLastError(), debugstr_w(InstanceId)); DevInstData->devInfoData.cbSize = 0; goto cleanup; }
SetLastError(ERROR_GEN_FAILURE); ret = SetupDiGetDeviceRegistryProperty( DevInstData->hDevInfo, &DevInstData->devInfoData, SPDRP_DEVICEDESC, &DevInstData->regDataType, NULL, 0, &DevInstData->requiredSize);
if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER && DevInstData->regDataType == REG_SZ) { DevInstData->buffer = HeapAlloc(GetProcessHeap(), 0, DevInstData->requiredSize); if (!DevInstData->buffer) { TRACE("HeapAlloc() failed\n"); SetLastError(ERROR_NOT_ENOUGH_MEMORY); } else { ret = SetupDiGetDeviceRegistryPropertyW( DevInstData->hDevInfo, &DevInstData->devInfoData, SPDRP_DEVICEDESC, &DevInstData->regDataType, DevInstData->buffer, DevInstData->requiredSize, &DevInstData->requiredSize); } } if (!ret) { TRACE("SetupDiGetDeviceRegistryProperty() failed with error 0x%x (InstanceId %s)\n", GetLastError(), debugstr_w(InstanceId)); goto cleanup; }
if (SetupDiGetDeviceRegistryPropertyW( DevInstData->hDevInfo, &DevInstData->devInfoData, SPDRP_CONFIGFLAGS, NULL, (BYTE *)&config_flags, sizeof(config_flags), NULL)) { if (config_flags & CONFIGFLAG_FAILEDINSTALL) { /* The device is disabled */ TRACE("Device is disabled\n"); retval = TRUE; goto cleanup; } }
TRACE("Installing %s (%s)\n", debugstr_w((PCWSTR)DevInstData->buffer), debugstr_w(InstanceId));
/* Search driver in default location and removable devices */ if (!PrepareFoldersToScan(DevInstData, FALSE, FALSE, NULL)) { TRACE("PrepareFoldersToScan() failed with error 0x%lx\n", GetLastError()); goto cleanup; } if (ScanFoldersForDriver(DevInstData)) { /* Driver found ; install it */ retval = InstallCurrentDriver(DevInstData); TRACE("InstallCurrentDriver() returned %d\n", retval); if (retval && Show != SW_HIDE) { /* Should we display the 'Need to reboot' page? */ SP_DEVINSTALL_PARAMS installParams; installParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS); if (SetupDiGetDeviceInstallParams( DevInstData->hDevInfo, &DevInstData->devInfoData, &installParams)) { if (installParams.Flags & (DI_NEEDRESTART | DI_NEEDREBOOT)) { TRACE("Displaying 'Reboot' wizard page\n"); retval = DisplayWizard(DevInstData, hWndParent, IDD_NEEDREBOOT); } } } goto cleanup; } else if (Show == SW_HIDE) { /* We can't show the wizard. Fail the install */ TRACE("No wizard\n"); goto cleanup; }
/* Prepare the wizard, and display it */ TRACE("Need to show install wizard\n"); retval = DisplayWizard(DevInstData, hWndParent, IDD_WELCOMEPAGE);
cleanup: if (DevInstData) { if (DevInstData->devInfoData.cbSize != 0) { if (!SetupDiDestroyDriverInfoList(DevInstData->hDevInfo, &DevInstData->devInfoData, SPDIT_COMPATDRIVER)) TRACE("SetupDiDestroyDriverInfoList() failed with error 0x%lx\n", GetLastError()); } if (DevInstData->hDevInfo != INVALID_HANDLE_VALUE) { if (!SetupDiDestroyDeviceInfoList(DevInstData->hDevInfo)) TRACE("SetupDiDestroyDeviceInfoList() failed with error 0x%lx\n", GetLastError()); } HeapFree(GetProcessHeap(), 0, DevInstData->buffer); HeapFree(GetProcessHeap(), 0, DevInstData); }
return retval;}
BOOLWINAPIInstallDevInstEx( IN HWND hWndParent, IN LPCWSTR InstanceId, IN BOOL bUpdate, OUT LPDWORD lpReboot, IN DWORD Unknown){ PDEVINSTDATA DevInstData = NULL; BOOL ret; BOOL retval = FALSE;
TRACE("InstllDevInstEx(%p, %s, %d, %p, %lx)\n", hWndParent, debugstr_w(InstanceId), bUpdate, lpReboot, Unknown);
DevInstData = HeapAlloc(GetProcessHeap(), 0, sizeof(DEVINSTDATA)); if (!DevInstData) { TRACE("HeapAlloc() failed\n"); SetLastError(ERROR_NOT_ENOUGH_MEMORY); goto cleanup; }
/* Clear devinst data */ ZeroMemory(DevInstData, sizeof(DEVINSTDATA)); DevInstData->devInfoData.cbSize = 0; /* Tell if the devInfoData is valid */ DevInstData->bUpdate = bUpdate;
/* Fill devinst data */ DevInstData->hDevInfo = SetupDiCreateDeviceInfoListExW(NULL, NULL, NULL, NULL); if (DevInstData->hDevInfo == INVALID_HANDLE_VALUE) { TRACE("SetupDiCreateDeviceInfoListExW() failed with error 0x%x\n", GetLastError()); goto cleanup; }
DevInstData->devInfoData.cbSize = sizeof(SP_DEVINFO_DATA); ret = SetupDiOpenDeviceInfoW( DevInstData->hDevInfo, InstanceId, NULL, 0, /* Open flags */ &DevInstData->devInfoData); if (!ret) { TRACE("SetupDiOpenDeviceInfoW() failed with error 0x%x (InstanceId %s)\n", GetLastError(), debugstr_w(InstanceId)); DevInstData->devInfoData.cbSize = 0; goto cleanup; }
SetLastError(ERROR_GEN_FAILURE); ret = SetupDiGetDeviceRegistryProperty( DevInstData->hDevInfo, &DevInstData->devInfoData, SPDRP_DEVICEDESC, &DevInstData->regDataType, NULL, 0, &DevInstData->requiredSize);
if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER && DevInstData->regDataType == REG_SZ) { DevInstData->buffer = HeapAlloc(GetProcessHeap(), 0, DevInstData->requiredSize); if (!DevInstData->buffer) { TRACE("HeapAlloc() failed\n"); SetLastError(ERROR_NOT_ENOUGH_MEMORY); } else { ret = SetupDiGetDeviceRegistryPropertyW( DevInstData->hDevInfo, &DevInstData->devInfoData, SPDRP_DEVICEDESC, &DevInstData->regDataType, DevInstData->buffer, DevInstData->requiredSize, &DevInstData->requiredSize); } }
if (!ret) { TRACE("SetupDiGetDeviceRegistryProperty() failed with error 0x%x (InstanceId %s)\n", GetLastError(), debugstr_w(InstanceId)); goto cleanup; }
/* Prepare the wizard, and display it */ TRACE("Need to show install wizard\n"); retval = DisplayWizard(DevInstData, hWndParent, IDD_WELCOMEPAGE);
cleanup: if (DevInstData) { if (DevInstData->devInfoData.cbSize != 0) { if (!SetupDiDestroyDriverInfoList(DevInstData->hDevInfo, &DevInstData->devInfoData, SPDIT_COMPATDRIVER)) TRACE("SetupDiDestroyDriverInfoList() failed with error 0x%lx\n", GetLastError()); } if (DevInstData->hDevInfo != INVALID_HANDLE_VALUE) { if (!SetupDiDestroyDeviceInfoList(DevInstData->hDevInfo)) TRACE("SetupDiDestroyDeviceInfoList() failed with error 0x%lx\n", GetLastError()); } HeapFree(GetProcessHeap(), 0, DevInstData->buffer); HeapFree(GetProcessHeap(), 0, DevInstData); }
return retval;}
/* * @implemented */BOOLWINAPIInstallDevInst( IN HWND hWndParent, IN LPCWSTR InstanceId, IN BOOL bUpdate, OUT LPDWORD lpReboot){ return InstallDevInstEx(hWndParent, InstanceId, bUpdate, lpReboot, 0);}
/** @implemented*/BOOL WINAPIClientSideInstallW( IN HWND hWndOwner, IN HINSTANCE hInstance, IN LPWSTR lpNamedPipeName, IN INT Show){ BOOL ReturnValue = FALSE; BOOL ShowWizard; DWORD BytesRead; DWORD Value; HANDLE hPipe = INVALID_HANDLE_VALUE; PWSTR DeviceInstance = NULL; PWSTR InstallEventName = NULL; HANDLE hInstallEvent;
/* Open the pipe */ hPipe = CreateFileW(lpNamedPipeName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(hPipe == INVALID_HANDLE_VALUE) { ERR("CreateFileW failed with error %u\n", GetLastError()); goto cleanup; }
/* Read the data. Some is just included for compatibility with Windows right now and not yet used by ReactOS. See umpnpmgr for more details. */ if(!ReadFile(hPipe, &Value, sizeof(Value), &BytesRead, NULL)) { ERR("ReadFile failed with error %u\n", GetLastError()); goto cleanup; }
InstallEventName = (PWSTR)HeapAlloc(GetProcessHeap(), 0, Value);
if(!ReadFile(hPipe, InstallEventName, Value, &BytesRead, NULL)) { ERR("ReadFile failed with error %u\n", GetLastError()); goto cleanup; }
/* I couldn't figure out what the following value means under Windows XP. Therefore I used it in umpnpmgr to pass the ShowWizard variable. */ if(!ReadFile(hPipe, &ShowWizard, sizeof(ShowWizard), &BytesRead, NULL)) { ERR("ReadFile failed with error %u\n", GetLastError()); goto cleanup; }
/* Next one is again size in bytes of the following string */ if(!ReadFile(hPipe, &Value, sizeof(Value), &BytesRead, NULL)) { ERR("ReadFile failed with error %u\n", GetLastError()); goto cleanup; }
DeviceInstance = (PWSTR)HeapAlloc(GetProcessHeap(), 0, Value);
if(!ReadFile(hPipe, DeviceInstance, Value, &BytesRead, NULL)) { ERR("ReadFile failed with error %u\n", GetLastError()); goto cleanup; }
ReturnValue = DevInstallW(NULL, NULL, DeviceInstance, ShowWizard ? SW_SHOWNOACTIVATE : SW_HIDE); if(!ReturnValue) { ERR("DevInstallW failed with error %lu\n", GetLastError()); goto cleanup; }
hInstallEvent = CreateEventW(NULL, TRUE, FALSE, InstallEventName); if(!hInstallEvent) { TRACE("CreateEventW('%ls') failed with error %lu\n", InstallEventName, GetLastError()); goto cleanup; }
SetEvent(hInstallEvent); CloseHandle(hInstallEvent);
cleanup: if(hPipe != INVALID_HANDLE_VALUE) CloseHandle(hPipe);
if(InstallEventName) HeapFree(GetProcessHeap(), 0, InstallEventName);
if(DeviceInstance) HeapFree(GetProcessHeap(), 0, DeviceInstance);
return ReturnValue;}
BOOL WINAPIDllMain( IN HINSTANCE hInstance, IN DWORD dwReason, IN LPVOID lpReserved){ if (dwReason == DLL_PROCESS_ATTACH) { INITCOMMONCONTROLSEX InitControls;
DisableThreadLibraryCalls(hInstance);
InitControls.dwSize = sizeof(INITCOMMONCONTROLSEX); InitControls.dwICC = ICC_PROGRESS_CLASS; InitCommonControlsEx(&InitControls); hDllInstance = hInstance; }
return TRUE;}