#include <stdarg.h>
-#include "windef.h"
-#include "winbase.h"
-#include "winnt.h"
-#include "winreg.h"
-#include "winternl.h"
-#include "wingdi.h"
-#include "winuser.h"
-#include "winnls.h"
+#include <windows.h>
#include "setupapi.h"
#include "wine/debug.h"
#include "wine/unicode.h"
#include "cfgmgr32.h"
#include "initguid.h"
-#include "winioctl.h"
-#include "rpc.h"
-#include "rpcdce.h"
+#define NTOS_MODE_USER
+#include <ndk/ntndk.h>
#include "setupapi_private.h"
{
LIST_ENTRY ListEntry;
+ HMODULE Module;
COINSTALLER_PROC Function;
BOOL DoPostProcessing;
PVOID PrivateData;
WCHAR SymbolicLink[0]; /* \\?\ACPI#PNP0501#4&2658d0a0&0#{GUID} */
};
+/* We don't want to open the .inf file to read only one information in it, so keep a handle to it once it
+ * has been already loaded once. Keep also a reference counter */
+struct InfFileDetails
+{
+ HINF hInf;
+ LONG References;
+};
+
struct DriverInfoElement /* Element of DeviceInfoSet.DriverListHead and DeviceInfoElement.DriverListHead */
{
LIST_ENTRY ListEntry;
DWORD DriverRank;
SP_DRVINFO_DATA_V2_W Info;
- LPWSTR InfPath;
- LPWSTR InfSection;
+ SP_DRVINFO_DETAIL_DATA_W Details;
+ GUID ClassGuid;
+ LPWSTR MatchingId;
+ struct InfFileDetails *InfFileDetails;
};
struct DeviceInfoElement /* Element of DeviceInfoSet.ListHead */
{
LIST_ENTRY ListEntry;
+ /* Reserved Field points to a struct DriverInfoElement */
+ SP_DEVINSTALL_PARAMS_W InstallParams;
+
/* Information about devnode:
* - DeviceName:
* "Root\*PNP0501" for example.
* the unique ID needs to be generated
* - DICD_INHERIT_CLASSDRVS
* inherit driver of the device info set (== same pointer)
- * - hwndParent
- * Used when doing device-specific actions. Can be NULL
*/
PCWSTR DeviceName;
PCWSTR UniqueId;
PCWSTR DeviceDescription;
GUID ClassGuid;
DWORD CreationFlags;
- HWND hwndParent;
-
- /* Flags is a combination of:
- * - DI_DIDCOMPAT
- * Set when the device driver list is created
- * FlagsEx is a combination of:
- */
- DWORD Flags;
- DWORD FlagsEx;
/* If CreationFlags contains DICD_INHERIT_CLASSDRVS, this list is invalid */
/* If the driver is not searched/detected, this list is empty */
LIST_ENTRY DriverListHead; /* List of struct DriverInfoElement */
- /* Points into DriverListHead list. The pointer is NULL if no driver is
- * currently chosen. */
- struct DriverInfoElement *SelectedDriver;
/* List of interfaces implemented by this device */
LIST_ENTRY InterfaceListHead; /* List of struct DeviceInterface */
{
DWORD magic; /* SETUP_DEV_INFO_SET_MAGIC */
GUID ClassGuid; /* If != GUID_NULL, only devices of this class can be in the device info set */
- HWND hwndParent; /* only used on non-device-specific actions, like as a select-device dialog using the global class driver list */
HKEY HKLM; /* Local or distant HKEY_LOCAL_MACHINE registry key */
- /* Flags is a combination of:
- * - DI_DIDCLASS
- * Set when the class driver list is created
- * - DI_COMPAT_FROM_CLASS (FIXME: not supported)
- * Forces SetupDiBuildDriverInfoList to build a class drivers list
- * FlagsEx is a combination of:
- */
- DWORD Flags;
- DWORD FlagsEx;
+ /* Reserved Field points to a struct DriverInfoElement */
+ SP_DEVINSTALL_PARAMS_W InstallParams;
/* If the driver is not searched/detected, this list is empty */
LIST_ENTRY DriverListHead; /* List of struct DriverInfoElement */
- /* Points into DriverListHead list. The pointer is NULL if no driver is
- * currently chosen. */
- struct DriverInfoElement *SelectedDriver;
LIST_ENTRY ListHead; /* List of struct DeviceInfoElement */
};
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return (HDEVINFO)INVALID_HANDLE_VALUE;
}
+ memset(list, 0, sizeof(struct DeviceInfoSet));
list->magic = SETUP_DEV_INFO_SET_MAGIC;
memcpy(
&list->ClassGuid,
ClassGuid ? ClassGuid : &GUID_NULL,
sizeof(list->ClassGuid));
- list->hwndParent = hwndParent;
+ list->InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
+ list->InstallParams.Flags |= DI_CLASSINSTALLPARAMS;
+ list->InstallParams.hwndParent = hwndParent;
if (MachineName)
{
rc = RegConnectRegistryW(MachineName, HKEY_LOCAL_MACHINE, &list->HKLM);
{
list->HKLM = HKEY_LOCAL_MACHINE;
}
- list->Flags = 0; /* FIXME */
- list->FlagsEx = 0; /* FIXME */
InitializeListHead(&list->DriverListHead);
InitializeListHead(&list->ListHead);
return (HDEVINFO)list;
static BOOL
CreateDeviceInfoElement(
IN LPCWSTR InstancePath,
- LPCGUID pClassGuid,
+ IN LPCGUID pClassGuid,
OUT struct DeviceInfoElement **pDeviceInfo)
{
+ DWORD size;
struct DeviceInfoElement *deviceInfo;
*pDeviceInfo = NULL;
- if (IsEqualIID(&pClassGuid, &GUID_NULL)) { FIXME("Bad argument!!!"); return FALSE; }/* FIXME: remove */
- deviceInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInfoElement) + (wcslen(InstancePath) + 1) * sizeof(WCHAR));
+ size = sizeof(struct DeviceInfoElement) + (wcslen(InstancePath) + 1) * sizeof(WCHAR);
+ deviceInfo = HeapAlloc(GetProcessHeap(), 0, size);
if (!deviceInfo)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
+ memset(deviceInfo, 0, size);
+ deviceInfo->InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
wcscpy(deviceInfo->Data, InstancePath);
deviceInfo->DeviceName = deviceInfo->Data;
deviceInfo->UniqueId = wcsrchr(deviceInfo->Data, '\\');
deviceInfo->DeviceDescription = NULL;
memcpy(&deviceInfo->ClassGuid, pClassGuid, sizeof(GUID));
deviceInfo->CreationFlags = 0;
- deviceInfo->hwndParent = NULL;
- deviceInfo->Flags = 0; /* FIXME */
- deviceInfo->FlagsEx = 0; /* FIXME */
- deviceInfo->SelectedDriver = NULL;
InitializeListHead(&deviceInfo->DriverListHead);
InitializeListHead(&deviceInfo->InterfaceListHead);
return ret;
}
+static VOID ReferenceInfFile(struct InfFileDetails* infFile)
+{
+ InterlockedIncrement(&infFile->References);
+}
+
+static VOID DereferenceInfFile(struct InfFileDetails* infFile)
+{
+ if (InterlockedDecrement(&infFile->References) == 0)
+ {
+ SetupCloseInfFile(infFile->hInf);
+ HeapFree(GetProcessHeap(), 0, infFile);
+ }
+}
+
+static BOOL DestroyDriverInfoElement(struct DriverInfoElement* driverInfo)
+{
+ DereferenceInfFile(driverInfo->InfFileDetails);
+ HeapFree(GetProcessHeap(), 0, driverInfo->MatchingId);
+ HeapFree(GetProcessHeap(), 0, driverInfo);
+ return TRUE;
+}
+
+static BOOL DestroyDeviceInfoElement(struct DeviceInfoElement* deviceInfo)
+{
+ PLIST_ENTRY ListEntry;
+ struct DriverInfoElement *driverInfo;
+
+ while (!IsListEmpty(&deviceInfo->DriverListHead))
+ {
+ ListEntry = RemoveHeadList(&deviceInfo->DriverListHead);
+ driverInfo = (struct DriverInfoElement *)ListEntry;
+ if (!DestroyDriverInfoElement(driverInfo))
+ return FALSE;
+ }
+ while (!IsListEmpty(&deviceInfo->InterfaceListHead))
+ {
+ ListEntry = RemoveHeadList(&deviceInfo->InterfaceListHead);
+ HeapFree(GetProcessHeap(), 0, ListEntry);
+ }
+ HeapFree(GetProcessHeap(), 0, deviceInfo);
+ return TRUE;
+}
+
+static BOOL DestroyDeviceInfoSet(struct DeviceInfoSet* list)
+{
+ PLIST_ENTRY ListEntry;
+ struct DeviceInfoElement *deviceInfo;
+
+ while (!IsListEmpty(&list->ListHead))
+ {
+ ListEntry = RemoveHeadList(&list->ListHead);
+ deviceInfo = (struct DeviceInfoElement *)ListEntry;
+ if (!DestroyDeviceInfoElement(deviceInfo))
+ return FALSE;
+ }
+ if (list->HKLM != HKEY_LOCAL_MACHINE)
+ RegCloseKey(list->HKLM);
+ HeapFree(GetProcessHeap(), 0, list);
+ return TRUE;
+}
+
/***********************************************************************
* SetupDiDestroyDeviceInfoList (SETUPAPI.@)
*/
struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo;
if (list->magic == SETUP_DEV_INFO_SET_MAGIC)
- {
- PLIST_ENTRY ListEntry, InterfaceEntry;
- struct DeviceInfoElement *deviceInfo;
- while (!IsListEmpty(&list->ListHead))
- {
- ListEntry = RemoveHeadList(&list->ListHead);
- deviceInfo = (struct DeviceInfoElement *)ListEntry;
- while (!IsListEmpty(&deviceInfo->InterfaceListHead))
- {
- InterfaceEntry = RemoveHeadList(&deviceInfo->InterfaceListHead);
- HeapFree(GetProcessHeap(), 0, InterfaceEntry);
- }
- HeapFree(GetProcessHeap(), 0, ListEntry);
- }
- if (list->HKLM != HKEY_LOCAL_MACHINE)
- RegCloseKey(list->HKLM);
- HeapFree(GetProcessHeap(), 0, list);
- ret = TRUE;
- }
+ ret = DestroyDeviceInfoSet(list);
else
SetLastError(ERROR_INVALID_HANDLE);
}
DWORD PropertyBufferSizeW;
PBYTE PropertyBufferW;
- TRACE("%04lx %p %ld %p %p %ld %p\n", (DWORD)devinfo, DeviceInfoData,
+ TRACE("%p %p %ld %p %p %ld %p\n", devinfo, DeviceInfoData,
Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
RequiredSize);
PropertyBufferSizeW,
&RequiredSizeW);
+ if (bResult || GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+ {
+ bIsStringProperty = (RegType == REG_SZ || RegType == REG_MULTI_SZ || RegType == REG_EXPAND_SZ);
+
+ if (bIsStringProperty)
+ RequiredSizeA = RequiredSizeW / sizeof(WCHAR);
+ else
+ RequiredSizeA = RequiredSizeW;
+ if (RequiredSize)
+ *RequiredSize = RequiredSizeA;
+ if (PropertyRegDataType)
+ *PropertyRegDataType = RegType;
+ }
+
if (!bResult)
{
HeapFree(GetProcessHeap(), 0, PropertyBufferW);
return bResult;
}
- bIsStringProperty = (RegType == REG_SZ || RegType == REG_MULTI_SZ || RegType == REG_EXPAND_SZ);
-
- if (bIsStringProperty)
- RequiredSizeA = RequiredSizeW / sizeof(WCHAR);
- else
- RequiredSizeA = RequiredSizeW;
-
if (RequiredSizeA <= PropertyBufferSize)
{
if (bIsStringProperty && PropertyBufferSize > 0)
}
HeapFree(GetProcessHeap(), 0, PropertyBufferW);
- if (PropertyRegDataType)
- *PropertyRegDataType = RegType;
- if (RequiredSize)
- *RequiredSize = RequiredSizeA;
return bResult;
}
case SPDRP_SECURITY:
case SPDRP_SERVICE:
case SPDRP_UI_NUMBER:
+ case SPDRP_UI_NUMBER_DESC_FORMAT:
case SPDRP_UPPERFILTERS:
{
LPCWSTR RegistryPropertyName;
RegistryPropertyName = L"Service"; break;
case SPDRP_UI_NUMBER:
RegistryPropertyName = L"UINumber"; break;
+ case SPDRP_UI_NUMBER_DESC_FORMAT:
+ RegistryPropertyName = L"UINumberDescFormat"; break;
case SPDRP_UPPERFILTERS:
RegistryPropertyName = L"UpperFilters"; break;
default:
&BufferSize);
if (RequiredSize)
*RequiredSize = BufferSize;
- if (rc == ERROR_SUCCESS)
- ret = TRUE;
- else
- SetLastError(rc);
+ switch(rc) {
+ case ERROR_SUCCESS:
+ if (PropertyBuffer != NULL || BufferSize == 0)
+ ret = TRUE;
+ else
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ break;
+ case ERROR_MORE_DATA:
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ break;
+ default:
+ SetLastError(rc);
+ }
RegCloseKey(hKey);
break;
}
case SPDRP_EXCLUSIVE:
case SPDRP_CHARACTERISTICS:
case SPDRP_ADDRESS:
- case SPDRP_UI_NUMBER_DESC_FORMAT:
case SPDRP_DEVICE_POWER_DATA:*/
#if (WINVER >= 0x501)
/*case SPDRP_REMOVAL_POLICY:
return ret;
}
+/***********************************************************************
+ * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiSetDeviceRegistryPropertyA(
+ IN HDEVINFO DeviceInfoSet,
+ IN OUT PSP_DEVINFO_DATA DeviceInfoData,
+ IN DWORD Property,
+ IN CONST BYTE *PropertyBuffer,
+ IN DWORD PropertyBufferSize)
+{
+ FIXME("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet, DeviceInfoData,
+ Property, PropertyBuffer, PropertyBufferSize);
+ SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ return FALSE;
+}
+
+/***********************************************************************
+ * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiSetDeviceRegistryPropertyW(
+ IN HDEVINFO DeviceInfoSet,
+ IN OUT PSP_DEVINFO_DATA DeviceInfoData,
+ IN DWORD Property,
+ IN const BYTE *PropertyBuffer,
+ IN DWORD PropertyBufferSize)
+{
+ struct DeviceInfoSet *list;
+ BOOL ret = FALSE;
+
+ TRACE("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet, DeviceInfoData,
+ Property, PropertyBuffer, PropertyBufferSize);
+
+ if (!DeviceInfoSet)
+ SetLastError(ERROR_INVALID_HANDLE);
+ else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
+ SetLastError(ERROR_INVALID_HANDLE);
+ else if (DeviceInfoData)
+ SetLastError(ERROR_INVALID_HANDLE);
+ else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
+ SetLastError(ERROR_INVALID_USER_BUFFER);
+ else
+ {
+ switch (Property)
+ {
+ case SPDRP_COMPATIBLEIDS:
+ case SPDRP_CONFIGFLAGS:
+ case SPDRP_FRIENDLYNAME:
+ case SPDRP_HARDWAREID:
+ case SPDRP_LOCATION_INFORMATION:
+ case SPDRP_LOWERFILTERS:
+ case SPDRP_SECURITY:
+ case SPDRP_SERVICE:
+ case SPDRP_UI_NUMBER_DESC_FORMAT:
+ case SPDRP_UPPERFILTERS:
+ {
+ LPCWSTR RegistryPropertyName;
+ DWORD RegistryDataType;
+ HKEY hKey;
+ LONG rc;
+
+ switch (Property)
+ {
+ case SPDRP_COMPATIBLEIDS:
+ RegistryPropertyName = L"CompatibleIDs";
+ RegistryDataType = REG_MULTI_SZ;
+ break;
+ case SPDRP_CONFIGFLAGS:
+ RegistryPropertyName = L"ConfigFlags";
+ RegistryDataType = REG_DWORD;
+ break;
+ case SPDRP_FRIENDLYNAME:
+ RegistryPropertyName = L"FriendlyName";
+ RegistryDataType = REG_SZ;
+ break;
+ case SPDRP_HARDWAREID:
+ RegistryPropertyName = L"HardwareID";
+ RegistryDataType = REG_MULTI_SZ;
+ break;
+ case SPDRP_LOCATION_INFORMATION:
+ RegistryPropertyName = L"LocationInformation";
+ RegistryDataType = REG_SZ;
+ break;
+ case SPDRP_LOWERFILTERS:
+ RegistryPropertyName = L"LowerFilters";
+ RegistryDataType = REG_MULTI_SZ;
+ break;
+ case SPDRP_SECURITY:
+ RegistryPropertyName = L"Security";
+ RegistryDataType = REG_BINARY;
+ break;
+ case SPDRP_SERVICE:
+ RegistryPropertyName = L"Service";
+ RegistryDataType = REG_SZ;
+ break;
+ case SPDRP_UI_NUMBER_DESC_FORMAT:
+ RegistryPropertyName = L"UINumberDescFormat";
+ RegistryDataType = REG_SZ;
+ break;
+ case SPDRP_UPPERFILTERS:
+ RegistryPropertyName = L"UpperFilters";
+ RegistryDataType = REG_MULTI_SZ;
+ break;
+ default:
+ /* Should not happen */
+ RegistryPropertyName = NULL;
+ RegistryDataType = REG_BINARY;
+ break;
+ }
+ /* Open device registry key */
+ hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_SET_VALUE);
+ if (hKey != INVALID_HANDLE_VALUE)
+ {
+ /* Write new data */
+ rc = RegSetValueExW(
+ hKey,
+ RegistryPropertyName,
+ 0, /* Reserved */
+ RegistryDataType,
+ PropertyBuffer,
+ PropertyBufferSize);
+ if (rc == ERROR_SUCCESS)
+ ret = TRUE;
+ else
+ SetLastError(rc);
+ RegCloseKey(hKey);
+ }
+ break;
+ }
+
+ /*case SPDRP_CHARACTERISTICS:
+ case SPDRP_DEVTYPE:
+ case SPDRP_EXCLUSIVE:*/
+#if (WINVER >= 0x501)
+ //case SPDRP_REMOVAL_POLICY_OVERRIDE:
+#endif
+ //case SPDRP_SECURITY_SDS:
+
+ default:
+ {
+ FIXME("Property 0x%lx not implemented\n", Property);
+ SetLastError(ERROR_NOT_SUPPORTED);
+ }
+ }
+ }
+
+ TRACE("Returning %d\n", ret);
+ return ret;
+}
/***********************************************************************
* SetupDiInstallClassA (SETUPAPI.@)
DWORD OpenFlags,
PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
{
- FIXME("%p %s %08lx %p\n", DeviceInfoSet,
- debugstr_a(DevicePath), OpenFlags, DeviceInterfaceData);
- return FALSE;
+ LPWSTR DevicePathW = NULL;
+ BOOL bResult;
+
+ TRACE("%p %s %08lx %p\n", DeviceInfoSet, debugstr_a(DevicePath), OpenFlags, DeviceInterfaceData);
+
+ DevicePathW = MultiByteToUnicode(DevicePath, CP_ACP);
+ if (DevicePathW == NULL)
+ return FALSE;
+
+ bResult = SetupDiOpenDeviceInterfaceW(DeviceInfoSet,
+ DevicePathW, OpenFlags, DeviceInterfaceData);
+
+ MyFree(DevicePathW);
+
+ return bResult;
}
/***********************************************************************
return FALSE;
}
+static DWORD
+GetFunctionPointer(
+ IN PWSTR InstallerName,
+ OUT HMODULE* ModulePointer,
+ OUT PVOID* FunctionPointer)
+{
+ HMODULE hModule = NULL;
+ LPSTR FunctionNameA = NULL;
+ PWCHAR Comma;
+ DWORD rc;
+
+ *ModulePointer = NULL;
+ *FunctionPointer = NULL;
+
+ Comma = strchrW(InstallerName, ',');
+ if (!Comma)
+ {
+ rc = ERROR_INVALID_PARAMETER;
+ goto cleanup;
+ }
+
+ /* Load library */
+ *Comma = '\0';
+ hModule = LoadLibraryW(InstallerName);
+ *Comma = ',';
+ if (!hModule)
+ {
+ rc = GetLastError();
+ goto cleanup;
+ }
+
+ /* Skip comma spaces */
+ while (*Comma == ',' || isspaceW(*Comma))
+ Comma++;
+
+ /* W->A conversion for function name */
+ FunctionNameA = UnicodeToMultiByte(Comma, CP_ACP);
+ if (!FunctionNameA)
+ {
+ rc = GetLastError();
+ goto cleanup;
+ }
+
+ /* Search function */
+ *FunctionPointer = GetProcAddress(hModule, FunctionNameA);
+ if (!*FunctionPointer)
+ {
+ rc = GetLastError();
+ goto cleanup;
+ }
+
+ *ModulePointer = hModule;
+ rc = ERROR_SUCCESS;
+
+cleanup:
+ if (rc != ERROR_SUCCESS && hModule)
+ FreeLibrary(hModule);
+ MyFree(FunctionNameA);
+ return rc;
+}
+
+static DWORD
+FreeFunctionPointer(
+ IN HMODULE ModulePointer,
+ IN PVOID FunctionPointer)
+{
+ if (ModulePointer == NULL)
+ return ERROR_SUCCESS;
+ if (FreeLibrary(ModulePointer))
+ return ERROR_SUCCESS;
+ else
+ return GetLastError();
+}
+
/***********************************************************************
* SetupDiCallClassInstaller (SETUPAPI.@)
*/
SetLastError(ERROR_INVALID_USER_BUFFER);
else
{
+ SP_DEVINSTALL_PARAMS_W InstallParams;
#define CLASS_COINSTALLER 0x1
#define DEVICE_COINSTALLER 0x2
#define CLASS_INSTALLER 0x4
SetLastError(ERROR_INVALID_PARAMETER);
}
+ InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
+ if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams))
+ /* Don't process this call, as a parameter is invalid */
+ CanHandle = 0;
+
if (CanHandle != 0)
{
LIST_ENTRY ClassCoInstallersListHead;
LIST_ENTRY DeviceCoInstallersListHead;
+ HMODULE ClassInstallerLibrary = NULL;
CLASS_INSTALL_PROC ClassInstaller = NULL;
COINSTALLER_CONTEXT_DATA Context;
PLIST_ENTRY ListEntry;
InitializeListHead(&ClassCoInstallersListHead);
InitializeListHead(&DeviceCoInstallersListHead);
- if (CanHandle & CLASS_COINSTALLER)
+ if (CanHandle & DEVICE_COINSTALLER)
{
- FIXME("Doesn't use Class co-installers at the moment\n");
+ hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_QUERY_VALUE);
+ if (hKey != INVALID_HANDLE_VALUE)
+ {
+ rc = RegQueryValueExW(hKey, L"CoInstallers32", NULL, &dwRegType, NULL, &dwLength);
+ if (rc == ERROR_SUCCESS && dwRegType == REG_MULTI_SZ)
+ {
+ LPWSTR KeyBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength);
+ if (KeyBuffer != NULL)
+ {
+ rc = RegQueryValueExW(hKey, L"CoInstallers32", NULL, NULL, (LPBYTE)KeyBuffer, &dwLength);
+ if (rc == ERROR_SUCCESS)
+ {
+ LPWSTR ptr;
+ for (ptr = KeyBuffer; *ptr; ptr += strlenW(ptr) + 1)
+ {
+ /* Add coinstaller to DeviceCoInstallersListHead list */
+ struct CoInstallerElement *coinstaller;
+ TRACE("Got device coinstaller '%s'\n", debugstr_w(ptr));
+ coinstaller = HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement));
+ if (!coinstaller)
+ continue;
+ memset(coinstaller, 0, sizeof(struct CoInstallerElement));
+ if (GetFunctionPointer(ptr, &coinstaller->Module, (PVOID*)&coinstaller->Function) == ERROR_SUCCESS)
+ InsertTailList(&DeviceCoInstallersListHead, &coinstaller->ListEntry);
+ else
+ HeapFree(GetProcessHeap(), 0, coinstaller);
+ }
+ }
+ HeapFree(GetProcessHeap(), 0, KeyBuffer);
+ }
+ }
+ RegCloseKey(hKey);
+ }
}
- if (CanHandle & DEVICE_COINSTALLER)
+ if (CanHandle & CLASS_COINSTALLER)
{
rc = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
LPWSTR lpGuidString;
if (UuidToStringW((UUID*)&DeviceInfoData->ClassGuid, &lpGuidString) == RPC_S_OK)
{
- rc = RegQueryValueExW(hKey, L"Installer32", NULL, &dwRegType, NULL, &dwLength);
- if (rc == ERROR_SUCCESS && dwRegType == REG_SZ)
+ rc = RegQueryValueExW(hKey, lpGuidString, NULL, &dwRegType, NULL, &dwLength);
+ if (rc == ERROR_SUCCESS && dwRegType == REG_MULTI_SZ)
{
LPWSTR KeyBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength);
if (KeyBuffer != NULL)
{
- rc = RegQueryValueExW(hKey, L"Installer32", NULL, NULL, (LPBYTE)KeyBuffer, &dwLength);
+ rc = RegQueryValueExW(hKey, lpGuidString, NULL, NULL, (LPBYTE)KeyBuffer, &dwLength);
if (rc == ERROR_SUCCESS)
{
- LPCWSTR ptr;
+ LPWSTR ptr;
for (ptr = KeyBuffer; *ptr; ptr += strlenW(ptr) + 1)
{
- /* Add coinstaller to DeviceCoInstallersListHead list */
- FIXME("Device coinstaller is '%S'\n", ptr);
+ /* Add coinstaller to ClassCoInstallersListHead list */
+ struct CoInstallerElement *coinstaller;
+ TRACE("Got class coinstaller '%s'\n", debugstr_w(ptr));
+ coinstaller = HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement));
+ if (!coinstaller)
+ continue;
+ memset(coinstaller, 0, sizeof(struct CoInstallerElement));
+ if (GetFunctionPointer(ptr, &coinstaller->Module, (PVOID*)&coinstaller->Function) == ERROR_SUCCESS)
+ InsertTailList(&ClassCoInstallersListHead, &coinstaller->ListEntry);
+ else
+ HeapFree(GetProcessHeap(), 0, coinstaller);
}
}
HeapFree(GetProcessHeap(), 0, KeyBuffer);
RegCloseKey(hKey);
}
}
- if (CanHandle & CLASS_INSTALLER)
+ if ((CanHandle & CLASS_INSTALLER) && !(InstallParams.FlagsEx & DI_FLAGSEX_CI_FAILED))
{
hKey = SetupDiOpenClassRegKey(&DeviceInfoData->ClassGuid, KEY_QUERY_VALUE);
if (hKey != INVALID_HANDLE_VALUE)
rc = RegQueryValueExW(hKey, L"Installer32", NULL, NULL, (LPBYTE)KeyBuffer, &dwLength);
if (rc == ERROR_SUCCESS)
{
- /* Set ClassInstaller function pointer */
- FIXME("Installer is '%S'\n", KeyBuffer);
+ /* Get ClassInstaller function pointer */
+ TRACE("Got class installer '%s'\n", debugstr_w(KeyBuffer));
+ if (GetFunctionPointer(KeyBuffer, &ClassInstallerLibrary, (PVOID*)&ClassInstaller) != ERROR_SUCCESS)
+ {
+ InstallParams.FlagsEx |= DI_FLAGSEX_CI_FAILED;
+ SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
+ }
}
HeapFree(GetProcessHeap(), 0, KeyBuffer);
}
/* Call Class installer */
if (ClassInstaller)
+ {
rc = (*ClassInstaller)(InstallFunction, DeviceInfoSet, DeviceInfoData);
+ FreeFunctionPointer(ClassInstallerLibrary, ClassInstaller);
+ }
else
rc = ERROR_DI_DO_DEFAULT;
/* Call default handler */
if (rc == ERROR_DI_DO_DEFAULT)
{
- if (DefaultHandler /*FIXME && DI_NODI_DEFAULTACTION not set */)
+ if (DefaultHandler && !(InstallParams.Flags & DI_NODI_DEFAULTACTION))
{
if ((*DefaultHandler)(DeviceInfoSet, DeviceInfoData))
rc = NO_ERROR;
Context.PrivateData = coinstaller->PrivateData;
rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context);
}
+ FreeFunctionPointer(coinstaller->Module, coinstaller->Function);
ListEntry = ListEntry->Flink;
}
Context.PrivateData = coinstaller->PrivateData;
rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context);
}
+ FreeFunctionPointer(coinstaller->Module, coinstaller->Function);
ListEntry = ListEntry->Flink;
}
IN PSP_DEVINFO_DATA DeviceInfoData,
OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams)
{
- FIXME("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
- return FALSE;
-}
+ struct DeviceInfoSet *list;
+ BOOL ret = FALSE;
-/***********************************************************************
- * SetupDiOpenDevRegKey (SETUPAPI.@)
- */
-HKEY WINAPI SetupDiOpenDevRegKey(
- HDEVINFO DeviceInfoSet,
- PSP_DEVINFO_DATA DeviceInfoData,
- DWORD Scope,
- DWORD HwProfile,
- DWORD KeyType,
- REGSAM samDesired)
-{
- FIXME("%p %p %ld %ld %ld %lx\n", DeviceInfoSet, DeviceInfoData,
- Scope, HwProfile, KeyType, samDesired);
- return INVALID_HANDLE_VALUE;
+ TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
+
+ if (!DeviceInfoSet)
+ SetLastError(ERROR_INVALID_HANDLE);
+ else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
+ SetLastError(ERROR_INVALID_HANDLE);
+ else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
+ SetLastError(ERROR_INVALID_USER_BUFFER);
+ else if (!DeviceInstallParams)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else if (DeviceInstallParams->cbSize != sizeof(SP_DEVINSTALL_PARAMS_W))
+ SetLastError(ERROR_INVALID_USER_BUFFER);
+ else
+ {
+ PSP_DEVINSTALL_PARAMS_W Source;
+
+ if (DeviceInfoData)
+ Source = &((struct DeviceInfoElement *)DeviceInfoData->Reserved)->InstallParams;
+ else
+ Source = &list->InstallParams;
+ memcpy(DeviceInstallParams, Source, Source->cbSize);
+ ret = TRUE;
+ }
+
+ TRACE("Returning %d\n", ret);
+ return ret;
}
/***********************************************************************
- * SetupDiCreateDeviceInfoA (SETUPAPI.@)
+ * SetupDiSetDeviceInstallParamsW (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiSetDeviceInstallParamsW(
+ IN HDEVINFO DeviceInfoSet,
+ IN PSP_DEVINFO_DATA DeviceInfoData,
+ IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams)
+{
+ struct DeviceInfoSet *list;
+ BOOL ret = FALSE;
+
+ TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
+
+ if (!DeviceInfoSet)
+ SetLastError(ERROR_INVALID_HANDLE);
+ else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
+ SetLastError(ERROR_INVALID_HANDLE);
+ else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
+ SetLastError(ERROR_INVALID_USER_BUFFER);
+ else if (!DeviceInstallParams)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else if (DeviceInstallParams->cbSize != sizeof(SP_DEVINSTALL_PARAMS_W))
+ SetLastError(ERROR_INVALID_USER_BUFFER);
+ else
+ {
+ PSP_DEVINSTALL_PARAMS_W Destination;
+
+ /* FIXME: Validate parameters */
+
+ if (DeviceInfoData)
+ Destination = &((struct DeviceInfoElement *)DeviceInfoData->Reserved)->InstallParams;
+ else
+ Destination = &list->InstallParams;
+ memcpy(Destination, DeviceInstallParams, DeviceInstallParams->cbSize);
+ ret = TRUE;
+ }
+
+ TRACE("Returning %d\n", ret);
+ return ret;
+}
+
+/***********************************************************************
+ * SetupDiCreateDevRegKey (SETUPAPI.@)
+ */
+HKEY WINAPI SetupDiCreateDevRegKeyW(
+ IN HDEVINFO DeviceInfoSet,
+ IN PSP_DEVINFO_DATA DeviceInfoData,
+ IN DWORD Scope,
+ IN DWORD HwProfile,
+ IN DWORD KeyType,
+ IN HINF InfHandle OPTIONAL,
+ IN PCWSTR InfSectionName OPTIONAL)
+{
+ struct DeviceInfoSet *list;
+ HKEY ret = INVALID_HANDLE_VALUE;
+
+ TRACE("%p %p %lu %lu %lu %p %s\n", DeviceInfoSet, DeviceInfoData,
+ Scope, HwProfile, KeyType, InfHandle, debugstr_w(InfSectionName));
+
+ if (!DeviceInfoSet)
+ SetLastError(ERROR_INVALID_HANDLE);
+ else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
+ SetLastError(ERROR_INVALID_HANDLE);
+ else if (!DeviceInfoData)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
+ SetLastError(ERROR_INVALID_USER_BUFFER);
+ else if (Scope != DICS_FLAG_GLOBAL && Scope != DICS_FLAG_CONFIGSPECIFIC)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else if (KeyType != DIREG_DEV && KeyType != DIREG_DRV)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else if (InfHandle && !InfSectionName)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else if (!InfHandle && InfSectionName)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else
+ {
+ LPWSTR lpGuidString = NULL;
+ LPWSTR DriverKey = NULL; /* {GUID}\Index */
+ LPWSTR pDeviceInstance; /* Points into DriverKey, on the Index field */
+ DWORD Index; /* Index used in the DriverKey name */
+ DWORD rc;
+ HKEY hClassKey = INVALID_HANDLE_VALUE;
+ HKEY hDeviceKey = INVALID_HANDLE_VALUE;
+ HKEY hKey = INVALID_HANDLE_VALUE;
+
+ if (Scope == DICS_FLAG_CONFIGSPECIFIC)
+ {
+ FIXME("DICS_FLAG_CONFIGSPECIFIC case unimplemented\n");
+ goto cleanup;
+ }
+
+ if (KeyType == DIREG_DEV)
+ {
+ FIXME("DIREG_DEV case unimplemented\n");
+ }
+ else /* KeyType == DIREG_DRV */
+ {
+ if (UuidToStringW((UUID*)&DeviceInfoData->ClassGuid, &lpGuidString) != RPC_S_OK)
+ goto cleanup;
+ /* The driver key is in HKLM\System\CurrentControlSet\Control\Class\{GUID}\Index */
+ DriverKey = HeapAlloc(GetProcessHeap(), 0, (wcslen(lpGuidString) + 7) * sizeof(WCHAR) + sizeof(UNICODE_STRING));
+ if (!DriverKey)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto cleanup;
+ }
+ wcscpy(DriverKey, L"{");
+ wcscat(DriverKey, lpGuidString);
+ wcscat(DriverKey, L"}\\");
+ pDeviceInstance = &DriverKey[wcslen(DriverKey)];
+ rc = RegOpenKeyExW(list->HKLM,
+ ControlClass,
+ 0,
+ KEY_CREATE_SUB_KEY,
+ &hClassKey);
+ if (rc != ERROR_SUCCESS)
+ {
+ SetLastError(rc);
+ goto cleanup;
+ }
+
+ /* Try all values for Index between 0 and 9999 */
+ Index = 0;
+ while (Index <= 9999)
+ {
+ DWORD Disposition;
+ wsprintf(pDeviceInstance, L"%04lu", Index);
+ rc = RegCreateKeyEx(hClassKey,
+ DriverKey,
+ 0,
+ NULL,
+ REG_OPTION_NON_VOLATILE,
+#if _WIN32_WINNT >= 0x502
+ KEY_READ | KEY_WRITE,
+#else
+ KEY_ALL_ACCESS,
+#endif
+ NULL,
+ &hKey,
+ &Disposition);
+ if (rc != ERROR_SUCCESS)
+ {
+ SetLastError(rc);
+ goto cleanup;
+ }
+ if (Disposition == REG_CREATED_NEW_KEY)
+ break;
+ RegCloseKey(hKey);
+ hKey = INVALID_HANDLE_VALUE;
+ Index++;
+ }
+ if (Index > 9999)
+ {
+ /* Unable to create more than 9999 devices within the same class */
+ SetLastError(ERROR_GEN_FAILURE);
+ goto cleanup;
+ }
+
+ /* Open device key, to write Driver value */
+ hDeviceKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, Scope, HwProfile, DIREG_DEV, KEY_SET_VALUE);
+ if (hDeviceKey == INVALID_HANDLE_VALUE)
+ goto cleanup;
+ rc = RegSetValueEx(hDeviceKey, L"Driver", 0, REG_SZ, (const BYTE *)DriverKey, (wcslen(DriverKey) + 1) * sizeof(WCHAR));
+ if (rc != ERROR_SUCCESS)
+ {
+ SetLastError(rc);
+ goto cleanup;
+ }
+ }
+
+ /* Do installation of the specified section */
+ if (InfHandle)
+ {
+ FIXME("Need to install section %s in file %p\n",
+ debugstr_w(InfSectionName), InfHandle);
+ }
+ ret = hKey;
+
+cleanup:
+ if (lpGuidString)
+ RpcStringFreeW(&lpGuidString);
+ HeapFree(GetProcessHeap(), 0, DriverKey);
+ if (hClassKey != INVALID_HANDLE_VALUE)
+ RegCloseKey(hClassKey);
+ if (hDeviceKey != INVALID_HANDLE_VALUE)
+ RegCloseKey(hDeviceKey);
+ if (hKey != INVALID_HANDLE_VALUE && hKey != ret)
+ RegCloseKey(hKey);
+ }
+
+ TRACE("Returning 0x%p\n", ret);
+ return ret;
+}
+
+/***********************************************************************
+ * SetupDiOpenDevRegKey (SETUPAPI.@)
+ */
+HKEY WINAPI SetupDiOpenDevRegKey(
+ HDEVINFO DeviceInfoSet,
+ PSP_DEVINFO_DATA DeviceInfoData,
+ DWORD Scope,
+ DWORD HwProfile,
+ DWORD KeyType,
+ REGSAM samDesired)
+{
+ struct DeviceInfoSet *list;
+ HKEY ret = INVALID_HANDLE_VALUE;
+
+ TRACE("%p %p %lu %lu %lu 0x%lx\n", DeviceInfoSet, DeviceInfoData,
+ Scope, HwProfile, KeyType, samDesired);
+
+ if (!DeviceInfoSet)
+ SetLastError(ERROR_INVALID_HANDLE);
+ else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
+ SetLastError(ERROR_INVALID_HANDLE);
+ else if (!DeviceInfoData)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
+ SetLastError(ERROR_INVALID_USER_BUFFER);
+ else if (Scope != DICS_FLAG_GLOBAL && Scope != DICS_FLAG_CONFIGSPECIFIC)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else if (KeyType != DIREG_DEV && KeyType != DIREG_DRV)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else
+ {
+ HKEY hKey = INVALID_HANDLE_VALUE;
+ HKEY hRootKey = INVALID_HANDLE_VALUE;
+ struct DeviceInfoElement *deviceInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
+ LPWSTR DriverKey = NULL;
+ DWORD dwLength = 0;
+ DWORD dwRegType;
+ DWORD rc;
+
+ if (Scope == DICS_FLAG_CONFIGSPECIFIC)
+ {
+ FIXME("DICS_FLAG_CONFIGSPECIFIC case unimplemented\n");
+ }
+ else /* Scope == DICS_FLAG_GLOBAL */
+ {
+ rc = RegOpenKeyExW(
+ list->HKLM,
+ EnumKeyName,
+ 0, /* Options */
+ KEY_ENUMERATE_SUB_KEYS,
+ &hRootKey);
+ if (rc != ERROR_SUCCESS)
+ {
+ SetLastError(rc);
+ goto cleanup;
+ }
+ rc = RegOpenKeyExW(
+ hRootKey,
+ deviceInfo->DeviceName,
+ 0, /* Options */
+ KeyType == DIREG_DEV ? samDesired : KEY_QUERY_VALUE,
+ &hKey);
+ RegCloseKey(hRootKey);
+ hRootKey = INVALID_HANDLE_VALUE;
+ if (rc != ERROR_SUCCESS)
+ {
+ SetLastError(rc);
+ goto cleanup;
+ }
+ if (KeyType == DIREG_DEV)
+ {
+ /* We're done. Just return the hKey handle */
+ ret = hKey;
+ goto cleanup;
+ }
+ /* Read the 'Driver' key */
+ rc = RegQueryValueExW(hKey, L"Driver", NULL, &dwRegType, NULL, &dwLength);
+ if (rc != ERROR_SUCCESS)
+ {
+ SetLastError(rc);
+ goto cleanup;
+ }
+ if (dwRegType != REG_SZ)
+ {
+ SetLastError(ERROR_GEN_FAILURE);
+ goto cleanup;
+ }
+ DriverKey = HeapAlloc(GetProcessHeap(), 0, dwLength);
+ if (!DriverKey)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto cleanup;
+ }
+ rc = RegQueryValueExW(hKey, L"Driver", NULL, &dwRegType, (LPBYTE)DriverKey, &dwLength);
+ if (rc != ERROR_SUCCESS)
+ {
+ SetLastError(rc);
+ goto cleanup;
+ }
+ RegCloseKey(hKey);
+ hKey = INVALID_HANDLE_VALUE;
+ /* Need to open the driver key */
+ rc = RegOpenKeyExW(
+ list->HKLM,
+ ControlClass,
+ 0, /* Options */
+ KEY_ENUMERATE_SUB_KEYS,
+ &hRootKey);
+ if (rc != ERROR_SUCCESS)
+ {
+ SetLastError(rc);
+ goto cleanup;
+ }
+ rc = RegOpenKeyExW(
+ hRootKey,
+ DriverKey,
+ 0, /* Options */
+ samDesired,
+ &hKey);
+ if (rc != ERROR_SUCCESS)
+ {
+ SetLastError(rc);
+ goto cleanup;
+ }
+ ret = hKey;
+ }
+cleanup:
+ if (hRootKey != INVALID_HANDLE_VALUE)
+ RegCloseKey(hRootKey);
+ if (hKey != INVALID_HANDLE_VALUE && hKey != ret)
+ RegCloseKey(hKey);
+ }
+
+ TRACE("Returning 0x%p\n", ret);
+ return ret;
+}
+
+/***********************************************************************
+ * SetupDiCreateDeviceInfoA (SETUPAPI.@)
*/
BOOL WINAPI SetupDiCreateDeviceInfoA(
HDEVINFO DeviceInfoSet,
AddDriverToList(
IN PLIST_ENTRY DriverListHead,
IN DWORD DriverType, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */
+ IN LPGUID ClassGuid,
IN INFCONTEXT ContextDevice,
+ IN struct InfFileDetails *InfFileDetails,
IN LPCWSTR InfFile,
IN LPCWSTR ProviderName,
IN LPCWSTR ManufacturerName,
+ IN LPCWSTR MatchingId,
FILETIME DriverDate,
DWORDLONG DriverVersion,
IN DWORD Rank)
{
- struct DriverInfoElement *driverInfo;
+ struct DriverInfoElement *driverInfo = NULL;
+ HANDLE hFile = INVALID_HANDLE_VALUE;
DWORD RequiredSize = 128; /* Initial buffer size */
BOOL Result = FALSE;
PLIST_ENTRY PreviousEntry;
- LPWSTR DeviceDescription = NULL;
LPWSTR InfInstallSection = NULL;
+ BOOL ret = FALSE;
driverInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(struct DriverInfoElement));
if (!driverInfo)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- return FALSE;
- }
-
- SetLastError(ERROR_INSUFFICIENT_BUFFER);
- driverInfo->InfSection = NULL;
- while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
- {
- HeapFree(GetProcessHeap(), 0, driverInfo->InfSection);
- driverInfo->InfSection = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
- if (!driverInfo->InfSection)
- {
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- HeapFree(GetProcessHeap(), 0, driverInfo);
- return FALSE;
- }
- Result = SetupGetStringFieldW(
- &ContextDevice,
- 1,
- driverInfo->InfSection, RequiredSize,
- &RequiredSize);
+ goto cleanup;
}
+ memset(driverInfo, 0, sizeof(struct DriverInfoElement));
+
+ driverInfo->Details.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
+ driverInfo->Details.Reserved = (ULONG_PTR)driverInfo;
+
+ /* Copy InfFileName field */
+ wcsncpy(driverInfo->Details.InfFileName, InfFile, MAX_PATH - 1);
+ driverInfo->Details.InfFileName[MAX_PATH - 1] = '\0';
+
+ /* Fill InfDate field */
+ /* FIXME: hFile = CreateFile(driverInfo->Details.InfFileName,
+ GENERIC_READ, FILE_SHARE_READ,
+ NULL, OPEN_EXISTING, 0, NULL);
+ if (hFile == INVALID_HANDLE_VALUE)
+ goto cleanup;
+ Result = GetFileTime(hFile, NULL, NULL, &driverInfo->Details.InfDate);
if (!Result)
- {
- HeapFree(GetProcessHeap(), 0, driverInfo->InfSection);
- HeapFree(GetProcessHeap(), 0, driverInfo);
- return FALSE;
- }
-
- driverInfo->InfPath = HeapAlloc(GetProcessHeap(), 0, (wcslen(InfFile) + 1) * sizeof(WCHAR));
- if (!driverInfo->InfPath)
- {
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- HeapFree(GetProcessHeap(), 0, driverInfo->InfSection);
- HeapFree(GetProcessHeap(), 0, driverInfo);
- return FALSE;
- }
- RtlCopyMemory(driverInfo->InfPath, InfFile, (wcslen(InfFile) + 1) * sizeof(WCHAR));
-
- Result = FALSE;
- RequiredSize = 128; /* Initial buffer size */
- SetLastError(ERROR_INSUFFICIENT_BUFFER);
- while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
- {
- HeapFree(GetProcessHeap(), 0, DeviceDescription);
- DeviceDescription = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
- if (!DeviceDescription)
- return FALSE;
- Result = SetupGetStringFieldW(
- &ContextDevice,
- 0, /* Field index */
- DeviceDescription, RequiredSize,
- &RequiredSize);
- }
+ goto cleanup;*/
+
+ /* Fill SectionName field */
+ Result = SetupGetStringFieldW(
+ &ContextDevice,
+ 1,
+ driverInfo->Details.SectionName, LINE_LEN,
+ NULL);
if (!Result)
+ goto cleanup;
+
+ /* Fill DrvDescription field */
+ Result = SetupGetStringFieldW(
+ &ContextDevice,
+ 0, /* Field index */
+ driverInfo->Details.DrvDescription, LINE_LEN,
+ NULL);
+
+ /* Copy MatchingId information */
+ driverInfo->MatchingId = HeapAlloc(GetProcessHeap(), 0, (wcslen(MatchingId) + 1) * sizeof(WCHAR));
+ if (!driverInfo->MatchingId)
{
- HeapFree(GetProcessHeap(), 0, driverInfo->InfPath);
- HeapFree(GetProcessHeap(), 0, driverInfo->InfSection);
- HeapFree(GetProcessHeap(), 0, driverInfo);
- HeapFree(GetProcessHeap(), 0, DeviceDescription);
- return FALSE;
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto cleanup;
}
+ RtlCopyMemory(driverInfo->MatchingId, MatchingId, (wcslen(MatchingId) + 1) * sizeof(WCHAR));
+ /* Get inf install section */
Result = FALSE;
RequiredSize = 128; /* Initial buffer size */
SetLastError(ERROR_INSUFFICIENT_BUFFER);
HeapFree(GetProcessHeap(), 0, InfInstallSection);
InfInstallSection = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
if (!InfInstallSection)
- {
- HeapFree(GetProcessHeap(), 0, driverInfo->InfPath);
- HeapFree(GetProcessHeap(), 0, driverInfo->InfSection);
- HeapFree(GetProcessHeap(), 0, driverInfo);
- HeapFree(GetProcessHeap(), 0, DeviceDescription);
- return FALSE;
- }
+ goto cleanup;
Result = SetupGetStringFieldW(
&ContextDevice,
1, /* Field index */
&RequiredSize);
}
if (!Result)
- {
- HeapFree(GetProcessHeap(), 0, driverInfo->InfPath);
- HeapFree(GetProcessHeap(), 0, driverInfo->InfSection);
- HeapFree(GetProcessHeap(), 0, driverInfo);
- HeapFree(GetProcessHeap(), 0, DeviceDescription);
- HeapFree(GetProcessHeap(), 0, InfInstallSection);
- return FALSE;
- }
+ goto cleanup;
TRACE("Adding driver '%S' [%S/%S] (Rank 0x%lx)\n",
- DeviceDescription, InfFile, InfInstallSection, Rank);
+ driverInfo->Details.DrvDescription, InfFile, InfInstallSection, Rank);
driverInfo->DriverRank = Rank;
+ memcpy(&driverInfo->ClassGuid, ClassGuid, sizeof(GUID));
driverInfo->Info.DriverType = DriverType;
driverInfo->Info.Reserved = (ULONG_PTR)driverInfo;
- wcsncpy(driverInfo->Info.Description, DeviceDescription, LINE_LEN - 1);
+ wcsncpy(driverInfo->Info.Description, driverInfo->Details.DrvDescription, LINE_LEN - 1);
driverInfo->Info.Description[LINE_LEN - 1] = '\0';
wcsncpy(driverInfo->Info.MfgName, ManufacturerName, LINE_LEN - 1);
driverInfo->Info.MfgName[LINE_LEN - 1] = '\0';
driverInfo->Info.ProviderName[0] = '\0';
driverInfo->Info.DriverDate = DriverDate;
driverInfo->Info.DriverVersion = DriverVersion;
+ ReferenceInfFile(InfFileDetails);
+ driverInfo->InfFileDetails = InfFileDetails;
/* Insert current driver in driver list, according to its rank */
PreviousEntry = DriverListHead->Flink;
InsertTailList(DriverListHead, &driverInfo->ListEntry);
}
- HeapFree(GetProcessHeap(), 0, DeviceDescription);
+ ret = TRUE;
+
+cleanup:
+ if (!ret)
+ {
+ if (driverInfo)
+ HeapFree(GetProcessHeap(), 0, driverInfo->MatchingId);
+ HeapFree(GetProcessHeap(), 0, driverInfo);
+ }
+ if (hFile != INVALID_HANDLE_VALUE)
+ CloseHandle(hFile);
HeapFree(GetProcessHeap(), 0, InfInstallSection);
- return TRUE;
+
+ return ret;
}
static BOOL
{
DWORD RequiredSize;
WCHAR guidW[MAX_GUID_STRING_LEN + 1];
+ LPWSTR DriverVer = NULL;
LPWSTR ProviderName = NULL;
+ LPWSTR pComma; /* Points into DriverVer */
+ LPWSTR pVersion = NULL; /* Points into DriverVer */
+ SYSTEMTIME SystemTime;
BOOL Result;
+ BOOL ret = FALSE; /* Final result */
+ /* Get class Guid */
if (!SetupGetLineTextW(
NULL, /* Context */
hInf,
guidW, sizeof(guidW),
NULL /* Required size */))
{
- return FALSE;
+ goto cleanup;
}
-
- /* Get Provider name, driver date, and driver version */
-
guidW[37] = '\0'; /* Replace the } by a NULL character */
if (UuidFromStringW(&guidW[1], ClassGuid) != RPC_S_OK)
{
- return FALSE;
+ SetLastError(ERROR_GEN_FAILURE);
+ goto cleanup;
}
+
+ /* Get provider name */
Result = SetupGetLineTextW(
NULL, /* Context */
hInf, L"Version", L"Provider",
NULL, 0,
&RequiredSize);
- if (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+ if (Result)
{
+ /* We know know the needed buffer size */
ProviderName = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
if (!ProviderName)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- return FALSE;
+ goto cleanup;
}
Result = SetupGetLineTextW(
NULL, /* Context */
ProviderName, RequiredSize,
&RequiredSize);
}
- //FIXME: DriverDate = Version.DriverVer => invalid date = 00/00/00
- RtlZeroMemory(DriverDate, sizeof(FILETIME));
- //FIXME: DriverVersion = Version.DriverVer => invalid = 0
+ if (!Result)
+ goto cleanup;
+ *pProviderName = ProviderName;
+
+ /* Read the "DriverVer" value */
+ Result = SetupGetLineTextW(
+ NULL, /* Context */
+ hInf, L"Version", L"DriverVer",
+ NULL, 0,
+ &RequiredSize);
+ if (Result)
+ {
+ /* We know know the needed buffer size */
+ DriverVer = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
+ if (!DriverVer)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto cleanup;
+ }
+ Result = SetupGetLineTextW(
+ NULL, /* Context */
+ hInf, L"Version", L"DriverVer",
+ DriverVer, RequiredSize,
+ &RequiredSize);
+ }
+ if (!Result)
+ goto cleanup;
+
+ /* Get driver date and driver version, by analyzing the "DriverVer" value */
+ pComma = wcschr(DriverVer, ',');
+ if (pComma != NULL)
+ {
+ *pComma = UNICODE_NULL;
+ pVersion = pComma + 1;
+ }
+ /* Get driver date version. Invalid date = 00/00/00 */
+ memset(DriverDate, 0, sizeof(FILETIME));
+ if (wcslen(DriverVer) == 10
+ && (DriverVer[2] == '-' || DriverVer[2] == '/')
+ && (DriverVer[5] == '-' || DriverVer[5] == '/'))
+ {
+ memset(&SystemTime, 0, sizeof(SYSTEMTIME));
+ DriverVer[2] = DriverVer[5] = UNICODE_NULL;
+ SystemTime.wMonth = ((DriverVer[0] - '0') * 10) + DriverVer[1] - '0';
+ SystemTime.wDay = ((DriverVer[3] - '0') * 10) + DriverVer[4] - '0';
+ SystemTime.wYear = ((DriverVer[6] - '0') * 1000) + ((DriverVer[7] - '0') * 100) + ((DriverVer[8] - '0') * 10) + DriverVer[9] - '0';
+ SystemTimeToFileTime(&SystemTime, DriverDate);
+ }
+ /* Get driver version. Invalid version = 0.0.0.0 */
*DriverVersion = 0;
+ /* FIXME: use pVersion to fill DriverVersion variable */
- *pProviderName = ProviderName;
- return TRUE;
+ ret = TRUE;
+
+cleanup:
+ if (!ret)
+ HeapFree(GetProcessHeap(), 0, ProviderName);
+ HeapFree(GetProcessHeap(), 0, DriverVer);
+
+ TRACE("Returning %d\n", ret);
+ return ret;
}
/***********************************************************************
IN DWORD DriverType)
{
struct DeviceInfoSet *list;
+ SP_DEVINSTALL_PARAMS_W InstallParams;
PVOID Buffer = NULL;
- HINF hInf = INVALID_HANDLE_VALUE;
+ struct InfFileDetails *currentInfFileDetails = NULL;
LPWSTR ProviderName = NULL;
LPWSTR ManufacturerName = NULL;
- LPWSTR ManufacturerSection = NULL;
+ WCHAR ManufacturerSection[LINE_LEN + 1];
LPWSTR HardwareIDs = NULL;
LPWSTR CompatibleIDs = NULL;
FILETIME DriverDate;
- DWORDLONG DriverVersion;
+ DWORDLONG DriverVersion = 0;
DWORD RequiredSize;
BOOL ret = FALSE;
SetLastError(ERROR_INVALID_USER_BUFFER);
else
{
- BOOL Result = FALSE;
+ BOOL Result;
+
+ InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
+ Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
+ if (!Result)
+ goto done;
if (DriverType == SPDIT_COMPATDRIVER)
{
break;
}
Result = SetupGetInfFileListW(
- NULL, /* Directory path */
+ *InstallParams.DriverPath ? InstallParams.DriverPath : NULL,
INF_STYLE_WIN4,
Buffer, RequiredSize,
&RequiredSize);
}
+ if (!Result && GetLastError() == ERROR_FILE_NOT_FOUND)
+ {
+ /* No .inf file in specified directory. So, we should
+ * success as we created an empty driver info list.
+ */
+ ret = TRUE;
+ goto done;
+ }
if (Result)
{
LPCWSTR filename;
GUID ClassGuid;
TRACE("Opening file %S\n", filename);
- hInf = SetupOpenInfFileW(filename, NULL, INF_STYLE_WIN4, NULL);
- if (hInf == INVALID_HANDLE_VALUE)
+ currentInfFileDetails = HeapAlloc(GetProcessHeap(), 0, sizeof(struct InfFileDetails));
+ if (!currentInfFileDetails)
+ continue;
+ memset(currentInfFileDetails, 0, sizeof(struct InfFileDetails));
+
+ currentInfFileDetails->hInf = SetupOpenInfFileW(filename, NULL, INF_STYLE_WIN4, NULL);
+ ReferenceInfFile(currentInfFileDetails);
+ if (currentInfFileDetails->hInf == INVALID_HANDLE_VALUE)
+ {
+ HeapFree(GetProcessHeap(), 0, currentInfFileDetails);
+ currentInfFileDetails = NULL;
continue;
+ }
if (!GetVersionInformationFromInfFile(
- hInf,
+ currentInfFileDetails->hInf,
&ClassGuid,
&ProviderName,
&DriverDate,
&DriverVersion))
{
- SetupCloseInfFile(hInf);
- hInf = INVALID_HANDLE_VALUE;
+ SetupCloseInfFile(currentInfFileDetails->hInf);
+ HeapFree(GetProcessHeap(), 0, currentInfFileDetails->hInf);
+ currentInfFileDetails = NULL;
continue;
}
}
/* Get the manufacturers list */
- Result = SetupFindFirstLineW(hInf, L"Manufacturer", NULL, &ContextManufacturer);
+ Result = SetupFindFirstLineW(currentInfFileDetails->hInf, L"Manufacturer", NULL, &ContextManufacturer);
while (Result)
{
Result = SetupGetStringFieldW(
ManufacturerName, RequiredSize,
&RequiredSize);
}
+ /* Get manufacturer section name */
Result = SetupGetStringFieldW(
&ContextManufacturer,
1, /* Field index */
- NULL, 0,
+ ManufacturerSection, LINE_LEN,
&RequiredSize);
if (Result)
{
- /* We got the needed size for the buffer */
- ManufacturerSection = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
- if (!ManufacturerSection)
+ ManufacturerSection[RequiredSize] = 0; /* Final NULL char */
+ /* Add (possible) extension to manufacturer section name */
+ Result = SetupDiGetActualSectionToInstallW(
+ currentInfFileDetails->hInf, ManufacturerSection, ManufacturerSection, LINE_LEN, NULL, NULL);
+ if (Result)
{
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- goto done;
+ TRACE("Enumerating devices in manufacturer %S\n", ManufacturerSection);
+ Result = SetupFindFirstLineW(currentInfFileDetails->hInf, ManufacturerSection, NULL, &ContextDevice);
}
- Result = SetupGetStringFieldW(
- &ContextManufacturer,
- 1, /* Field index */
- ManufacturerSection, RequiredSize,
- &RequiredSize);
}
-
- TRACE("Enumerating devices in manufacturer %S\n", ManufacturerSection);
- Result = SetupFindFirstLineW(hInf, ManufacturerSection, NULL, &ContextDevice);
while (Result)
{
if (DriverType == SPDIT_CLASSDRIVER)
if (!AddDriverToList(
&list->DriverListHead,
DriverType,
+ &ClassGuid,
ContextDevice,
+ currentInfFileDetails,
filename,
ProviderName,
ManufacturerName,
+ NULL,
DriverDate, DriverVersion,
0))
{
AddDriverToList(
&((struct DeviceInfoElement *)DeviceInfoData->Reserved)->DriverListHead,
DriverType,
+ &ClassGuid,
ContextDevice,
+ currentInfFileDetails,
filename,
ProviderName,
ManufacturerName,
+ currentId,
DriverDate, DriverVersion,
DriverRank + (i == 2 ? 0 : 0x1000 + i - 3));
DriverAlreadyAdded = TRUE;
AddDriverToList(
&((struct DeviceInfoElement *)DeviceInfoData->Reserved)->DriverListHead,
DriverType,
+ &ClassGuid,
ContextDevice,
+ currentInfFileDetails,
filename,
ProviderName,
ManufacturerName,
+ currentId,
DriverDate, DriverVersion,
DriverRank + (i == 2 ? 0x2000 : 0x3000 + i - 3));
DriverAlreadyAdded = TRUE;
}
HeapFree(GetProcessHeap(), 0, ManufacturerName);
- HeapFree(GetProcessHeap(), 0, ManufacturerSection);
- ManufacturerName = ManufacturerSection = NULL;
+ ManufacturerName = NULL;
Result = SetupFindNextLine(&ContextManufacturer, &ContextManufacturer);
}
HeapFree(GetProcessHeap(), 0, ProviderName);
ProviderName = NULL;
- SetupCloseInfFile(hInf);
- hInf = INVALID_HANDLE_VALUE;
+ DereferenceInfFile(currentInfFileDetails);
+ currentInfFileDetails = NULL;
}
ret = TRUE;
}
{
if (DeviceInfoData)
{
- struct DeviceInfoElement *deviceInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
- deviceInfo->Flags |= DI_DIDCOMPAT;
+ InstallParams.Flags |= DI_DIDCOMPAT;
+ InstallParams.FlagsEx |= DI_FLAGSEX_DIDCOMPATINFO;
}
else
- list->Flags |= DI_DIDCLASS;
+ {
+ InstallParams.Flags |= DI_DIDCLASS;
+ InstallParams.FlagsEx |= DI_FLAGSEX_DIDINFOLIST;
+ }
+ ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
}
HeapFree(GetProcessHeap(), 0, ProviderName);
HeapFree(GetProcessHeap(), 0, ManufacturerName);
- HeapFree(GetProcessHeap(), 0, ManufacturerSection);
HeapFree(GetProcessHeap(), 0, HardwareIDs);
HeapFree(GetProcessHeap(), 0, CompatibleIDs);
- if (hInf != INVALID_HANDLE_VALUE)
- SetupCloseInfFile(hInf);
+ if (currentInfFileDetails)
+ DereferenceInfFile(currentInfFileDetails);
HeapFree(GetProcessHeap(), 0, Buffer);
TRACE("Returning %d\n", ret);
IN PSP_DEVINFO_DATA DeviceInfoData,
IN DWORD DriverType)
{
+ struct DeviceInfoSet *list;
+ BOOL ret = FALSE;
+
TRACE("%p %p 0x%lx\n", DeviceInfoSet, DeviceInfoData, DriverType);
- FIXME("not implemented\n");
- SetLastError(ERROR_GEN_FAILURE);
- return FALSE;
+ if (!DeviceInfoSet)
+ SetLastError(ERROR_INVALID_HANDLE);
+ else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
+ SetLastError(ERROR_INVALID_HANDLE);
+ else if (DriverType != SPDIT_CLASSDRIVER && DriverType != SPDIT_COMPATDRIVER)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else if (DriverType == SPDIT_COMPATDRIVER && !DeviceInfoData)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
+ SetLastError(ERROR_INVALID_USER_BUFFER);
+ else
+ {
+ PLIST_ENTRY ListEntry;
+ struct DriverInfoElement *driverInfo;
+ SP_DEVINSTALL_PARAMS_W InstallParams;
+
+ InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
+ if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams))
+ goto done;
+
+ if (!DeviceInfoData)
+ /* Fall back to destroying class driver list */
+ DriverType = SPDIT_CLASSDRIVER;
+
+ if (DriverType == SPDIT_CLASSDRIVER)
+ {
+ while (!IsListEmpty(&list->DriverListHead))
+ {
+ ListEntry = RemoveHeadList(&list->DriverListHead);
+ driverInfo = (struct DriverInfoElement *)ListEntry;
+ DestroyDriverInfoElement(driverInfo);
+ }
+ InstallParams.Reserved = 0;
+ InstallParams.Flags &= ~(DI_DIDCLASS | DI_MULTMFGS);
+ InstallParams.FlagsEx &= ~DI_FLAGSEX_DIDINFOLIST;
+ ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, NULL, &InstallParams);
+ }
+ else
+ {
+ SP_DEVINSTALL_PARAMS_W InstallParamsSet;
+ struct DeviceInfoElement *deviceInfo;
+
+ InstallParamsSet.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
+ if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet, NULL, &InstallParamsSet))
+ goto done;
+ deviceInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
+ while (!IsListEmpty(&deviceInfo->DriverListHead))
+ {
+ ListEntry = RemoveHeadList(&deviceInfo->DriverListHead);
+ driverInfo = (struct DriverInfoElement *)ListEntry;
+ if ((PVOID)InstallParamsSet.Reserved == driverInfo)
+ {
+ InstallParamsSet.Reserved = 0;
+ SetupDiSetDeviceInstallParamsW(DeviceInfoSet, NULL, &InstallParamsSet);
+ }
+ DestroyDriverInfoElement(driverInfo);
+ }
+ InstallParams.Reserved = 0;
+ InstallParams.Flags &= ~DI_DIDCOMPAT;
+ InstallParams.FlagsEx &= ~DI_FLAGSEX_DIDCOMPATINFO;
+ ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
+ }
+ }
+
+done:
+ TRACE("Returning %d\n", ret);
+ return ret;
}
SetLastError(ERROR_INVALID_USER_BUFFER);
else
{
- struct DriverInfoElement *driverInfo;
-
- if (DeviceInfoData)
- driverInfo = ((struct DeviceInfoElement *)DeviceInfoData->Reserved)->SelectedDriver;
- else
- driverInfo = ((struct DeviceInfoSet *)DeviceInfoSet)->SelectedDriver;
+ SP_DEVINSTALL_PARAMS InstallParams;
- if (driverInfo == NULL)
- SetLastError(ERROR_NO_DRIVER_SELECTED);
- else
+ InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
+ if (SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams))
{
- memcpy(
- &DriverInfoData->DriverType,
- &driverInfo->Info.DriverType,
- DriverInfoData->cbSize - FIELD_OFFSET(SP_DRVINFO_DATA_W, DriverType));
- ret = TRUE;
+ struct DriverInfoElement *driverInfo;
+ driverInfo = (struct DriverInfoElement *)InstallParams.Reserved;
+ if (driverInfo == NULL)
+ SetLastError(ERROR_NO_DRIVER_SELECTED);
+ else
+ {
+ memcpy(
+ &DriverInfoData->DriverType,
+ &driverInfo->Info.DriverType,
+ DriverInfoData->cbSize - FIELD_OFFSET(SP_DRVINFO_DATA_W, DriverType));
+ ret = TRUE;
+ }
+ }
+ }
+
+ TRACE("Returning %d\n", ret);
+ return ret;
+}
+
+
+/***********************************************************************
+ * SetupDiSetSelectedDriverA (SETUPAPI.@)
+ */
+BOOL WINAPI
+SetupDiSetSelectedDriverA(
+ IN HDEVINFO DeviceInfoSet,
+ IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
+ IN OUT PSP_DRVINFO_DATA_A DriverInfoData OPTIONAL)
+{
+ SP_DRVINFO_DATA_V1_W DriverInfoDataW;
+ PSP_DRVINFO_DATA_W pDriverInfoDataW = NULL;
+ BOOL ret = FALSE;
+
+ if (DriverInfoData != NULL)
+ {
+ if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_A) &&
+ DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_A));
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ DriverInfoDataW.cbSize = sizeof(SP_DRVINFO_DATA_V1_W);
+ DriverInfoDataW.Reserved = DriverInfoData->Reserved;
+
+ if (DriverInfoDataW.Reserved == 0)
+ {
+ DriverInfoDataW.DriverType = DriverInfoData->DriverType;
+
+ /* convert the strings to unicode */
+ if (!MultiByteToWideChar(CP_ACP,
+ 0,
+ DriverInfoData->Description,
+ LINE_LEN,
+ DriverInfoDataW.Description,
+ LINE_LEN) ||
+ !MultiByteToWideChar(CP_ACP,
+ 0,
+ DriverInfoData->ProviderName,
+ LINE_LEN,
+ DriverInfoDataW.ProviderName,
+ LINE_LEN))
+ {
+ return FALSE;
+ }
}
+
+ pDriverInfoDataW = (PSP_DRVINFO_DATA_W)&DriverInfoDataW;
+ }
+
+ ret = SetupDiSetSelectedDriverW(DeviceInfoSet,
+ DeviceInfoData,
+ pDriverInfoDataW);
+
+ if (ret && pDriverInfoDataW != NULL)
+ {
+ DriverInfoData->Reserved = DriverInfoDataW.Reserved;
}
- TRACE("Returning %d\n", ret);
return ret;
}
+
/***********************************************************************
* SetupDiSetSelectedDriverW (SETUPAPI.@)
*/
if (DeviceInfoData)
{
- pDriverInfo = &((struct DeviceInfoElement *)DeviceInfoData->Reserved)->SelectedDriver;
+ pDriverInfo = (struct DriverInfoElement **)&((struct DeviceInfoElement *)DeviceInfoData->Reserved)->InstallParams.Reserved;
ListHead = &((struct DeviceInfoElement *)DeviceInfoData->Reserved)->DriverListHead;
}
else
{
- pDriverInfo = &((struct DeviceInfoSet *)DeviceInfoSet)->SelectedDriver;
+ pDriverInfo = (struct DriverInfoElement **)&((struct DeviceInfoSet *)DeviceInfoSet)->InstallParams.Reserved;
ListHead = &((struct DeviceInfoSet *)DeviceInfoSet)->DriverListHead;
}
ret = TRUE;
TRACE("Choosing driver whose rank is 0x%lx\n",
((struct DriverInfoElement *)ItemList)->DriverRank);
+ if (DeviceInfoData)
+ memcpy(&DeviceInfoData->ClassGuid, &(*pDriverInfo)->ClassGuid, sizeof(GUID));
+ }
+ }
+ }
+
+ TRACE("Returning %d\n", ret);
+ return ret;
+}
+
+/***********************************************************************
+ * SetupDiGetDriverInfoDetailA (SETUPAPI.@)
+ */
+BOOL WINAPI
+SetupDiGetDriverInfoDetailA(
+ IN HDEVINFO DeviceInfoSet,
+ IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
+ IN PSP_DRVINFO_DATA_A DriverInfoData,
+ OUT PSP_DRVINFO_DETAIL_DATA_A DriverInfoDetailData OPTIONAL,
+ IN DWORD DriverInfoDetailDataSize,
+ OUT PDWORD RequiredSize OPTIONAL)
+{
+ SP_DRVINFO_DATA_V2_W DriverInfoDataW;
+ PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailDataW = NULL;
+ DWORD BufSize = 0;
+ DWORD HardwareIDLen = 0;
+ BOOL ret = FALSE;
+
+ /* do some sanity checks, the unicode version might do more thorough checks */
+ if (DriverInfoData == NULL ||
+ (DriverInfoDetailData == NULL && DriverInfoDetailDataSize != 0) ||
+ (DriverInfoDetailData != NULL &&
+ (DriverInfoDetailDataSize < FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A, HardwareID) + sizeof(CHAR) ||
+ DriverInfoDetailData->cbSize != sizeof(SP_DRVINFO_DETAIL_DATA_A))))
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ goto Cleanup;
+ }
+
+ /* make sure we support both versions of the SP_DRVINFO_DATA structure */
+ if (DriverInfoData->cbSize == sizeof(SP_DRVINFO_DATA_V1_A))
+ {
+ DriverInfoDataW.cbSize = sizeof(SP_DRVINFO_DATA_V1_W);
+ }
+ else if (DriverInfoData->cbSize == sizeof(SP_DRVINFO_DATA_V2_A))
+ {
+ DriverInfoDataW.cbSize = sizeof(SP_DRVINFO_DATA_V2_W);
+ }
+ else
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ goto Cleanup;
+ }
+ DriverInfoDataW.DriverType = DriverInfoData->DriverType;
+ DriverInfoDataW.Reserved = DriverInfoData->Reserved;
+
+ /* convert the strings to unicode */
+ if (MultiByteToWideChar(CP_ACP,
+ 0,
+ DriverInfoData->Description,
+ LINE_LEN,
+ DriverInfoDataW.Description,
+ LINE_LEN) &&
+ MultiByteToWideChar(CP_ACP,
+ 0,
+ DriverInfoData->MfgName,
+ LINE_LEN,
+ DriverInfoDataW.MfgName,
+ LINE_LEN) &&
+ MultiByteToWideChar(CP_ACP,
+ 0,
+ DriverInfoData->ProviderName,
+ LINE_LEN,
+ DriverInfoDataW.ProviderName,
+ LINE_LEN))
+ {
+ if (DriverInfoDataW.cbSize == sizeof(SP_DRVINFO_DATA_V2_W))
+ {
+ DriverInfoDataW.DriverDate = ((PSP_DRVINFO_DATA_V2_A)DriverInfoData)->DriverDate;
+ DriverInfoDataW.DriverVersion = ((PSP_DRVINFO_DATA_V2_A)DriverInfoData)->DriverVersion;
+ }
+
+ if (DriverInfoDetailData != NULL)
+ {
+ /* calculate the unicode buffer size from the ansi buffer size */
+ HardwareIDLen = DriverInfoDetailDataSize - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A, HardwareID);
+ BufSize = FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W, HardwareID) +
+ (HardwareIDLen * sizeof(WCHAR));
+
+ DriverInfoDetailDataW = MyMalloc(BufSize);
+ if (DriverInfoDetailDataW == NULL)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto Cleanup;
+ }
+
+ /* initialize the buffer */
+ ZeroMemory(DriverInfoDetailDataW,
+ BufSize);
+ DriverInfoDetailDataW->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA_W);
+ }
+
+ /* call the unicode version */
+ ret = SetupDiGetDriverInfoDetailW(DeviceInfoSet,
+ DeviceInfoData,
+ &DriverInfoDataW,
+ DriverInfoDetailDataW,
+ BufSize,
+ RequiredSize);
+
+ if (ret)
+ {
+ if (DriverInfoDetailDataW != NULL)
+ {
+ /* convert the SP_DRVINFO_DETAIL_DATA_W structure to ansi */
+ DriverInfoDetailData->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA_A);
+ DriverInfoDetailData->InfDate = DriverInfoDetailDataW->InfDate;
+ DriverInfoDetailData->Reserved = DriverInfoDetailDataW->Reserved;
+ if (WideCharToMultiByte(CP_ACP,
+ 0,
+ DriverInfoDetailDataW->SectionName,
+ LINE_LEN,
+ DriverInfoDetailData->SectionName,
+ LINE_LEN,
+ NULL,
+ NULL) &&
+ WideCharToMultiByte(CP_ACP,
+ 0,
+ DriverInfoDetailDataW->InfFileName,
+ MAX_PATH,
+ DriverInfoDetailData->InfFileName,
+ MAX_PATH,
+ NULL,
+ NULL) &&
+ WideCharToMultiByte(CP_ACP,
+ 0,
+ DriverInfoDetailDataW->DrvDescription,
+ LINE_LEN,
+ DriverInfoDetailData->DrvDescription,
+ LINE_LEN,
+ NULL,
+ NULL) &&
+ WideCharToMultiByte(CP_ACP,
+ 0,
+ DriverInfoDetailDataW->HardwareID,
+ HardwareIDLen,
+ DriverInfoDetailData->HardwareID,
+ HardwareIDLen,
+ NULL,
+ NULL))
+ {
+ DWORD len, cnt = 0;
+ DWORD hwidlen = HardwareIDLen;
+ CHAR *s = DriverInfoDetailData->HardwareID;
+
+ /* count the strings in the list */
+ while (*s != '\0')
+ {
+ len = lstrlenA(s) + 1;
+ if (hwidlen > len)
+ {
+ cnt++;
+ s += len;
+ hwidlen -= len;
+ }
+ else
+ {
+ /* looks like the string list wasn't terminated... */
+ SetLastError(ERROR_INVALID_USER_BUFFER);
+ ret = FALSE;
+ break;
+ }
+ }
+
+ /* make sure CompatIDsOffset points to the second string in the
+ list, if present */
+ if (cnt > 1)
+ {
+ DriverInfoDetailData->CompatIDsOffset = lstrlenA(DriverInfoDetailData->HardwareID) + 1;
+ DriverInfoDetailData->CompatIDsLength = (DWORD)(s - DriverInfoDetailData->HardwareID) -
+ DriverInfoDetailData->CompatIDsOffset + 1;
+ }
+ else
+ {
+ DriverInfoDetailData->CompatIDsOffset = 0;
+ DriverInfoDetailData->CompatIDsLength = 0;
+ }
+ }
+ else
+ {
+ ret = FALSE;
+ }
+ }
+
+ if (RequiredSize != NULL)
+ {
+ *RequiredSize = FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A, HardwareID) +
+ (((*RequiredSize) - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W, HardwareID)) / sizeof(WCHAR));
}
}
}
+
+Cleanup:
+ if (DriverInfoDetailDataW != NULL)
+ {
+ MyFree(DriverInfoDetailDataW);
+ }
+
+ return ret;
+}
+
+/***********************************************************************
+ * SetupDiGetDriverInfoDetailW (SETUPAPI.@)
+ */
+BOOL WINAPI
+SetupDiGetDriverInfoDetailW(
+ IN HDEVINFO DeviceInfoSet,
+ IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
+ IN PSP_DRVINFO_DATA_W DriverInfoData,
+ OUT PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailData OPTIONAL,
+ IN DWORD DriverInfoDetailDataSize,
+ OUT PDWORD RequiredSize OPTIONAL)
+{
+ BOOL ret = FALSE;
+
+ if (!DeviceInfoSet)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
+ SetLastError(ERROR_INVALID_HANDLE);
+ else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
+ SetLastError(ERROR_INVALID_HANDLE);
+ else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
+ SetLastError(ERROR_INVALID_USER_BUFFER);
+ else if (!DriverInfoData)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else if (!DriverInfoDetailData && DriverInfoDetailDataSize != 0)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else if (DriverInfoDetailData && DriverInfoDetailDataSize < sizeof(SP_DRVINFO_DETAIL_DATA_W))
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else if (DriverInfoDetailData && DriverInfoDetailData->cbSize != sizeof(SP_DRVINFO_DETAIL_DATA_W))
+ SetLastError(ERROR_INVALID_USER_BUFFER);
+ else if (DriverInfoDetailData && DriverInfoDetailData->Reserved == 0)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else
+ {
+ struct DriverInfoElement *driverInfoElement;
+ driverInfoElement = (struct DriverInfoElement *)DriverInfoData->Reserved;
+
+ memcpy(
+ DriverInfoDetailData,
+ &driverInfoElement->Details,
+ driverInfoElement->Details.cbSize);
+ /* FIXME: copy HardwareIDs/CompatibleIDs if buffer is big enough
+ * Don't forget to set CompatIDsOffset and CompatIDsLength fields.
+ */
+ ret = TRUE;
+ }
TRACE("Returning %d\n", ret);
return ret;
SetLastError(ERROR_INVALID_HANDLE);
else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
SetLastError(ERROR_INVALID_USER_BUFFER);
- else if (DeviceInfoData && ((struct DeviceInfoElement *)DeviceInfoData->Reserved)->SelectedDriver == NULL)
- SetLastError(ERROR_INVALID_PARAMETER);
- else if (!DeviceInfoData && ((struct DeviceInfoSet *)DeviceInfoSet)->SelectedDriver == NULL)
- SetLastError(ERROR_INVALID_PARAMETER);
+ else if (DeviceInfoData && ((struct DeviceInfoElement *)DeviceInfoData->Reserved)->InstallParams.Reserved == 0)
+ SetLastError(ERROR_NO_DRIVER_SELECTED);
+ else if (!DeviceInfoData && ((struct DeviceInfoSet *)DeviceInfoSet)->InstallParams.Reserved == 0)
+ SetLastError(ERROR_NO_DRIVER_SELECTED);
else
{
- struct DriverInfoElement *DriverInfo;
- HWND hWnd;
- HINF hInf;
-
- if (DeviceInfoData)
- {
- DriverInfo = ((struct DeviceInfoElement *)DeviceInfoData->Reserved)->SelectedDriver;
- hWnd = ((struct DeviceInfoElement *)DeviceInfoData->Reserved)->hwndParent;
- }
- else
+ SP_DEVINSTALL_PARAMS_W InstallParams;
+ struct DriverInfoElement *SelectedDriver;
+ WCHAR SectionName[MAX_PATH];
+ DWORD SectionNameLength = 0;
+
+ InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
+ ret = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
+ if (!ret)
+ goto done;
+
+ SelectedDriver = (struct DriverInfoElement *)InstallParams.Reserved;
+ if (!SelectedDriver)
{
- DriverInfo = ((struct DeviceInfoSet *)DeviceInfoSet)->SelectedDriver;
- hWnd = ((struct DeviceInfoSet *)DeviceInfoSet)->hwndParent;
+ SetLastError(ERROR_NO_DRIVER_SELECTED);
+ goto done;
}
- hInf = SetupOpenInfFileW(DriverInfo->InfPath, NULL, INF_STYLE_WIN4, NULL);
- if (hInf != INVALID_HANDLE_VALUE)
- {
- WCHAR SectionName[MAX_PATH];
- DWORD SectionNameLength = 0;
+ ret = SetupDiGetActualSectionToInstallW(
+ SelectedDriver->InfFileDetails->hInf,
+ SelectedDriver->Details.SectionName,
+ SectionName, MAX_PATH, &SectionNameLength, NULL);
+ if (!ret)
+ goto done;
- ret = SetupDiGetActualSectionToInstallW(hInf, DriverInfo->InfSection,
- SectionName, MAX_PATH, &SectionNameLength, NULL);
- if (ret)
- {
- PVOID callback_context = SetupInitDefaultQueueCallback(hWnd);
- ret = SetupInstallFromInfSectionW(hWnd, hInf, SectionName,
- SPINST_FILES, NULL, NULL, SP_COPY_NEWER,
- SetupDefaultQueueCallbackW, callback_context,
- NULL, NULL);
- SetupTermDefaultQueueCallback(callback_context);
- }
- SetupCloseInfFile(hInf);
+ if (!InstallParams.InstallMsgHandler)
+ {
+ InstallParams.InstallMsgHandler = SetupDefaultQueueCallbackW;
+ InstallParams.InstallMsgHandlerContext = SetupInitDefaultQueueCallback(InstallParams.hwndParent);
+ SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
}
+ ret = SetupInstallFromInfSectionW(InstallParams.hwndParent,
+ SelectedDriver->InfFileDetails->hInf, SectionName,
+ SPINST_FILES, NULL, NULL, SP_COPY_NEWER,
+ InstallParams.InstallMsgHandler, InstallParams.InstallMsgHandlerContext,
+ DeviceInfoSet, DeviceInfoData);
}
+done:
TRACE("Returning %d\n", ret);
return ret;
}
IN HDEVINFO DeviceInfoSet,
IN PSP_DEVINFO_DATA DeviceInfoData)
{
+ BOOL ret = FALSE; /* Return value */
+
TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
- FIXME("SetupDiRegisterCoDeviceInstallers not implemented. Doing nothing\n");
- //SetLastError(ERROR_GEN_FAILURE);
- //return FALSE;
- return TRUE;
+ if (!DeviceInfoSet)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
+ SetLastError(ERROR_INVALID_HANDLE);
+ else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
+ SetLastError(ERROR_INVALID_HANDLE);
+ else if (!DeviceInfoData)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
+ SetLastError(ERROR_INVALID_USER_BUFFER);
+ else
+ {
+ SP_DEVINSTALL_PARAMS_W InstallParams;
+ struct DriverInfoElement *SelectedDriver;
+ BOOL Result;
+ DWORD DoAction;
+ WCHAR SectionName[MAX_PATH];
+ DWORD SectionNameLength = 0;
+ HKEY hKey = INVALID_HANDLE_VALUE;;
+
+ InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
+ Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
+ if (!Result)
+ goto cleanup;
+
+ SelectedDriver = (struct DriverInfoElement *)InstallParams.Reserved;
+ if (SelectedDriver == NULL)
+ {
+ SetLastError(ERROR_NO_DRIVER_SELECTED);
+ goto cleanup;
+ }
+
+ /* Get .CoInstallers section name */
+ Result = SetupDiGetActualSectionToInstallW(
+ SelectedDriver->InfFileDetails->hInf,
+ SelectedDriver->Details.SectionName,
+ SectionName, MAX_PATH, &SectionNameLength, NULL);
+ if (!Result || SectionNameLength > MAX_PATH - wcslen(L".CoInstallers") - 1)
+ goto cleanup;
+ wcscat(SectionName, L".CoInstallers");
+
+ /* Open/Create driver key information */
+#if _WIN32_WINNT >= 0x502
+ hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_READ | KEY_WRITE);
+#else
+ hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_ALL_ACCESS);
+#endif
+ if (hKey == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND)
+ hKey = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, NULL, NULL);
+ if (hKey == INVALID_HANDLE_VALUE)
+ goto cleanup;
+
+ /* Install .CoInstallers section */
+ DoAction = SPINST_REGISTRY;
+ if (!(InstallParams.Flags & DI_NOFILECOPY))
+ {
+ DoAction |= SPINST_FILES;
+ if (!InstallParams.InstallMsgHandler)
+ {
+ InstallParams.InstallMsgHandler = SetupDefaultQueueCallbackW;
+ InstallParams.InstallMsgHandlerContext = SetupInitDefaultQueueCallback(InstallParams.hwndParent);
+ SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
+ }
+ }
+ Result = SetupInstallFromInfSectionW(InstallParams.hwndParent,
+ SelectedDriver->InfFileDetails->hInf, SectionName,
+ DoAction, hKey, NULL, SP_COPY_NEWER,
+ InstallParams.InstallMsgHandler, InstallParams.InstallMsgHandlerContext,
+ DeviceInfoSet, DeviceInfoData);
+ if (!Result)
+ goto cleanup;
+
+ ret = TRUE;
+
+cleanup:
+ if (hKey != INVALID_HANDLE_VALUE)
+ RegCloseKey(hKey);
+ }
+
+ TRACE("Returning %d\n", ret);
+ return ret;
}
/***********************************************************************
IN HDEVINFO DeviceInfoSet,
IN PSP_DEVINFO_DATA DeviceInfoData)
{
- struct DriverInfoElement *DriverInfo;
- struct DeviceInfoSet *DevInfoSet = (struct DeviceInfoSet *)DeviceInfoSet;
struct DeviceInfoElement *DevInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
+ SP_DEVINSTALL_PARAMS_W InstallParams;
+ struct DriverInfoElement *SelectedDriver;
SYSTEMTIME DriverDate;
WCHAR SectionName[MAX_PATH];
+ WCHAR Buffer[32];
DWORD SectionNameLength = 0;
BOOL Result = FALSE;
INFCONTEXT ContextService;
INT Flags;
+ ULONG DoAction;
DWORD RequiredSize;
- HINF hInf = NULL;
LPCWSTR AssociatedService = NULL;
+ LPWSTR pSectionName = NULL;
+ WCHAR ClassName[MAX_CLASS_NAME_LEN];
+ GUID ClassGuid;
+ LPWSTR lpGuidString = NULL, lpFullGuidString = NULL;
BOOL RebootRequired = FALSE;
- HKEY hEnumKey, hKey;
+ HKEY hKey = INVALID_HANDLE_VALUE;
+ HKEY hClassKey = INVALID_HANDLE_VALUE;
LONG rc;
+ BOOL ret = FALSE; /* Return value */
TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
SetLastError(ERROR_INVALID_HANDLE);
else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
SetLastError(ERROR_INVALID_USER_BUFFER);
- else if (DeviceInfoData && ((struct DeviceInfoElement *)DeviceInfoData->Reserved)->SelectedDriver == NULL)
- SetLastError(ERROR_INVALID_PARAMETER);
- else if (!DeviceInfoData && ((struct DeviceInfoSet *)DeviceInfoSet)->SelectedDriver == NULL)
- SetLastError(ERROR_INVALID_PARAMETER);
else
Result = TRUE;
if (!Result)
{
/* One parameter is bad */
- return FALSE;
+ goto cleanup;
}
- /* FIXME: If DI_FLAGSEX_SETFAILEDINSTALL is set, set FAILEDINSTALL flag in ConfigFlags registry and exit */
+ InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
+ Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
+ if (!Result)
+ goto cleanup;
- if (DeviceInfoData)
- DriverInfo = ((struct DeviceInfoElement *)DeviceInfoData->Reserved)->SelectedDriver;
- else
- DriverInfo = ((struct DeviceInfoSet *)DeviceInfoSet)->SelectedDriver;
- FileTimeToSystemTime(&DriverInfo->Info.DriverDate, &DriverDate);
+ if (InstallParams.FlagsEx & DI_FLAGSEX_SETFAILEDINSTALL)
+ {
+ /* FIXME: set FAILEDINSTALL in ConfigFlags registry value */
+ goto cleanup;
+ }
- hInf = SetupOpenInfFileW(DriverInfo->InfPath, NULL, INF_STYLE_WIN4, NULL);
- if (hInf == INVALID_HANDLE_VALUE)
- return FALSE;
+ SelectedDriver = (struct DriverInfoElement *)InstallParams.Reserved;
+ if (SelectedDriver == NULL)
+ {
+ SetLastError(ERROR_NO_DRIVER_SELECTED);
+ goto cleanup;
+ }
+
+ FileTimeToSystemTime(&SelectedDriver->Info.DriverDate, &DriverDate);
- Result = SetupDiGetActualSectionToInstallW(hInf, DriverInfo->InfSection,
+ Result = SetupDiGetActualSectionToInstallW(
+ SelectedDriver->InfFileDetails->hInf,
+ SelectedDriver->Details.SectionName,
SectionName, MAX_PATH, &SectionNameLength, NULL);
if (!Result || SectionNameLength > MAX_PATH - 9)
+ goto cleanup;
+ pSectionName = &SectionName[wcslen(SectionName)];
+
+ /* Get information from [Version] section */
+ if (!SetupDiGetINFClassW(SelectedDriver->Details.InfFileName, &ClassGuid, ClassName, MAX_CLASS_NAME_LEN, &RequiredSize))
+ goto cleanup;
+ /* Format ClassGuid to a string */
+ if (UuidToStringW((UUID*)&ClassGuid, &lpGuidString) != RPC_S_OK)
+ goto cleanup;
+ RequiredSize = lstrlenW(lpGuidString);
+ lpFullGuidString = HeapAlloc(GetProcessHeap(), 0, (RequiredSize + 3) * sizeof(WCHAR));
+ if (!lpFullGuidString)
{
- SetupCloseInfFile(hInf);
- return FALSE;
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto cleanup;
}
+ lpFullGuidString[0] = '{';
+ memcpy(&lpFullGuidString[1], lpGuidString, RequiredSize * sizeof(WCHAR));
+ lpFullGuidString[RequiredSize + 1] = '}';
+ lpFullGuidString[RequiredSize + 2] = '\0';
+
+ /* Open/Create driver key information */
+#if _WIN32_WINNT >= 0x502
+ hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_READ | KEY_WRITE);
+#else
+ hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_ALL_ACCESS);
+#endif
+ if (hKey == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND)
+ hKey = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, NULL, NULL);
+ if (hKey == INVALID_HANDLE_VALUE)
+ goto cleanup;
+
+ /* Install main section */
+ DoAction = SPINST_REGISTRY;
+ if (!(InstallParams.Flags & DI_NOFILECOPY))
+ {
+ DoAction |= SPINST_FILES;
+ if (!InstallParams.InstallMsgHandler)
+ {
+ InstallParams.InstallMsgHandler = SetupDefaultQueueCallbackW;
+ InstallParams.InstallMsgHandlerContext = SetupInitDefaultQueueCallback(InstallParams.hwndParent);
+ SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
+ }
+ }
+ *pSectionName = '\0';
+ Result = SetupInstallFromInfSectionW(InstallParams.hwndParent,
+ SelectedDriver->InfFileDetails->hInf, SectionName,
+ DoAction, hKey, NULL, SP_COPY_NEWER,
+ InstallParams.InstallMsgHandler, InstallParams.InstallMsgHandlerContext,
+ DeviceInfoSet, DeviceInfoData);
+ if (!Result)
+ goto cleanup;
+ if (!(InstallParams.Flags & DI_NOFILECOPY) && !(InstallParams.Flags & DI_NOVCP))
+ {
+ if (Result && InstallParams.InstallMsgHandler == SetupDefaultQueueCallbackW)
+ {
+ /* Delete resources allocated by SetupInitDefaultQueueCallback */
+ SetupTermDefaultQueueCallback(InstallParams.InstallMsgHandlerContext);
+ }
+ }
+ InstallParams.Flags |= DI_NOFILECOPY;
+ SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
- /* Create driver key information */
- FIXME("FIXME: Create driver key information\n");
-
/* Write information to driver key */
- FIXME("FIXME: Write information to driver key\n");
- FIXME("DriverDate : '%u-%u-%u'\n", 0, DriverDate.wMonth, DriverDate.wDay, DriverDate.wYear);
- FIXME("DriverDateData :"); { ULONG i; for (i = 0; i < sizeof(DriverInfo->Info.DriverDate); i++) DbgPrint(" %02x", ((PCHAR)&DriverInfo->Info.DriverDate)[i] & 0xff); } DbgPrint("\n");
- FIXME("DriverDesc : '%S'\n", DriverInfo->Info.Description);
- FIXME("DriverVersion : '%u.%u.%u.%u'\n", DriverInfo->Info.DriverVersion & 0xff, (DriverInfo->Info.DriverVersion >> 8) & 0xff, (DriverInfo->Info.DriverVersion >> 16) & 0xff, (DriverInfo->Info.DriverVersion >> 24) & 0xff);
- FIXME("InfPath : '%S'\n", DriverInfo->InfPath);
- FIXME("InfSection : '%S'\n", DriverInfo->InfSection); /* FIXME: remove extension */
- FIXME("InfSectionExt : '%S'\n", L"???"); /* FIXME */
- FIXME("MatchingDeviceId: '%S'\n", L"???"); /* FIXME */
- FIXME("ProviderName : '%S'\n", DriverInfo->Info.ProviderName);
-
- /* Install services */
- wcscat(SectionName, L".Services");
- Result = SetupFindFirstLineW(hInf, SectionName, NULL, &ContextService);
+ *pSectionName = UNICODE_NULL;
+ TRACE("Write information to driver key\n");
+ TRACE("DriverDate : '%u-%u-%u'\n", DriverDate.wMonth, DriverDate.wDay, DriverDate.wYear);
+ TRACE("DriverDesc : '%S'\n", SelectedDriver->Info.Description);
+ TRACE("DriverVersion : '%u.%u.%u.%u'\n", SelectedDriver->Info.DriverVersion & 0xff, (SelectedDriver->Info.DriverVersion >> 8) & 0xff, (SelectedDriver->Info.DriverVersion >> 16) & 0xff, (SelectedDriver->Info.DriverVersion >> 24) & 0xff);
+ TRACE("InfPath : '%S'\n", SelectedDriver->Details.InfFileName);
+ TRACE("InfSection : '%S'\n", SelectedDriver->Details.SectionName);
+ TRACE("InfSectionExt : '%S'\n", &SectionName[wcslen(SelectedDriver->Details.SectionName)]);
+ TRACE("MatchingDeviceId: '%S'\n", SelectedDriver->MatchingId);
+ TRACE("ProviderName : '%S'\n", SelectedDriver->Info.ProviderName);
+ swprintf(Buffer, L"%u-%u-%u", DriverDate.wMonth, DriverDate.wDay, DriverDate.wYear);
+ rc = RegSetValueEx(hKey, L"DriverDate", 0, REG_SZ, (const BYTE *)Buffer, (wcslen(Buffer) + 1) * sizeof(WCHAR));
+ if (rc == ERROR_SUCCESS)
+ rc = RegSetValueEx(hKey, L"DriverDateData", 0, REG_BINARY, (const BYTE *)&SelectedDriver->Info.DriverDate, sizeof(FILETIME));
+ if (rc == ERROR_SUCCESS)
+ rc = RegSetValueEx(hKey, L"DriverDesc", 0, REG_SZ, (const BYTE *)SelectedDriver->Info.Description, (wcslen(SelectedDriver->Info.Description) + 1) * sizeof(WCHAR));
+ if (rc == ERROR_SUCCESS)
+ {
+ swprintf(Buffer, L"%u.%u.%u.%u", SelectedDriver->Info.DriverVersion & 0xff, (SelectedDriver->Info.DriverVersion >> 8) & 0xff, (SelectedDriver->Info.DriverVersion >> 16) & 0xff, (SelectedDriver->Info.DriverVersion >> 24) & 0xff);
+ rc = RegSetValueEx(hKey, L"DriverVersion", 0, REG_SZ, (const BYTE *)Buffer, (wcslen(Buffer) + 1) * sizeof(WCHAR));
+ }
+ if (rc == ERROR_SUCCESS)
+ rc = RegSetValueEx(hKey, L"InfPath", 0, REG_SZ, (const BYTE *)SelectedDriver->Details.InfFileName, (wcslen(SelectedDriver->Details.InfFileName) + 1) * sizeof(WCHAR));
+ if (rc == ERROR_SUCCESS)
+ rc = RegSetValueEx(hKey, L"InfSection", 0, REG_SZ, (const BYTE *)SelectedDriver->Details.SectionName, (wcslen(SelectedDriver->Details.SectionName) + 1) * sizeof(WCHAR));
+ if (rc == ERROR_SUCCESS)
+ rc = RegSetValueEx(hKey, L"InfSectionExt", 0, REG_SZ, (const BYTE *)&SectionName[wcslen(SelectedDriver->Details.SectionName)], (wcslen(SectionName) - wcslen(SelectedDriver->Details.SectionName) + 1) * sizeof(WCHAR));
+ if (rc == ERROR_SUCCESS)
+ rc = RegSetValueEx(hKey, L"MatchingDeviceId", 0, REG_SZ, (const BYTE *)SelectedDriver->MatchingId, (wcslen(SelectedDriver->MatchingId) + 1) * sizeof(WCHAR));
+ if (rc == ERROR_SUCCESS)
+ rc = RegSetValueEx(hKey, L"ProviderName", 0, REG_SZ, (const BYTE *)SelectedDriver->Info.ProviderName, (wcslen(SelectedDriver->Info.ProviderName) + 1) * sizeof(WCHAR));
+ if (rc != ERROR_SUCCESS)
+ {
+ SetLastError(rc);
+ goto cleanup;
+ }
+ RegCloseKey(hKey);
+ hKey = INVALID_HANDLE_VALUE;
+
+ /* FIXME: Process .LogConfigOverride section */
+
+ /* Install .Services section */
+ wcscpy(pSectionName, L".Services");
+ Result = SetupFindFirstLineW(SelectedDriver->InfFileDetails->hInf, SectionName, NULL, &ContextService);
while (Result)
{
LPWSTR ServiceName = NULL;
NULL, 0,
&RequiredSize);
if (!Result)
- goto cleanup;
+ goto nextfile;
if (RequiredSize > 0)
{
/* We got the needed size for the buffer */
if (!ServiceName)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- goto cleanup;
+ goto nextfile;
}
Result = SetupGetStringFieldW(
&ContextService,
ServiceName, RequiredSize,
&RequiredSize);
if (!Result)
- goto cleanup;
+ goto nextfile;
}
Result = SetupGetIntField(
&ContextService,
NULL, 0,
&RequiredSize);
if (!Result)
- goto cleanup;
+ goto nextfile;
if (RequiredSize > 0)
{
/* We got the needed size for the buffer */
if (!ServiceSection)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- goto cleanup;
+ goto nextfile;
}
Result = SetupGetStringFieldW(
&ContextService,
3, /* Field index */
ServiceSection, RequiredSize,
- &RequiredSize);
+ &RequiredSize);
if (!Result)
- goto cleanup;
+ goto nextfile;
}
SetLastError(ERROR_SUCCESS);
- Result = SetupInstallServicesFromInfSectionExW(hInf, ServiceSection, Flags, DeviceInfoSet, DeviceInfoData, NULL, NULL);
+ Result = SetupInstallServicesFromInfSectionExW(
+ SelectedDriver->InfFileDetails->hInf,
+ ServiceSection, Flags, DeviceInfoSet, DeviceInfoData, ServiceName, NULL);
if (Result && (Flags & SPSVCINST_ASSOCSERVICE))
{
AssociatedService = ServiceName;
if (GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED)
RebootRequired = TRUE;
}
-cleanup:
+nextfile:
HeapFree(GetProcessHeap(), 0, ServiceName);
HeapFree(GetProcessHeap(), 0, ServiceSection);
if (!Result)
- {
- HeapFree(GetProcessHeap(), 0, (LPWSTR)AssociatedService);
- SetupCloseInfFile(hInf);
- return FALSE;
- }
+ goto cleanup;
Result = SetupFindNextLine(&ContextService, &ContextService);
}
/* Copy .inf file to Inf\ directory */
FIXME("FIXME: Copy .inf file to Inf\\ directory\n"); /* SetupCopyOEMInf */
+ /* Open device registry key */
+ hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_SET_VALUE);
+ if (hKey == INVALID_HANDLE_VALUE)
+ goto cleanup;
+
+ /* Install .HW section */
+ wcscpy(pSectionName, L".HW");
+ Result = SetupInstallFromInfSectionW(InstallParams.hwndParent,
+ SelectedDriver->InfFileDetails->hInf, SectionName,
+ SPINST_REGISTRY, hKey, NULL, 0,
+ InstallParams.InstallMsgHandler, InstallParams.InstallMsgHandlerContext,
+ DeviceInfoSet, DeviceInfoData);
+ if (!Result)
+ goto cleanup;
+
/* Write information to enum key */
- rc = RegOpenKeyExW(DevInfoSet->HKLM,
- EnumKeyName,
- 0,
- KEY_ENUMERATE_SUB_KEYS,
- &hEnumKey);
- if (rc != ERROR_SUCCESS)
- {
- SetLastError(rc);
- HeapFree(GetProcessHeap(), 0, (LPWSTR)AssociatedService);
- SetupCloseInfFile(hInf);
- return FALSE;
- }
- rc = RegOpenKeyExW(
- hEnumKey,
- DevInfo->DeviceName,
- 0, /* Options */
- KEY_SET_VALUE,
- &hKey);
- RegCloseKey(hEnumKey);
- if (rc != ERROR_SUCCESS)
- {
- SetLastError(rc);
- HeapFree(GetProcessHeap(), 0, (LPWSTR)AssociatedService);
- SetupCloseInfFile(hInf);
- return FALSE;
- }
- FIXME("FIXME: Write information to enum key\n");
- FIXME("ParentIdPrefix : '%S'\n", L"0000"); /* FIXME */
- //FIXME("Service : '%S'\n", AssociatedService);
- FIXME("Class : '%S'\n", L"???"); /* FIXME: SetupDiGetINFClass */
- FIXME("ClassGUID : '%S'\n", L"???"); /* FIXME: SetupDiGetINFClass */
- //FIXME("DeviceDesc : '%S'\n", DriverInfo->Info.Description);
- FIXME("Driver : '%S'\n", L"???"); /* FIXME: autogenerated key */
- //FIXME("Mfg : '%S'\n", DriverInfo->Info.MfgName);
+ TRACE("Write information to enum key\n");
+ TRACE("Service : '%S'\n", AssociatedService);
+ TRACE("Class : '%S'\n", ClassName);
+ TRACE("ClassGUID : '%S'\n", lpFullGuidString);
+ TRACE("DeviceDesc : '%S'\n", SelectedDriver->Info.Description);
+ TRACE("Mfg : '%S'\n", SelectedDriver->Info.MfgName);
rc = RegSetValueEx(hKey, L"Service", 0, REG_SZ, (const BYTE *)AssociatedService, (wcslen(AssociatedService) + 1) * sizeof(WCHAR));
if (rc == ERROR_SUCCESS)
- rc = RegSetValueEx(hKey, L"DeviceDesc", 0, REG_SZ, (const BYTE *)DriverInfo->Info.Description, (wcslen(DriverInfo->Info.Description) + 1) * sizeof(WCHAR));
+ rc = RegSetValueEx(hKey, L"Class", 0, REG_SZ, (const BYTE *)ClassName, (wcslen(ClassName) + 1) * sizeof(WCHAR));
if (rc == ERROR_SUCCESS)
- rc = RegSetValueEx(hKey, L"Mfg", 0, REG_SZ, (const BYTE *)DriverInfo->Info.MfgName, (wcslen(DriverInfo->Info.MfgName) + 1) * sizeof(WCHAR));
- RegCloseKey(hKey);
+ rc = RegSetValueEx(hKey, L"ClassGUID", 0, REG_SZ, (const BYTE *)lpFullGuidString, (wcslen(lpFullGuidString) + 1) * sizeof(WCHAR));
+ if (rc == ERROR_SUCCESS)
+ rc = RegSetValueEx(hKey, L"DeviceDesc", 0, REG_SZ, (const BYTE *)SelectedDriver->Info.Description, (wcslen(SelectedDriver->Info.Description) + 1) * sizeof(WCHAR));
+ if (rc == ERROR_SUCCESS)
+ rc = RegSetValueEx(hKey, L"Mfg", 0, REG_SZ, (const BYTE *)SelectedDriver->Info.MfgName, (wcslen(SelectedDriver->Info.MfgName) + 1) * sizeof(WCHAR));
if (rc != ERROR_SUCCESS)
{
SetLastError(rc);
- HeapFree(GetProcessHeap(), 0, (LPWSTR)AssociatedService);
- SetupCloseInfFile(hInf);
- return FALSE;
+ goto cleanup;
}
- /* Load the driver/call AddDevice */
- FIXME("FIXME: Load the driver/call AddDevice\n");
-
- /* Send IRP_MN_START_DEVICE if needed */
- //if (!RebootRequired && !(Flags & (DI_NEEDRESTART | DI_NEEDREBOOT | DI_DONOTCALLCONFIGMG)))
- FIXME("FIXME: Send IRP_MN_START_DEVICE\n");
+ /* Start the device */
+ if (!RebootRequired && !(InstallParams.Flags & (DI_NEEDRESTART | DI_NEEDREBOOT | DI_DONOTCALLCONFIGMG)))
+ {
+ PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData;
+ NTSTATUS Status;
+ RtlInitUnicodeString(&ResetDeviceData.DeviceInstance, DevInfo->DeviceName);
+ Status = NtPlugPlayControl(PlugPlayControlResetDevice, &ResetDeviceData, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA));
+ ret = NT_SUCCESS(Status);
+ }
+ else
+ ret = TRUE;
+cleanup:
/* End of installation */
+ if (hClassKey != INVALID_HANDLE_VALUE)
+ RegCloseKey(hClassKey);
+ if (hKey != INVALID_HANDLE_VALUE)
+ RegCloseKey(hKey);
+ if (lpGuidString)
+ RpcStringFreeW(&lpGuidString);
HeapFree(GetProcessHeap(), 0, (LPWSTR)AssociatedService);
- SetupCloseInfFile(hInf);
- return TRUE;
+ HeapFree(GetProcessHeap(), 0, lpFullGuidString);
+
+ TRACE("Returning %d\n", ret);
+ return ret;
}