* SetupAPI device installer
*
* Copyright 2000 Andreas Mohr for CodeWeavers
- * 2005 Hervé Poussineau (hpoussin@reactos.com)
+ * 2005 Hervé Poussineau (hpoussin@reactos.org)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "config.h"
-#include "wine/port.h"
-
-#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 "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 INITGUID
#include "setupapi_private.h"
-
WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
/* Unicode constants */
static const WCHAR ClassGUID[] = {'C','l','a','s','s','G','U','I','D',0};
static const WCHAR Class[] = {'C','l','a','s','s',0};
static const WCHAR ClassInstall32[] = {'C','l','a','s','s','I','n','s','t','a','l','l','3','2',0};
+static const WCHAR Control[] = {'C','o','n','t','r','o','l',0};
static const WCHAR DeviceInstance[] = {'D','e','v','i','c','e','I','n','s','t','a','n','c','e',0};
-static const WCHAR NoDisplayClass[] = {'N','o','D','i','s','p','l','a','y','C','l','a','s','s',0};
-static const WCHAR NoInstallClass[] = {'N','o','I','s','t','a','l','l','C','l','a','s','s',0};
-static const WCHAR NoUseClass[] = {'N','o','U','s','e','C','l','a','s','s',0};
-static const WCHAR NtExtension[] = {'.','N','T',0};
-static const WCHAR NtPlatformExtension[] = {'.','N','T','x','8','6',0};
+static const WCHAR DotCoInstallers[] = {'.','C','o','I','n','s','t','a','l','l','e','r','s',0};
+static const WCHAR DotServices[] = {'.','S','e','r','v','i','c','e','s',0};
+static const WCHAR InterfaceInstall32[] = {'I','n','t','e','r','f','a','c','e','I','n','s','t','a','l','l','3','2',0};
+static const WCHAR Linked[] = {'L','i','n','k','e','d',0};
static const WCHAR SymbolicLink[] = {'S','y','m','b','o','l','i','c','L','i','n','k',0};
static const WCHAR Version[] = {'V','e','r','s','i','o','n',0};
-static const WCHAR WinExtension[] = {'.','W','i','n',0};
-
-/* Registry key and value names */
-static const WCHAR ControlClass[] = {'S','y','s','t','e','m','\\',
- 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
- 'C','o','n','t','r','o','l','\\',
- 'C','l','a','s','s',0};
-
-static const WCHAR DeviceClasses[] = {'S','y','s','t','e','m','\\',
- 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
- 'C','o','n','t','r','o','l','\\',
- 'D','e','v','i','c','e','C','l','a','s','s','e','s',0};
-
-static const WCHAR EnumKeyName[] = {'S','y','s','t','e','m','\\',
- 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
- 'E','n','u','m',0};
-
/* FIXME: header mess */
DEFINE_GUID(GUID_NULL,
0x00000000L, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
+typedef DWORD
+(CALLBACK* CLASS_INSTALL_PROC) (
+ IN DI_FUNCTION InstallFunction,
+ IN HDEVINFO DeviceInfoSet,
+ IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL);
+typedef BOOL
+(WINAPI* DEFAULT_CLASS_INSTALL_PROC) (
+ IN HDEVINFO DeviceInfoSet,
+ IN OUT PSP_DEVINFO_DATA DeviceInfoData);
+typedef DWORD
+(CALLBACK* COINSTALLER_PROC) (
+ IN DI_FUNCTION InstallFunction,
+ IN HDEVINFO DeviceInfoSet,
+ IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
+ IN OUT PCOINSTALLER_CONTEXT_DATA Context);
+typedef BOOL
+(WINAPI* PROPERTY_PAGE_PROVIDER) (
+ IN PSP_PROPSHEETPAGE_REQUEST PropPageRequest,
+ IN LPFNADDPROPSHEETPAGE fAddFunc,
+ IN LPARAM lParam);
+typedef BOOL
+(*UPDATE_CLASS_PARAM_HANDLER) (
+ IN HDEVINFO DeviceInfoSet,
+ IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
+ IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL,
+ IN DWORD ClassInstallParamsSize);
-#define SETUP_DEV_INFO_SET_MAGIC 0xd00ff057
-
-struct DeviceInterface /* Element of DeviceInfoElement.InterfaceHead */
-{
- LIST_ENTRY ListEntry;
-
- GUID InterfaceClassGuid;
-
- /* SPINT_ACTIVE : the interface is active/enabled
- * SPINT_DEFAULT: the interface is the default interface for the device class FIXME???
- * SPINT_REMOVED: the interface is removed
- */
- DWORD Flags;
-
- WCHAR SymbolicLink[0]; /* \\?\ACPI#PNP0501#4&2658d0a0&0#{GUID} */
-};
-
-struct DriverInfoElement /* Element of DeviceInfoSet.DriverListHead and DeviceInfoElement.DriverListHead */
-{
- LIST_ENTRY ListEntry;
-
- SP_DRVINFO_DATA_V2_W Info;
-};
-
-struct DeviceInfoElement /* Element of DeviceInfoSet.ListHead */
+struct CoInstallerElement
{
LIST_ENTRY ListEntry;
- /* Information about devnode:
- * - DeviceName:
- * "Root\*PNP0501" for example.
- * It doesn't contain the unique ID for the device
- * (points into the Data field at the end of the structure)
- * WARNING: no NULL char exist between DeviceName and UniqueId
- * in Data field!
- * - UniqueId
- * "5&1be2108e&0" or "0000"
- * If DICD_GENERATE_ID is specified in creation flags,
- * this unique ID is autogenerated using 4 digits, base 10
- * (points into the Data field at the end of the structure)
- * - DeviceDescription
- * String which identifies the device. Can be NULL. If not NULL,
- * points into the Data field at the end of the structure
- * - ClassGuid
- * Identifies the class of this device. FIXME: can it be GUID_NULL?
- * - CreationFlags
- * Is a combination of:
- * - DICD_GENERATE_ID
- * 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 InterfaceHead; /* List of struct DeviceInterface */
-
- WCHAR Data[0];
+ HMODULE Module;
+ COINSTALLER_PROC Function;
+ BOOL DoPostProcessing;
+ PVOID PrivateData;
};
-struct DeviceInfoSet /* HDEVINFO */
-{
- 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;
-
- /* 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 */
+static BOOL
+PropertyChangeHandler(
+ IN HDEVINFO DeviceInfoSet,
+ IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
+ IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL,
+ IN DWORD ClassInstallParamsSize);
+
+static UPDATE_CLASS_PARAM_HANDLER UpdateClassInstallParamHandlers[] = {
+ NULL, /* DIF_SELECTDEVICE */
+ NULL, /* DIF_INSTALLDEVICE */
+ NULL, /* DIF_ASSIGNRESOURCES */
+ NULL, /* DIF_PROPERTIES */
+ NULL, /* DIF_REMOVE */
+ NULL, /* DIF_FIRSTTIMESETUP */
+ NULL, /* DIF_FOUNDDEVICE */
+ NULL, /* DIF_SELECTCLASSDRIVERS */
+ NULL, /* DIF_VALIDATECLASSDRIVERS */
+ NULL, /* DIF_INSTALLCLASSDRIVERS */
+ NULL, /* DIF_CALCDISKSPACE */
+ NULL, /* DIF_DESTROYPRIVATEDATA */
+ NULL, /* DIF_VALIDATEDRIVER */
+ NULL, /* DIF_MOVEDEVICE */
+ NULL, /* DIF_DETECT */
+ NULL, /* DIF_INSTALLWIZARD */
+ NULL, /* DIF_DESTROYWIZARDDATA */
+ PropertyChangeHandler, /* DIF_PROPERTYCHANGE */
+ NULL, /* DIF_ENABLECLASS */
+ NULL, /* DIF_DETECTVERIFY */
+ NULL, /* DIF_INSTALLDEVICEFILES */
+ NULL, /* DIF_UNREMOVE */
+ NULL, /* DIF_SELECTBESTCOMPATDRV */
+ NULL, /* DIF_ALLOW_INSTALL */
+ NULL, /* DIF_REGISTERDEVICE */
+ NULL, /* DIF_NEWDEVICEWIZARD_PRESELECT */
+ NULL, /* DIF_NEWDEVICEWIZARD_SELECT */
+ NULL, /* DIF_NEWDEVICEWIZARD_PREANALYZE */
+ NULL, /* DIF_NEWDEVICEWIZARD_POSTANALYZE */
+ NULL, /* DIF_NEWDEVICEWIZARD_FINISHINSTALL */
+ NULL, /* DIF_UNUSED1 */
+ NULL, /* DIF_INSTALLINTERFACES */
+ NULL, /* DIF_DETECTCANCEL */
+ NULL, /* DIF_REGISTER_COINSTALLERS */
+ NULL, /* DIF_ADDPROPERTYPAGE_ADVANCED */
+ NULL, /* DIF_ADDPROPERTYPAGE_BASIC */
+ NULL, /* DIF_RESERVED1 */
+ NULL, /* DIF_TROUBLESHOOTER */
+ NULL, /* DIF_POWERMESSAGEWAKE */
+ NULL, /* DIF_ADDREMOTEPROPERTYPAGE_ADVANCED */
+ NULL, /* DIF_UPDATEDRIVER_UI */
+ NULL /* DIF_RESERVED2 */
};
/***********************************************************************
LONG lError;
DWORD dwGuidListIndex = 0;
- TRACE("\n");
+ TRACE("0x%lx %p %lu %p %s %p\n", Flags, ClassGuidList,
+ ClassGuidListSize, RequiredSize, debugstr_w(MachineName), Reserved);
if (RequiredSize != NULL)
*RequiredSize = 0;
hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
- KEY_ALL_ACCESS,
+ KEY_ENUMERATE_SUB_KEYS,
DIOCR_INSTALLER,
MachineName,
Reserved);
TRACE("RegEnumKeyExW() returns %ld\n", lError);
if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
{
- TRACE("Key name: %p\n", szKeyName);
+ TRACE("Key name: %s\n", debugstr_w(szKeyName));
if (RegOpenKeyExW(hClassesKey,
szKeyName,
0,
- KEY_ALL_ACCESS,
+ KEY_QUERY_VALUE,
&hClassKey))
{
RegCloseKey(hClassesKey);
}
if (!RegQueryValueExW(hClassKey,
- NoUseClass,
+ REGSTR_VAL_NOUSECLASS,
NULL,
NULL,
NULL,
if ((Flags & DIBCI_NOINSTALLCLASS) &&
(!RegQueryValueExW(hClassKey,
- NoInstallClass,
+ REGSTR_VAL_NOINSTALLCLASS,
NULL,
NULL,
NULL,
if ((Flags & DIBCI_NODISPLAYCLASS) &&
(!RegQueryValueExW(hClassKey,
- NoDisplayClass,
+ REGSTR_VAL_NODISPLAYCLASS,
NULL,
NULL,
NULL,
RegCloseKey(hClassKey);
- TRACE("Guid: %p\n", szKeyName);
+ TRACE("Guid: %s\n", debugstr_w(szKeyName));
if (dwGuidListIndex < ClassGuidListSize)
{
if (szKeyName[0] == L'{' && szKeyName[37] == L'}')
{
szKeyName[37] = 0;
}
- TRACE("Guid: %p\n", &szKeyName[1]);
+ TRACE("Guid: %s\n", debugstr_w(&szKeyName[1]));
UuidFromStringW(&szKeyName[1],
&ClassGuidList[dwGuidListIndex]);
LONG lError;
DWORD dwGuidListIndex = 0;
+ TRACE("%s %p %lu %p %s %p\n", debugstr_w(ClassName), ClassGuidList,
+ ClassGuidListSize, RequiredSize, debugstr_w(MachineName), Reserved);
+
if (RequiredSize != NULL)
*RequiredSize = 0;
TRACE("RegEnumKeyExW() returns %ld\n", lError);
if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
{
- TRACE("Key name: %p\n", szKeyName);
+ TRACE("Key name: %s\n", debugstr_w(szKeyName));
if (RegOpenKeyExW(hClassesKey,
szKeyName,
(LPBYTE)szClassName,
&dwLength))
{
- TRACE("Class name: %p\n", szClassName);
+ TRACE("Class name: %s\n", debugstr_w(szClassName));
if (strcmpiW(szClassName, ClassName) == 0)
{
TRACE("Found matching class name\n");
- TRACE("Guid: %p\n", szKeyName);
+ TRACE("Guid: %s\n", debugstr_w(szKeyName));
if (dwGuidListIndex < ClassGuidListSize)
{
if (szKeyName[0] == L'{' && szKeyName[37] == L'}')
{
szKeyName[37] = 0;
}
- TRACE("Guid: %p\n", &szKeyName[1]);
+ TRACE("Guid: %s\n", debugstr_w(&szKeyName[1]));
UuidFromStringW(&szKeyName[1],
&ClassGuidList[dwGuidListIndex]);
DWORD dwLength;
LONG rc;
+ TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid), ClassName,
+ ClassNameSize, RequiredSize, debugstr_w(MachineName), Reserved);
+
hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
KEY_QUERY_VALUE,
DIOCR_INSTALLER,
LPWSTR MachineNameW = NULL;
HDEVINFO hDevInfo;
- TRACE("%p %p %s %p\n", ClassGuid, hwndParent, MachineName, Reserved);
+ TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid), hwndParent,
+ debugstr_a(MachineName), Reserved);
if (MachineName)
{
return hDevInfo;
}
+static DWORD
+GetErrorCodeFromCrCode(const IN CONFIGRET cr)
+{
+ switch (cr)
+ {
+ case CR_INVALID_MACHINENAME: return ERROR_INVALID_COMPUTERNAME;
+ case CR_OUT_OF_MEMORY: return ERROR_NOT_ENOUGH_MEMORY;
+ case CR_SUCCESS: return ERROR_SUCCESS;
+ default:
+ /* FIXME */
+ return ERROR_GEN_FAILURE;
+ }
+
+ /* Does not happen */
+}
+
/***********************************************************************
* SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
*/
PVOID Reserved)
{
struct DeviceInfoSet *list;
+ LPWSTR UNCServerName = NULL;
+ DWORD size;
DWORD rc;
+ //CONFIGRET cr;
+ HDEVINFO ret = (HDEVINFO)INVALID_HANDLE_VALUE;;
- TRACE("%p %p %S %p\n", ClassGuid, hwndParent, MachineName, Reserved);
+ TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid), hwndParent,
+ debugstr_w(MachineName), Reserved);
- list = HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInfoSet));
+ size = FIELD_OFFSET(struct DeviceInfoSet, szData);
+ if (MachineName)
+ size += (wcslen(MachineName) + 3) * sizeof(WCHAR);
+ list = HeapAlloc(GetProcessHeap(), 0, size);
if (!list)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- return (HDEVINFO)INVALID_HANDLE_VALUE;
+ goto cleanup;
}
+ 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);
if (rc != ERROR_SUCCESS)
{
SetLastError(rc);
- HeapFree(GetProcessHeap(), 0, list);
- return (HDEVINFO)INVALID_HANDLE_VALUE;
+ goto cleanup;
+ }
+ UNCServerName = HeapAlloc(GetProcessHeap(), 0, (strlenW(MachineName) + 3) * sizeof(WCHAR));
+ if (!UNCServerName)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto cleanup;
}
+
+ strcpyW(UNCServerName + 2, MachineName);
+ list->szData[0] = list->szData[1] = '\\';
+ strcpyW(list->szData + 2, MachineName);
+ list->MachineName = list->szData;
}
else
{
+ DWORD Size = MAX_PATH;
list->HKLM = HKEY_LOCAL_MACHINE;
+ UNCServerName = HeapAlloc(GetProcessHeap(), 0, (MAX_PATH + 2) * sizeof(WCHAR));
+ if (!UNCServerName)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto cleanup;
+ }
+ if (!GetComputerNameW(UNCServerName + 2, &Size))
+ goto cleanup;
+ list->MachineName = NULL;
+ }
+#if 0
+ UNCServerName[0] = UNCServerName[1] = '\\';
+ cr = CM_Connect_MachineW(UNCServerName, &list->hMachine);
+ if (cr != CR_SUCCESS)
+ {
+ SetLastError(GetErrorCodeFromCrCode(cr));
+ goto cleanup;
}
- list->Flags = 0; /* FIXME */
- list->FlagsEx = 0; /* FIXME */
+#endif
InitializeListHead(&list->DriverListHead);
InitializeListHead(&list->ListHead);
- return (HDEVINFO)list;
+
+ ret = (HDEVINFO)list;
+
+cleanup:
+ if (ret == INVALID_HANDLE_VALUE)
+ {
+ if (list && list->HKLM != 0 && list->HKLM != HKEY_LOCAL_MACHINE)
+ RegCloseKey(list->HKLM);
+ HeapFree(GetProcessHeap(), 0, list);
+ }
+ HeapFree(GetProcessHeap(), 0, UNCServerName);
+ return ret;
}
/***********************************************************************
else if (DeviceInfoSet && DeviceInfoSet != (HDEVINFO)INVALID_HANDLE_VALUE)
{
struct DeviceInfoSet *list = (struct DeviceInfoSet *)DeviceInfoSet;
-
+
if (list->magic != SETUP_DEV_INFO_SET_MAGIC)
SetLastError(ERROR_INVALID_HANDLE);
else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
memcpy(&DeviceInfoData->ClassGuid,
&DevInfo->ClassGuid,
sizeof(GUID));
- DeviceInfoData->DevInst = 0; /* FIXME */
- /* Note: this appears to be dangerous, passing a private
- * pointer a heap-allocated datum to the caller. However, the
- * expected lifetime of the device data is the same as the
- * HDEVINFO; once that is closed, the data are no longer valid.
- */
+ DeviceInfoData->DevInst = DevInfo->dnDevInst;
DeviceInfoData->Reserved = (ULONG_PTR)DevInfo;
ret = TRUE;
}
/***********************************************************************
* SetupDiGetActualSectionToInstallA (SETUPAPI.@)
*/
-BOOL WINAPI SetupDiGetActualSectionToInstallA(
- HINF InfHandle,
- PCSTR InfSectionName,
- PSTR InfSectionWithExt,
- DWORD InfSectionWithExtSize,
- PDWORD RequiredSize,
- PSTR *Extension)
+BOOL WINAPI
+SetupDiGetActualSectionToInstallA(
+ IN HINF InfHandle,
+ IN PCSTR InfSectionName,
+ OUT PSTR InfSectionWithExt OPTIONAL,
+ IN DWORD InfSectionWithExtSize,
+ OUT PDWORD RequiredSize OPTIONAL,
+ OUT PSTR *Extension OPTIONAL)
+{
+ return SetupDiGetActualSectionToInstallExA(InfHandle, InfSectionName,
+ NULL, InfSectionWithExt, InfSectionWithExtSize, RequiredSize,
+ Extension, NULL);
+}
+
+/***********************************************************************
+ * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
+ */
+BOOL WINAPI
+SetupDiGetActualSectionToInstallW(
+ IN HINF InfHandle,
+ IN PCWSTR InfSectionName,
+ OUT PWSTR InfSectionWithExt OPTIONAL,
+ IN DWORD InfSectionWithExtSize,
+ OUT PDWORD RequiredSize OPTIONAL,
+ OUT PWSTR *Extension OPTIONAL)
+{
+ return SetupDiGetActualSectionToInstallExW(InfHandle, InfSectionName,
+ NULL, InfSectionWithExt, InfSectionWithExtSize, RequiredSize,
+ Extension, NULL);
+}
+
+/***********************************************************************
+ * SetupDiGetActualSectionToInstallExA (SETUPAPI.@)
+ */
+BOOL WINAPI
+SetupDiGetActualSectionToInstallExA(
+ IN HINF InfHandle,
+ IN PCSTR InfSectionName,
+ IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL,
+ OUT PSTR InfSectionWithExt OPTIONAL,
+ IN DWORD InfSectionWithExtSize,
+ OUT PDWORD RequiredSize OPTIONAL,
+ OUT PSTR* Extension OPTIONAL,
+ IN PVOID Reserved)
{
LPWSTR InfSectionNameW = NULL;
- PWSTR InfSectionWithExtW = NULL;
+ LPWSTR InfSectionWithExtW = NULL;
PWSTR ExtensionW;
BOOL bResult = FALSE;
if (InfSectionName)
{
InfSectionNameW = MultiByteToUnicode(InfSectionName, CP_ACP);
- if (InfSectionNameW == NULL) goto end;
+ if (InfSectionNameW == NULL)
+ goto cleanup;
}
if (InfSectionWithExt)
{
- InfSectionWithExtW = HeapAlloc(GetProcessHeap(), 0, InfSectionWithExtSize * sizeof(WCHAR));
- if (InfSectionWithExtW == NULL) goto end;
+ InfSectionWithExtW = MyMalloc(InfSectionWithExtSize * sizeof(WCHAR));
+ if (InfSectionWithExtW == NULL)
+ goto cleanup;
}
- bResult = SetupDiGetActualSectionToInstallW(InfHandle, InfSectionNameW,
- InfSectionWithExt ? InfSectionNameW : NULL,
- InfSectionWithExtSize, RequiredSize,
- Extension ? &ExtensionW : NULL);
+ bResult = SetupDiGetActualSectionToInstallExW(
+ InfHandle, InfSectionNameW, AlternatePlatformInfo,
+ InfSectionWithExt ? InfSectionWithExtW : NULL,
+ InfSectionWithExtSize,
+ RequiredSize,
+ Extension ? &ExtensionW : NULL,
+ Reserved);
if (bResult && InfSectionWithExt)
{
*Extension = &InfSectionWithExt[ExtensionW - InfSectionWithExtW];
}
-end:
- if (InfSectionNameW) MyFree(InfSectionNameW);
- if (InfSectionWithExtW) HeapFree(GetProcessHeap(), 0, InfSectionWithExtW);
+cleanup:
+ MyFree(InfSectionNameW);
+ MyFree(InfSectionWithExtW);
return bResult;
}
/***********************************************************************
- * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
+ * SetupDiGetActualSectionToInstallExW (SETUPAPI.@)
*/
-BOOL WINAPI SetupDiGetActualSectionToInstallW(
- HINF InfHandle,
- PCWSTR InfSectionName,
- PWSTR InfSectionWithExt,
- DWORD InfSectionWithExtSize,
- PDWORD RequiredSize,
- PWSTR *Extension)
+BOOL WINAPI
+SetupDiGetActualSectionToInstallExW(
+ IN HINF InfHandle,
+ IN PCWSTR InfSectionName,
+ IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL,
+ OUT PWSTR InfSectionWithExt OPTIONAL,
+ IN DWORD InfSectionWithExtSize,
+ OUT PDWORD RequiredSize OPTIONAL,
+ OUT PWSTR* Extension OPTIONAL,
+ IN PVOID Reserved)
{
- WCHAR szBuffer[MAX_PATH];
- DWORD dwLength;
- DWORD dwFullLength;
- LONG lLineCount = -1;
-
- lstrcpyW(szBuffer, InfSectionName);
- dwLength = lstrlenW(szBuffer);
+ BOOL ret = FALSE;
- if (OsVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
- {
- /* Test section name with '.NTx86' extension */
- lstrcpyW(&szBuffer[dwLength], NtPlatformExtension);
- lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
+ TRACE("%p %s %p %p %lu %p %p %p\n", InfHandle, debugstr_w(InfSectionName),
+ AlternatePlatformInfo, InfSectionWithExt, InfSectionWithExtSize,
+ RequiredSize, Extension, Reserved);
- if (lLineCount == -1)
- {
- /* Test section name with '.NT' extension */
- lstrcpyW(&szBuffer[dwLength], NtExtension);
- lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
- }
- }
+ if (!InfHandle || InfHandle == (HINF)INVALID_HANDLE_VALUE)
+ SetLastError(ERROR_INVALID_HANDLE);
+ else if (!InfSectionName)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else if (AlternatePlatformInfo && AlternatePlatformInfo->cbSize != sizeof(SP_ALTPLATFORM_INFO))
+ SetLastError(ERROR_INVALID_USER_BUFFER);
+ else if (Reserved != NULL)
+ SetLastError(ERROR_INVALID_PARAMETER);
else
{
- /* Test section name with '.Win' extension */
- lstrcpyW(&szBuffer[dwLength], WinExtension);
- lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
- }
+ static SP_ALTPLATFORM_INFO CurrentPlatform = { 0, };
+ PSP_ALTPLATFORM_INFO pPlatformInfo = &CurrentPlatform;
+ LPCWSTR pExtensionPlatform, pExtensionArchitecture;
+ WCHAR SectionName[LINE_LEN + 1];
+ LONG lLineCount = -1;
+ DWORD dwFullLength;
+
+ /* Fill platform info if needed */
+ if (AlternatePlatformInfo)
+ pPlatformInfo = AlternatePlatformInfo;
+ else if (CurrentPlatform.cbSize != sizeof(SP_ALTPLATFORM_INFO))
+ {
+ /* That's the first time we go here. We need to fill in the structure */
+ OSVERSIONINFO VersionInfo;
+ SYSTEM_INFO SystemInfo;
+ VersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+ ret = GetVersionEx(&VersionInfo);
+ if (!ret)
+ goto done;
+ GetSystemInfo(&SystemInfo);
+ CurrentPlatform.cbSize = sizeof(SP_ALTPLATFORM_INFO);
+ CurrentPlatform.Platform = VersionInfo.dwPlatformId;
+ CurrentPlatform.MajorVersion = VersionInfo.dwMajorVersion;
+ CurrentPlatform.MinorVersion = VersionInfo.dwMinorVersion;
+ CurrentPlatform.ProcessorArchitecture = SystemInfo.wProcessorArchitecture;
+ CurrentPlatform.Reserved = 0;
+ }
- if (lLineCount == -1)
- {
- /* Test section name without extension */
- szBuffer[dwLength] = 0;
- lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
- }
+static const WCHAR ExtensionPlatformNone[] = {'.',0};
+static const WCHAR ExtensionPlatformNT[] = {'.','N','T',0};
+static const WCHAR ExtensionPlatformWindows[] = {'.','W','i','n',0};
- if (lLineCount == -1)
- {
- SetLastError(ERROR_INVALID_PARAMETER);
- return FALSE;
- }
+static const WCHAR ExtensionArchitectureNone[] = {0};
+static const WCHAR ExtensionArchitectureamd64[] = {'a','m','d','6','4',0};
+static const WCHAR ExtensionArchitectureppc[] = {'p','p','c',0};
+static const WCHAR ExtensionArchitecturex86[] = {'x','8','6',0};
- dwFullLength = lstrlenW(szBuffer);
+ /* Set various extensions values */
+ switch (pPlatformInfo->Platform)
+ {
+ case VER_PLATFORM_WIN32_WINDOWS:
+ pExtensionPlatform = ExtensionPlatformWindows;
+ break;
+ case VER_PLATFORM_WIN32_NT:
+ pExtensionPlatform = ExtensionPlatformNT;
+ break;
+ default:
+ pExtensionPlatform = ExtensionPlatformNone;
+ break;
+ }
+ switch (pPlatformInfo->ProcessorArchitecture)
+ {
+ case PROCESSOR_ARCHITECTURE_AMD64:
+ pExtensionArchitecture = ExtensionArchitectureamd64;
+ break;
+ case PROCESSOR_ARCHITECTURE_INTEL:
+ pExtensionArchitecture = ExtensionArchitecturex86;
+ break;
+ case PROCESSOR_ARCHITECTURE_PPC:
+ pExtensionArchitecture = ExtensionArchitectureppc;
+ break;
+ default:
+ ERR("Unknown processor architecture 0x%x\n", pPlatformInfo->ProcessorArchitecture);
+ case PROCESSOR_ARCHITECTURE_UNKNOWN:
+ pExtensionArchitecture = ExtensionArchitectureNone;
+ break;
+ }
- if (InfSectionWithExt != NULL && InfSectionWithExtSize != 0)
- {
- if (InfSectionWithExtSize < (dwFullLength + 1))
- {
- SetLastError(ERROR_INSUFFICIENT_BUFFER);
- return FALSE;
- }
+ SectionName[LINE_LEN] = UNICODE_NULL;
+
+ /* Test with platform.architecture.major.minor extension */
+ snprintfW(SectionName, LINE_LEN, L"%s%s%s.%lu.%lu", InfSectionName,
+ pExtensionPlatform, pExtensionArchitecture, pPlatformInfo->MajorVersion, pPlatformInfo->MinorVersion);
+ lLineCount = SetupGetLineCountW(InfHandle, SectionName);
+ if (lLineCount != -1) goto sectionfound;
+
+ /* Test with platform.major.minor extension */
+ snprintfW(SectionName, LINE_LEN, L"%s%s.%lu.%lu", InfSectionName,
+ pExtensionPlatform, pPlatformInfo->MajorVersion, pPlatformInfo->MinorVersion);
+ lLineCount = SetupGetLineCountW(InfHandle, SectionName);
+ if (lLineCount != -1) goto sectionfound;
+
+ /* Test with platform.architecture.major extension */
+ snprintfW(SectionName, LINE_LEN, L"%s%s%s.%lu", InfSectionName,
+ pExtensionPlatform, pExtensionArchitecture, pPlatformInfo->MajorVersion);
+ lLineCount = SetupGetLineCountW(InfHandle, SectionName);
+ if (lLineCount != -1) goto sectionfound;
+
+ /* Test with platform.major extension */
+ snprintfW(SectionName, LINE_LEN, L"%s%s.%lu", InfSectionName,
+ pExtensionPlatform, pPlatformInfo->MajorVersion);
+ lLineCount = SetupGetLineCountW(InfHandle, SectionName);
+ if (lLineCount != -1) goto sectionfound;
+
+ /* Test with platform.architecture extension */
+ snprintfW(SectionName, LINE_LEN, L"%s%s%s", InfSectionName,
+ pExtensionPlatform, pExtensionArchitecture);
+ lLineCount = SetupGetLineCountW(InfHandle, SectionName);
+ if (lLineCount != -1) goto sectionfound;
+
+ /* Test with platform extension */
+ snprintfW(SectionName, LINE_LEN, L"%s%s", InfSectionName,
+ pExtensionPlatform);
+ lLineCount = SetupGetLineCountW(InfHandle, SectionName);
+ if (lLineCount != -1) goto sectionfound;
+
+ /* Test without extension */
+ snprintfW(SectionName, LINE_LEN, L"%s", InfSectionName);
+ lLineCount = SetupGetLineCountW(InfHandle, SectionName);
+ if (lLineCount != -1) goto sectionfound;
+
+ /* No appropriate section found */
+ SetLastError(ERROR_INVALID_PARAMETER);
+ goto done;
- lstrcpyW(InfSectionWithExt, szBuffer);
- if (Extension != NULL)
- {
- *Extension = (dwLength == dwFullLength) ? NULL : &InfSectionWithExt[dwLength];
- }
- }
+sectionfound:
+ dwFullLength = lstrlenW(SectionName);
+ if (InfSectionWithExt != NULL && InfSectionWithExtSize != 0)
+ {
+ if (InfSectionWithExtSize < (dwFullLength + 1))
+ {
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ goto done;
+ }
- if (RequiredSize != NULL)
- {
- *RequiredSize = dwFullLength + 1;
+ lstrcpyW(InfSectionWithExt, SectionName);
+ if (Extension != NULL)
+ {
+ DWORD dwLength = lstrlenW(SectionName);
+ *Extension = (dwLength == dwFullLength) ? NULL : &InfSectionWithExt[dwLength];
+ }
+ }
+
+ if (RequiredSize != NULL)
+ *RequiredSize = dwFullLength + 1;
+
+ ret = TRUE;
}
- return TRUE;
+done:
+ TRACE("Returning %d\n", ret);
+ return ret;
}
+
/***********************************************************************
* SetupDiGetClassDescriptionA (SETUPAPI.@)
*/
HKEY hKey;
DWORD dwLength;
+ TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid), ClassDescription,
+ ClassDescriptionSize, RequiredSize, debugstr_w(MachineName), Reserved);
+
hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
- KEY_ALL_ACCESS,
+ KEY_QUERY_VALUE,
DIOCR_INSTALLER,
MachineName,
Reserved);
static BOOL
CreateDeviceInfoElement(
+ IN struct DeviceInfoSet *list,
IN LPCWSTR InstancePath,
- LPCGUID pClassGuid,
+ IN LPCGUID pClassGuid,
OUT struct DeviceInfoElement **pDeviceInfo)
{
+ DWORD size;
+ CONFIGRET cr;
struct DeviceInfoElement *deviceInfo;
*pDeviceInfo = NULL;
- deviceInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInfoElement) + (wcslen(InstancePath) + 1) * sizeof(WCHAR));
+ size = FIELD_OFFSET(struct DeviceInfoElement, Data) + (wcslen(InstancePath) + 1) * sizeof(WCHAR);
+ deviceInfo = HeapAlloc(GetProcessHeap(), 0, size);
if (!deviceInfo)
{
- SetLastError(ERROR_NO_SYSTEM_RESOURCES);
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return FALSE;
+ }
+ memset(deviceInfo, 0, size);
+
+ cr = CM_Locate_DevNode_ExW(&deviceInfo->dnDevInst, (DEVINSTID_W)InstancePath, CM_LOCATE_DEVNODE_PHANTOM, list->hMachine);
+ if (cr != CR_SUCCESS)
+ {
+ SetLastError(GetErrorCodeFromCrCode(cr));
return FALSE;
}
+
+ 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->InterfaceHead);
+ InitializeListHead(&deviceInfo->InterfaceListHead);
*pDeviceInfo = deviceInfo;
return TRUE;
}
+static BOOL
+CreateDeviceInterface(
+ IN struct DeviceInfoElement* deviceInfo,
+ IN LPCWSTR SymbolicLink,
+ IN LPCGUID pInterfaceGuid,
+ OUT struct DeviceInterface **pDeviceInterface)
+{
+ struct DeviceInterface *deviceInterface;
+
+ *pDeviceInterface = NULL;
+
+ deviceInterface = HeapAlloc(GetProcessHeap(), 0,
+ FIELD_OFFSET(struct DeviceInterface, SymbolicLink) + (wcslen(SymbolicLink) + 1) * sizeof(WCHAR));
+ if (!deviceInterface)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return FALSE;
+ }
+ deviceInterface->DeviceInfo = deviceInfo;
+ wcscpy(deviceInterface->SymbolicLink, SymbolicLink);
+ deviceInterface->Flags = 0; /* FIXME */
+ memcpy(&deviceInterface->InterfaceClassGuid, pInterfaceGuid, sizeof(GUID));
+
+ *pDeviceInterface = deviceInterface;
+ return TRUE;
+}
+
static LONG SETUP_CreateDevListFromEnumerator(
struct DeviceInfoSet *list,
LPCGUID pClassGuid OPTIONAL,
DWORD i = 0, j;
DWORD dwLength, dwRegType;
DWORD rc;
-
+
/* Enumerate device IDs (subkeys of hEnumeratorKey) */
while (TRUE)
{
j = 0;
while (TRUE)
{
+ GUID KeyGuid;
+
dwLength = sizeof(KeyBuffer) / sizeof(KeyBuffer[0]);
rc = RegEnumKeyExW(hDeviceIdKey, j, KeyBuffer, &dwLength, NULL, NULL, NULL, NULL);
if (rc == ERROR_NO_MORE_ITEMS)
if (pClassGuid)
/* Skip this bad entry as we can't verify it */
continue;
+ /* Set a default GUID for this device */
+ memcpy(&KeyGuid, &GUID_NULL, sizeof(GUID));
}
else if (rc != ERROR_SUCCESS)
{
RegCloseKey(hDeviceIdKey);
return ERROR_GEN_FAILURE;
}
- else if (pClassGuid)
+ else
{
- GUID KeyGuid;
KeyBuffer[37] = '\0'; /* Replace the } by a NULL character */
if (UuidFromStringW(&KeyBuffer[1], &KeyGuid) != RPC_S_OK)
- {
- RegCloseKey(hDeviceIdKey);
- return GetLastError();
- }
- if (!IsEqualIID(&KeyGuid, pClassGuid))
- /* Skip this entry as it is not the right device class */
+ /* Bad GUID, skip the entry */
continue;
}
+ if (pClassGuid && !IsEqualIID(&KeyGuid, pClassGuid))
+ {
+ /* Skip this entry as it is not the right device class */
+ continue;
+ }
+
/* Add the entry to the list */
- if (!CreateDeviceInfoElement(InstancePath, pClassGuid, &deviceInfo))
+ if (!CreateDeviceInfoElement(list, InstancePath, &KeyGuid, &deviceInfo))
{
RegCloseKey(hDeviceIdKey);
return GetLastError();
DWORD dwLength;
DWORD rc;
- if (IsEqualIID(class, &GUID_NULL))
+ if (class && IsEqualIID(class, &GUID_NULL))
class = NULL;
/* Open Enum key */
HKLM = HKEY_LOCAL_MACHINE;
rc = RegOpenKeyExW(HKLM,
- EnumKeyName,
+ REGSTR_PATH_SYSTEMENUM,
0,
KEY_ENUMERATE_SUB_KEYS,
&hEnumKey);
return rc;
/* If enumerator is provided, call directly SETUP_CreateDevListFromEnumerator.
- * Else, enumerate all enumerators all call SETUP_CreateDevListFromEnumerator
+ * Else, enumerate all enumerators and call SETUP_CreateDevListFromEnumerator
* for each one.
*/
if (Enumerator)
}
}
-#ifdef __WINESRC__
+#ifndef __REACTOS__
static LONG SETUP_CreateSerialDeviceList(
struct DeviceInfoSet *list,
PCWSTR MachineName,
LPWSTR devices;
static const WCHAR devicePrefixW[] = { 'C','O','M',0 };
LPWSTR ptr;
- //DeviceInfo *deviceInfo;
+ struct DeviceInfoElement *deviceInfo;
if (MachineName)
WARN("'MachineName' is ignored on Wine!\n");
HeapFree(GetProcessHeap(), 0, devices);
devices = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
if (!devices)
- return ERROR_NO_SYSTEM_RESOURCES;
+ return ERROR_NOT_ENOUGH_MEMORY;
*devices = '\0';
}
else
if (strncmpW(devicePrefixW, ptr, sizeof(devicePrefixW) / sizeof(devicePrefixW[0]) - 1) == 0)
{
/* We have found a device */
+ struct DeviceInterface *interfaceInfo;
TRACE("Adding %s to list\n", debugstr_w(ptr));
-#if 0
- deviceInfo = HeapAlloc(GetProcessHeap(), 0,
- FIELD_OFFSET(DeviceInfo, Interface.Data) + (strlenW(ptr) + 1) * sizeof(WCHAR));
- if (!deviceInfo)
+ /* Step 1. Create a device info element */
+ if (!CreateDeviceInfoElement(list, ptr, &GUID_SERENUM_BUS_ENUMERATOR, &deviceInfo))
+ {
+ if (devices != buf)
+ HeapFree(GetProcessHeap(), 0, devices);
+ return GetLastError();
+ }
+ InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
+
+ /* Step 2. Create an interface list for this element */
+ if (!CreateDeviceInterface(deviceInfo, ptr, InterfaceGuid, &interfaceInfo))
{
if (devices != buf)
HeapFree(GetProcessHeap(), 0, devices);
- return ERROR_NO_SYSTEM_RESOURCES;
+ return GetLastError();
}
- deviceInfo->IsDevice = FALSE;
- deviceInfo->Interface.pSymbolicLink = &deviceInfo->Interface.Data[0];
- memcpy(&deviceInfo->Interface.InterfaceGuid, InterfaceGuid, sizeof(GUID));
- wcscpy(deviceInfo->Interface.pSymbolicLink, ptr);
- InsertTailList(&list->ListHead, &deviceInfo->ItemEntry);
-#else
- FIXME("not implemented\n");
-#endif
+ interfaceInfo->Flags |= SPINT_ACTIVE | SPINT_DEFAULT;
+ InsertTailList(&deviceInfo->InterfaceListHead, &interfaceInfo->ListEntry);
}
}
if (devices != buf)
return ERROR_SUCCESS;
}
-#else /* __WINESRC__ */
+#else /* __REACTOS__ */
static LONG SETUP_CreateInterfaceList(
struct DeviceInfoSet *list,
HKEY hInterfaceKey; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID} */
HKEY hDeviceInstanceKey; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath} */
HKEY hReferenceKey; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath}\#{ReferenceString} */
+ HKEY hControlKey; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath}\#{ReferenceString}\Control */
HKEY hEnumKey; /* HKLM\SYSTEM\CurrentControlSet\Enum */
HKEY hKey; /* HKLM\SYSTEM\CurrentControlSet\Enum\{Instance\Path} */
LONG rc;
DWORD i, j;
DWORD dwLength, dwInstancePathLength;
DWORD dwRegType;
+ DWORD LinkedValue;
GUID ClassGuid;
- DeviceInfo *deviceInfo;
+ struct DeviceInfoElement *deviceInfo;
/* Open registry key related to this interface */
hInterfaceKey = SetupDiOpenClassRegKeyExW(InterfaceGuid, KEY_ENUMERATE_SUB_KEYS, DIOCR_INTERFACE, MachineName, NULL);
{
RegCloseKey(hDeviceInstanceKey);
RegCloseKey(hInterfaceKey);
- return ERROR_NO_SYSTEM_RESOURCES;
+ return ERROR_NOT_ENOUGH_MEMORY;
}
rc = RegQueryValueExW(hDeviceInstanceKey, DeviceInstance, NULL, NULL, (LPBYTE)InstancePath, &dwInstancePathLength);
if (rc != ERROR_SUCCESS)
/* Find class GUID associated to the device instance */
rc = RegOpenKeyExW(
- HKEY_LOCAL_MACHINE,
- EnumKeyName,
+ list->HKLM,
+ REGSTR_PATH_SYSTEMENUM,
0, /* Options */
- KEY_ENUMERATE_SUB_KEYS,
+ 0,
&hEnumKey);
if (rc != ERROR_SUCCESS)
{
RegCloseKey(hDeviceInstanceKey);
continue;
}
-
+
/* Enumerate subkeys of hDeviceInstanceKey (ie "#ReferenceString" in IoRegisterDeviceInterface). Skip entries that don't start with '#' */
j = 0;
while (TRUE)
{
+ LPWSTR pSymbolicLink;
+ struct DeviceInterface *interfaceInfo;
+
dwLength = sizeof(KeyBuffer) / sizeof(KeyBuffer[0]);
rc = RegEnumKeyExW(hDeviceInstanceKey, j, KeyBuffer, &dwLength, NULL, NULL, NULL, NULL);
if (rc == ERROR_NO_MORE_ITEMS)
RegCloseKey(hInterfaceKey);
return ERROR_GEN_FAILURE;
}
- deviceInfo = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(DeviceInfo, Interface.Data) + dwInstancePathLength + dwLength + 2 * sizeof(WCHAR));
- if (!deviceInfo)
+
+ /* We have found a device */
+ /* Step 1. Create a device info element */
+ if (!CreateDeviceInfoElement(list, InstancePath, &ClassGuid, &deviceInfo))
+ {
+ RegCloseKey(hReferenceKey);
+ RegCloseKey(hDeviceInstanceKey);
+ RegCloseKey(hInterfaceKey);
+ return GetLastError();
+ }
+ TRACE("Adding device %s to list\n", debugstr_w(InstancePath));
+ InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
+
+ /* Step 2. Create an interface list for this element */
+ pSymbolicLink = HeapAlloc(GetProcessHeap(), 0, (dwLength + 1) * sizeof(WCHAR));
+ if (!pSymbolicLink)
{
RegCloseKey(hReferenceKey);
RegCloseKey(hDeviceInstanceKey);
RegCloseKey(hInterfaceKey);
- return ERROR_NO_SYSTEM_RESOURCES;
+ return ERROR_NOT_ENOUGH_MEMORY;
}
- deviceInfo->Interface.pInstancePath = &deviceInfo->Interface.Data[0];
- deviceInfo->Interface.pSymbolicLink = &deviceInfo->Interface.Data[dwInstancePathLength + 1];
- rc = RegQueryValueExW(hReferenceKey, SymbolicLink, NULL, NULL, (LPBYTE)deviceInfo->Interface.pSymbolicLink, &dwLength);
+ rc = RegQueryValueExW(hReferenceKey, SymbolicLink, NULL, NULL, (LPBYTE)pSymbolicLink, &dwLength);
+ pSymbolicLink[dwLength / sizeof(WCHAR)] = '\0';
RegCloseKey(hReferenceKey);
if (rc != ERROR_SUCCESS)
{
- HeapFree(GetProcessHeap(), 0, deviceInfo);
+ HeapFree(GetProcessHeap(), 0, pSymbolicLink);
RegCloseKey(hDeviceInstanceKey);
RegCloseKey(hInterfaceKey);
return rc;
}
- deviceInfo->Interface.pSymbolicLink[dwLength / sizeof(WCHAR)] = '\0';
- TRACE("Symbolic link %s\n", debugstr_w(deviceInfo->Interface.pSymbolicLink));
+ if (!CreateDeviceInterface(deviceInfo, pSymbolicLink, InterfaceGuid, &interfaceInfo))
+ {
+ HeapFree(GetProcessHeap(), 0, pSymbolicLink);
+ RegCloseKey(hDeviceInstanceKey);
+ RegCloseKey(hInterfaceKey);
+ return GetLastError();
+ }
- /* Add this entry to the list */
- TRACE("Entry found\n");
- deviceInfo->IsDevice = FALSE;
- memcpy(
- &deviceInfo->Interface.InterfaceGuid,
- InterfaceGuid,
- sizeof(deviceInfo->Interface.InterfaceGuid));
- wcscpy(deviceInfo->Interface.pInstancePath, InstancePath);
- InsertTailList(&list->ListHead, &deviceInfo->ItemEntry);
- list->numberOfEntries++;
+ /* Step 3. Update flags */
+ if (KeyBuffer[1] == '\0')
+ interfaceInfo->Flags |= SPINT_DEFAULT;
+ rc = RegOpenKeyExW(hReferenceKey, Control, 0, KEY_QUERY_VALUE, &hControlKey);
+ if (!rc)
+ interfaceInfo->Flags |= SPINT_REMOVED;
+ else
+ {
+ dwLength = sizeof(DWORD);
+ if (RegQueryValueExW(hControlKey, Linked, NULL, &dwRegType, (LPBYTE)&LinkedValue, &dwLength)
+ && dwRegType == REG_DWORD && LinkedValue)
+ interfaceInfo->Flags |= SPINT_ACTIVE;
+ RegCloseKey(hControlKey);
+ }
+
+ TRACE("Adding interface %s to list\n", debugstr_w(pSymbolicLink));
+ HeapFree(GetProcessHeap(), 0, pSymbolicLink);
+ InsertTailList(&deviceInfo->InterfaceListHead, &interfaceInfo->ListEntry);
}
RegCloseKey(hDeviceInstanceKey);
}
RegCloseKey(hInterfaceKey);
return ERROR_SUCCESS;
}
-#endif /* __WINESRC__ */
+#endif /* __REACTOS__ */
/***********************************************************************
* SetupDiGetClassDevsExW (SETUPAPI.@)
return INVALID_HANDLE_VALUE;
}
-#ifdef __WINESRC__
+#ifndef __REACTOS__
/* Special case: find serial ports by calling QueryDosDevice */
if (IsEqualIID(class, &GUID_DEVINTERFACE_COMPORT))
rc = SETUP_CreateSerialDeviceList(list, machine, (LPGUID)class, enumstr);
ERR("Wine can only enumerate serial devices at the moment!\n");
rc = ERROR_INVALID_PARAMETER;
}
-#else /* __WINESRC__ */
+#else /* __REACTOS__ */
rc = SETUP_CreateInterfaceList(list, machine, (LPGUID)class, enumstr);
-#endif /* __WINESRC__ */
+#endif /* __REACTOS__ */
if (rc != ERROR_SUCCESS)
{
SetLastError(rc);
}
/***********************************************************************
- * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
+ * SetupDiGetClassImageIndex (SETUPAPI.@)
*/
-BOOL WINAPI SetupDiEnumDeviceInterfaces(
- HDEVINFO DeviceInfoSet,
- PSP_DEVINFO_DATA DeviceInfoData,
- CONST GUID * InterfaceClassGuid,
- DWORD MemberIndex,
- PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
+
+static BOOL GetIconIndex(
+ IN HKEY hClassKey,
+ OUT PINT ImageIndex)
{
+ LPWSTR Buffer = NULL;
+ DWORD dwRegType, dwLength;
+ LONG rc;
BOOL ret = FALSE;
- TRACE("%p, %p, %s, 0x%08lx, %p\n", DeviceInfoSet, DeviceInfoData,
- debugstr_guid(InterfaceClassGuid), MemberIndex, DeviceInterfaceData);
+ /* Read icon registry key */
+ rc = RegQueryValueExW(hClassKey, REGSTR_VAL_INSICON, NULL, &dwRegType, NULL, &dwLength);
+ if (rc != ERROR_SUCCESS)
+ {
+ SetLastError(rc);
+ goto cleanup;
+ } else if (dwRegType != REG_SZ)
+ {
+ SetLastError(ERROR_INVALID_INDEX);
+ goto cleanup;
+ }
+ Buffer = MyMalloc(dwLength + sizeof(WCHAR));
+ if (!Buffer)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto cleanup;
+ }
+ rc = RegQueryValueExW(hClassKey, REGSTR_VAL_INSICON, NULL, NULL, (LPBYTE)Buffer, &dwLength);
+ if (rc != ERROR_SUCCESS)
+ {
+ SetLastError(rc);
+ goto cleanup;
+ }
+ /* make sure the returned buffer is NULL-terminated */
+ Buffer[dwLength / sizeof(WCHAR)] = 0;
- if (!DeviceInterfaceData)
+ /* Transform icon value to a INT */
+ *ImageIndex = atoiW(Buffer);
+ ret = TRUE;
+
+cleanup:
+ MyFree(Buffer);
+ return ret;
+}
+
+BOOL WINAPI SetupDiGetClassImageIndex(
+ IN PSP_CLASSIMAGELIST_DATA ClassImageListData,
+ IN CONST GUID *ClassGuid,
+ OUT PINT ImageIndex)
+{
+ struct ClassImageList *list;
+ BOOL ret = FALSE;
+
+ TRACE("%p %s %p\n", ClassImageListData, debugstr_guid(ClassGuid), ImageIndex);
+
+ if (!ClassImageListData || !ClassGuid || !ImageIndex)
SetLastError(ERROR_INVALID_PARAMETER);
- else if (DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA))
+ else if (ClassImageListData->cbSize != sizeof(SP_CLASSIMAGELIST_DATA))
SetLastError(ERROR_INVALID_USER_BUFFER);
- else if (DeviceInfoSet && DeviceInfoSet != (HDEVINFO)INVALID_HANDLE_VALUE)
+ else if ((list = (struct ClassImageList *)ClassImageListData->Reserved) == NULL)
+ SetLastError(ERROR_INVALID_USER_BUFFER);
+ else if (list->magic != SETUP_CLASS_IMAGE_LIST_MAGIC)
+ SetLastError(ERROR_INVALID_USER_BUFFER);
+ else if (!ImageIndex)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else
{
- struct DeviceInfoSet *list = (struct DeviceInfoSet *)DeviceInfoSet;
+ HKEY hKey = INVALID_HANDLE_VALUE;
+ INT iconIndex;
- if (list->magic == SETUP_DEV_INFO_SET_MAGIC)
+ /* Read Icon registry entry into Buffer */
+ hKey = SetupDiOpenClassRegKeyExW(ClassGuid, KEY_QUERY_VALUE, DIOCR_INTERFACE, list->MachineName, NULL);
+ if (hKey == INVALID_HANDLE_VALUE)
+ goto cleanup;
+ if (!GetIconIndex(hKey, &iconIndex))
+ goto cleanup;
+
+ if (iconIndex >= 0)
{
- PLIST_ENTRY ItemList = list->ListHead.Flink;
- BOOL Found = FALSE;
- while (ItemList != &list->ListHead && !Found)
- {
- PLIST_ENTRY InterfaceListEntry;
- struct DeviceInfoElement *DevInfo = (struct DeviceInfoElement *)ItemList;
- if (DeviceInfoData && (struct DeviceInfoElement *)DeviceInfoData->Reserved != DevInfo)
+ SetLastError(ERROR_INVALID_INDEX);
+ goto cleanup;
+ }
+
+ *ImageIndex = -iconIndex;
+ ret = TRUE;
+
+cleanup:
+ if (hKey != INVALID_HANDLE_VALUE)
+ RegCloseKey(hKey);
+ }
+
+ TRACE("Returning %d\n", ret);
+ return ret;
+}
+
+/***********************************************************************
+ * SetupDiGetClassImageList(SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiGetClassImageList(
+ OUT PSP_CLASSIMAGELIST_DATA ClassImageListData)
+{
+ return SetupDiGetClassImageListExW(ClassImageListData, NULL, NULL);
+}
+
+/***********************************************************************
+ * SetupDiGetClassImageListExA(SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiGetClassImageListExA(
+ OUT PSP_CLASSIMAGELIST_DATA ClassImageListData,
+ IN PCSTR MachineName OPTIONAL,
+ IN PVOID Reserved)
+{
+ PWSTR MachineNameW = NULL;
+ BOOL ret;
+
+ if (MachineName)
+ {
+ MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
+ if (MachineNameW == NULL)
+ return FALSE;
+ }
+
+ ret = SetupDiGetClassImageListExW(ClassImageListData, MachineNameW, Reserved);
+
+ if (MachineNameW)
+ MyFree(MachineNameW);
+
+ return ret;
+}
+
+/***********************************************************************
+ * SetupDiGetClassImageListExW(SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiGetClassImageListExW(
+ OUT PSP_CLASSIMAGELIST_DATA ClassImageListData,
+ IN PCWSTR MachineName OPTIONAL,
+ IN PVOID Reserved)
+{
+ BOOL ret = FALSE;
+
+ TRACE("%p %p %p\n", ClassImageListData, debugstr_w(MachineName), Reserved);
+
+ if (!ClassImageListData)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else if (ClassImageListData->cbSize != sizeof(SP_CLASSIMAGELIST_DATA))
+ SetLastError(ERROR_INVALID_USER_BUFFER);
+ else if (Reserved)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else
+ {
+ struct ClassImageList *list = NULL;
+ DWORD size;
+
+ size = FIELD_OFFSET(struct ClassImageList, szData);
+ if (MachineName)
+ size += (wcslen(MachineName) + 3) * sizeof(WCHAR);
+ list = HeapAlloc(GetProcessHeap(), 0, size);
+ if (!list)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto cleanup;
+ }
+ list->magic = SETUP_CLASS_IMAGE_LIST_MAGIC;
+ if (MachineName)
+ {
+ list->szData[0] = list->szData[1] = '\\';
+ strcpyW(list->szData + 2, MachineName);
+ list->MachineName = list->szData;
+ }
+ else
+ {
+ list->MachineName = NULL;
+ }
+
+ ClassImageListData->Reserved = (DWORD)list; /* FIXME: 64 bit portability issue */
+ ret = TRUE;
+
+cleanup:
+ if (!ret)
+ MyFree(list);
+ }
+
+ TRACE("Returning %d\n", ret);
+ return ret;
+}
+
+/***********************************************************************
+ * SetupDiLoadClassIcon(SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiLoadClassIcon(
+ IN CONST GUID *ClassGuid,
+ OUT HICON *LargeIcon OPTIONAL,
+ OUT PINT MiniIconIndex OPTIONAL)
+{
+ BOOL ret = FALSE;
+
+ if (!ClassGuid)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else
+ {
+ LPWSTR Buffer = NULL;
+ LPCWSTR DllName;
+ INT iconIndex;
+ HKEY hKey = INVALID_HANDLE_VALUE;
+
+ hKey = SetupDiOpenClassRegKey(ClassGuid, KEY_QUERY_VALUE);
+ if (hKey == INVALID_HANDLE_VALUE)
+ goto cleanup;
+
+ if (!GetIconIndex(hKey, &iconIndex))
+ goto cleanup;
+
+ if (iconIndex > 0)
+ {
+ /* Look up icon in dll specified by Installer32 or EnumPropPages32 key */
+ PWCHAR Comma;
+ LONG rc;
+ DWORD dwRegType, dwLength;
+ rc = RegQueryValueExW(hKey, REGSTR_VAL_INSTALLER_32, NULL, &dwRegType, NULL, &dwLength);
+ if (rc == ERROR_SUCCESS && dwRegType == REG_SZ)
+ {
+ Buffer = MyMalloc(dwLength + sizeof(WCHAR));
+ if (Buffer == NULL)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto cleanup;
+ }
+ rc = RegQueryValueExW(hKey, REGSTR_VAL_INSTALLER_32, NULL, NULL, (LPBYTE)Buffer, &dwLength);
+ if (rc != ERROR_SUCCESS)
+ {
+ SetLastError(rc);
+ goto cleanup;
+ }
+ /* make sure the returned buffer is NULL-terminated */
+ Buffer[dwLength / sizeof(WCHAR)] = 0;
+ }
+ else if
+ (ERROR_SUCCESS == (rc = RegQueryValueExW(hKey, REGSTR_VAL_ENUMPROPPAGES_32, NULL, &dwRegType, NULL, &dwLength))
+ && dwRegType == REG_SZ)
+ {
+ Buffer = MyMalloc(dwLength + sizeof(WCHAR));
+ if (Buffer == NULL)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto cleanup;
+ }
+ rc = RegQueryValueExW(hKey, REGSTR_VAL_ENUMPROPPAGES_32, NULL, NULL, (LPBYTE)Buffer, &dwLength);
+ if (rc != ERROR_SUCCESS)
+ {
+ SetLastError(rc);
+ goto cleanup;
+ }
+ /* make sure the returned buffer is NULL-terminated */
+ Buffer[dwLength / sizeof(WCHAR)] = 0;
+ }
+ else
+ {
+ /* Unable to find where to load the icon */
+ SetLastError(ERROR_FILE_NOT_FOUND);
+ goto cleanup;
+ }
+ Comma = strchrW(Buffer, ',');
+ if (!Comma)
+ {
+ SetLastError(ERROR_GEN_FAILURE);
+ goto cleanup;
+ }
+ *Comma = '\0';
+ DllName = Buffer;
+ }
+ else
+ {
+ /* Look up icon in setupapi.dll */
+ DllName = L"setupapi.dll";
+ iconIndex = -iconIndex;
+ }
+
+ TRACE("Icon index %d, dll name %s\n", iconIndex, debugstr_w(DllName));
+ if (LargeIcon)
+ {
+ if (1 != ExtractIconEx(DllName, iconIndex, LargeIcon, NULL, 1))
+ {
+ SetLastError(ERROR_INVALID_INDEX);
+ goto cleanup;
+ }
+ }
+ if (MiniIconIndex)
+ *MiniIconIndex = iconIndex;
+ ret = TRUE;
+
+cleanup:
+ if (hKey != INVALID_HANDLE_VALUE)
+ RegCloseKey(hKey);
+ MyFree(Buffer);
+ }
+
+ TRACE("Returning %d\n", ret);
+ return ret;
+}
+
+/***********************************************************************
+ * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiEnumDeviceInterfaces(
+ HDEVINFO DeviceInfoSet,
+ PSP_DEVINFO_DATA DeviceInfoData,
+ CONST GUID * InterfaceClassGuid,
+ DWORD MemberIndex,
+ PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
+{
+ BOOL ret = FALSE;
+
+ TRACE("%p, %p, %s, %ld, %p\n", DeviceInfoSet, DeviceInfoData,
+ debugstr_guid(InterfaceClassGuid), MemberIndex, DeviceInterfaceData);
+
+ if (!DeviceInterfaceData)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else if (DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA))
+ SetLastError(ERROR_INVALID_USER_BUFFER);
+ else if (DeviceInfoSet && DeviceInfoSet != (HDEVINFO)INVALID_HANDLE_VALUE)
+ {
+ struct DeviceInfoSet *list = (struct DeviceInfoSet *)DeviceInfoSet;
+
+ if (list->magic == SETUP_DEV_INFO_SET_MAGIC)
+ {
+ PLIST_ENTRY ItemList = list->ListHead.Flink;
+ BOOL Found = FALSE;
+ while (ItemList != &list->ListHead && !Found)
+ {
+ PLIST_ENTRY InterfaceListEntry;
+ struct DeviceInfoElement *DevInfo = (struct DeviceInfoElement *)ItemList;
+ if (DeviceInfoData && (struct DeviceInfoElement *)DeviceInfoData->Reserved != DevInfo)
{
/* We are not searching for this element */
ItemList = ItemList->Flink;
continue;
}
- InterfaceListEntry = DevInfo->InterfaceHead.Flink;
- while (InterfaceListEntry != &DevInfo->InterfaceHead && !Found)
+ InterfaceListEntry = DevInfo->InterfaceListHead.Flink;
+ while (InterfaceListEntry != &DevInfo->InterfaceListHead && !Found)
{
struct DeviceInterface *DevItf = (struct DeviceInterface *)InterfaceListEntry;
if (!IsEqualIID(&DevItf->InterfaceClassGuid, InterfaceClassGuid))
memcpy(&DeviceInterfaceData->InterfaceClassGuid,
&DevItf->InterfaceClassGuid,
sizeof(GUID));
- DeviceInterfaceData->Flags = 0; /* FIXME */
- /* Note: this appears to be dangerous, passing a private
- * pointer a heap-allocated datum to the caller. However, the
- * expected lifetime of the device data is the same as the
- * HDEVINFO; once that is closed, the data are no longer valid.
- */
+ DeviceInterfaceData->Flags = DevItf->Flags;
DeviceInterfaceData->Reserved = (ULONG_PTR)DevItf;
Found = TRUE;
}
- MemberIndex--;
+ InterfaceListEntry = InterfaceListEntry->Flink;
}
ItemList = ItemList->Flink;
}
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 DestroyClassInstallParams(struct ClassInstallParams* installParams)
+{
+ HeapFree(GetProcessHeap(), 0, installParams->PropChange);
+ 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);
+ }
+ DestroyClassInstallParams(&deviceInfo->ClassInstallParams);
+ 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);
+ CM_Disconnect_Machine(list->hMachine);
+ DestroyClassInstallParams(&list->ClassInstallParams);
+ 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->InterfaceHead))
- {
- InterfaceEntry = RemoveHeadList(&deviceInfo->InterfaceHead);
- 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);
}
else
SetLastError(ERROR_INVALID_HANDLE);
+
+ TRACE("Returning %d\n", ret);
return ret;
}
DWORD sizeW = 0, sizeA;
BOOL ret = FALSE;
- TRACE("(%p, %p, %p, %ld, %p, %p)\n", DeviceInfoSet,
+ TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet,
DeviceInterfaceData, DeviceInterfaceDetailData,
DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
{
BOOL ret = FALSE;
- TRACE("(%p, %p, %p, %ld, %p, %p): stub\n", DeviceInfoSet,
+ TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet,
DeviceInterfaceData, DeviceInterfaceDetailData,
DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
SetLastError(ERROR_INVALID_PARAMETER);
else
{
-#if 0
- DeviceInfo *deviceInfo = (DeviceInfo *)DeviceInterfaceData->Reserved;
- LPCWSTR devName = deviceInfo->Interface.pSymbolicLink;
+ struct DeviceInterface *deviceInterface = (struct DeviceInterface *)DeviceInterfaceData->Reserved;
+ LPCWSTR devName = deviceInterface->SymbolicLink;
DWORD sizeRequired = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) +
- lstrlenW(devName);
+ (lstrlenW(devName) + 1) * sizeof(WCHAR);
if (sizeRequired > DeviceInterfaceDetailDataSize)
{
if (DeviceInfoData)
{
memcpy(&DeviceInfoData->ClassGuid,
- &deviceInfo->Interface.ClassGuid,
+ &deviceInterface->DeviceInfo->ClassGuid,
sizeof(GUID));
- DeviceInfoData->DevInst = 0; /* FIXME */
- /* Note: this appears to be dangerous, passing a private
- * pointer a heap-allocated datum to the caller. However, the
- * expected lifetime of the device data is the same as the
- * HDEVINFO; once that is closed, the data are no longer valid.
- */
- DeviceInfoData->Reserved = (ULONG_PTR)deviceInfo;
+ DeviceInfoData->DevInst = deviceInterface->DeviceInfo->dnDevInst;
+ DeviceInfoData->Reserved = (ULONG_PTR)deviceInterface->DeviceInfo;
}
ret = TRUE;
}
-#else
- FIXME("not implemented\n");
- SetLastError(ERROR_GEN_FAILURE);
- ret = FALSE;
-#endif
}
TRACE("Returning %d\n", ret);
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;
DWORD BufferSize;
-
+
switch (Property)
{
case SPDRP_CAPABILITIES:
- RegistryPropertyName = L"Capabilities"; break;
+ RegistryPropertyName = REGSTR_VAL_CAPABILITIES; break;
case SPDRP_CLASS:
- RegistryPropertyName = L"Class"; break;
+ RegistryPropertyName = REGSTR_VAL_CLASS; break;
case SPDRP_CLASSGUID:
- RegistryPropertyName = L"ClassGUID"; break;
+ RegistryPropertyName = REGSTR_VAL_CLASSGUID; break;
case SPDRP_COMPATIBLEIDS:
- RegistryPropertyName = L"CompatibleIDs"; break;
+ RegistryPropertyName = REGSTR_VAL_COMPATIBLEIDS; break;
case SPDRP_CONFIGFLAGS:
- RegistryPropertyName = L"ConfigFlags"; break;
+ RegistryPropertyName = REGSTR_VAL_CONFIGFLAGS; break;
case SPDRP_DEVICEDESC:
- RegistryPropertyName = L"DeviceDesc"; break;
+ RegistryPropertyName = REGSTR_VAL_DEVDESC; break;
case SPDRP_DRIVER:
- RegistryPropertyName = L"Driver"; break;
+ RegistryPropertyName = REGSTR_VAL_DRIVER; break;
case SPDRP_FRIENDLYNAME:
- RegistryPropertyName = L"FriendlyName"; break;
+ RegistryPropertyName = REGSTR_VAL_FRIENDLYNAME; break;
case SPDRP_HARDWAREID:
- RegistryPropertyName = L"HardwareID"; break;
+ RegistryPropertyName = REGSTR_VAL_HARDWAREID; break;
case SPDRP_LOCATION_INFORMATION:
- RegistryPropertyName = L"LocationInformation"; break;
+ RegistryPropertyName = REGSTR_VAL_LOCATION_INFORMATION; break;
case SPDRP_LOWERFILTERS:
- RegistryPropertyName = L"LowerFilters"; break;
+ RegistryPropertyName = REGSTR_VAL_LOWERFILTERS; break;
case SPDRP_MFG:
- RegistryPropertyName = L"Mfg"; break;
+ RegistryPropertyName = REGSTR_VAL_MFG; break;
case SPDRP_SECURITY:
RegistryPropertyName = L"Security"; break;
case SPDRP_SERVICE:
- RegistryPropertyName = L"Service"; break;
+ RegistryPropertyName = REGSTR_VAL_SERVICE; break;
case SPDRP_UI_NUMBER:
- RegistryPropertyName = L"UINumber"; break;
+ RegistryPropertyName = REGSTR_VAL_UI_NUMBER; break;
+ case SPDRP_UI_NUMBER_DESC_FORMAT:
+ RegistryPropertyName = L"UINumberDescFormat"; break;
case SPDRP_UPPERFILTERS:
- RegistryPropertyName = L"UpperFilters"; break;
+ RegistryPropertyName = REGSTR_VAL_UPPERFILTERS; break;
default:
/* Should not happen */
RegistryPropertyName = NULL; break;
/* Open registry key name */
rc = RegOpenKeyExW(
list->HKLM,
- EnumKeyName,
+ REGSTR_PATH_SYSTEMENUM,
0, /* Options */
- KEY_ENUMERATE_SUB_KEYS,
+ 0,
&hEnumKey);
if (rc != ERROR_SUCCESS)
{
&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:
default:
{
- FIXME("Property 0x%lx not implemented\n", Property);
+ ERR("Property 0x%lx not implemented\n", Property);
SetLastError(ERROR_NOT_SUPPORTED);
}
}
return ret;
}
-
/***********************************************************************
- * SetupDiInstallClassA (SETUPAPI.@)
+ * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
*/
-BOOL WINAPI SetupDiInstallClassA(
- HWND hwndParent,
- PCSTR InfFileName,
- DWORD Flags,
- HSPFILEQ FileQueue)
+BOOL WINAPI SetupDiSetDeviceRegistryPropertyA(
+ IN HDEVINFO DeviceInfoSet,
+ IN OUT PSP_DEVINFO_DATA DeviceInfoData,
+ IN DWORD Property,
+ IN CONST BYTE *PropertyBuffer,
+ IN DWORD PropertyBufferSize)
{
- UNICODE_STRING FileNameW;
- BOOL Result;
-
- if (!RtlCreateUnicodeStringFromAsciiz(&FileNameW, InfFileName))
- {
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- return FALSE;
- }
-
- Result = SetupDiInstallClassW(hwndParent, FileNameW.Buffer, Flags, FileQueue);
-
- RtlFreeUnicodeString(&FileNameW);
-
- return Result;
+ FIXME("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet, DeviceInfoData,
+ Property, PropertyBuffer, PropertyBufferSize);
+ SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ return FALSE;
}
-static HKEY CreateClassKey(HINF hInf)
+/***********************************************************************
+ * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiSetDeviceRegistryPropertyW(
+ IN HDEVINFO DeviceInfoSet,
+ IN OUT PSP_DEVINFO_DATA DeviceInfoData,
+ IN DWORD Property,
+ IN const BYTE *PropertyBuffer,
+ IN DWORD PropertyBufferSize)
{
- WCHAR FullBuffer[MAX_PATH];
- WCHAR Buffer[MAX_PATH];
- DWORD RequiredSize;
- HKEY hClassKey;
-
- Buffer[0] = '\\';
- if (!SetupGetLineTextW(NULL,
- hInf,
- Version,
- ClassGUID,
- &Buffer[1],
- MAX_PATH - 1,
- &RequiredSize))
- {
- return INVALID_HANDLE_VALUE;
- }
-
- lstrcpyW(FullBuffer, ControlClass);
- lstrcatW(FullBuffer, Buffer);
+ 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 = REGSTR_VAL_COMPATIBLEIDS;
+ RegistryDataType = REG_MULTI_SZ;
+ break;
+ case SPDRP_CONFIGFLAGS:
+ RegistryPropertyName = REGSTR_VAL_CONFIGFLAGS;
+ RegistryDataType = REG_DWORD;
+ break;
+ case SPDRP_FRIENDLYNAME:
+ RegistryPropertyName = REGSTR_VAL_FRIENDLYNAME;
+ RegistryDataType = REG_SZ;
+ break;
+ case SPDRP_HARDWAREID:
+ RegistryPropertyName = REGSTR_VAL_HARDWAREID;
+ RegistryDataType = REG_MULTI_SZ;
+ break;
+ case SPDRP_LOCATION_INFORMATION:
+ RegistryPropertyName = REGSTR_VAL_LOCATION_INFORMATION;
+ RegistryDataType = REG_SZ;
+ break;
+ case SPDRP_LOWERFILTERS:
+ RegistryPropertyName = REGSTR_VAL_LOWERFILTERS;
+ RegistryDataType = REG_MULTI_SZ;
+ break;
+ case SPDRP_SECURITY:
+ RegistryPropertyName = L"Security";
+ RegistryDataType = REG_BINARY;
+ break;
+ case SPDRP_SERVICE:
+ RegistryPropertyName = REGSTR_VAL_SERVICE;
+ RegistryDataType = REG_SZ;
+ break;
+ case SPDRP_UI_NUMBER_DESC_FORMAT:
+ RegistryPropertyName = L"UINumberDescFormat";
+ RegistryDataType = REG_SZ;
+ break;
+ case SPDRP_UPPERFILTERS:
+ RegistryPropertyName = REGSTR_VAL_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:
+ {
+ ERR("Property 0x%lx not implemented\n", Property);
+ SetLastError(ERROR_NOT_SUPPORTED);
+ }
+ }
+ }
+
+ TRACE("Returning %d\n", ret);
+ return ret;
+}
+
+
+/***********************************************************************
+ * SetupDiInstallClassA (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiInstallClassA(
+ IN HWND hwndParent OPTIONAL,
+ IN PCSTR InfFileName,
+ IN DWORD Flags,
+ IN HSPFILEQ FileQueue OPTIONAL)
+{
+ return SetupDiInstallClassExA(hwndParent, InfFileName, Flags, FileQueue, NULL, NULL, NULL);
+}
+
+
+/***********************************************************************
+ * SetupDiInstallClassW (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiInstallClassW(
+ IN HWND hwndParent OPTIONAL,
+ IN PCWSTR InfFileName,
+ IN DWORD Flags,
+ IN HSPFILEQ FileQueue OPTIONAL)
+{
+ return SetupDiInstallClassExW(hwndParent, InfFileName, Flags, FileQueue, NULL, NULL, NULL);
+}
+
+
+/***********************************************************************
+ * SetupDiInstallClassExA (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiInstallClassExA(
+ IN HWND hwndParent OPTIONAL,
+ IN PCSTR InfFileName OPTIONAL,
+ IN DWORD Flags,
+ IN HSPFILEQ FileQueue OPTIONAL,
+ IN const GUID* InterfaceClassGuid OPTIONAL,
+ IN PVOID Reserved1,
+ IN PVOID Reserved2)
+{
+ PWSTR InfFileNameW = NULL;
+ BOOL Result;
+
+ if (InfFileName)
+ {
+ InfFileNameW = MultiByteToUnicode(InfFileName, CP_ACP);
+ if (InfFileNameW == NULL)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return FALSE;
+ }
+ }
+
+ Result = SetupDiInstallClassExW(hwndParent, InfFileNameW, Flags,
+ FileQueue, InterfaceClassGuid, Reserved1, Reserved2);
+
+ MyFree(InfFileNameW);
+
+ return Result;
+}
+
+
+static HKEY CreateClassKey(HINF hInf)
+{
+ WCHAR FullBuffer[MAX_PATH];
+ WCHAR Buffer[MAX_PATH];
+ DWORD RequiredSize;
+ HKEY hClassKey;
+
+ Buffer[0] = '\\';
+ if (!SetupGetLineTextW(NULL,
+ hInf,
+ Version,
+ ClassGUID,
+ &Buffer[1],
+ MAX_PATH - 1,
+ &RequiredSize))
+ {
+ return INVALID_HANDLE_VALUE;
+ }
+
+ lstrcpyW(FullBuffer, REGSTR_PATH_CLASS_NT);
+ lstrcatW(FullBuffer, Buffer);
if (!SetupGetLineTextW(NULL,
0,
NULL,
REG_OPTION_NON_VOLATILE,
- KEY_ALL_ACCESS,
+ KEY_SET_VALUE,
NULL,
&hClassKey,
NULL))
return hClassKey;
}
+
/***********************************************************************
- * SetupDiInstallClassW (SETUPAPI.@)
+ * SetupDiInstallClassExW (SETUPAPI.@)
*/
-BOOL WINAPI SetupDiInstallClassW(
- HWND hwndParent,
- PCWSTR InfFileName,
- DWORD Flags,
- HSPFILEQ FileQueue)
+BOOL WINAPI SetupDiInstallClassExW(
+ IN HWND hwndParent OPTIONAL,
+ IN PCWSTR InfFileName OPTIONAL,
+ IN DWORD Flags,
+ IN HSPFILEQ FileQueue OPTIONAL,
+ IN const GUID* InterfaceClassGuid OPTIONAL,
+ IN PVOID Reserved1,
+ IN PVOID Reserved2)
{
- WCHAR SectionName[MAX_PATH];
- DWORD SectionNameLength = 0;
- HINF hInf;
- BOOL bFileQueueCreated = FALSE;
- HKEY hClassKey;
-
- FIXME("not fully implemented\n");
+ BOOL ret = FALSE;
- if ((Flags & DI_NOVCP) && (FileQueue == NULL || FileQueue == INVALID_HANDLE_VALUE))
- {
- SetLastError(ERROR_INVALID_PARAMETER);
- return FALSE;
- }
+ TRACE("%p %s 0x%lx %p %s %p %p\n", hwndParent, debugstr_w(InfFileName), Flags,
+ FileQueue, debugstr_guid(InterfaceClassGuid), Reserved1, Reserved2);
- /* Open the .inf file */
- hInf = SetupOpenInfFileW(InfFileName,
- NULL,
- INF_STYLE_WIN4,
- NULL);
- if (hInf == INVALID_HANDLE_VALUE)
+ if (!InfFileName && !InterfaceClassGuid)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else if (Flags & ~(DI_NOVCP | DI_NOBROWSE | DI_FORCECOPY | DI_QUIETINSTALL))
{
-
- return FALSE;
+ TRACE("Unknown flags: 0x%08lx\n", Flags & ~(DI_NOVCP | DI_NOBROWSE | DI_FORCECOPY | DI_QUIETINSTALL));
+ SetLastError(ERROR_INVALID_FLAGS);
}
-
- /* Create or open the class registry key 'HKLM\\CurrentControlSet\\Class\\{GUID}' */
- hClassKey = CreateClassKey(hInf);
- if (hClassKey == INVALID_HANDLE_VALUE)
+ else if ((Flags & DI_NOVCP) && FileQueue == NULL)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else if (Reserved1 != NULL)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else if (Reserved2 != NULL)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else
{
- SetupCloseInfFile(hInf);
- return FALSE;
- }
+ WCHAR SectionName[MAX_PATH];
+ HINF hInf = INVALID_HANDLE_VALUE;
+ HKEY hClassKey = INVALID_HANDLE_VALUE;
+ PVOID callback_context = NULL;
+ if (InterfaceClassGuid)
+ {
+ /* SetupDiCreateDeviceInterface??? */
+ FIXME("Installing an interface is not implemented\n");
+ SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ }
+ else
+ {
+ if (Flags & DI_NOVCP)
+ FIXME("FileQueue argument ignored\n");
+ if (Flags & (DI_NOBROWSE | DI_FORCECOPY | DI_QUIETINSTALL))
+ FIXME("Flags 0x%lx ignored\n", Flags & (DI_NOBROWSE | DI_FORCECOPY | DI_QUIETINSTALL));
+
+ /* Open the .inf file */
+ hInf = SetupOpenInfFileW(
+ InfFileName,
+ NULL,
+ INF_STYLE_WIN4,
+ NULL);
+ if (hInf == INVALID_HANDLE_VALUE)
+ goto cleanup;
+
+ /* Create or open the class registry key 'HKLM\CurrentControlSet\Class\{GUID}' */
+ hClassKey = CreateClassKey(hInf);
+ if (hClassKey == INVALID_HANDLE_VALUE)
+ goto cleanup;
+
+ /* Try to append a layout file */
+ ret = SetupOpenAppendInfFileW(NULL, hInf, NULL);
+ if (!ret)
+ goto cleanup;
+
+ /* Retrieve the actual section name */
+ ret = SetupDiGetActualSectionToInstallW(
+ hInf,
+ ClassInstall32,
+ SectionName,
+ MAX_PATH - wcslen(DotServices),
+ NULL,
+ NULL);
+ if (!ret)
+ goto cleanup;
+
+ callback_context = SetupInitDefaultQueueCallback(hwndParent);
+ if (!callback_context)
+ goto cleanup;
+
+ ret = SetupInstallFromInfSectionW(
+ hwndParent,
+ hInf,
+ SectionName,
+ SPINST_REGISTRY | SPINST_FILES | SPINST_BITREG | SPINST_INIFILES | SPINST_INI2REG,
+ hClassKey,
+ NULL, /* SourceRootPath */
+ 0, /* CopyFlags */
+ SetupDefaultQueueCallbackW,
+ callback_context,
+ NULL,
+ NULL);
+ if (!ret)
+ goto cleanup;
+
+ /* Install .Services section */
+ lstrcatW(SectionName, DotServices);
+ ret = SetupInstallServicesFromInfSectionW(hInf, SectionName, 0);
+ if (!ret)
+ goto cleanup;
+ ret = TRUE;
+ }
- /* Try to append a layout file */
-#if 0
- SetupOpenAppendInfFileW(NULL, hInf, NULL);
-#endif
-
- /* Retrieve the actual section name */
- SetupDiGetActualSectionToInstallW(hInf,
- ClassInstall32,
- SectionName,
- MAX_PATH,
- &SectionNameLength,
- NULL);
-
-#if 0
- if (!(Flags & DI_NOVCP))
- {
- FileQueue = SetupOpenFileQueue();
- if (FileQueue == INVALID_HANDLE_VALUE)
- {
- SetupCloseInfFile(hInf);
- RegCloseKey(hClassKey);
- return FALSE;
- }
-
- bFileQueueCreated = TRUE;
-
+cleanup:
+ if (hInf != INVALID_HANDLE_VALUE)
+ SetupCloseInfFile(hInf);
+ if (hClassKey != INVALID_HANDLE_VALUE)
+ RegCloseKey(hClassKey);
+ SetupTermDefaultQueueCallback(callback_context);
}
-#endif
-
- SetupInstallFromInfSectionW(NULL,
- hInf,
- SectionName,
- SPINST_REGISTRY,
- hClassKey,
- NULL,
- 0,
- NULL,
- NULL,
- INVALID_HANDLE_VALUE,
- NULL);
- /* FIXME: More code! */
-
- if (bFileQueueCreated)
- SetupCloseFileQueue(FileQueue);
-
- SetupCloseInfFile(hInf);
-
- RegCloseKey(hClassKey);
- return TRUE;
+ TRACE("Returning %d\n", ret);
+ return ret;
}
* SetupDiOpenClassRegKeyExA (SETUPAPI.@)
*/
HKEY WINAPI SetupDiOpenClassRegKeyExA(
- const GUID* ClassGuid,
+ const GUID* ClassGuid OPTIONAL,
REGSAM samDesired,
DWORD Flags,
- PCSTR MachineName,
+ PCSTR MachineName OPTIONAL,
PVOID Reserved)
{
PWSTR MachineNameW = NULL;
* SetupDiOpenClassRegKeyExW (SETUPAPI.@)
*/
HKEY WINAPI SetupDiOpenClassRegKeyExW(
- const GUID* ClassGuid,
+ const GUID* ClassGuid OPTIONAL,
REGSAM samDesired,
DWORD Flags,
- PCWSTR MachineName,
+ PCWSTR MachineName OPTIONAL,
PVOID Reserved)
{
LPWSTR lpGuidString;
DWORD rc;
LPCWSTR lpKeyName;
+ TRACE("%s 0x%lx 0x%lx %s %p\n", debugstr_guid(ClassGuid), samDesired,
+ Flags, debugstr_w(MachineName), Reserved);
+
if (Flags == DIOCR_INSTALLER)
{
- lpKeyName = ControlClass;
+ lpKeyName = REGSTR_PATH_CLASS_NT;
}
else if (Flags == DIOCR_INTERFACE)
{
- lpKeyName = DeviceClasses;
+ lpKeyName = REGSTR_PATH_DEVICE_CLASSES;
}
else
{
ERR("Invalid Flags parameter!\n");
- SetLastError(ERROR_INVALID_PARAMETER);
+ SetLastError(ERROR_INVALID_FLAGS);
return INVALID_HANDLE_VALUE;
}
rc = RegOpenKeyExW(HKLM,
lpKeyName,
0,
- KEY_ALL_ACCESS,
+ ClassGuid ? 0 : samDesired,
&hClassesKey);
if (MachineName != NULL) RegCloseKey(HKLM);
if (rc != ERROR_SUCCESS)
lpFullGuidString = HeapAlloc(GetProcessHeap(), 0, (dwLength + 3) * sizeof(WCHAR));
if (!lpFullGuidString)
{
- SetLastError(ERROR_NO_SYSTEM_RESOURCES);
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
RpcStringFreeW(&lpGuidString);
return INVALID_HANDLE_VALUE;
}
rc = RegOpenKeyExW(hClassesKey,
lpFullGuidString,
0,
- KEY_ALL_ACCESS,
+ samDesired,
&hClassKey);
if (rc != ERROR_SUCCESS)
{
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;
}
/***********************************************************************
}
/***********************************************************************
- * SetupDiCallClassInstaller (SETUPAPI.@)
- */
-BOOL WINAPI SetupDiCallClassInstaller(
- DI_FUNCTION InstallFunction,
- HDEVINFO DeviceInfoSet,
- PSP_DEVINFO_DATA DeviceInfoData)
-{
- FIXME("%ld %p %p\n", InstallFunction, DeviceInfoSet, DeviceInfoData);
- return FALSE;
-}
-
-/***********************************************************************
- * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
+ * SetupDiSetClassInstallParamsW (SETUPAPI.@)
*/
-BOOL WINAPI SetupDiGetDeviceInstallParamsA(
- HDEVINFO DeviceInfoSet,
- PSP_DEVINFO_DATA DeviceInfoData,
- PSP_DEVINSTALL_PARAMS_A DeviceInstallParams)
+BOOL WINAPI SetupDiSetClassInstallParamsW(
+ IN HDEVINFO DeviceInfoSet,
+ IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
+ IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL,
+ IN DWORD ClassInstallParamsSize)
{
- 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 %lu\n", DeviceInfoSet, DeviceInfoData,
+ ClassInstallParams, ClassInstallParamsSize);
-/***********************************************************************
- * SetupDiCreateDeviceInfoA (SETUPAPI.@)
- */
-BOOL WINAPI SetupDiCreateDeviceInfoA(
- HDEVINFO DeviceInfoSet,
- PCSTR DeviceName,
- CONST GUID *ClassGuid,
- PCSTR DeviceDescription,
- HWND hwndParent,
- DWORD CreationFlags,
- PSP_DEVINFO_DATA DeviceInfoData)
-{
- LPWSTR DeviceNameW = NULL;
- LPWSTR DeviceDescriptionW = NULL;
- BOOL bResult;
+ if (!DeviceInfoSet)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
+ 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 (ClassInstallParams && ClassInstallParams->cbSize != sizeof(SP_CLASSINSTALL_HEADER))
+ SetLastError(ERROR_INVALID_USER_BUFFER);
+ else if (ClassInstallParams && ClassInstallParamsSize < sizeof(SP_CLASSINSTALL_HEADER))
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else if (!ClassInstallParams && ClassInstallParamsSize != 0)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else
+ {
+ SP_DEVINSTALL_PARAMS_W InstallParams;
+ BOOL Result;
- TRACE("\n");
+ InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
+ Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
+ if (!Result)
+ goto done;
- if (DeviceName)
- {
- DeviceNameW = MultiByteToUnicode(DeviceName, CP_ACP);
- if (DeviceNameW == NULL) return FALSE;
- }
- if (DeviceDescription)
- {
- DeviceDescriptionW = MultiByteToUnicode(DeviceDescription, CP_ACP);
- if (DeviceDescriptionW == NULL)
+ if (ClassInstallParams)
{
- if (DeviceNameW) MyFree(DeviceNameW);
- return FALSE;
+ /* Check parameters in ClassInstallParams */
+ if (ClassInstallParams->InstallFunction < DIF_SELECTDEVICE
+ || ClassInstallParams->InstallFunction - DIF_SELECTDEVICE >= sizeof(UpdateClassInstallParamHandlers)/sizeof(UpdateClassInstallParamHandlers[0]))
+ {
+ SetLastError(ERROR_INVALID_USER_BUFFER);
+ goto done;
+ }
+ else if (UpdateClassInstallParamHandlers[ClassInstallParams->InstallFunction - DIF_SELECTDEVICE] == NULL)
+ {
+ FIXME("InstallFunction %u is valid, but has no associated update handler\n", ClassInstallParams->InstallFunction);
+ SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ goto done;
+ }
+ ret = UpdateClassInstallParamHandlers[ClassInstallParams->InstallFunction - DIF_SELECTDEVICE](DeviceInfoSet, DeviceInfoData, ClassInstallParams, ClassInstallParamsSize);
+ if (!ret)
+ goto done;
+ InstallParams.Flags |= DI_CLASSINSTALLPARAMS;
+ }
+ else
+ {
+ InstallParams.Flags &= ~DI_CLASSINSTALLPARAMS;
}
- }
-
- bResult = SetupDiCreateDeviceInfoW(DeviceInfoSet, DeviceNameW,
- ClassGuid, DeviceDescriptionW,
- hwndParent, CreationFlags,
- DeviceInfoData);
- if (DeviceNameW) MyFree(DeviceNameW);
- if (DeviceDescriptionW) MyFree(DeviceDescriptionW);
+ ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
+ }
- return bResult;
+done:
+ TRACE("Returning %d\n", ret);
+ return ret;
}
-/***********************************************************************
- * SetupDiCreateDeviceInfoW (SETUPAPI.@)
- */
-BOOL WINAPI SetupDiCreateDeviceInfoW(
- HDEVINFO DeviceInfoSet,
- PCWSTR DeviceName,
- CONST GUID *ClassGuid,
- PCWSTR DeviceDescription,
- HWND hwndParent,
- DWORD CreationFlags,
- PSP_DEVINFO_DATA DeviceInfoData)
+static BOOL PropertyChangeHandler(
+ IN HDEVINFO DeviceInfoSet,
+ IN PSP_DEVINFO_DATA DeviceInfoData,
+ IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL,
+ IN DWORD ClassInstallParamsSize)
{
- struct DeviceInfoSet *list;
+ PSP_PROPCHANGE_PARAMS PropChangeParams = (PSP_PROPCHANGE_PARAMS)ClassInstallParams;
BOOL ret = FALSE;
- TRACE("%p %S %s %S %p %lx %p\n", DeviceInfoSet, DeviceName,
- debugstr_guid(ClassGuid), DeviceDescription,
- hwndParent, CreationFlags, DeviceInfoData);
-
- if (!DeviceInfoSet)
- SetLastError(ERROR_INVALID_HANDLE);
- else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
- SetLastError(ERROR_INVALID_HANDLE);
- else if (!ClassGuid)
+ if (!DeviceInfoData)
SetLastError(ERROR_INVALID_PARAMETER);
- else if (!IsEqualIID(&list->ClassGuid, &GUID_NULL) && !IsEqualIID(&list->ClassGuid, ClassGuid))
- SetLastError(ERROR_CLASS_MISMATCH);
- else if (CreationFlags & ~(DICD_GENERATE_ID | DICD_INHERIT_CLASSDRVS))
- {
- TRACE("Unknown flags: 0x%08lx\n", CreationFlags & ~(DICD_GENERATE_ID | DICD_INHERIT_CLASSDRVS));
+ else if (ClassInstallParamsSize != sizeof(SP_PROPCHANGE_PARAMS))
SetLastError(ERROR_INVALID_PARAMETER);
- }
+ else if (PropChangeParams && PropChangeParams->StateChange != DICS_ENABLE
+ && PropChangeParams->StateChange != DICS_DISABLE && PropChangeParams->StateChange != DICS_PROPCHANGE
+ && PropChangeParams->StateChange != DICS_START && PropChangeParams->StateChange != DICS_STOP)
+ SetLastError(ERROR_INVALID_FLAGS);
+ else if (PropChangeParams && PropChangeParams->Scope != DICS_FLAG_GLOBAL
+ && PropChangeParams->Scope != DICS_FLAG_CONFIGSPECIFIC)
+ SetLastError(ERROR_INVALID_FLAGS);
+ else if (PropChangeParams
+ && (PropChangeParams->StateChange == DICS_START || PropChangeParams->StateChange == DICS_STOP)
+ && PropChangeParams->Scope != DICS_FLAG_CONFIGSPECIFIC)
+ SetLastError(ERROR_INVALID_USER_BUFFER);
else
{
- SP_DEVINFO_DATA DevInfo;
-
- if (CreationFlags & DICD_GENERATE_ID)
+ PSP_PROPCHANGE_PARAMS *CurrentPropChangeParams;
+ if (!DeviceInfoData)
{
- /* Generate a new unique ID for this device */
- SetLastError(ERROR_GEN_FAILURE);
- FIXME("not implemented\n");
+ struct DeviceInfoSet *list = (struct DeviceInfoSet *)DeviceInfoSet;
+ CurrentPropChangeParams = &list->ClassInstallParams.PropChange;
}
else
{
- /* Device name is fully qualified. Try to open it */
- BOOL rc;
-
- DevInfo.cbSize = sizeof(SP_DEVINFO_DATA);
- rc = SetupDiOpenDeviceInfoW(
- DeviceInfoSet,
- DeviceName,
- NULL, /* hwndParent */
- CreationFlags & DICD_INHERIT_CLASSDRVS ? DIOD_INHERIT_CLASSDRVS : 0,
- &DevInfo);
-
- if (rc)
- {
- /* SetupDiOpenDeviceInfoW has already added
- * the device info to the device info set
- */
- SetLastError(ERROR_DEVINST_ALREADY_EXISTS);
- }
- else if (GetLastError() == ERROR_FILE_NOT_FOUND)
+ struct DeviceInfoElement *deviceInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
+ CurrentPropChangeParams = &deviceInfo->ClassInstallParams.PropChange;
+ }
+ if (*CurrentPropChangeParams)
+ {
+ MyFree(*CurrentPropChangeParams);
+ *CurrentPropChangeParams = NULL;
+ }
+ if (PropChangeParams)
+ {
+ *CurrentPropChangeParams = MyMalloc(sizeof(SP_PROPCHANGE_PARAMS));
+ if (!*CurrentPropChangeParams)
{
- struct DeviceInfoElement *deviceInfo;
-
- if (CreateDeviceInfoElement(DeviceName, &GUID_NULL /* FIXME */, &deviceInfo))
- {
- InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
-
- if (!DeviceInfoData)
- ret = TRUE;
- else
- {
- if (DeviceInfoData->cbSize != sizeof(PSP_DEVINFO_DATA))
- {
- SetLastError(ERROR_INVALID_USER_BUFFER);
- }
- else
- {
- memcpy(&DeviceInfoData->ClassGuid, ClassGuid, sizeof(GUID));
- DeviceInfoData->DevInst = 0; /* FIXME */
- DeviceInfoData->Reserved = (ULONG_PTR)deviceInfo;
- ret = TRUE;
- }
- }
- }
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto done;
}
+ memcpy(*CurrentPropChangeParams, PropChangeParams, sizeof(SP_PROPCHANGE_PARAMS));
}
+ ret = TRUE;
}
- TRACE("Returning %d\n", ret);
+done:
return ret;
}
-/***********************************************************************
- * Helper functions for SetupDiBuildDriverInfoList
- */
-static BOOL
-AddDriverToList(
- IN PLIST_ENTRY DriverListHead,
- IN DWORD DriverType, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */
- IN INFCONTEXT ContextDevice,
- IN LPCWSTR InfFile,
- IN LPCWSTR ProviderName,
- IN LPCWSTR ManufacturerName,
- FILETIME DriverDate,
- DWORDLONG DriverVersion,
- IN DWORD Rank)
+static DWORD
+GetFunctionPointer(
+ IN PWSTR InstallerName,
+ OUT HMODULE* ModulePointer,
+ OUT PVOID* FunctionPointer)
{
- struct DriverInfoElement *driverInfo;
- DWORD RequiredSize = 128; /* Initial buffer size */
- BOOL Result = FALSE;
- LPWSTR DeviceDescription = NULL;
- LPWSTR InfInstallSection = NULL;
+ HMODULE hModule = NULL;
+ LPSTR FunctionNameA = NULL;
+ PWCHAR Comma;
+ DWORD rc;
- driverInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(struct DriverInfoElement));
- if (!driverInfo)
- {
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- return FALSE;
- }
+ *ModulePointer = NULL;
+ *FunctionPointer = NULL;
- 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);
- }
- if (!Result)
+ Comma = strchrW(InstallerName, ',');
+ if (!Comma)
{
- HeapFree(GetProcessHeap(), 0, driverInfo);
- HeapFree(GetProcessHeap(), 0, DeviceDescription);
- return FALSE;
+ rc = ERROR_INVALID_PARAMETER;
+ goto cleanup;
}
- Result = FALSE;
- RequiredSize = 128; /* Initial buffer size */
- SetLastError(ERROR_INSUFFICIENT_BUFFER);
- while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
- {
- HeapFree(GetProcessHeap(), 0, InfInstallSection);
- InfInstallSection = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
- if (!InfInstallSection)
- {
- HeapFree(GetProcessHeap(), 0, driverInfo);
- HeapFree(GetProcessHeap(), 0, DeviceDescription);
- return FALSE;
- }
- Result = SetupGetStringFieldW(
- &ContextDevice,
- 1, /* Field index */
- InfInstallSection, RequiredSize,
- &RequiredSize);
- }
- if (!Result)
+ /* Load library */
+ *Comma = '\0';
+ hModule = LoadLibraryW(InstallerName);
+ *Comma = ',';
+ if (!hModule)
{
- HeapFree(GetProcessHeap(), 0, driverInfo);
- HeapFree(GetProcessHeap(), 0, DeviceDescription);
- HeapFree(GetProcessHeap(), 0, InfInstallSection);
- return FALSE;
+ rc = GetLastError();
+ goto cleanup;
}
- TRACE("Adding driver '%S' [%S/%S] (Rank 0x%lx)\n",
- DeviceDescription, InfFile, InfInstallSection, Rank);
+ /* Skip comma spaces */
+ while (*Comma == ',' || isspaceW(*Comma))
+ Comma++;
- driverInfo->Info.DriverType = DriverType;
- driverInfo->Info.Reserved = (ULONG_PTR)driverInfo;
- wcsncpy(driverInfo->Info.Description, DeviceDescription, 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';
- if (ProviderName)
+ /* W->A conversion for function name */
+ FunctionNameA = UnicodeToMultiByte(Comma, CP_ACP);
+ if (!FunctionNameA)
{
- wcsncpy(driverInfo->Info.ProviderName, ProviderName, LINE_LEN - 1);
- driverInfo->Info.ProviderName[LINE_LEN - 1] = '\0';
+ rc = GetLastError();
+ goto cleanup;
}
- else
- driverInfo->Info.ProviderName[0] = '\0';
- driverInfo->Info.DriverDate = DriverDate;
- driverInfo->Info.DriverVersion = DriverVersion;
- InsertTailList(DriverListHead, &driverInfo->ListEntry);
-
- HeapFree(GetProcessHeap(), 0, DeviceDescription);
- HeapFree(GetProcessHeap(), 0, InfInstallSection);
- return TRUE;
-}
-
-static BOOL
-GetVersionInformationFromInfFile(
- IN HINF hInf,
- OUT LPGUID ClassGuid,
- OUT LPWSTR* pProviderName,
- OUT FILETIME* DriverDate,
- OUT DWORDLONG* DriverVersion)
-{
- DWORD RequiredSize;
- WCHAR guidW[MAX_GUID_STRING_LEN + 1];
- LPWSTR ProviderName = NULL;
- BOOL Result;
- if (!SetupGetLineTextW(
- NULL, /* Context */
- hInf,
- L"Version", L"ClassGUID",
- guidW, sizeof(guidW),
- NULL /* Required size */))
+ /* Search function */
+ *FunctionPointer = GetProcAddress(hModule, FunctionNameA);
+ if (!*FunctionPointer)
{
- return FALSE;
+ rc = GetLastError();
+ goto cleanup;
}
- /* Get Provider name, driver date, and driver version */
+ *ModulePointer = hModule;
+ rc = ERROR_SUCCESS;
- guidW[37] = '\0'; /* Replace the } by a NULL character */
- if (UuidFromStringW(&guidW[1], ClassGuid) != RPC_S_OK)
- {
- return FALSE;
- }
- Result = SetupGetLineTextW(
- NULL, /* Context */
- hInf, L"Version", L"Provider",
- NULL, 0,
- &RequiredSize);
- if (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
- {
- ProviderName = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
- if (!ProviderName)
- {
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- return FALSE;
- }
- Result = SetupGetLineTextW(
- NULL, /* Context */
- hInf, L"Version", L"Provider",
- ProviderName, RequiredSize,
- &RequiredSize);
- }
- //FIXME: DriverDate = Version.DriverVer => invalid date = 00/00/00
- //FIXME: DriverVersion = Version.DriverVer => invalid = 0
+cleanup:
+ if (rc != ERROR_SUCCESS && hModule)
+ FreeLibrary(hModule);
+ MyFree(FunctionNameA);
+ return rc;
+}
- *pProviderName = ProviderName;
- return TRUE;
+static DWORD
+FreeFunctionPointer(
+ IN HMODULE ModulePointer,
+ IN PVOID FunctionPointer)
+{
+ if (ModulePointer == NULL)
+ return ERROR_SUCCESS;
+ if (FreeLibrary(ModulePointer))
+ return ERROR_SUCCESS;
+ else
+ return GetLastError();
}
/***********************************************************************
- * SetupDiBuildDriverInfoList (SETUPAPI.@)
+ * SetupDiCallClassInstaller (SETUPAPI.@)
*/
-BOOL WINAPI
-SetupDiBuildDriverInfoList(
- IN HDEVINFO DeviceInfoSet,
- IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
- IN DWORD DriverType)
+BOOL WINAPI SetupDiCallClassInstaller(
+ IN DI_FUNCTION InstallFunction,
+ IN HDEVINFO DeviceInfoSet,
+ IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
{
- struct DeviceInfoSet *list;
- PVOID Buffer = NULL;
- HINF hInf = INVALID_HANDLE_VALUE;
- LPWSTR ProviderName = NULL;
- LPWSTR ManufacturerName = NULL;
- LPWSTR ManufacturerSection = NULL;
- LPWSTR HardwareIDs = NULL;
- LPWSTR CompatibleIDs = NULL;
- FILETIME DriverDate;
- DWORDLONG DriverVersion;
- DWORD RequiredSize;
BOOL ret = FALSE;
- TRACE("%p %p %ld\n", DeviceInfoSet, DeviceInfoData, DriverType);
+ TRACE("%u %p %p\n", InstallFunction, DeviceInfoSet, DeviceInfoData);
if (!DeviceInfoSet)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
SetLastError(ERROR_INVALID_HANDLE);
- else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
- SetLastError(ERROR_INVALID_HANDLE);
- else if (list->HKLM != HKEY_LOCAL_MACHINE)
+ else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
+ SetLastError(ERROR_INVALID_HANDLE);
+ else if (((struct DeviceInfoSet *)DeviceInfoSet)->HKLM != HKEY_LOCAL_MACHINE)
SetLastError(ERROR_INVALID_HANDLE);
- else if (DriverType != SPDIT_CLASSDRIVER && DriverType != SPDIT_COMPATDRIVER)
- SetLastError(ERROR_INVALID_PARAMETER);
- else if (DriverType == SPDIT_CLASSDRIVER && DeviceInfoData)
- 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
{
- BOOL Result = FALSE;
+ SP_DEVINSTALL_PARAMS_W InstallParams;
+#define CLASS_COINSTALLER 0x1
+#define DEVICE_COINSTALLER 0x2
+#define CLASS_INSTALLER 0x4
+ UCHAR CanHandle = 0;
+ DEFAULT_CLASS_INSTALL_PROC DefaultHandler = NULL;
+
+ switch (InstallFunction)
+ {
+ case DIF_ADDPROPERTYPAGE_ADVANCED:
+ CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
+ break;
+ case DIF_ALLOW_INSTALL:
+ CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
+ break;
+ case DIF_DESTROYPRIVATEDATA:
+ CanHandle = CLASS_INSTALLER;
+ break;
+ case DIF_INSTALLDEVICE:
+ CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
+ DefaultHandler = SetupDiInstallDevice;
+ break;
+ case DIF_INSTALLDEVICEFILES:
+ CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
+ DefaultHandler = SetupDiInstallDriverFiles;
+ break;
+ case DIF_INSTALLINTERFACES:
+ CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
+ DefaultHandler = SetupDiInstallDeviceInterfaces;
+ break;
+ case DIF_NEWDEVICEWIZARD_FINISHINSTALL:
+ CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
+ break;
+ case DIF_NEWDEVICEWIZARD_POSTANALYZE:
+ CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
+ break;
+ case DIF_NEWDEVICEWIZARD_PREANALYZE:
+ CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
+ break;
+ case DIF_PROPERTYCHANGE:
+ CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
+ DefaultHandler = SetupDiChangeState;
+ break;
+ case DIF_REGISTER_COINSTALLERS:
+ CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
+ DefaultHandler = SetupDiRegisterCoDeviceInstallers;
+ break;
+ case DIF_SELECTBESTCOMPATDRV:
+ CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
+ DefaultHandler = SetupDiSelectBestCompatDrv;
+ break;
+ default:
+ ERR("Install function %u not supported\n", InstallFunction);
+ SetLastError(ERROR_NOT_SUPPORTED);
+ }
- if (DriverType == SPDIT_COMPATDRIVER)
+ 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)
{
- /* Get hardware IDs list */
- Result = FALSE;
- RequiredSize = 512; /* Initial buffer size */
- SetLastError(ERROR_INSUFFICIENT_BUFFER);
- while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+ LIST_ENTRY ClassCoInstallersListHead;
+ LIST_ENTRY DeviceCoInstallersListHead;
+ HMODULE ClassInstallerLibrary = NULL;
+ CLASS_INSTALL_PROC ClassInstaller = NULL;
+ COINSTALLER_CONTEXT_DATA Context;
+ PLIST_ENTRY ListEntry;
+ HKEY hKey;
+ DWORD dwRegType, dwLength;
+ DWORD rc = NO_ERROR;
+
+ InitializeListHead(&ClassCoInstallersListHead);
+ InitializeListHead(&DeviceCoInstallersListHead);
+
+ if (CanHandle & DEVICE_COINSTALLER)
{
- HeapFree(GetProcessHeap(), 0, HardwareIDs);
- HardwareIDs = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
- if (!HardwareIDs)
+ hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_QUERY_VALUE);
+ if (hKey != INVALID_HANDLE_VALUE)
{
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- goto done;
+ rc = RegQueryValueExW(hKey, REGSTR_VAL_COINSTALLERS_32, NULL, &dwRegType, NULL, &dwLength);
+ if (rc == ERROR_SUCCESS && dwRegType == REG_MULTI_SZ)
+ {
+ LPWSTR KeyBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength);
+ if (KeyBuffer != NULL)
+ {
+ rc = RegQueryValueExW(hKey, REGSTR_VAL_COINSTALLERS_32, 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);
}
- Result = SetupDiGetDeviceRegistryPropertyW(
- DeviceInfoSet,
- DeviceInfoData,
- SPDRP_HARDWAREID,
- NULL,
- (PBYTE)HardwareIDs,
- RequiredSize,
- &RequiredSize);
}
- if (!Result)
- goto done;
-
- /* Get compatible IDs list */
- Result = FALSE;
- RequiredSize = 512; /* Initial buffer size */
- SetLastError(ERROR_INSUFFICIENT_BUFFER);
- while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+ if (CanHandle & CLASS_COINSTALLER)
{
- HeapFree(GetProcessHeap(), 0, CompatibleIDs);
- CompatibleIDs = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
- if (!CompatibleIDs)
+ rc = RegOpenKeyEx(
+ HKEY_LOCAL_MACHINE,
+ REGSTR_PATH_CODEVICEINSTALLERS,
+ 0, /* Options */
+ KEY_QUERY_VALUE,
+ &hKey);
+ if (rc == ERROR_SUCCESS)
{
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- goto done;
+ LPWSTR lpGuidString;
+ if (UuidToStringW((UUID*)&DeviceInfoData->ClassGuid, &lpGuidString) == RPC_S_OK)
+ {
+ 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, lpGuidString, NULL, NULL, (LPBYTE)KeyBuffer, &dwLength);
+ if (rc == ERROR_SUCCESS)
+ {
+ LPWSTR ptr;
+ for (ptr = KeyBuffer; *ptr; ptr += strlenW(ptr) + 1)
+ {
+ /* 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);
+ }
+ }
+ RpcStringFreeW(&lpGuidString);
+ }
+ RegCloseKey(hKey);
}
- Result = SetupDiGetDeviceRegistryPropertyW(
- DeviceInfoSet,
- DeviceInfoData,
- SPDRP_COMPATIBLEIDS,
- NULL,
- (PBYTE)CompatibleIDs,
- RequiredSize,
- &RequiredSize);
- if (!Result && GetLastError() == ERROR_FILE_NOT_FOUND)
+ }
+ if ((CanHandle & CLASS_INSTALLER) && !(InstallParams.FlagsEx & DI_FLAGSEX_CI_FAILED))
+ {
+ hKey = SetupDiOpenClassRegKey(&DeviceInfoData->ClassGuid, KEY_QUERY_VALUE);
+ if (hKey != INVALID_HANDLE_VALUE)
{
- /* No compatible ID for this device */
- HeapFree(GetProcessHeap(), 0, CompatibleIDs);
- CompatibleIDs = NULL;
- Result = TRUE;
+ rc = RegQueryValueExW(hKey, REGSTR_VAL_INSTALLER_32, NULL, &dwRegType, NULL, &dwLength);
+ if (rc == ERROR_SUCCESS && dwRegType == REG_SZ)
+ {
+ LPWSTR KeyBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength);
+ if (KeyBuffer != NULL)
+ {
+ rc = RegQueryValueExW(hKey, REGSTR_VAL_INSTALLER_32, NULL, NULL, (LPBYTE)KeyBuffer, &dwLength);
+ if (rc == ERROR_SUCCESS)
+ {
+ /* 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);
+ }
+ }
+ RegCloseKey(hKey);
}
}
- if (!Result)
- goto done;
- }
- /* Enumerate .inf files */
- Result = FALSE;
- RequiredSize = 32768; /* Initial buffer size */
- SetLastError(ERROR_INSUFFICIENT_BUFFER);
- while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
- {
- HeapFree(GetProcessHeap(), 0, Buffer);
- Buffer = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
- if (!Buffer)
+ /* Call Class co-installers */
+ Context.PostProcessing = FALSE;
+ rc = NO_ERROR;
+ ListEntry = ClassCoInstallersListHead.Flink;
+ while (rc == NO_ERROR && ListEntry != &ClassCoInstallersListHead)
{
- Result = FALSE;
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- break;
+ struct CoInstallerElement *coinstaller = (struct CoInstallerElement *)ListEntry;
+ rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context);
+ coinstaller->PrivateData = Context.PrivateData;
+ if (rc == ERROR_DI_POSTPROCESSING_REQUIRED)
+ {
+ coinstaller->DoPostProcessing = TRUE;
+ rc = NO_ERROR;
+ }
+ ListEntry = ListEntry->Flink;
}
- Result = SetupGetInfFileListW(
- NULL, /* Directory path */
- INF_STYLE_WIN4,
- Buffer, RequiredSize,
- &RequiredSize);
- }
- if (Result)
- {
- LPCWSTR filename;
- for (filename = (LPCWSTR)Buffer; *filename; filename += wcslen(filename) + 1)
+ /* Call Device co-installers */
+ ListEntry = DeviceCoInstallersListHead.Flink;
+ while (rc == NO_ERROR && ListEntry != &DeviceCoInstallersListHead)
{
- INFCONTEXT ContextManufacturer, ContextDevice;
- GUID ClassGuid;
- TRACE("Opening file %S\n", filename);
+ struct CoInstallerElement *coinstaller = (struct CoInstallerElement *)ListEntry;
+ rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context);
+ coinstaller->PrivateData = Context.PrivateData;
+ if (rc == ERROR_DI_POSTPROCESSING_REQUIRED)
+ {
+ coinstaller->DoPostProcessing = TRUE;
+ rc = NO_ERROR;
+ }
+ ListEntry = ListEntry->Flink;
+ }
- hInf = SetupOpenInfFileW(filename, NULL, INF_STYLE_WIN4, NULL);
- if (hInf == INVALID_HANDLE_VALUE)
- continue;
+ /* Call Class installer */
+ if (ClassInstaller)
+ {
+ rc = (*ClassInstaller)(InstallFunction, DeviceInfoSet, DeviceInfoData);
+ FreeFunctionPointer(ClassInstallerLibrary, ClassInstaller);
+ }
+ else
+ rc = ERROR_DI_DO_DEFAULT;
- if (!GetVersionInformationFromInfFile(
- hInf,
- &ClassGuid,
- &ProviderName,
- &DriverDate,
- &DriverVersion))
+ /* Call default handler */
+ if (rc == ERROR_DI_DO_DEFAULT)
+ {
+ if (DefaultHandler && !(InstallParams.Flags & DI_NODI_DEFAULTACTION))
{
- SetupCloseInfFile(hInf);
- hInf = INVALID_HANDLE_VALUE;
- continue;
+ if ((*DefaultHandler)(DeviceInfoSet, DeviceInfoData))
+ rc = NO_ERROR;
+ else
+ rc = GetLastError();
}
+ else
+ rc = NO_ERROR;
+ }
- if (DriverType == SPDIT_CLASSDRIVER)
+ /* Call Class co-installers that required postprocessing */
+ Context.PostProcessing = TRUE;
+ ListEntry = ClassCoInstallersListHead.Flink;
+ while (ListEntry != &ClassCoInstallersListHead)
+ {
+ struct CoInstallerElement *coinstaller = (struct CoInstallerElement *)ListEntry;
+ if (coinstaller->DoPostProcessing)
{
- /* Check if the ClassGuid in this .inf file is corresponding with our needs */
- if (!IsEqualIID(&list->ClassGuid, &GUID_NULL) && !IsEqualIID(&list->ClassGuid, &ClassGuid))
- {
- SetupCloseInfFile(hInf);
- hInf = INVALID_HANDLE_VALUE;
- continue;
- }
+ Context.InstallResult = rc;
+ Context.PrivateData = coinstaller->PrivateData;
+ rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context);
}
+ FreeFunctionPointer(coinstaller->Module, coinstaller->Function);
+ ListEntry = ListEntry->Flink;
+ }
- /* Get the manufacturers list */
- Result = SetupFindFirstLineW(hInf, L"Manufacturer", NULL, &ContextManufacturer);
- while (Result)
+ /* Call Device co-installers that required postprocessing */
+ ListEntry = DeviceCoInstallersListHead.Flink;
+ while (ListEntry != &DeviceCoInstallersListHead)
+ {
+ struct CoInstallerElement *coinstaller = (struct CoInstallerElement *)ListEntry;
+ if (coinstaller->DoPostProcessing)
{
- Result = SetupGetStringFieldW(
- &ContextManufacturer,
- 0, /* Field index */
- NULL, 0,
- &RequiredSize);
- if (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
- {
- ManufacturerName = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
- if (!ManufacturerName)
- {
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- goto done;
- }
- Result = SetupGetStringFieldW(
- &ContextManufacturer,
- 0, /* Field index */
- ManufacturerName, RequiredSize,
- &RequiredSize);
- }
- Result = SetupGetStringFieldW(
- &ContextManufacturer,
- 1, /* Field index */
- NULL, 0,
- &RequiredSize);
- if (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
- {
- ManufacturerSection = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
- if (!ManufacturerSection)
- {
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- goto done;
- }
- Result = SetupGetStringFieldW(
- &ContextManufacturer,
- 1, /* Field index */
- ManufacturerSection, RequiredSize,
- &RequiredSize);
- }
+ Context.InstallResult = rc;
+ Context.PrivateData = coinstaller->PrivateData;
+ rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context);
+ }
+ FreeFunctionPointer(coinstaller->Module, coinstaller->Function);
+ ListEntry = ListEntry->Flink;
+ }
- TRACE("Enumerating devices in manufacturer %S\n", ManufacturerSection);
- Result = SetupFindFirstLineW(hInf, ManufacturerSection, NULL, &ContextDevice);
- while (Result)
- {
- if (DriverType == SPDIT_CLASSDRIVER)
- {
- /* FIXME: read [ControlFlags] / ExcludeFromSelect */
- if (!AddDriverToList(
- &list->DriverListHead,
- DriverType,
- ContextDevice,
- filename,
- ProviderName,
- ManufacturerName,
- DriverDate, DriverVersion,
- 0))
- {
- break;
- }
- }
- else /* DriverType = SPDIT_COMPATDRIVER */
- {
- /* 1. Get all fields */
- DWORD FieldCount = SetupGetFieldCount(&ContextDevice);
- DWORD DriverRank;
- DWORD i;
- LPCWSTR currentId;
- BOOL DriverAlreadyAdded;
+ /* Free allocated memory */
+ while (!IsListEmpty(&ClassCoInstallersListHead))
+ {
+ ListEntry = RemoveHeadList(&ClassCoInstallersListHead);
+ HeapFree(GetProcessHeap(), 0, ListEntry);
+ }
+ while (!IsListEmpty(&DeviceCoInstallersListHead))
+ {
+ ListEntry = RemoveHeadList(&DeviceCoInstallersListHead);
+ HeapFree(GetProcessHeap(), 0, ListEntry);
+ }
- for (i = 2; i <= FieldCount; i++)
- {
- LPWSTR DeviceId = NULL;
- Result = FALSE;
- RequiredSize = 128; /* Initial buffer size */
- SetLastError(ERROR_INSUFFICIENT_BUFFER);
- while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
- {
- HeapFree(GetProcessHeap(), 0, DeviceId);
- DeviceId = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
- if (!DeviceId)
- {
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- goto done;
- }
- Result = SetupGetStringFieldW(
- &ContextDevice,
- i,
- DeviceId, RequiredSize,
- &RequiredSize);
- }
- if (!Result)
- {
- HeapFree(GetProcessHeap(), 0, DeviceId);
- goto done;
- }
- DriverAlreadyAdded = FALSE;
- for (DriverRank = 0, currentId = (LPCWSTR)HardwareIDs; !DriverAlreadyAdded && *currentId; currentId += wcslen(currentId) + 1, DriverRank++)
- {
- if (wcscmp(DeviceId, currentId) == 0)
- {
- AddDriverToList(
- &((struct DeviceInfoElement *)DeviceInfoData->Reserved)->DriverListHead,
- DriverType,
- ContextDevice,
- filename,
- ProviderName,
- ManufacturerName,
- DriverDate, DriverVersion,
- DriverRank + (i == 2 ? 0 : 0x1000 + i - 3));
+ ret = (rc == NO_ERROR);
+ }
+ }
+
+ TRACE("Returning %d\n", ret);
+ return ret;
+}
+
+/***********************************************************************
+ * SetupDiGetDeviceInfoListClass (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiGetDeviceInfoListClass(
+ IN HDEVINFO DeviceInfoSet,
+ OUT LPGUID ClassGuid)
+{
+ struct DeviceInfoSet *list;
+ BOOL ret = FALSE;
+
+ TRACE("%p %p\n", DeviceInfoSet, ClassGuid);
+
+ if (!DeviceInfoSet)
+ SetLastError(ERROR_INVALID_HANDLE);
+ else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
+ SetLastError(ERROR_INVALID_HANDLE);
+ else if (IsEqualIID(&list->ClassGuid, &GUID_NULL))
+ SetLastError(ERROR_NO_ASSOCIATED_CLASS);
+ else
+ {
+ memcpy(&ClassGuid, &list->ClassGuid, sizeof(GUID));
+
+ ret = TRUE;
+ }
+
+ TRACE("Returning %d\n", ret);
+ return ret;
+}
+
+/***********************************************************************
+ * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiGetDeviceInfoListDetailW(
+ IN HDEVINFO DeviceInfoSet,
+ OUT PSP_DEVINFO_LIST_DETAIL_DATA_W DeviceInfoListDetailData)
+{
+ struct DeviceInfoSet *list;
+ BOOL ret = FALSE;
+
+ TRACE("%p %p\n", DeviceInfoSet, DeviceInfoListDetailData);
+
+ if (!DeviceInfoSet)
+ SetLastError(ERROR_INVALID_HANDLE);
+ else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
+ SetLastError(ERROR_INVALID_HANDLE);
+ else if (!DeviceInfoListDetailData)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else if (DeviceInfoListDetailData->cbSize != sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W))
+ SetLastError(ERROR_INVALID_USER_BUFFER);
+ else
+ {
+ memcpy(
+ &DeviceInfoListDetailData->ClassGuid,
+ &list->ClassGuid,
+ sizeof(GUID));
+ DeviceInfoListDetailData->RemoteMachineHandle = list->hMachine;
+ if (list->MachineName)
+ strcpyW(DeviceInfoListDetailData->RemoteMachineName, list->MachineName + 2);
+ else
+ DeviceInfoListDetailData->RemoteMachineName[0] = 0;
+
+ ret = TRUE;
+ }
+
+ TRACE("Returning %d\n", ret);
+ return ret;
+}
+
+/***********************************************************************
+ * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiGetDeviceInstallParamsA(
+ IN HDEVINFO DeviceInfoSet,
+ IN PSP_DEVINFO_DATA DeviceInfoData,
+ OUT PSP_DEVINSTALL_PARAMS_A DeviceInstallParams)
+{
+ SP_DEVINSTALL_PARAMS_W deviceInstallParamsW;
+ BOOL ret = FALSE;
+
+ TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
+
+ if (DeviceInstallParams == NULL)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else if (DeviceInstallParams->cbSize != sizeof(SP_DEVINSTALL_PARAMS_A))
+ SetLastError(ERROR_INVALID_USER_BUFFER);
+ else
+ {
+ deviceInstallParamsW.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
+ ret = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &deviceInstallParamsW);
+
+ if (ret)
+ {
+ /* Do W->A conversion */
+ memcpy(
+ DeviceInstallParams,
+ &deviceInstallParamsW,
+ FIELD_OFFSET(SP_DEVINSTALL_PARAMS_W, DriverPath));
+ if (WideCharToMultiByte(CP_ACP, 0, deviceInstallParamsW.DriverPath, -1,
+ DeviceInstallParams->DriverPath, MAX_PATH, NULL, NULL) == 0)
+ {
+ DeviceInstallParams->DriverPath[0] = '\0';
+ ret = FALSE;
+ }
+ }
+ }
+
+ TRACE("Returning %d\n", ret);
+ return ret;
+}
+
+/***********************************************************************
+ * SetupDiGetDeviceInstallParamsW (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiGetDeviceInstallParamsW(
+ IN HDEVINFO DeviceInfoSet,
+ IN PSP_DEVINFO_DATA DeviceInfoData,
+ OUT 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 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;
+}
+
+/***********************************************************************
+ * 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;
+}
+
+/***********************************************************************
+ * SetupDiGetDeviceInstanceIdA(SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiGetDeviceInstanceIdA(
+ IN HDEVINFO DeviceInfoSet,
+ IN PSP_DEVINFO_DATA DeviceInfoData,
+ OUT PSTR DeviceInstanceId OPTIONAL,
+ IN DWORD DeviceInstanceIdSize,
+ OUT PDWORD RequiredSize OPTIONAL)
+{
+ PWSTR DeviceInstanceIdW = NULL;
+ BOOL ret = FALSE;
+
+ TRACE("%p %p %p %lu %p\n", DeviceInfoSet, DeviceInfoData,
+ DeviceInstanceId, DeviceInstanceIdSize, RequiredSize);
+
+ if (!DeviceInstanceId && DeviceInstanceIdSize > 0)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else
+ {
+ if (DeviceInstanceIdSize != 0)
+ {
+ DeviceInstanceIdW = MyMalloc(DeviceInstanceIdSize * sizeof(WCHAR));
+ if (DeviceInstanceIdW == NULL)
+ return FALSE;
+ }
+
+ ret = SetupDiGetDeviceInstanceIdW(DeviceInfoSet, DeviceInfoData,
+ DeviceInstanceIdW, DeviceInstanceIdSize,
+ RequiredSize);
+
+ if (ret && DeviceInstanceIdW != NULL)
+ {
+ if (WideCharToMultiByte(CP_ACP, 0, DeviceInstanceIdW, -1,
+ DeviceInstanceId, DeviceInstanceIdSize, NULL, NULL) == 0)
+ {
+ DeviceInstanceId[0] = '\0';
+ ret = FALSE;
+ }
+ }
+ }
+
+ TRACE("Returning %d\n", ret);
+ return ret;
+}
+
+/***********************************************************************
+ * SetupDiGetDeviceInstanceIdW(SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiGetDeviceInstanceIdW(
+ IN HDEVINFO DeviceInfoSet,
+ IN PSP_DEVINFO_DATA DeviceInfoData,
+ OUT PWSTR DeviceInstanceId OPTIONAL,
+ IN DWORD DeviceInstanceIdSize,
+ OUT PDWORD RequiredSize OPTIONAL)
+{
+ BOOL ret = FALSE;
+
+ TRACE("%p %p %p %lu %p\n", DeviceInfoSet, DeviceInfoData,
+ DeviceInstanceId, DeviceInstanceIdSize, RequiredSize);
+
+ if (!DeviceInfoSet)
+ 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 if (!DeviceInstanceId && DeviceInstanceIdSize > 0)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else if (DeviceInstanceId && DeviceInstanceIdSize == 0)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else
+ {
+ struct DeviceInfoElement *DevInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
+ DWORD required;
+
+ required = (wcslen(DevInfo->DeviceName) + 1) * sizeof(WCHAR);
+ if (RequiredSize)
+ *RequiredSize = required;
+
+ if (required <= DeviceInstanceIdSize)
+ {
+ wcscpy(DeviceInstanceId, DevInfo->DeviceName);
+ ret = TRUE;
+ }
+ else
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ }
+
+ TRACE("Returning %d\n", ret);
+ return ret;
+}
+
+/***********************************************************************
+ * SetupDiGetClassDevPropertySheetsA(SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiGetClassDevPropertySheetsA(
+ IN HDEVINFO DeviceInfoSet,
+ IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
+ IN LPPROPSHEETHEADERA PropertySheetHeader,
+ IN DWORD PropertySheetHeaderPageListSize,
+ OUT PDWORD RequiredSize OPTIONAL,
+ IN DWORD PropertySheetType)
+{
+ PROPSHEETHEADERW psh;
+ BOOL ret = FALSE;
+
+ TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet, DeviceInfoData,
+ PropertySheetHeader, PropertySheetHeaderPageListSize,
+ RequiredSize, PropertySheetType);
+
+ psh.dwFlags = PropertySheetHeader->dwFlags;
+ psh.phpage = PropertySheetHeader->phpage;
+ psh.nPages = PropertySheetHeader->nPages;
+
+ ret = SetupDiGetClassDevPropertySheetsW(DeviceInfoSet, DeviceInfoData, PropertySheetHeader ? &psh : NULL,
+ PropertySheetHeaderPageListSize, RequiredSize,
+ PropertySheetType);
+ if (ret)
+ {
+ PropertySheetHeader->nPages = psh.nPages;
+ }
+
+ TRACE("Returning %d\n", ret);
+ return ret;
+}
+
+struct ClassDevPropertySheetsData
+{
+ HPROPSHEETPAGE *PropertySheetPages;
+ DWORD MaximumNumberOfPages;
+ DWORD NumberOfPages;
+};
+
+static BOOL WINAPI GetClassDevPropertySheetsCallback(
+ IN HPROPSHEETPAGE hPropSheetPage,
+ IN OUT LPARAM lParam)
+{
+ struct ClassDevPropertySheetsData *PropPageData;
+
+ PropPageData = (struct ClassDevPropertySheetsData *)lParam;
+
+ if (PropPageData->NumberOfPages < PropPageData->MaximumNumberOfPages)
+ {
+ *PropPageData->PropertySheetPages = hPropSheetPage;
+ PropPageData->PropertySheetPages++;
+ }
+
+ PropPageData->NumberOfPages++;
+ return TRUE;
+}
+
+/***********************************************************************
+ * SetupDiGetClassDevPropertySheetsW(SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiGetClassDevPropertySheetsW(
+ IN HDEVINFO DeviceInfoSet,
+ IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
+ IN OUT LPPROPSHEETHEADERW PropertySheetHeader,
+ IN DWORD PropertySheetHeaderPageListSize,
+ OUT PDWORD RequiredSize OPTIONAL,
+ IN DWORD PropertySheetType)
+{
+ struct DeviceInfoSet *list;
+ BOOL ret = FALSE;
+
+ TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet, DeviceInfoData,
+ PropertySheetHeader, PropertySheetHeaderPageListSize,
+ RequiredSize, PropertySheetType);
+
+ if (!DeviceInfoSet)
+ SetLastError(ERROR_INVALID_HANDLE);
+ else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
+ SetLastError(ERROR_INVALID_HANDLE);
+ else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
+ SetLastError(ERROR_INVALID_HANDLE);
+ else if (!PropertySheetHeader)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else if (PropertySheetHeader->dwFlags & PSH_PROPSHEETPAGE)
+ SetLastError(ERROR_INVALID_FLAGS);
+ else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
+ SetLastError(ERROR_INVALID_USER_BUFFER);
+ else if (!DeviceInfoData && IsEqualIID(&list->ClassGuid, &GUID_NULL))
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else if (!PropertySheetHeader)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else if (PropertySheetType != DIGCDP_FLAG_ADVANCED
+ && PropertySheetType != DIGCDP_FLAG_BASIC
+ && PropertySheetType != DIGCDP_FLAG_REMOTE_ADVANCED
+ && PropertySheetType != DIGCDP_FLAG_REMOTE_BASIC)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else
+ {
+ HKEY hKey = INVALID_HANDLE_VALUE;
+ SP_PROPSHEETPAGE_REQUEST Request;
+ LPWSTR PropPageProvider = NULL;
+ HMODULE hModule = NULL;
+ PROPERTY_PAGE_PROVIDER pPropPageProvider = NULL;
+ struct ClassDevPropertySheetsData PropPageData;
+ DWORD dwLength, dwRegType;
+ DWORD rc;
+
+ if (DeviceInfoData)
+ hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_QUERY_VALUE);
+ else
+ {
+ hKey = SetupDiOpenClassRegKeyExW(&list->ClassGuid, KEY_QUERY_VALUE,
+ DIOCR_INSTALLER, list->MachineName + 2, NULL);
+ }
+ if (hKey == INVALID_HANDLE_VALUE)
+ goto cleanup;
+
+ rc = RegQueryValueExW(hKey, REGSTR_VAL_ENUMPROPPAGES_32, NULL, &dwRegType, NULL, &dwLength);
+ if (rc == ERROR_FILE_NOT_FOUND)
+ {
+ /* No registry key. As it is optional, don't say it's a bad error */
+ if (RequiredSize)
+ *RequiredSize = 0;
+ ret = TRUE;
+ goto cleanup;
+ }
+ else if (rc != ERROR_SUCCESS && dwRegType != REG_SZ)
+ {
+ SetLastError(rc);
+ goto cleanup;
+ }
+
+ PropPageProvider = HeapAlloc(GetProcessHeap(), 0, dwLength + sizeof(WCHAR));
+ if (!PropPageProvider)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto cleanup;
+ }
+ rc = RegQueryValueExW(hKey, REGSTR_VAL_ENUMPROPPAGES_32, NULL, NULL, (LPBYTE)PropPageProvider, &dwLength);
+ if (rc != ERROR_SUCCESS)
+ {
+ SetLastError(rc);
+ goto cleanup;
+ }
+ PropPageProvider[dwLength / sizeof(WCHAR)] = 0;
+
+ rc = GetFunctionPointer(PropPageProvider, &hModule, (PVOID*)&pPropPageProvider);
+ if (rc != ERROR_SUCCESS)
+ {
+ SetLastError(ERROR_INVALID_PROPPAGE_PROVIDER);
+ goto cleanup;
+ }
+
+ Request.cbSize = sizeof(SP_PROPSHEETPAGE_REQUEST);
+ Request.PageRequested = SPPSR_ENUM_ADV_DEVICE_PROPERTIES;
+ Request.DeviceInfoSet = DeviceInfoSet;
+ Request.DeviceInfoData = DeviceInfoData;
+ PropPageData.PropertySheetPages = &PropertySheetHeader->phpage[PropertySheetHeader->nPages];
+ PropPageData.MaximumNumberOfPages = PropertySheetHeaderPageListSize - PropertySheetHeader->nPages;
+ PropPageData.NumberOfPages = 0;
+ ret = pPropPageProvider(&Request, GetClassDevPropertySheetsCallback, (LPARAM)&PropPageData);
+ if (!ret)
+ goto cleanup;
+
+ if (RequiredSize)
+ *RequiredSize = PropPageData.NumberOfPages + PropertySheetHeader->nPages;
+ if (PropPageData.NumberOfPages <= PropPageData.MaximumNumberOfPages)
+ {
+ PropertySheetHeader->nPages += PropPageData.NumberOfPages;
+ ret = TRUE;
+ }
+ else
+ {
+ PropertySheetHeader->nPages += PropPageData.MaximumNumberOfPages;
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ }
+
+cleanup:
+ if (hKey != INVALID_HANDLE_VALUE)
+ RegCloseKey(hKey);
+ HeapFree(GetProcessHeap(), 0, PropPageProvider);
+ FreeFunctionPointer(hModule, pPropPageProvider);
+ }
+
+ TRACE("Returning %d\n", ret);
+ return ret;
+}
+
+/***********************************************************************
+ * SetupDiCreateDevRegKeyA (SETUPAPI.@)
+ */
+HKEY WINAPI SetupDiCreateDevRegKeyA(
+ IN HDEVINFO DeviceInfoSet,
+ IN PSP_DEVINFO_DATA DeviceInfoData,
+ IN DWORD Scope,
+ IN DWORD HwProfile,
+ IN DWORD KeyType,
+ IN HINF InfHandle OPTIONAL,
+ IN PCSTR InfSectionName OPTIONAL)
+{
+ PCWSTR InfSectionNameW = NULL;
+ HKEY ret = INVALID_HANDLE_VALUE;
+
+ if (InfSectionName)
+ {
+ InfSectionNameW = MultiByteToUnicode(InfSectionName, CP_ACP);
+ if (InfSectionNameW == NULL) return INVALID_HANDLE_VALUE;
+ }
+
+ ret = SetupDiCreateDevRegKeyW(DeviceInfoSet,
+ DeviceInfoData,
+ Scope,
+ HwProfile,
+ KeyType,
+ InfHandle,
+ InfSectionNameW);
+
+ if (InfSectionNameW != NULL)
+ MyFree((PVOID)InfSectionNameW);
+
+ return ret;
+}
+
+static HKEY
+OpenHardwareProfileKey(
+ IN HKEY HKLM,
+ IN DWORD HwProfile,
+ IN DWORD samDesired)
+{
+ HKEY hHWProfilesKey = INVALID_HANDLE_VALUE;
+ HKEY hHWProfileKey = INVALID_HANDLE_VALUE;
+ HKEY ret = INVALID_HANDLE_VALUE;
+ LONG rc;
+
+ rc = RegOpenKeyExW(HKLM,
+ REGSTR_PATH_HWPROFILES,
+ 0,
+ 0,
+ &hHWProfilesKey);
+ if (rc != ERROR_SUCCESS)
+ {
+ SetLastError(rc);
+ goto cleanup;
+ }
+ if (HwProfile == 0)
+ {
+ rc = RegOpenKeyExW(
+ hHWProfilesKey,
+ REGSTR_KEY_CURRENT,
+ 0,
+ KEY_CREATE_SUB_KEY,
+ &hHWProfileKey);
+ }
+ else
+ {
+ WCHAR subKey[5];
+ snprintfW(subKey, 4, L"%04lu", HwProfile);
+ subKey[4] = '\0';
+ rc = RegOpenKeyExW(
+ hHWProfilesKey,
+ subKey,
+ 0,
+ KEY_CREATE_SUB_KEY,
+ &hHWProfileKey);
+ }
+ if (rc != ERROR_SUCCESS)
+ {
+ SetLastError(rc);
+ goto cleanup;
+ }
+ ret = hHWProfileKey;
+
+cleanup:
+ if (hHWProfilesKey != INVALID_HANDLE_VALUE)
+ RegCloseKey(hHWProfilesKey);
+ if (hHWProfileKey != INVALID_HANDLE_VALUE && hHWProfileKey != ret)
+ RegCloseKey(hHWProfileKey);
+ return ret;
+}
+
+/***********************************************************************
+ * SetupDiCreateDevRegKeyW (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 hHWProfileKey = INVALID_HANDLE_VALUE;
+ HKEY hEnumKey = INVALID_HANDLE_VALUE;
+ HKEY hClassKey = INVALID_HANDLE_VALUE;
+ HKEY hDeviceKey = INVALID_HANDLE_VALUE;
+ HKEY hKey = INVALID_HANDLE_VALUE;
+ HKEY RootKey;
+
+ if (Scope == DICS_FLAG_GLOBAL)
+ RootKey = list->HKLM;
+ else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
+ {
+ hHWProfileKey = OpenHardwareProfileKey(list->HKLM, HwProfile, KEY_CREATE_SUB_KEY);
+ if (hHWProfileKey == INVALID_HANDLE_VALUE)
+ goto cleanup;
+ RootKey = hHWProfileKey;
+ }
+
+ if (KeyType == DIREG_DEV)
+ {
+ struct DeviceInfoElement *deviceInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
+
+ rc = RegCreateKeyExW(
+ RootKey,
+ REGSTR_PATH_SYSTEMENUM,
+ 0,
+ NULL,
+ REG_OPTION_NON_VOLATILE,
+ KEY_CREATE_SUB_KEY,
+ NULL,
+ &hEnumKey,
+ NULL);
+ if (rc != ERROR_SUCCESS)
+ {
+ SetLastError(rc);
+ goto cleanup;
+ }
+ rc = RegCreateKeyExW(
+ hEnumKey,
+ deviceInfo->DeviceName,
+ 0,
+ NULL,
+ REG_OPTION_NON_VOLATILE,
+#if _WIN32_WINNT >= 0x502
+ KEY_READ | KEY_WRITE,
+#else
+ KEY_ALL_ACCESS,
+#endif
+ NULL,
+ &hKey,
+ NULL);
+ if (rc != ERROR_SUCCESS)
+ {
+ SetLastError(rc);
+ goto cleanup;
+ }
+ }
+ else /* KeyType == DIREG_DRV */
+ {
+ if (UuidToStringW((UUID*)&DeviceInfoData->ClassGuid, &lpGuidString) != RPC_S_OK)
+ goto cleanup;
+ /* The driver key is in \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(RootKey,
+ REGSTR_PATH_CLASS_NT,
+ 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, REGSTR_VAL_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 (hHWProfileKey != INVALID_HANDLE_VALUE)
+ RegCloseKey(hHWProfileKey);
+ if (hEnumKey != INVALID_HANDLE_VALUE)
+ RegCloseKey(hEnumKey);
+ 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
+ {
+ struct DeviceInfoElement *deviceInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
+ LPWSTR DriverKey = NULL;
+ DWORD dwLength = 0;
+ DWORD dwRegType;
+ DWORD rc;
+ HKEY hHWProfileKey = INVALID_HANDLE_VALUE;
+ HKEY hEnumKey = INVALID_HANDLE_VALUE;
+ HKEY hKey = INVALID_HANDLE_VALUE;
+ HKEY RootKey;
+
+ if (Scope == DICS_FLAG_GLOBAL)
+ RootKey = list->HKLM;
+ else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
+ {
+ hHWProfileKey = OpenHardwareProfileKey(list->HKLM, HwProfile, 0);
+ if (hHWProfileKey == INVALID_HANDLE_VALUE)
+ goto cleanup;
+ RootKey = hHWProfileKey;
+ }
+
+ rc = RegOpenKeyExW(
+ RootKey,
+ REGSTR_PATH_SYSTEMENUM,
+ 0, /* Options */
+ 0,
+ &hEnumKey);
+ if (rc != ERROR_SUCCESS)
+ {
+ SetLastError(rc);
+ goto cleanup;
+ }
+ rc = RegOpenKeyExW(
+ hEnumKey,
+ deviceInfo->DeviceName,
+ 0, /* Options */
+ KeyType == DIREG_DEV ? samDesired : KEY_QUERY_VALUE,
+ &hKey);
+ RegCloseKey(hEnumKey);
+ hEnumKey = 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, REGSTR_VAL_DRIVER, NULL, &dwRegType, NULL, &dwLength);
+ if (rc != ERROR_SUCCESS)
+ {
+ SetLastError(rc);
+ goto cleanup;
+ }
+ else 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, REGSTR_VAL_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(
+ RootKey,
+ REGSTR_PATH_CLASS_NT,
+ 0, /* Options */
+ 0,
+ &hEnumKey);
+ if (rc != ERROR_SUCCESS)
+ {
+ SetLastError(rc);
+ goto cleanup;
+ }
+ rc = RegOpenKeyExW(
+ hEnumKey,
+ DriverKey,
+ 0, /* Options */
+ samDesired,
+ &hKey);
+ if (rc != ERROR_SUCCESS)
+ {
+ SetLastError(rc);
+ goto cleanup;
+ }
+ ret = hKey;
+
+cleanup:
+ if (hHWProfileKey != INVALID_HANDLE_VALUE)
+ RegCloseKey(hHWProfileKey);
+ if (hEnumKey != INVALID_HANDLE_VALUE)
+ RegCloseKey(hEnumKey);
+ if (hKey != INVALID_HANDLE_VALUE && hKey != ret)
+ RegCloseKey(hKey);
+ }
+
+ TRACE("Returning 0x%p\n", ret);
+ return ret;
+}
+
+/***********************************************************************
+ * SetupDiCreateDeviceInfoA (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiCreateDeviceInfoA(
+ HDEVINFO DeviceInfoSet,
+ PCSTR DeviceName,
+ CONST GUID *ClassGuid,
+ PCSTR DeviceDescription,
+ HWND hwndParent,
+ DWORD CreationFlags,
+ PSP_DEVINFO_DATA DeviceInfoData)
+{
+ LPWSTR DeviceNameW = NULL;
+ LPWSTR DeviceDescriptionW = NULL;
+ BOOL bResult;
+
+ TRACE("\n");
+
+ if (DeviceName)
+ {
+ DeviceNameW = MultiByteToUnicode(DeviceName, CP_ACP);
+ if (DeviceNameW == NULL) return FALSE;
+ }
+ if (DeviceDescription)
+ {
+ DeviceDescriptionW = MultiByteToUnicode(DeviceDescription, CP_ACP);
+ if (DeviceDescriptionW == NULL)
+ {
+ if (DeviceNameW) MyFree(DeviceNameW);
+ return FALSE;
+ }
+ }
+
+ bResult = SetupDiCreateDeviceInfoW(DeviceInfoSet, DeviceNameW,
+ ClassGuid, DeviceDescriptionW,
+ hwndParent, CreationFlags,
+ DeviceInfoData);
+
+ if (DeviceNameW) MyFree(DeviceNameW);
+ if (DeviceDescriptionW) MyFree(DeviceDescriptionW);
+
+ return bResult;
+}
+
+/***********************************************************************
+ * SetupDiCreateDeviceInfoW (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiCreateDeviceInfoW(
+ HDEVINFO DeviceInfoSet,
+ PCWSTR DeviceName,
+ CONST GUID *ClassGuid,
+ PCWSTR DeviceDescription,
+ HWND hwndParent,
+ DWORD CreationFlags,
+ PSP_DEVINFO_DATA DeviceInfoData)
+{
+ struct DeviceInfoSet *list;
+ BOOL ret = FALSE;
+
+ TRACE("%p %S %s %S %p %lx %p\n", DeviceInfoSet, DeviceName,
+ debugstr_guid(ClassGuid), DeviceDescription,
+ hwndParent, CreationFlags, DeviceInfoData);
+
+ if (!DeviceInfoSet)
+ SetLastError(ERROR_INVALID_HANDLE);
+ else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
+ SetLastError(ERROR_INVALID_HANDLE);
+ else if (!ClassGuid)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else if (!IsEqualIID(&list->ClassGuid, &GUID_NULL) && !IsEqualIID(&list->ClassGuid, ClassGuid))
+ SetLastError(ERROR_CLASS_MISMATCH);
+ else if (CreationFlags & ~(DICD_GENERATE_ID | DICD_INHERIT_CLASSDRVS))
+ {
+ TRACE("Unknown flags: 0x%08lx\n", CreationFlags & ~(DICD_GENERATE_ID | DICD_INHERIT_CLASSDRVS));
+ SetLastError(ERROR_INVALID_FLAGS);
+ }
+ else
+ {
+ SP_DEVINFO_DATA DevInfo;
+
+ if (CreationFlags & DICD_GENERATE_ID)
+ {
+ /* Generate a new unique ID for this device */
+ SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ FIXME("not implemented\n");
+ }
+ else
+ {
+ /* Device name is fully qualified. Try to open it */
+ BOOL rc;
+
+ DevInfo.cbSize = sizeof(SP_DEVINFO_DATA);
+ rc = SetupDiOpenDeviceInfoW(
+ DeviceInfoSet,
+ DeviceName,
+ NULL, /* hwndParent */
+ CreationFlags & DICD_INHERIT_CLASSDRVS ? DIOD_INHERIT_CLASSDRVS : 0,
+ &DevInfo);
+
+ if (rc)
+ {
+ /* SetupDiOpenDeviceInfoW has already added
+ * the device info to the device info set
+ */
+ SetLastError(ERROR_DEVINST_ALREADY_EXISTS);
+ }
+ else if (GetLastError() == ERROR_FILE_NOT_FOUND)
+ {
+ struct DeviceInfoElement *deviceInfo;
+
+ if (CreateDeviceInfoElement(list, DeviceName, ClassGuid, &deviceInfo))
+ {
+ InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
+
+ if (!DeviceInfoData)
+ ret = TRUE;
+ else
+ {
+ if (DeviceInfoData->cbSize != sizeof(PSP_DEVINFO_DATA))
+ {
+ SetLastError(ERROR_INVALID_USER_BUFFER);
+ }
+ else
+ {
+ memcpy(&DeviceInfoData->ClassGuid, ClassGuid, sizeof(GUID));
+ DeviceInfoData->DevInst = deviceInfo->dnDevInst;
+ DeviceInfoData->Reserved = (ULONG_PTR)deviceInfo;
+ ret = TRUE;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ TRACE("Returning %d\n", ret);
+ return ret;
+}
+
+/***********************************************************************
+ * Helper functions for SetupDiBuildDriverInfoList
+ */
+static BOOL
+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 = NULL;
+ HANDLE hFile = INVALID_HANDLE_VALUE;
+ DWORD RequiredSize = 128; /* Initial buffer size */
+ BOOL Result = FALSE;
+ PLIST_ENTRY PreviousEntry;
+ LPWSTR InfInstallSection = NULL;
+ BOOL ret = FALSE;
+
+ driverInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(struct DriverInfoElement));
+ if (!driverInfo)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ 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)
+ 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 */
+ if (MatchingId)
+ {
+ driverInfo->MatchingId = HeapAlloc(GetProcessHeap(), 0, (wcslen(MatchingId) + 1) * sizeof(WCHAR));
+ if (!driverInfo->MatchingId)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto cleanup;
+ }
+ RtlCopyMemory(driverInfo->MatchingId, MatchingId, (wcslen(MatchingId) + 1) * sizeof(WCHAR));
+ }
+ else
+ driverInfo->MatchingId = NULL;
+
+ /* Get inf install section */
+ Result = FALSE;
+ RequiredSize = 128; /* Initial buffer size */
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+ {
+ HeapFree(GetProcessHeap(), 0, InfInstallSection);
+ InfInstallSection = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
+ if (!InfInstallSection)
+ goto cleanup;
+ Result = SetupGetStringFieldW(
+ &ContextDevice,
+ 1, /* Field index */
+ InfInstallSection, RequiredSize,
+ &RequiredSize);
+ }
+ if (!Result)
+ goto cleanup;
+
+ TRACE("Adding driver '%S' [%S/%S] (Rank 0x%lx)\n",
+ driverInfo->Details.DrvDescription, InfFile, InfInstallSection, Rank);
+
+ driverInfo->DriverRank = Rank;
+ memcpy(&driverInfo->DriverDate, &DriverDate, sizeof(FILETIME));
+ memcpy(&driverInfo->ClassGuid, ClassGuid, sizeof(GUID));
+ driverInfo->Info.DriverType = DriverType;
+ driverInfo->Info.Reserved = (ULONG_PTR)driverInfo;
+ 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';
+ if (ProviderName)
+ {
+ wcsncpy(driverInfo->Info.ProviderName, ProviderName, LINE_LEN - 1);
+ driverInfo->Info.ProviderName[LINE_LEN - 1] = '\0';
+ }
+ else
+ 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;
+ while (PreviousEntry != DriverListHead)
+ {
+ struct DriverInfoElement *CurrentDriver;
+ CurrentDriver = CONTAINING_RECORD(PreviousEntry, struct DriverInfoElement, ListEntry);
+ if (CurrentDriver->DriverRank > Rank ||
+ (CurrentDriver->DriverRank == Rank && CurrentDriver->DriverDate.QuadPart > driverInfo->DriverDate.QuadPart))
+ {
+ /* Insert before the current item */
+ InsertHeadList(PreviousEntry, &driverInfo->ListEntry);
+ break;
+ }
+ PreviousEntry = PreviousEntry->Flink;
+ }
+ if (PreviousEntry == DriverListHead)
+ {
+ /* Insert at the end of the list */
+ InsertTailList(DriverListHead, &driverInfo->ListEntry);
+ }
+
+ 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 ret;
+}
+
+static BOOL
+GetVersionInformationFromInfFile(
+ IN HINF hInf,
+ OUT LPGUID ClassGuid,
+ OUT LPWSTR* pProviderName,
+ OUT FILETIME* DriverDate,
+ OUT DWORDLONG* DriverVersion)
+{
+ 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,
+ L"Version", L"ClassGUID",
+ guidW, sizeof(guidW),
+ NULL /* Required size */))
+ {
+ goto cleanup;
+ }
+ guidW[37] = '\0'; /* Replace the } by a NULL character */
+ if (UuidFromStringW(&guidW[1], ClassGuid) != RPC_S_OK)
+ {
+ SetLastError(ERROR_GEN_FAILURE);
+ goto cleanup;
+ }
+
+ /* Get provider name */
+ Result = SetupGetLineTextW(
+ NULL, /* Context */
+ hInf, L"Version", L"Provider",
+ NULL, 0,
+ &RequiredSize);
+ if (Result)
+ {
+ /* We know know the needed buffer size */
+ ProviderName = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
+ if (!ProviderName)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto cleanup;
+ }
+ Result = SetupGetLineTextW(
+ NULL, /* Context */
+ hInf, L"Version", L"Provider",
+ ProviderName, RequiredSize,
+ &RequiredSize);
+ }
+ 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;
+ if (pVersion)
+ {
+ WORD Major, Minor = 0, Revision = 0, Build = 0;
+ LPWSTR pMinor = NULL, pRevision = NULL, pBuild = NULL;
+ LARGE_INTEGER fullVersion;
+
+ pMinor = strchrW(pVersion, '.');
+ if (pMinor)
+ {
+ *pMinor = 0;
+ pRevision = strchrW(++pMinor, '.');
+ Minor = atoiW(pMinor);
+ }
+ if (pRevision)
+ {
+ *pRevision = 0;
+ pBuild = strchrW(++pRevision, '.');
+ Revision = atoiW(pRevision);
+ }
+ if (pBuild)
+ {
+ *pBuild = 0;
+ pBuild++;
+ Build = atoiW(pBuild);
+ }
+ Major = atoiW(pVersion);
+ fullVersion.u.HighPart = Major << 16 | Minor;
+ fullVersion.u.LowPart = Revision << 16 | Build;
+ memcpy(DriverVersion, &fullVersion, sizeof(LARGE_INTEGER));
+ }
+
+ ret = TRUE;
+
+cleanup:
+ if (!ret)
+ HeapFree(GetProcessHeap(), 0, ProviderName);
+ HeapFree(GetProcessHeap(), 0, DriverVer);
+
+ return ret;
+}
+
+/***********************************************************************
+ * SetupDiBuildDriverInfoList (SETUPAPI.@)
+ */
+BOOL WINAPI
+SetupDiBuildDriverInfoList(
+ IN HDEVINFO DeviceInfoSet,
+ IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
+ IN DWORD DriverType)
+{
+ struct DeviceInfoSet *list;
+ SP_DEVINSTALL_PARAMS_W InstallParams;
+ PVOID Buffer = NULL;
+ struct InfFileDetails *currentInfFileDetails = NULL;
+ LPWSTR ProviderName = NULL;
+ LPWSTR ManufacturerName = NULL;
+ WCHAR ManufacturerSection[LINE_LEN + 1];
+ LPWSTR HardwareIDs = NULL;
+ LPWSTR CompatibleIDs = NULL;
+ LPWSTR FullInfFileName = NULL;
+ FILETIME DriverDate;
+ DWORDLONG DriverVersion = 0;
+ DWORD RequiredSize;
+ BOOL ret = FALSE;
+
+ TRACE("%p %p %ld\n", DeviceInfoSet, DeviceInfoData, DriverType);
+
+ if (!DeviceInfoSet)
+ SetLastError(ERROR_INVALID_HANDLE);
+ else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
+ SetLastError(ERROR_INVALID_HANDLE);
+ else if (list->HKLM != HKEY_LOCAL_MACHINE)
+ 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
+ {
+ BOOL Result;
+
+ InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
+ Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
+ if (!Result)
+ goto done;
+
+ if (DriverType == SPDIT_COMPATDRIVER)
+ {
+ /* Get hardware IDs list */
+ Result = FALSE;
+ RequiredSize = 512; /* Initial buffer size */
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+ {
+ HeapFree(GetProcessHeap(), 0, HardwareIDs);
+ HardwareIDs = HeapAlloc(GetProcessHeap(), 0, RequiredSize);
+ if (!HardwareIDs)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto done;
+ }
+ Result = SetupDiGetDeviceRegistryPropertyW(
+ DeviceInfoSet,
+ DeviceInfoData,
+ SPDRP_HARDWAREID,
+ NULL,
+ (PBYTE)HardwareIDs,
+ RequiredSize,
+ &RequiredSize);
+ }
+ if (!Result)
+ goto done;
+
+ /* Get compatible IDs list */
+ Result = FALSE;
+ RequiredSize = 512; /* Initial buffer size */
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+ {
+ HeapFree(GetProcessHeap(), 0, CompatibleIDs);
+ CompatibleIDs = HeapAlloc(GetProcessHeap(), 0, RequiredSize);
+ if (!CompatibleIDs)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto done;
+ }
+ Result = SetupDiGetDeviceRegistryPropertyW(
+ DeviceInfoSet,
+ DeviceInfoData,
+ SPDRP_COMPATIBLEIDS,
+ NULL,
+ (PBYTE)CompatibleIDs,
+ RequiredSize,
+ &RequiredSize);
+ if (!Result && GetLastError() == ERROR_FILE_NOT_FOUND)
+ {
+ /* No compatible ID for this device */
+ HeapFree(GetProcessHeap(), 0, CompatibleIDs);
+ CompatibleIDs = NULL;
+ Result = TRUE;
+ }
+ }
+ if (!Result)
+ goto done;
+ }
+
+ if (InstallParams.Flags & DI_ENUMSINGLEINF)
+ {
+ /* InstallParams.DriverPath contains the name of a .inf file */
+ RequiredSize = wcslen(InstallParams.DriverPath) + 2;
+ Buffer = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
+ if (!Buffer)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto done;
+ }
+ wcscpy(Buffer, InstallParams.DriverPath);
+ ((LPWSTR)Buffer)[RequiredSize - 1] = 0;
+ Result = TRUE;
+ }
+ else
+ {
+ /* Enumerate .inf files */
+ Result = FALSE;
+ RequiredSize = 32768; /* Initial buffer size */
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+ {
+ HeapFree(GetProcessHeap(), 0, Buffer);
+ Buffer = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
+ if (!Buffer)
+ {
+ Result = FALSE;
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ break;
+ }
+ Result = SetupGetInfFileListW(
+ *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;
+ LPWSTR pFullFilename;
+
+ if (InstallParams.Flags & DI_ENUMSINGLEINF)
+ {
+ FullInfFileName = HeapAlloc(GetProcessHeap(), 0, MAX_PATH);
+ if (!FullInfFileName)
+ goto done;
+ pFullFilename = &FullInfFileName[0];
+ }
+ else if (*InstallParams.DriverPath)
+ {
+ DWORD len;
+ len = GetFullPathNameW(InstallParams.DriverPath, 0, NULL, NULL);
+ if (len == 0)
+ goto done;
+ FullInfFileName = HeapAlloc(GetProcessHeap(), 0, len + MAX_PATH);
+ if (!FullInfFileName)
+ goto done;
+ len = GetFullPathNameW(InstallParams.DriverPath, len, FullInfFileName, NULL);
+ if (len == 0)
+ goto done;
+ if (*FullInfFileName && FullInfFileName[wcslen(FullInfFileName) - 1] != '\\')
+ wcscat(FullInfFileName, L"\\");
+ pFullFilename = &FullInfFileName[wcslen(FullInfFileName)];
+ }
+ else
+ {
+ FullInfFileName = HeapAlloc(GetProcessHeap(), 0, MAX_PATH);
+ if (!FullInfFileName)
+ goto done;
+ pFullFilename = &FullInfFileName[0];
+ }
+
+ for (filename = (LPCWSTR)Buffer; *filename; filename += wcslen(filename) + 1)
+ {
+ INFCONTEXT ContextManufacturer, ContextDevice;
+ GUID ClassGuid;
+
+ wcscpy(pFullFilename, filename);
+ TRACE("Opening file %S\n", FullInfFileName);
+
+ currentInfFileDetails = HeapAlloc(
+ GetProcessHeap(),
+ 0,
+ FIELD_OFFSET(struct InfFileDetails, FullInfFileName) + wcslen(FullInfFileName) * sizeof(WCHAR) + UNICODE_NULL);
+ if (!currentInfFileDetails)
+ continue;
+ memset(currentInfFileDetails, 0, sizeof(struct InfFileDetails));
+ wcscpy(currentInfFileDetails->FullInfFileName, FullInfFileName);
+
+ currentInfFileDetails->hInf = SetupOpenInfFileW(FullInfFileName, NULL, INF_STYLE_WIN4, NULL);
+ ReferenceInfFile(currentInfFileDetails);
+ if (currentInfFileDetails->hInf == INVALID_HANDLE_VALUE)
+ {
+ HeapFree(GetProcessHeap(), 0, currentInfFileDetails);
+ currentInfFileDetails = NULL;
+ continue;
+ }
+
+ if (!GetVersionInformationFromInfFile(
+ currentInfFileDetails->hInf,
+ &ClassGuid,
+ &ProviderName,
+ &DriverDate,
+ &DriverVersion))
+ {
+ SetupCloseInfFile(currentInfFileDetails->hInf);
+ HeapFree(GetProcessHeap(), 0, currentInfFileDetails->hInf);
+ currentInfFileDetails = NULL;
+ continue;
+ }
+
+ if (DriverType == SPDIT_CLASSDRIVER)
+ {
+ /* Check if the ClassGuid in this .inf file is corresponding with our needs */
+ if (!IsEqualIID(&list->ClassGuid, &GUID_NULL) && !IsEqualIID(&list->ClassGuid, &ClassGuid))
+ {
+ goto next;
+ }
+ }
+
+ /* Get the manufacturers list */
+ Result = SetupFindFirstLineW(currentInfFileDetails->hInf, L"Manufacturer", NULL, &ContextManufacturer);
+ while (Result)
+ {
+ Result = SetupGetStringFieldW(
+ &ContextManufacturer,
+ 0, /* Field index */
+ NULL, 0,
+ &RequiredSize);
+ if (Result)
+ {
+ /* We got the needed size for the buffer */
+ ManufacturerName = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
+ if (!ManufacturerName)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto done;
+ }
+ Result = SetupGetStringFieldW(
+ &ContextManufacturer,
+ 0, /* Field index */
+ ManufacturerName, RequiredSize,
+ &RequiredSize);
+ }
+ /* Get manufacturer section name */
+ Result = SetupGetStringFieldW(
+ &ContextManufacturer,
+ 1, /* Field index */
+ ManufacturerSection, LINE_LEN,
+ &RequiredSize);
+ if (Result)
+ {
+ 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)
+ {
+ TRACE("Enumerating devices in manufacturer %S\n", ManufacturerSection);
+ Result = SetupFindFirstLineW(currentInfFileDetails->hInf, ManufacturerSection, NULL, &ContextDevice);
+ }
+ }
+ while (Result)
+ {
+ if (DriverType == SPDIT_CLASSDRIVER)
+ {
+ /* FIXME: read [ControlFlags] / ExcludeFromSelect */
+ if (!AddDriverToList(
+ &list->DriverListHead,
+ DriverType,
+ &ClassGuid,
+ ContextDevice,
+ currentInfFileDetails,
+ filename,
+ ProviderName,
+ ManufacturerName,
+ NULL,
+ DriverDate, DriverVersion,
+ 0))
+ {
+ break;
+ }
+ }
+ else /* DriverType = SPDIT_COMPATDRIVER */
+ {
+ /* 1. Get all fields */
+ DWORD FieldCount = SetupGetFieldCount(&ContextDevice);
+ DWORD DriverRank;
+ DWORD i;
+ LPCWSTR currentId;
+ BOOL DriverAlreadyAdded;
+
+ for (i = 2; i <= FieldCount; i++)
+ {
+ LPWSTR DeviceId = NULL;
+ Result = FALSE;
+ RequiredSize = 128; /* Initial buffer size */
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+ {
+ HeapFree(GetProcessHeap(), 0, DeviceId);
+ DeviceId = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
+ if (!DeviceId)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto done;
+ }
+ Result = SetupGetStringFieldW(
+ &ContextDevice,
+ i,
+ DeviceId, RequiredSize,
+ &RequiredSize);
+ }
+ if (!Result)
+ {
+ HeapFree(GetProcessHeap(), 0, DeviceId);
+ goto done;
+ }
+ DriverAlreadyAdded = FALSE;
+ for (DriverRank = 0, currentId = (LPCWSTR)HardwareIDs; !DriverAlreadyAdded && *currentId; currentId += wcslen(currentId) + 1, DriverRank++)
+ {
+ if (wcsicmp(DeviceId, currentId) == 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;
}
}
{
for (DriverRank = 0, currentId = (LPCWSTR)CompatibleIDs; !DriverAlreadyAdded && *currentId; currentId += wcslen(currentId) + 1, DriverRank++)
{
- if (wcscmp(DeviceId, currentId) == 0)
+ if (wcsicmp(DeviceId, currentId) == 0)
{
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, DeviceId);
}
}
- Result = SetupFindNextLine(&ContextDevice, &ContextDevice);
+ Result = SetupFindNextLine(&ContextDevice, &ContextDevice);
+ }
+
+ HeapFree(GetProcessHeap(), 0, ManufacturerName);
+ ManufacturerName = NULL;
+ Result = SetupFindNextLine(&ContextManufacturer, &ContextManufacturer);
+ }
+
+ ret = TRUE;
+next:
+ HeapFree(GetProcessHeap(), 0, ProviderName);
+ ProviderName = NULL;
+
+ DereferenceInfFile(currentInfFileDetails);
+ currentInfFileDetails = NULL;
+ }
+ ret = TRUE;
+ }
+ }
+
+done:
+ if (ret)
+ {
+ if (DeviceInfoData)
+ {
+ InstallParams.Flags |= DI_DIDCOMPAT;
+ InstallParams.FlagsEx |= DI_FLAGSEX_DIDCOMPATINFO;
+ }
+ else
+ {
+ 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, HardwareIDs);
+ HeapFree(GetProcessHeap(), 0, CompatibleIDs);
+ HeapFree(GetProcessHeap(), 0, FullInfFileName);
+ if (currentInfFileDetails)
+ DereferenceInfFile(currentInfFileDetails);
+ HeapFree(GetProcessHeap(), 0, Buffer);
+
+ TRACE("Returning %d\n", ret);
+ return ret;
+}
+
+/***********************************************************************
+ * SetupDiDeleteDeviceInfo (SETUPAPI.@)
+ */
+BOOL WINAPI
+SetupDiDeleteDeviceInfo(
+ IN HDEVINFO DeviceInfoSet,
+ IN PSP_DEVINFO_DATA DeviceInfoData)
+{
+ TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
+
+ FIXME("not implemented\n");
+ SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ return FALSE;
+}
+
+
+/***********************************************************************
+ * SetupDiDestroyDriverInfoList (SETUPAPI.@)
+ */
+BOOL WINAPI
+SetupDiDestroyDriverInfoList(
+ IN HDEVINFO DeviceInfoSet,
+ IN PSP_DEVINFO_DATA DeviceInfoData,
+ IN DWORD DriverType)
+{
+ struct DeviceInfoSet *list;
+ BOOL ret = FALSE;
+
+ TRACE("%p %p 0x%lx\n", DeviceInfoSet, DeviceInfoData, DriverType);
+
+ 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;
+}
+
+
+/***********************************************************************
+ * SetupDiOpenDeviceInfoA (SETUPAPI.@)
+ */
+BOOL WINAPI
+SetupDiOpenDeviceInfoA(
+ IN HDEVINFO DeviceInfoSet,
+ IN PCSTR DeviceInstanceId,
+ IN HWND hwndParent OPTIONAL,
+ IN DWORD OpenFlags,
+ OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
+{
+ LPWSTR DeviceInstanceIdW = NULL;
+ BOOL bResult;
+
+ TRACE("%p %s %p %lx %p\n", DeviceInfoSet, DeviceInstanceId, hwndParent, OpenFlags, DeviceInfoData);
+
+ DeviceInstanceIdW = MultiByteToUnicode(DeviceInstanceId, CP_ACP);
+ if (DeviceInstanceIdW == NULL)
+ return FALSE;
+
+ bResult = SetupDiOpenDeviceInfoW(DeviceInfoSet,
+ DeviceInstanceIdW, hwndParent, OpenFlags, DeviceInfoData);
+
+ MyFree(DeviceInstanceIdW);
+
+ return bResult;
+}
+
+
+/***********************************************************************
+ * SetupDiOpenDeviceInfoW (SETUPAPI.@)
+ */
+BOOL WINAPI
+SetupDiOpenDeviceInfoW(
+ IN HDEVINFO DeviceInfoSet,
+ IN PCWSTR DeviceInstanceId,
+ IN HWND hwndParent OPTIONAL,
+ IN DWORD OpenFlags,
+ OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
+{
+ struct DeviceInfoSet *list;
+ HKEY hEnumKey, hKey;
+ DWORD rc;
+ BOOL ret = FALSE;
+
+ TRACE("%p %S %p %lx %p\n", DeviceInfoSet, DeviceInstanceId, hwndParent, OpenFlags, DeviceInfoData);
+
+ if (OpenFlags & DIOD_CANCEL_REMOVE)
+ FIXME("DIOD_CANCEL_REMOVE flag not implemented\n");
+
+ if (!DeviceInfoSet)
+ SetLastError(ERROR_INVALID_HANDLE);
+ else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
+ SetLastError(ERROR_INVALID_HANDLE);
+ else if (!DeviceInstanceId)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else if (OpenFlags & ~(DIOD_CANCEL_REMOVE | DIOD_INHERIT_CLASSDRVS))
+ {
+ TRACE("Unknown flags: 0x%08lx\n", OpenFlags & ~(DIOD_CANCEL_REMOVE | DIOD_INHERIT_CLASSDRVS));
+ SetLastError(ERROR_INVALID_FLAGS);
+ }
+ else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
+ SetLastError(ERROR_INVALID_USER_BUFFER);
+ else
+ {
+ struct DeviceInfoElement *deviceInfo = NULL;
+ /* Search if device already exists in DeviceInfoSet.
+ * If yes, return the existing element
+ * If no, create a new element using informations in registry
+ */
+ PLIST_ENTRY ItemList = list->ListHead.Flink;
+ while (ItemList != &list->ListHead)
+ {
+ // TODO
+ //if (good one)
+ // break;
+ FIXME("not implemented\n");
+ ItemList = ItemList->Flink;
+ }
+
+ if (deviceInfo)
+ {
+ /* good one found */
+ ret = TRUE;
+ }
+ else
+ {
+ /* Open supposed registry key */
+ rc = RegOpenKeyExW(
+ list->HKLM,
+ REGSTR_PATH_SYSTEMENUM,
+ 0, /* Options */
+ 0,
+ &hEnumKey);
+ if (rc != ERROR_SUCCESS)
+ {
+ SetLastError(rc);
+ return FALSE;
+ }
+ rc = RegOpenKeyExW(
+ hEnumKey,
+ DeviceInstanceId,
+ 0, /* Options */
+ KEY_QUERY_VALUE,
+ &hKey);
+ RegCloseKey(hEnumKey);
+ if (rc != ERROR_SUCCESS)
+ {
+ if (rc == ERROR_FILE_NOT_FOUND)
+ rc = ERROR_NO_SUCH_DEVINST;
+ SetLastError(rc);
+ return FALSE;
+ }
+
+ /* FIXME: try to get ClassGUID from registry, instead of
+ * sending GUID_NULL to CreateDeviceInfoElement
+ */
+ if (!CreateDeviceInfoElement(list, DeviceInstanceId, &GUID_NULL, &deviceInfo))
+ {
+ RegCloseKey(hKey);
+ return FALSE;
+ }
+ InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
+
+ RegCloseKey(hKey);
+ ret = TRUE;
+ }
+
+ if (ret && deviceInfo && DeviceInfoData)
+ {
+ memcpy(&DeviceInfoData->ClassGuid, &deviceInfo->ClassGuid, sizeof(GUID));
+ DeviceInfoData->DevInst = deviceInfo->dnDevInst;
+ DeviceInfoData->Reserved = (ULONG_PTR)deviceInfo;
+ }
+ }
+
+ return ret;
+}
+
+
+/***********************************************************************
+ * SetupDiEnumDriverInfoA (SETUPAPI.@)
+ */
+BOOL WINAPI
+SetupDiEnumDriverInfoA(
+ IN HDEVINFO DeviceInfoSet,
+ IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
+ IN DWORD DriverType,
+ IN DWORD MemberIndex,
+ OUT PSP_DRVINFO_DATA_A DriverInfoData)
+{
+ SP_DRVINFO_DATA_V2_W driverInfoData2W;
+ BOOL ret = FALSE;
+
+ TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet, DeviceInfoData,
+ DriverType, MemberIndex, DriverInfoData);
+
+ if (DriverInfoData == NULL)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_A) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_A))
+ SetLastError(ERROR_INVALID_USER_BUFFER);
+ else
+ {
+ driverInfoData2W.cbSize = sizeof(SP_DRVINFO_DATA_V2_W);
+ ret = SetupDiEnumDriverInfoW(DeviceInfoSet, DeviceInfoData,
+ DriverType, MemberIndex, &driverInfoData2W);
+
+ if (ret)
+ {
+ /* Do W->A conversion */
+ DriverInfoData->DriverType = driverInfoData2W.DriverType;
+ DriverInfoData->Reserved = driverInfoData2W.Reserved;
+ if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.Description, -1,
+ DriverInfoData->Description, LINE_LEN, NULL, NULL) == 0)
+ {
+ DriverInfoData->Description[0] = '\0';
+ ret = FALSE;
+ }
+ if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.MfgName, -1,
+ DriverInfoData->MfgName, LINE_LEN, NULL, NULL) == 0)
+ {
+ DriverInfoData->MfgName[0] = '\0';
+ ret = FALSE;
+ }
+ if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.ProviderName, -1,
+ DriverInfoData->ProviderName, LINE_LEN, NULL, NULL) == 0)
+ {
+ DriverInfoData->ProviderName[0] = '\0';
+ ret = FALSE;
+ }
+ if (DriverInfoData->cbSize == sizeof(SP_DRVINFO_DATA_V2_A))
+ {
+ /* Copy more fields */
+ DriverInfoData->DriverDate = driverInfoData2W.DriverDate;
+ DriverInfoData->DriverVersion = driverInfoData2W.DriverVersion;
+ }
+ }
+ }
+
+ TRACE("Returning %d\n", ret);
+ return ret;
+}
+
+
+/***********************************************************************
+ * SetupDiEnumDriverInfoW (SETUPAPI.@)
+ */
+BOOL WINAPI
+SetupDiEnumDriverInfoW(
+ IN HDEVINFO DeviceInfoSet,
+ IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
+ IN DWORD DriverType,
+ IN DWORD MemberIndex,
+ OUT PSP_DRVINFO_DATA_W DriverInfoData)
+{
+ PLIST_ENTRY ListHead;
+ BOOL ret = FALSE;
+
+ TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet, DeviceInfoData,
+ DriverType, MemberIndex, DriverInfoData);
+
+ if (!DeviceInfoSet || !DriverInfoData)
+ 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 (DriverType != SPDIT_CLASSDRIVER && DriverType != SPDIT_COMPATDRIVER)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else if (DriverType == SPDIT_CLASSDRIVER && DeviceInfoData)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else if (DriverType == SPDIT_COMPATDRIVER && !DeviceInfoData)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_W) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_W))
+ SetLastError(ERROR_INVALID_USER_BUFFER);
+ else
+ {
+ struct DeviceInfoElement *devInfo = NULL;
+ PLIST_ENTRY ItemList;
+ if (DeviceInfoData)
+ devInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
+ if (DriverType == SPDIT_CLASSDRIVER ||
+ (devInfo && devInfo->CreationFlags & DICD_INHERIT_CLASSDRVS))
+ {
+ ListHead = &((struct DeviceInfoSet *)DeviceInfoSet)->DriverListHead;
+ }
+ else
+ {
+ ListHead = &devInfo->DriverListHead;
+ }
+
+ ItemList = ListHead->Flink;
+ while (ItemList != ListHead && MemberIndex-- > 0)
+ ItemList = ItemList->Flink;
+ if (ItemList == ListHead)
+ SetLastError(ERROR_NO_MORE_ITEMS);
+ else
+ {
+ struct DriverInfoElement *DrvInfo = (struct DriverInfoElement *)ItemList;
+
+ memcpy(
+ &DriverInfoData->DriverType,
+ &DrvInfo->Info.DriverType,
+ DriverInfoData->cbSize - FIELD_OFFSET(SP_DRVINFO_DATA_W, DriverType));
+ ret = TRUE;
+ }
+ }
+
+ TRACE("Returning %d\n", ret);
+ return ret;
+}
+
+
+/***********************************************************************
+ * SetupDiGetSelectedDevice (SETUPAPI.@)
+ */
+BOOL WINAPI
+SetupDiGetSelectedDevice(
+ IN HDEVINFO DeviceInfoSet,
+ OUT PSP_DEVINFO_DATA DeviceInfoData)
+{
+ struct DeviceInfoSet *list;
+ BOOL ret = FALSE;
+
+ TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
+
+ if (!DeviceInfoSet)
+ SetLastError(ERROR_INVALID_HANDLE);
+ else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
+ SetLastError(ERROR_INVALID_HANDLE);
+ else if (list->SelectedDevice == NULL)
+ SetLastError(ERROR_NO_DEVICE_SELECTED);
+ else if (!DeviceInfoData)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
+ SetLastError(ERROR_INVALID_USER_BUFFER);
+ else
+ {
+ memcpy(&DeviceInfoData->ClassGuid,
+ &list->SelectedDevice->ClassGuid,
+ sizeof(GUID));
+ DeviceInfoData->DevInst = list->SelectedDevice->dnDevInst;
+ DeviceInfoData->Reserved = (ULONG_PTR)list->SelectedDevice;
+ ret = TRUE;
+ }
+
+ TRACE("Returning %d\n", ret);
+ return ret;
+}
+
+
+/***********************************************************************
+ * SetupDiGetSelectedDriverA (SETUPAPI.@)
+ */
+BOOL WINAPI
+SetupDiGetSelectedDriverA(
+ IN HDEVINFO DeviceInfoSet,
+ IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
+ OUT PSP_DRVINFO_DATA_A DriverInfoData)
+{
+ SP_DRVINFO_DATA_V2_W driverInfoData2W;
+ BOOL ret = FALSE;
+
+ if (DriverInfoData == NULL)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_A) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_A))
+ SetLastError(ERROR_INVALID_USER_BUFFER);
+ else
+ {
+ driverInfoData2W.cbSize = sizeof(SP_DRVINFO_DATA_V2_W);
+
+ ret = SetupDiGetSelectedDriverW(DeviceInfoSet,
+ DeviceInfoData,
+ &driverInfoData2W);
+
+ if (ret)
+ {
+ /* Do W->A conversion */
+ DriverInfoData->DriverType = driverInfoData2W.DriverType;
+ DriverInfoData->Reserved = driverInfoData2W.Reserved;
+ if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.Description, -1,
+ DriverInfoData->Description, LINE_LEN, NULL, NULL) == 0)
+ {
+ DriverInfoData->Description[0] = '\0';
+ ret = FALSE;
+ }
+ if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.MfgName, -1,
+ DriverInfoData->MfgName, LINE_LEN, NULL, NULL) == 0)
+ {
+ DriverInfoData->MfgName[0] = '\0';
+ ret = FALSE;
+ }
+ if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.ProviderName, -1,
+ DriverInfoData->ProviderName, LINE_LEN, NULL, NULL) == 0)
+ {
+ DriverInfoData->ProviderName[0] = '\0';
+ ret = FALSE;
+ }
+ if (DriverInfoData->cbSize == sizeof(SP_DRVINFO_DATA_V2_A))
+ {
+ /* Copy more fields */
+ DriverInfoData->DriverDate = driverInfoData2W.DriverDate;
+ DriverInfoData->DriverVersion = driverInfoData2W.DriverVersion;
+ }
+ }
+ }
+
+ return ret;
+}
+
+
+/***********************************************************************
+ * SetupDiGetSelectedDriverW (SETUPAPI.@)
+ */
+BOOL WINAPI
+SetupDiGetSelectedDriverW(
+ IN HDEVINFO DeviceInfoSet,
+ IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
+ OUT PSP_DRVINFO_DATA_W DriverInfoData)
+{
+ BOOL ret = FALSE;
+
+ TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DriverInfoData);
+
+ if (!DeviceInfoSet || !DriverInfoData)
+ 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->cbSize != sizeof(SP_DRVINFO_DATA_V1_W) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_W))
+ SetLastError(ERROR_INVALID_USER_BUFFER);
+ else
+ {
+ SP_DEVINSTALL_PARAMS InstallParams;
+
+ InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
+ if (SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams))
+ {
+ 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;
+}
+
+
+/***********************************************************************
+ * SetupDiSetSelectedDevice (SETUPAPI.@)
+ */
+BOOL WINAPI
+SetupDiSetSelectedDevice(
+ IN HDEVINFO DeviceInfoSet,
+ IN PSP_DEVINFO_DATA DeviceInfoData)
+{
+ struct DeviceInfoSet *list;
+ BOOL ret = FALSE;
+
+ TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
+
+ 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 (DeviceInfoData->Reserved == 0)
+ SetLastError(ERROR_INVALID_USER_BUFFER);
+ else
+ {
+ list->SelectedDevice = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
+ 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;
+ }
+
+ return ret;
+}
+
+
+/***********************************************************************
+ * SetupDiSetSelectedDriverW (SETUPAPI.@)
+ */
+BOOL WINAPI
+SetupDiSetSelectedDriverW(
+ IN HDEVINFO DeviceInfoSet,
+ IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
+ IN OUT PSP_DRVINFO_DATA_W DriverInfoData OPTIONAL)
+{
+ BOOL ret = FALSE;
+
+ TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DriverInfoData);
+
+ 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 && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_W) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_W))
+ SetLastError(ERROR_INVALID_USER_BUFFER);
+ else
+ {
+ struct DriverInfoElement **pDriverInfo;
+ PLIST_ENTRY ListHead, ItemList;
+
+ if (DeviceInfoData)
+ {
+ pDriverInfo = (struct DriverInfoElement **)&((struct DeviceInfoElement *)DeviceInfoData->Reserved)->InstallParams.Reserved;
+ ListHead = &((struct DeviceInfoElement *)DeviceInfoData->Reserved)->DriverListHead;
+ }
+ else
+ {
+ pDriverInfo = (struct DriverInfoElement **)&((struct DeviceInfoSet *)DeviceInfoSet)->InstallParams.Reserved;
+ ListHead = &((struct DeviceInfoSet *)DeviceInfoSet)->DriverListHead;
+ }
+
+ if (!DriverInfoData)
+ {
+ *pDriverInfo = NULL;
+ ret = TRUE;
+ }
+ else
+ {
+ /* Search selected driver in list */
+ ItemList = ListHead->Flink;
+ while (ItemList != ListHead)
+ {
+ if (DriverInfoData->Reserved != 0)
+ {
+ if (DriverInfoData->Reserved == (ULONG_PTR)ItemList)
+ break;
+ }
+ else
+ {
+ /* The caller wants to compare only DriverType, Description and ProviderName fields */
+ struct DriverInfoElement *driverInfo = (struct DriverInfoElement *)ItemList;
+ if (driverInfo->Info.DriverType == DriverInfoData->DriverType
+ && wcscmp(driverInfo->Info.Description, DriverInfoData->Description) == 0
+ && wcscmp(driverInfo->Info.ProviderName, DriverInfoData->ProviderName) == 0)
+ {
+ break;
+ }
+ }
+ }
+ if (ItemList == ListHead)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else
+ {
+ *pDriverInfo = (struct DriverInfoElement *)ItemList;
+ DriverInfoData->Reserved = (ULONG_PTR)ItemList;
+ 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;
+ }
}
- HeapFree(GetProcessHeap(), 0, ManufacturerName);
- HeapFree(GetProcessHeap(), 0, ManufacturerSection);
- ManufacturerName = ManufacturerSection = NULL;
- Result = SetupFindNextLine(&ContextManufacturer, &ContextManufacturer);
+ /* 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;
+ }
}
- HeapFree(GetProcessHeap(), 0, ProviderName);
- ProviderName = NULL;
- ret = TRUE;
+ else
+ {
+ ret = FALSE;
+ }
+ }
- SetupCloseInfFile(hInf);
- hInf = INVALID_HANDLE_VALUE;
+ if (RequiredSize != NULL)
+ {
+ *RequiredSize = FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A, HardwareID) +
+ (((*RequiredSize) - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W, HardwareID)) / sizeof(WCHAR));
}
- ret = TRUE;
}
}
-done:
- if (ret)
+Cleanup:
+ if (DriverInfoDetailDataW != NULL)
{
- if (DeviceInfoData)
- {
- struct DeviceInfoElement *deviceInfo = (struct DeviceInfoElement *)DeviceInfoData;
- deviceInfo->Flags |= DI_DIDCOMPAT;
- }
- else
- list->Flags |= DI_DIDCLASS;
+ MyFree(DriverInfoDetailDataW);
}
- 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);
- HeapFree(GetProcessHeap(), 0, Buffer);
-
- TRACE("Returning %d\n", ret);
return ret;
}
/***********************************************************************
- * SetupDiDeleteDeviceInfo (SETUPAPI.@)
+ * SetupDiGetDriverInfoDetailW (SETUPAPI.@)
*/
BOOL WINAPI
-SetupDiDeleteDeviceInfo(
+SetupDiGetDriverInfoDetailW(
IN HDEVINFO DeviceInfoSet,
- IN PSP_DEVINFO_DATA DeviceInfoData)
+ 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)
{
- TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
+ BOOL ret = FALSE;
- FIXME("not implemented\n");
- SetLastError(ERROR_GEN_FAILURE);
- return FALSE;
-}
+ TRACE("%p %p %p %p %lu %p\n", DeviceInfoSet, DeviceInfoData,
+ DriverInfoData, DriverInfoDetailData,
+ DriverInfoDetailDataSize, RequiredSize);
+
+ 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 (DriverInfoData->Reserved == 0)
+ SetLastError(ERROR_NO_DRIVER_SELECTED);
+ 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;
+}
-/***********************************************************************
- * SetupDiDestroyDriverInfoList (SETUPAPI.@)
- */
-BOOL WINAPI
-SetupDiDestroyDriverInfoList(
- IN HDEVINFO DeviceInfoSet,
- IN PSP_DEVINFO_DATA DeviceInfoData,
- IN DWORD DriverType)
+/* Return the current hardware profile id, or -1 if error */
+static DWORD
+GetCurrentHwProfile(
+ IN HDEVINFO DeviceInfoSet)
{
- TRACE("%p %p 0x%lx\n", DeviceInfoSet, DeviceInfoData, DriverType);
+ HKEY hKey = INVALID_HANDLE_VALUE;
+ DWORD dwRegType, dwLength;
+ DWORD hwProfile;
+ LONG rc;
+ DWORD ret = (DWORD)-1;
+
+ rc = RegOpenKeyExW(
+ ((struct DeviceInfoSet *)DeviceInfoSet)->HKLM,
+ REGSTR_PATH_IDCONFIGDB,
+ 0, /* Options */
+ KEY_QUERY_VALUE,
+ &hKey);
+ if (rc != ERROR_SUCCESS)
+ {
+ SetLastError(rc);
+ goto cleanup;
+ }
- FIXME("not implemented\n");
- SetLastError(ERROR_GEN_FAILURE);
- return FALSE;
-}
+ dwLength = sizeof(DWORD);
+ rc = RegQueryValueExW(
+ hKey,
+ REGSTR_VAL_CURRENTCONFIG,
+ NULL,
+ &dwRegType,
+ (LPBYTE)&hwProfile, &dwLength);
+ if (rc != ERROR_SUCCESS)
+ {
+ SetLastError(rc);
+ goto cleanup;
+ }
+ else if (dwRegType != REG_DWORD || dwLength != sizeof(DWORD))
+ {
+ SetLastError(ERROR_GEN_FAILURE);
+ goto cleanup;
+ }
+ ret = hwProfile;
-/***********************************************************************
- * SetupDiOpenDeviceInfoA (SETUPAPI.@)
- */
-BOOL WINAPI
-SetupDiOpenDeviceInfoA(
+cleanup:
+ if (hKey != INVALID_HANDLE_VALUE)
+ RegCloseKey(hKey);
+
+ return hwProfile;
+}
+
+static BOOL
+ResetDevice(
IN HDEVINFO DeviceInfoSet,
- IN PCSTR DeviceInstanceId,
- IN HWND hwndParent OPTIONAL,
- IN DWORD OpenFlags,
- OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
+ IN PSP_DEVINFO_DATA DeviceInfoData)
{
- LPWSTR DeviceInstanceIdW = NULL;
- BOOL bResult;
-
- TRACE("%p %s %p %lx %p\n", DeviceInfoSet, DeviceInstanceId, hwndParent, OpenFlags, DeviceInfoData);
+ PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData;
+ struct DeviceInfoElement *deviceInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
+ NTSTATUS Status;
- DeviceInstanceIdW = MultiByteToUnicode(DeviceInstanceId, CP_ACP);
- if (DeviceInstanceIdW == NULL)
+ if (((struct DeviceInfoSet *)DeviceInfoSet)->HKLM != HKEY_LOCAL_MACHINE)
+ {
+ /* At the moment, I only know how to start local devices */
+ SetLastError(ERROR_INVALID_COMPUTERNAME);
return FALSE;
+ }
- bResult = SetupDiOpenDeviceInfoW(DeviceInfoSet,
- DeviceInstanceIdW, hwndParent, OpenFlags, DeviceInfoData);
-
- MyFree(DeviceInstanceIdW);
-
- return bResult;
+ RtlInitUnicodeString(&ResetDeviceData.DeviceInstance, deviceInfo->DeviceName);
+ Status = NtPlugPlayControl(PlugPlayControlResetDevice, &ResetDeviceData, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA));
+ SetLastError(RtlNtStatusToDosError(Status));
+ return NT_SUCCESS(Status);
}
+static BOOL StopDevice(
+ IN HDEVINFO DeviceInfoSet,
+ IN PSP_DEVINFO_DATA DeviceInfoData)
+{
+ FIXME("Stub %p %p\n", DeviceInfoSet, DeviceInfoData);
+ return TRUE;
+}
/***********************************************************************
- * SetupDiOpenDeviceInfoW (SETUPAPI.@)
+ * SetupDiChangeState (SETUPAPI.@)
*/
BOOL WINAPI
-SetupDiOpenDeviceInfoW(
+SetupDiChangeState(
IN HDEVINFO DeviceInfoSet,
- IN PCWSTR DeviceInstanceId,
- IN HWND hwndParent OPTIONAL,
- IN DWORD OpenFlags,
- OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
+ IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
{
- struct DeviceInfoSet *list;
- HKEY hEnumKey, hKey;
- DWORD rc;
+ PSP_PROPCHANGE_PARAMS PropChange;
+ HKEY hKey = INVALID_HANDLE_VALUE;
+ LPCWSTR RegistryValueName;
+ DWORD dwConfigFlags, dwLength, dwRegType;
+ LONG rc;
BOOL ret = FALSE;
- TRACE("%p %S %p %lx %p\n", DeviceInfoSet, DeviceInstanceId, hwndParent, OpenFlags, DeviceInfoData);
-
- if (OpenFlags & DIOD_CANCEL_REMOVE)
- FIXME("DIOD_CANCEL_REMOVE flag not implemented\n");
+ TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
- if (!DeviceInfoSet)
- SetLastError(ERROR_INVALID_HANDLE);
- else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
- SetLastError(ERROR_INVALID_HANDLE);
- else if (!DeviceInstanceId)
- SetLastError(ERROR_INVALID_PARAMETER);
- else if (OpenFlags & ~(DIOD_CANCEL_REMOVE | DIOD_INHERIT_CLASSDRVS))
+ if (!DeviceInfoData)
+ PropChange = ((struct DeviceInfoSet *)DeviceInfoSet)->ClassInstallParams.PropChange;
+ else
+ PropChange = ((struct DeviceInfoElement *)DeviceInfoData->Reserved)->ClassInstallParams.PropChange;
+ if (!PropChange)
{
- TRACE("Unknown flags: 0x%08lx\n", OpenFlags & ~(DIOD_CANCEL_REMOVE | DIOD_INHERIT_CLASSDRVS));
SetLastError(ERROR_INVALID_PARAMETER);
+ goto cleanup;
}
- else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
- SetLastError(ERROR_INVALID_USER_BUFFER);
+
+ if (PropChange->Scope == DICS_FLAG_GLOBAL)
+ RegistryValueName = REGSTR_VAL_CONFIGFLAGS;
else
- {
- struct DeviceInfoElement *deviceInfo = NULL;
- /* Search if device already exists in DeviceInfoSet.
- * If yes, return the existing element
- * If no, create a new element using informations in registry
- */
- PLIST_ENTRY ItemList = list->ListHead.Flink;
- while (ItemList != &list->ListHead)
- {
- // TODO
- //if (good one)
- // break;
- FIXME("not implemented\n");
- ItemList = ItemList->Flink;
- }
+ RegistryValueName = REGSTR_VAL_CSCONFIGFLAGS;
- if (deviceInfo)
+ switch (PropChange->StateChange)
+ {
+ case DICS_ENABLE:
+ case DICS_DISABLE:
{
- // good one found
- if (DeviceInfoData)
+ /* Enable/disable device in registry */
+ hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, PropChange->Scope, PropChange->HwProfile, DIREG_DEV, KEY_QUERY_VALUE | KEY_SET_VALUE);
+ if (hKey == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND)
+ hKey = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, PropChange->Scope, PropChange->HwProfile, DIREG_DEV, NULL, NULL);
+ if (hKey == INVALID_HANDLE_VALUE)
+ break;
+ dwLength = sizeof(DWORD);
+ rc = RegQueryValueExW(
+ hKey,
+ RegistryValueName,
+ NULL,
+ &dwRegType,
+ (LPBYTE)&dwConfigFlags, &dwLength);
+ if (rc == ERROR_FILE_NOT_FOUND)
+ dwConfigFlags = 0;
+ else if (rc != ERROR_SUCCESS)
{
- memcpy(&DeviceInfoData->ClassGuid, &deviceInfo->ClassGuid, sizeof(GUID));
- DeviceInfoData->DevInst = 0; /* FIXME */
- DeviceInfoData->Reserved = (ULONG_PTR)deviceInfo;
+ SetLastError(rc);
+ goto cleanup;
}
- ret = TRUE;
- }
- else
- {
- /* Open supposed registry key */
- rc = RegOpenKeyExW(
- list->HKLM,
- EnumKeyName,
- 0, /* Options */
- KEY_ENUMERATE_SUB_KEYS,
- &hEnumKey);
- if (rc != ERROR_SUCCESS)
+ else if (dwRegType != REG_DWORD || dwLength != sizeof(DWORD))
{
- SetLastError(rc);
- return FALSE;
+ SetLastError(ERROR_GEN_FAILURE);
+ goto cleanup;
}
- rc = RegOpenKeyExW(
- hEnumKey,
- DeviceInstanceId,
- 0, /* Options */
- KEY_QUERY_VALUE,
- &hKey);
- RegCloseKey(hEnumKey);
+ if (PropChange->StateChange == DICS_ENABLE)
+ dwConfigFlags &= ~(PropChange->Scope == DICS_FLAG_GLOBAL ? CONFIGFLAG_DISABLED : CSCONFIGFLAG_DISABLED);
+ else
+ dwConfigFlags |= (PropChange->Scope == DICS_FLAG_GLOBAL ? CONFIGFLAG_DISABLED : CSCONFIGFLAG_DISABLED);
+ rc = RegSetValueEx(
+ hKey,
+ RegistryValueName,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&dwConfigFlags, sizeof(DWORD));
if (rc != ERROR_SUCCESS)
{
SetLastError(rc);
- return FALSE;
+ goto cleanup;
}
- if (!CreateDeviceInfoElement(DeviceInstanceId, &GUID_NULL /* FIXME */, &deviceInfo))
+ /* Enable/disable device if needed */
+ if (PropChange->Scope == DICS_FLAG_GLOBAL
+ || PropChange->HwProfile == 0
+ || PropChange->HwProfile == GetCurrentHwProfile(DeviceInfoSet))
{
- RegCloseKey(hKey);
- return FALSE;
+ if (PropChange->StateChange == DICS_ENABLE)
+ ret = ResetDevice(DeviceInfoSet, DeviceInfoData);
+ else
+ ret = StopDevice(DeviceInfoSet, DeviceInfoData);
}
- InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
-
- RegCloseKey(hKey);
- ret = TRUE;
+ else
+ ret = TRUE;
+ break;
}
-
- if (ret && deviceInfo && DeviceInfoData)
+ case DICS_PROPCHANGE:
{
- memcpy(&DeviceInfoData->ClassGuid, &deviceInfo->ClassGuid, sizeof(GUID));
- DeviceInfoData->DevInst = 0; /* FIXME */
- DeviceInfoData->Reserved = (ULONG_PTR)deviceInfo;
+ ret = ResetDevice(DeviceInfoSet, DeviceInfoData);
+ break;
+ }
+ default:
+ {
+ ERR("Unknown StateChange 0x%lx\n", PropChange->StateChange);
+ SetLastError(ERROR_NOT_SUPPORTED);
}
}
+cleanup:
+ if (hKey != INVALID_HANDLE_VALUE)
+ RegCloseKey(hKey);
+
+ TRACE("Returning %d\n", ret);
return ret;
}
-
/***********************************************************************
- * SetupDiEnumDriverInfoA (SETUPAPI.@)
+ * SetupDiSelectBestCompatDrv (SETUPAPI.@)
*/
BOOL WINAPI
-SetupDiEnumDriverInfoA(
+SetupDiSelectBestCompatDrv(
IN HDEVINFO DeviceInfoSet,
- IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
- IN DWORD DriverType,
- IN DWORD MemberIndex,
- OUT PSP_DRVINFO_DATA_A DriverInfoData)
+ IN PSP_DEVINFO_DATA DeviceInfoData)
{
- SP_DRVINFO_DATA_V2_W driverInfoData2W;
- BOOL ret = FALSE;
-
- TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet, DeviceInfoData,
- DriverType, MemberIndex, DriverInfoData);
-
- if (DriverInfoData == NULL)
- SetLastError(ERROR_INVALID_PARAMETER);
- else if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_A) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_A))
- SetLastError(ERROR_INVALID_USER_BUFFER);
- else
- {
- driverInfoData2W.cbSize = sizeof(SP_DRVINFO_DATA_V2_W);
- ret = SetupDiEnumDriverInfoW(DeviceInfoSet, DeviceInfoData,
- DriverType, MemberIndex, &driverInfoData2W);
+ SP_DRVINFO_DATA_W drvInfoData;
+ BOOL ret;
- if (ret)
- {
- /* Do W->A conversion */
- DriverInfoData->DriverType = driverInfoData2W.DriverType;
- DriverInfoData->Reserved = driverInfoData2W.Reserved;
- if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.Description, -1,
- DriverInfoData->Description, LINE_LEN, NULL, NULL) == 0)
- {
- DriverInfoData->Description[0] = '\0';
- ret = FALSE;
- }
- if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.MfgName, -1,
- DriverInfoData->MfgName, LINE_LEN, NULL, NULL) == 0)
- {
- DriverInfoData->MfgName[0] = '\0';
- ret = FALSE;
- }
- if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.ProviderName, -1,
- DriverInfoData->ProviderName, LINE_LEN, NULL, NULL) == 0)
- {
- DriverInfoData->ProviderName[0] = '\0';
- ret = FALSE;
- }
- if (DriverInfoData->cbSize == sizeof(SP_DRVINFO_DATA_V2_A))
- {
- /* Copy more fields */
- DriverInfoData->DriverDate = driverInfoData2W.DriverDate;
- DriverInfoData->DriverVersion = driverInfoData2W.DriverVersion;
- }
- }
+ TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
+
+ /* Drivers are sorted by rank in the driver list, so
+ * the first driver in the list is the best one.
+ */
+ drvInfoData.cbSize = sizeof(SP_DRVINFO_DATA_W);
+ ret = SetupDiEnumDriverInfoW(
+ DeviceInfoSet,
+ DeviceInfoData,
+ SPDIT_COMPATDRIVER,
+ 0, /* Member index */
+ &drvInfoData);
+
+ if (ret)
+ {
+ ret = SetupDiSetSelectedDriverW(
+ DeviceInfoSet,
+ DeviceInfoData,
+ &drvInfoData);
}
TRACE("Returning %d\n", ret);
return ret;
}
-
/***********************************************************************
- * SetupDiEnumDriverInfoW (SETUPAPI.@)
+ * SetupDiInstallDriverFiles (SETUPAPI.@)
*/
BOOL WINAPI
-SetupDiEnumDriverInfoW(
+SetupDiInstallDriverFiles(
IN HDEVINFO DeviceInfoSet,
- IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
- IN DWORD DriverType,
- IN DWORD MemberIndex,
- OUT PSP_DRVINFO_DATA_W DriverInfoData)
+ IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
{
- PLIST_ENTRY ListHead;
BOOL ret = FALSE;
- TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet, DeviceInfoData,
- DriverType, MemberIndex, DriverInfoData);
+ TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
- if (!DeviceInfoSet || !DriverInfoData)
+ 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 (DriverType != SPDIT_CLASSDRIVER && DriverType != SPDIT_COMPATDRIVER)
- SetLastError(ERROR_INVALID_PARAMETER);
- else if (DriverType == SPDIT_CLASSDRIVER && DeviceInfoData)
- SetLastError(ERROR_INVALID_PARAMETER);
- else if (DriverType == SPDIT_COMPATDRIVER && !DeviceInfoData)
- SetLastError(ERROR_INVALID_PARAMETER);
- else if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_W) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_W))
+ else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
SetLastError(ERROR_INVALID_USER_BUFFER);
+ 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 DeviceInfoElement *devInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
- PLIST_ENTRY ItemList;
- if (DriverType == SPDIT_CLASSDRIVER ||
- devInfo->CreationFlags & DICD_INHERIT_CLASSDRVS)
+ SP_DEVINSTALL_PARAMS_W InstallParams;
+ struct DriverInfoElement *SelectedDriver;
+ WCHAR SectionName[MAX_PATH];
+ DWORD SectionNameLength = 0;
+ PVOID InstallMsgHandler;
+ PVOID InstallMsgHandlerContext;
+ PVOID Context = NULL;
+
+ InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
+ ret = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
+ if (!ret)
+ goto done;
+
+ SelectedDriver = (struct DriverInfoElement *)InstallParams.Reserved;
+ if (!SelectedDriver)
{
- ListHead = &((struct DeviceInfoSet *)DeviceInfoSet)->DriverListHead;
+ SetLastError(ERROR_NO_DRIVER_SELECTED);
+ goto done;
}
- else
+
+ ret = SetupDiGetActualSectionToInstallW(
+ SelectedDriver->InfFileDetails->hInf,
+ SelectedDriver->Details.SectionName,
+ SectionName, MAX_PATH - strlenW(DotCoInstallers), &SectionNameLength, NULL);
+ if (!ret)
+ goto done;
+
+ if (InstallParams.InstallMsgHandler)
{
- ListHead = &devInfo->DriverListHead;
+ InstallMsgHandler = InstallParams.InstallMsgHandler;
+ InstallMsgHandlerContext = InstallParams.InstallMsgHandlerContext;
}
-
- ItemList = ListHead->Flink;
- while (ItemList != ListHead && MemberIndex-- > 0)
- ItemList = ItemList->Flink;
- if (ItemList == ListHead)
- SetLastError(ERROR_NO_MORE_ITEMS);
else
{
- struct DriverInfoElement *DrvInfo = (struct DriverInfoElement *)ItemList;
-
- memcpy(
- DriverInfoData,
- &DrvInfo->Info,
- DriverInfoData->cbSize);
- ret = TRUE;
+ Context = SetupInitDefaultQueueCallback(InstallParams.hwndParent);
+ if (!Context)
+ goto cleanup;
+ InstallMsgHandler = SetupDefaultQueueCallback;
+ InstallMsgHandlerContext = Context;
}
+ ret = SetupInstallFromInfSectionW(InstallParams.hwndParent,
+ SelectedDriver->InfFileDetails->hInf, SectionName,
+ SPINST_FILES, NULL, NULL, SP_COPY_NEWER,
+ InstallMsgHandler, InstallMsgHandlerContext,
+ DeviceInfoSet, DeviceInfoData);
+ if (!ret)
+ goto done;
+
+ /* Install files from .CoInstallers section */
+ lstrcatW(SectionName, DotCoInstallers);
+ ret = SetupInstallFromInfSectionW(InstallParams.hwndParent,
+ SelectedDriver->InfFileDetails->hInf, SectionName,
+ SPINST_FILES, NULL, NULL, SP_COPY_NEWER,
+ InstallMsgHandler, InstallMsgHandlerContext,
+ DeviceInfoSet, DeviceInfoData);
+ if (!ret)
+ goto done;
+
+ /* Set the DI_NOFILECOPY flag to prevent another
+ * installation during SetupDiInstallDevice */
+ InstallParams.Flags |= DI_NOFILECOPY;
+ ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
+
+cleanup:
+ if (Context)
+ SetupTermDefaultQueueCallback(Context);
}
+done:
TRACE("Returning %d\n", ret);
return ret;
}
/***********************************************************************
- * SetupDiGetSelectedDriverW (SETUPAPI.@)
+ * SetupDiRegisterCoDeviceInstallers (SETUPAPI.@)
*/
BOOL WINAPI
-SetupDiGetSelectedDriverW(
+SetupDiRegisterCoDeviceInstallers(
IN HDEVINFO DeviceInfoSet,
- IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
- OUT PSP_DRVINFO_DATA_W DriverInfoData)
+ IN PSP_DEVINFO_DATA DeviceInfoData)
{
- BOOL ret = FALSE;
+ BOOL ret = FALSE; /* Return value */
- TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DriverInfoData);
+ TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
- if (!DeviceInfoSet || !DriverInfoData)
+ 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->cbSize != sizeof(SP_DRVINFO_DATA_V1_W) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_W))
+ else if (!DeviceInfoData)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
SetLastError(ERROR_INVALID_USER_BUFFER);
else
{
- struct DriverInfoElement *driverInfo;
-
- if (DeviceInfoData)
- driverInfo = ((struct DeviceInfoElement *)DeviceInfoData->Reserved)->SelectedDriver;
- else
- driverInfo = ((struct DeviceInfoSet *)DeviceInfoSet)->SelectedDriver;
-
- if (driverInfo == NULL)
+ SP_DEVINSTALL_PARAMS_W InstallParams;
+ struct DriverInfoElement *SelectedDriver;
+ BOOL Result;
+ DWORD DoAction;
+ WCHAR SectionName[MAX_PATH];
+ DWORD SectionNameLength = 0;
+ HKEY hKey = INVALID_HANDLE_VALUE;
+ PVOID Context = NULL;
+
+ 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);
- else
+ goto cleanup;
+ }
+
+ /* Get .CoInstallers section name */
+ Result = SetupDiGetActualSectionToInstallW(
+ SelectedDriver->InfFileDetails->hInf,
+ SelectedDriver->Details.SectionName,
+ SectionName, MAX_PATH, &SectionNameLength, NULL);
+ if (!Result || SectionNameLength > MAX_PATH - strlenW(DotCoInstallers) - 1)
+ goto cleanup;
+ lstrcatW(SectionName, DotCoInstallers);
+
+ /* 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))
{
- memcpy(
- DriverInfoData,
- &driverInfo->Info,
- DriverInfoData->cbSize);
- ret = TRUE;
+ DoAction |= SPINST_FILES;
+ Context = SetupInitDefaultQueueCallback(InstallParams.hwndParent);
+ if (!Context)
+ goto cleanup;
}
+ Result = SetupInstallFromInfSectionW(InstallParams.hwndParent,
+ SelectedDriver->InfFileDetails->hInf, SectionName,
+ DoAction, hKey, NULL, SP_COPY_NEWER,
+ SetupDefaultQueueCallback, Context,
+ DeviceInfoSet, DeviceInfoData);
+ if (!Result)
+ goto cleanup;
+
+ ret = TRUE;
+
+cleanup:
+ if (Context)
+ SetupTermDefaultQueueCallback(Context);
+ if (hKey != INVALID_HANDLE_VALUE)
+ RegCloseKey(hKey);
}
TRACE("Returning %d\n", ret);
return ret;
}
+static BOOL
+InstallOneInterface(
+ IN LPGUID InterfaceGuid,
+ IN LPCWSTR ReferenceString,
+ IN LPCWSTR InterfaceSection,
+ IN UINT InterfaceFlags)
+{
+ if (InterfaceFlags != 0)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ FIXME("Need to AddInterface(%s %s %s %u)\n", debugstr_guid(InterfaceGuid),
+ debugstr_w(ReferenceString), debugstr_w(InterfaceSection), InterfaceFlags);
+ return TRUE;
+}
+
/***********************************************************************
- * SetupDiSetSelectedDriverW (SETUPAPI.@)
+ * SetupDiInstallDeviceInterfaces (SETUPAPI.@)
*/
BOOL WINAPI
-SetupDiSetSelectedDriverW(
+SetupDiInstallDeviceInterfaces(
IN HDEVINFO DeviceInfoSet,
- IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
- IN OUT PSP_DRVINFO_DATA_W DriverInfoData OPTIONAL)
+ IN PSP_DEVINFO_DATA DeviceInfoData)
{
+ struct DeviceInfoSet *list = NULL;
BOOL ret = FALSE;
- TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DriverInfoData);
+ TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
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)
+ 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 && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
SetLastError(ERROR_INVALID_USER_BUFFER);
- else if (DriverInfoData && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_W) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_W))
- SetLastError(ERROR_INVALID_USER_BUFFER);
else
{
- struct DriverInfoElement **pDriverInfo;
- PLIST_ENTRY ListHead, ItemList;
+ struct DriverInfoElement *SelectedDriver;
+ SP_DEVINSTALL_PARAMS_W InstallParams;
+ WCHAR SectionName[MAX_PATH];
+ DWORD SectionNameLength = 0;
+ INFCONTEXT ContextInterface;
+ LPWSTR InterfaceGuidString = NULL;
+ LPWSTR ReferenceString = NULL;
+ LPWSTR InterfaceSection = NULL;
+ UINT InterfaceFlags;
+ GUID InterfaceGuid;
+ BOOL Result;
+
+ 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);
+ ret = FALSE;
+ goto cleanup;
+ }
- if (DeviceInfoData)
+ /* Get .Interfaces section name */
+ Result = SetupDiGetActualSectionToInstallW(
+ SelectedDriver->InfFileDetails->hInf,
+ SelectedDriver->Details.SectionName,
+ SectionName, MAX_PATH, &SectionNameLength, NULL);
+ if (!Result || SectionNameLength > MAX_PATH - wcslen(L".Interfaces") - 1)
+ goto cleanup;
+ wcscat(SectionName, L".Interfaces");
+
+ ret = TRUE;
+ Result = SetupFindFirstLineW(
+ SelectedDriver->InfFileDetails->hInf,
+ SectionName,
+ L"AddInterface",
+ &ContextInterface);
+ while (ret && Result)
{
- pDriverInfo = &((struct DeviceInfoElement *)DeviceInfoData->Reserved)->SelectedDriver;
- ListHead = &((struct DeviceInfoElement *)DeviceInfoData->Reserved)->DriverListHead;
+ ret = GetStringField(&ContextInterface, 1, &InterfaceGuidString);
+ if (!ret)
+ goto cleanup;
+ else if (strlenW(InterfaceGuidString) != MAX_GUID_STRING_LEN - 1)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ ret = FALSE;
+ goto cleanup;
+ }
+
+ InterfaceGuidString[MAX_GUID_STRING_LEN - 2] = '\0'; /* Replace the } by a NULL character */
+ if (UuidFromStringW(&InterfaceGuidString[1], &InterfaceGuid) != RPC_S_OK)
+ {
+ /* Bad GUID, skip the entry */
+ SetLastError(ERROR_INVALID_PARAMETER);
+ ret = FALSE;
+ goto cleanup;
+ }
+
+ ret = GetStringField(&ContextInterface, 2, &ReferenceString);
+ if (!ret)
+ goto cleanup;
+
+ ret = GetStringField(&ContextInterface, 3, &InterfaceSection);
+ if (!ret)
+ goto cleanup;
+
+ ret = SetupGetIntField(
+ &ContextInterface,
+ 4, /* Field index */
+ &InterfaceFlags);
+ if (!ret)
+ {
+ if (GetLastError() == ERROR_INVALID_PARAMETER)
+ {
+ /* The field may be empty. Ignore the error */
+ InterfaceFlags = 0;
+ ret = TRUE;
+ }
+ else
+ goto cleanup;
+ }
+
+ /* Install Interface */
+ ret = InstallOneInterface(&InterfaceGuid, ReferenceString, InterfaceSection, InterfaceFlags);
+
+cleanup:
+ MyFree(InterfaceGuidString);
+ MyFree(ReferenceString);
+ MyFree(InterfaceSection);
+ InterfaceGuidString = ReferenceString = InterfaceSection = NULL;
+ Result = SetupFindNextMatchLineW(&ContextInterface, L"AddInterface", &ContextInterface);
}
- else
+ }
+
+ TRACE("Returning %d\n", ret);
+ return ret;
+}
+
+BOOL
+InfIsFromOEMLocation(
+ IN PCWSTR FullName,
+ OUT LPBOOL IsOEMLocation)
+{
+ PWCHAR last;
+
+ last = strrchrW(FullName, '\\');
+ if (!last)
+ {
+ /* No directory specified */
+ *IsOEMLocation = FALSE;
+ }
+ else
+ {
+ WCHAR Windir[MAX_PATH];
+ UINT ret;
+
+ ret = GetWindowsDirectory(Windir, MAX_PATH);
+ if (ret == 0 || ret >= MAX_PATH)
{
- pDriverInfo = &((struct DeviceInfoSet *)DeviceInfoSet)->SelectedDriver;
- ListHead = &((struct DeviceInfoSet *)DeviceInfoSet)->DriverListHead;
+ SetLastError(ERROR_GEN_FAILURE);
+ return FALSE;
}
- if (!DriverInfoData)
+ if (strncmpW(FullName, Windir, last - FullName) == 0)
{
- *pDriverInfo = NULL;
- ret = TRUE;
+ /* The path is %SYSTEMROOT%\Inf */
+ *IsOEMLocation = FALSE;
}
else
{
- /* Search selected driver in list */
- ItemList = ListHead->Flink;
- while (ItemList != ListHead)
- {
- if (DriverInfoData->Reserved != 0)
- {
- if (DriverInfoData->Reserved == (ULONG_PTR)ItemList)
- break;
- }
- else
- {
- /* The caller wants to compare only DriverType, Description and ProviderName fields */
- struct DriverInfoElement *driverInfo = (struct DriverInfoElement *)ItemList;
- if (driverInfo->Info.DriverType == DriverInfoData->DriverType
- && wcscmp(driverInfo->Info.Description, DriverInfoData->Description) == 0
- && wcscmp(driverInfo->Info.ProviderName, DriverInfoData->ProviderName) == 0)
- {
- break;
- }
- }
- }
- if (ItemList == ListHead)
- SetLastError(ERROR_INVALID_PARAMETER);
- else
- {
- *pDriverInfo = (struct DriverInfoElement *)ItemList;
- DriverInfoData->Reserved = (ULONG_PTR)ItemList;
- ret = TRUE;
- }
+ /* The file is in another place */
+ *IsOEMLocation = TRUE;
}
}
+ return TRUE;
+}
+
+/***********************************************************************
+ * SetupDiInstallDevice (SETUPAPI.@)
+ */
+BOOL WINAPI
+SetupDiInstallDevice(
+ IN HDEVINFO DeviceInfoSet,
+ IN PSP_DEVINFO_DATA DeviceInfoData)
+{
+ SP_DEVINSTALL_PARAMS_W InstallParams;
+ struct DriverInfoElement *SelectedDriver;
+ SYSTEMTIME DriverDate;
+ WCHAR SectionName[MAX_PATH];
+ WCHAR Buffer[32];
+ DWORD SectionNameLength = 0;
+ BOOL Result = FALSE;
+ ULONG DoAction;
+ DWORD RequiredSize;
+ LPWSTR pSectionName = NULL;
+ WCHAR ClassName[MAX_CLASS_NAME_LEN];
+ GUID ClassGuid;
+ LPWSTR lpGuidString = NULL, lpFullGuidString = NULL;
+ BOOL RebootRequired = FALSE;
+ HKEY hKey = INVALID_HANDLE_VALUE;
+ HKEY hClassKey = INVALID_HANDLE_VALUE;
+ BOOL NeedtoCopyFile;
+ LARGE_INTEGER fullVersion;
+ LONG rc;
+ PVOID Context = NULL;
+ BOOL ret = FALSE; /* Return value */
+
+ TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
+
+ 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
+ Result = TRUE;
+
+ if (!Result)
+ {
+ /* One parameter is bad */
+ goto cleanup;
+ }
+
+ InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
+ Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
+ if (!Result)
+ goto cleanup;
+
+ if (InstallParams.FlagsEx & DI_FLAGSEX_SETFAILEDINSTALL)
+ {
+ /* FIXME: set FAILEDINSTALL in ConfigFlags registry value */
+ goto cleanup;
+ }
+
+ SelectedDriver = (struct DriverInfoElement *)InstallParams.Reserved;
+ if (SelectedDriver == NULL)
+ {
+ SetLastError(ERROR_NO_DRIVER_SELECTED);
+ goto cleanup;
+ }
+
+ FileTimeToSystemTime(&SelectedDriver->Info.DriverDate, &DriverDate);
+
+ Result = SetupDiGetActualSectionToInstallW(
+ SelectedDriver->InfFileDetails->hInf,
+ SelectedDriver->Details.SectionName,
+ SectionName, MAX_PATH, &SectionNameLength, NULL);
+ if (!Result || SectionNameLength > MAX_PATH - wcslen(DotServices))
+ 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)
+ {
+ 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 = 0;
+ if (!(InstallParams.FlagsEx & DI_FLAGSEX_NO_DRVREG_MODIFY))
+ DoAction |= SPINST_REGISTRY;
+ if (!(InstallParams.Flags & DI_NOFILECOPY))
+ {
+ DoAction |= SPINST_FILES;
+ Context = SetupInitDefaultQueueCallback(InstallParams.hwndParent);
+ if (!Context)
+ goto cleanup;
+ }
+ *pSectionName = '\0';
+ Result = SetupInstallFromInfSectionW(InstallParams.hwndParent,
+ SelectedDriver->InfFileDetails->hInf, SectionName,
+ DoAction, hKey, NULL, SP_COPY_NEWER,
+ SetupDefaultQueueCallback, Context,
+ DeviceInfoSet, DeviceInfoData);
+ if (!Result)
+ goto cleanup;
+ InstallParams.Flags |= DI_NOFILECOPY;
+ SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
+
+ /* Write information to driver key */
+ *pSectionName = UNICODE_NULL;
+ memcpy(&fullVersion, &SelectedDriver->Info.DriverVersion, sizeof(LARGE_INTEGER));
+ 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", fullVersion.HighPart >> 16, fullVersion.HighPart & 0xffff, fullVersion.LowPart >> 16, fullVersion.LowPart & 0xffff);
+ 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, REGSTR_VAL_DRVDESC, 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", fullVersion.HighPart >> 16, fullVersion.HighPart & 0xffff, fullVersion.LowPart >> 16, fullVersion.LowPart & 0xffff);
+ rc = RegSetValueEx(hKey, L"DriverVersion", 0, REG_SZ, (const BYTE *)Buffer, (wcslen(Buffer) + 1) * sizeof(WCHAR));
+ }
+ if (rc == ERROR_SUCCESS)
+ rc = RegSetValueEx(hKey, REGSTR_VAL_INFPATH, 0, REG_SZ, (const BYTE *)SelectedDriver->Details.InfFileName, (wcslen(SelectedDriver->Details.InfFileName) + 1) * sizeof(WCHAR));
+ if (rc == ERROR_SUCCESS)
+ rc = RegSetValueEx(hKey, REGSTR_VAL_INFSECTION, 0, REG_SZ, (const BYTE *)SelectedDriver->Details.SectionName, (wcslen(SelectedDriver->Details.SectionName) + 1) * sizeof(WCHAR));
+ if (rc == ERROR_SUCCESS)
+ rc = RegSetValueEx(hKey, REGSTR_VAL_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, REGSTR_VAL_MATCHINGDEVID, 0, REG_SZ, (const BYTE *)SelectedDriver->MatchingId, (wcslen(SelectedDriver->MatchingId) + 1) * sizeof(WCHAR));
+ if (rc == ERROR_SUCCESS)
+ rc = RegSetValueEx(hKey, REGSTR_VAL_PROVIDER_NAME, 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, DotServices);
+ Result = SetupInstallServicesFromInfSectionExW(
+ SelectedDriver->InfFileDetails->hInf,
+ SectionName,
+ 0,
+ DeviceInfoSet,
+ DeviceInfoData,
+ NULL,
+ NULL);
+ if (!Result)
+ goto cleanup;
+ if (GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED)
+ RebootRequired = TRUE;
+
+ /* Copy .inf file to Inf\ directory (if needed) */
+ Result = InfIsFromOEMLocation(SelectedDriver->InfFileDetails->FullInfFileName, &NeedtoCopyFile);
+ if (!Result)
+ goto cleanup;
+ if (NeedtoCopyFile)
+ {
+ Result = SetupCopyOEMInfW(
+ SelectedDriver->InfFileDetails->FullInfFileName,
+ NULL,
+ SPOST_NONE,
+ SP_COPY_NOOVERWRITE,
+ NULL, 0,
+ NULL,
+ NULL);
+ if (!Result)
+ goto cleanup;
+ /* FIXME: create a new struct InfFileDetails, and set it to SelectedDriver->InfFileDetails,
+ * to release use of current InfFile */
+ }
+
+ /* 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 */
+ DoAction = 0;
+ if (!(InstallParams.FlagsEx & DI_FLAGSEX_NO_DRVREG_MODIFY))
+ DoAction |= SPINST_REGISTRY;
+ wcscpy(pSectionName, L".HW");
+ Result = SetupInstallFromInfSectionW(InstallParams.hwndParent,
+ SelectedDriver->InfFileDetails->hInf, SectionName,
+ DoAction, hKey, NULL, 0,
+ NULL, NULL,
+ DeviceInfoSet, DeviceInfoData);
+ if (!Result)
+ goto cleanup;
+
+ /* Write information to enum key */
+ TRACE("Write information to enum key\n");
+ 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, REGSTR_VAL_CLASS, 0, REG_SZ, (const BYTE *)ClassName, (wcslen(ClassName) + 1) * sizeof(WCHAR));
+ if (rc == ERROR_SUCCESS)
+ rc = RegSetValueEx(hKey, REGSTR_VAL_CLASSGUID, 0, REG_SZ, (const BYTE *)lpFullGuidString, (wcslen(lpFullGuidString) + 1) * sizeof(WCHAR));
+ if (rc == ERROR_SUCCESS)
+ rc = RegSetValueEx(hKey, REGSTR_VAL_DEVDESC, 0, REG_SZ, (const BYTE *)SelectedDriver->Info.Description, (wcslen(SelectedDriver->Info.Description) + 1) * sizeof(WCHAR));
+ if (rc == ERROR_SUCCESS)
+ rc = RegSetValueEx(hKey, REGSTR_VAL_MFG, 0, REG_SZ, (const BYTE *)SelectedDriver->Info.MfgName, (wcslen(SelectedDriver->Info.MfgName) + 1) * sizeof(WCHAR));
+ if (rc != ERROR_SUCCESS)
+ {
+ SetLastError(rc);
+ goto cleanup;
+ }
+
+ /* Start the device */
+ if (!RebootRequired && !(InstallParams.Flags & (DI_NEEDRESTART | DI_NEEDREBOOT | DI_DONOTCALLCONFIGMG)))
+ ret = ResetDevice(DeviceInfoSet, DeviceInfoData);
+ 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, lpFullGuidString);
+ if (Context)
+ SetupTermDefaultQueueCallback(Context);
TRACE("Returning %d\n", ret);
return ret;
}