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 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 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 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,
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);
struct CoInstallerElement
{
PVOID PrivateData;
};
+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 */
+};
+
/***********************************************************************
* SetupDiBuildClassInfoList (SETUPAPI.@)
*/
}
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,
/* FIXME */
return ERROR_GEN_FAILURE;
}
-
+
/* Does not happen */
}
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto cleanup;
}
-
+
strcpyW(UNCServerName + 2, MachineName);
list->szData[0] = list->szData[1] = '\\';
strcpyW(list->szData + 2, MachineName);
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))
/***********************************************************************
* 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;
-
- TRACE("%p %s %p %lu %p %p\n", InfHandle, debugstr_w(InfSectionName),
- InfSectionWithExt, InfSectionWithExtSize, RequiredSize, Extension);
-
- 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};
+
+ /* 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;
+ }
- dwFullLength = lstrlenW(szBuffer);
+ 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;
- if (InfSectionWithExt != NULL && InfSectionWithExtSize != 0)
- {
- if (InfSectionWithExtSize < (dwFullLength + 1))
- {
- SetLastError(ERROR_INSUFFICIENT_BUFFER);
- return FALSE;
- }
+sectionfound:
+ dwFullLength = lstrlenW(SectionName);
+ if (InfSectionWithExt != NULL && InfSectionWithExtSize != 0)
+ {
+ if (InfSectionWithExtSize < (dwFullLength + 1))
+ {
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ goto done;
+ }
- lstrcpyW(InfSectionWithExt, szBuffer);
- if (Extension != NULL)
- {
- *Extension = (dwLength == dwFullLength) ? NULL : &InfSectionWithExt[dwLength];
- }
- }
+ lstrcpyW(InfSectionWithExt, SectionName);
+ if (Extension != NULL)
+ {
+ DWORD dwLength = lstrlenW(SectionName);
+ *Extension = (dwLength == dwFullLength) ? NULL : &InfSectionWithExt[dwLength];
+ }
+ }
- if (RequiredSize != NULL)
- {
- *RequiredSize = dwFullLength + 1;
+ if (RequiredSize != NULL)
+ *RequiredSize = dwFullLength + 1;
+
+ ret = TRUE;
}
- return TRUE;
+done:
+ TRACE("Returning %d\n", ret);
+ return ret;
}
+
/***********************************************************************
* SetupDiGetClassDescriptionA (SETUPAPI.@)
*/
*pDeviceInterface = NULL;
- deviceInterface = HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInterface) + (wcslen(SymbolicLink) + 1) * sizeof(WCHAR));
+ deviceInterface = HeapAlloc(GetProcessHeap(), 0,
+ FIELD_OFFSET(struct DeviceInterface, SymbolicLink) + (wcslen(SymbolicLink) + 1) * sizeof(WCHAR));
if (!deviceInterface)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
DWORD i = 0, j;
DWORD dwLength, dwRegType;
DWORD rc;
-
+
/* Enumerate device IDs (subkeys of hEnumeratorKey) */
while (TRUE)
{
HKLM = HKEY_LOCAL_MACHINE;
rc = RegOpenKeyExW(HKLM,
- EnumKeyName,
+ REGSTR_PATH_SYSTEMENUM,
0,
KEY_ENUMERATE_SUB_KEYS,
&hEnumKey);
/* 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)
LONG rc;
BOOL ret = FALSE;
- /* Read "Icon" registry key */
- rc = RegQueryValueExW(hClassKey, L"Icon", NULL, &dwRegType, NULL, &dwLength);
+ /* Read icon registry key */
+ rc = RegQueryValueExW(hClassKey, REGSTR_VAL_INSICON, NULL, &dwRegType, NULL, &dwLength);
if (rc != ERROR_SUCCESS)
{
SetLastError(rc);
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto cleanup;
}
- Buffer[dwLength / sizeof(WCHAR)] = 0;
- rc = RegQueryValueExW(hClassKey, L"Icon", NULL, NULL, (LPBYTE)Buffer, &dwLength);
+ 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;
- /* Transform "Icon" value to a INT */
+ /* Transform icon value to a INT */
*ImageIndex = atoiW(Buffer);
ret = TRUE;
PWCHAR Comma;
LONG rc;
DWORD dwRegType, dwLength;
- rc = RegQueryValueExW(hKey, L"Installer32", NULL, &dwRegType, NULL, &dwLength);
+ rc = RegQueryValueExW(hKey, REGSTR_VAL_INSTALLER_32, NULL, &dwRegType, NULL, &dwLength);
if (rc == ERROR_SUCCESS && dwRegType == REG_SZ)
{
- Buffer = MyMalloc(dwLength);
+ Buffer = MyMalloc(dwLength + sizeof(WCHAR));
if (Buffer == NULL)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto cleanup;
}
- rc = RegQueryValueExW(hKey, L"Installer32", NULL, NULL, (LPBYTE)Buffer, &dwLength);
+ 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, L"EnumPropPages32", NULL, &dwRegType, NULL, &dwLength))
+ (ERROR_SUCCESS == (rc = RegQueryValueExW(hKey, REGSTR_VAL_ENUMPROPPAGES_32, NULL, &dwRegType, NULL, &dwLength))
&& dwRegType == REG_SZ)
{
- Buffer = MyMalloc(dwLength);
+ Buffer = MyMalloc(dwLength + sizeof(WCHAR));
if (Buffer == NULL)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto cleanup;
}
- rc = RegQueryValueExW(hKey, L"EnumPropPages32", NULL, NULL, (LPBYTE)Buffer, &dwLength);
+ 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
{
goto cleanup;
}
*Comma = '\0';
+ DllName = Buffer;
}
else
{
return TRUE;
}
+static BOOL DestroyClassInstallParams(struct ClassInstallParams* installParams)
+{
+ HeapFree(GetProcessHeap(), 0, installParams->PropChange);
+ return TRUE;
+}
+
static BOOL DestroyDeviceInfoElement(struct DeviceInfoElement* deviceInfo)
{
PLIST_ENTRY ListEntry;
ListEntry = RemoveHeadList(&deviceInfo->InterfaceListHead);
HeapFree(GetProcessHeap(), 0, ListEntry);
}
+ DestroyClassInstallParams(&deviceInfo->ClassInstallParams);
HeapFree(GetProcessHeap(), 0, deviceInfo);
return TRUE;
}
if (list->HKLM != HKEY_LOCAL_MACHINE)
RegCloseKey(list->HKLM);
CM_Disconnect_Machine(list->hMachine);
+ DestroyClassInstallParams(&list->ClassInstallParams);
HeapFree(GetProcessHeap(), 0, list);
return TRUE;
}
{
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)
{
SetLastError(ERROR_INVALID_HANDLE);
else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
SetLastError(ERROR_INVALID_HANDLE);
- else if (DeviceInfoData)
+ else if (!DeviceInfoData)
SetLastError(ERROR_INVALID_HANDLE);
else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
SetLastError(ERROR_INVALID_USER_BUFFER);
switch (Property)
{
case SPDRP_COMPATIBLEIDS:
- RegistryPropertyName = L"CompatibleIDs";
+ RegistryPropertyName = REGSTR_VAL_COMPATIBLEIDS;
RegistryDataType = REG_MULTI_SZ;
break;
case SPDRP_CONFIGFLAGS:
- RegistryPropertyName = L"ConfigFlags";
+ RegistryPropertyName = REGSTR_VAL_CONFIGFLAGS;
RegistryDataType = REG_DWORD;
break;
case SPDRP_FRIENDLYNAME:
- RegistryPropertyName = L"FriendlyName";
+ RegistryPropertyName = REGSTR_VAL_FRIENDLYNAME;
RegistryDataType = REG_SZ;
break;
case SPDRP_HARDWAREID:
- RegistryPropertyName = L"HardwareID";
+ RegistryPropertyName = REGSTR_VAL_HARDWAREID;
RegistryDataType = REG_MULTI_SZ;
break;
case SPDRP_LOCATION_INFORMATION:
- RegistryPropertyName = L"LocationInformation";
+ RegistryPropertyName = REGSTR_VAL_LOCATION_INFORMATION;
RegistryDataType = REG_SZ;
break;
case SPDRP_LOWERFILTERS:
- RegistryPropertyName = L"LowerFilters";
+ RegistryPropertyName = REGSTR_VAL_LOWERFILTERS;
RegistryDataType = REG_MULTI_SZ;
break;
case SPDRP_SECURITY:
RegistryDataType = REG_BINARY;
break;
case SPDRP_SERVICE:
- RegistryPropertyName = L"Service";
+ RegistryPropertyName = REGSTR_VAL_SERVICE;
RegistryDataType = REG_SZ;
break;
case SPDRP_UI_NUMBER_DESC_FORMAT:
RegistryDataType = REG_SZ;
break;
case SPDRP_UPPERFILTERS:
- RegistryPropertyName = L"UpperFilters";
+ RegistryPropertyName = REGSTR_VAL_UPPERFILTERS;
RegistryDataType = REG_MULTI_SZ;
break;
default:
return ret;
}
+
/***********************************************************************
* SetupDiInstallClassA (SETUPAPI.@)
*/
BOOL WINAPI SetupDiInstallClassA(
- HWND hwndParent,
- PCSTR InfFileName,
- DWORD Flags,
- HSPFILEQ FileQueue)
+ 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)
{
- UNICODE_STRING FileNameW;
+ PWSTR InfFileNameW = NULL;
BOOL Result;
- if (!RtlCreateUnicodeStringFromAsciiz(&FileNameW, InfFileName))
+ if (InfFileName)
{
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- return FALSE;
+ InfFileNameW = MultiByteToUnicode(InfFileName, CP_ACP);
+ if (InfFileNameW == NULL)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return FALSE;
+ }
}
- Result = SetupDiInstallClassW(hwndParent, FileNameW.Buffer, Flags, FileQueue);
+ Result = SetupDiInstallClassExW(hwndParent, InfFileNameW, Flags,
+ FileQueue, InterfaceClassGuid, Reserved1, Reserved2);
- RtlFreeUnicodeString(&FileNameW);
+ MyFree(InfFileNameW);
return Result;
}
+
static HKEY CreateClassKey(HINF hInf)
{
WCHAR FullBuffer[MAX_PATH];
return INVALID_HANDLE_VALUE;
}
- lstrcpyW(FullBuffer, ControlClass);
+ lstrcpyW(FullBuffer, REGSTR_PATH_CLASS_NT);
lstrcatW(FullBuffer, Buffer);
return hClassKey;
}
-/***********************************************************************
- * SetupDiInstallClassW (SETUPAPI.@)
- */
-BOOL WINAPI SetupDiInstallClassW(
- HWND hwndParent,
- PCWSTR InfFileName,
- DWORD Flags,
- HSPFILEQ FileQueue)
+
+static BOOL
+InstallServicesSection(
+ IN HINF hInf,
+ IN PCWSTR SectionName,
+ IN HDEVINFO DeviceInfoSet OPTIONAL,
+ IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
+ OUT PCWSTR* pAssociatedService OPTIONAL,
+ OUT PBOOL pRebootRequired OPTIONAL)
{
- WCHAR SectionName[MAX_PATH];
- DWORD SectionNameLength = 0;
- HINF hInf;
- BOOL bFileQueueCreated = FALSE;
- HKEY hClassKey;
+ INFCONTEXT ContextService;
+ DWORD RequiredSize;
+ INT Flags;
+ BOOL ret = FALSE;
- TRACE("%p %s 0x%lx %p\n", hwndParent, debugstr_w(InfFileName),
- Flags, FileQueue);
+ ret = SetupFindFirstLineW(hInf, SectionName, NULL, &ContextService);
+ while (ret)
+ {
+ LPWSTR ServiceName = NULL;
+ LPWSTR ServiceSection = NULL;
- FIXME("not fully implemented\n");
+ ret = SetupGetStringFieldW(
+ &ContextService,
+ 1, /* Field index */
+ NULL, 0,
+ &RequiredSize);
+ if (!ret)
+ goto nextservice;
+ if (RequiredSize > 0)
+ {
+ /* We got the needed size for the buffer */
+ ServiceName = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
+ if (!ServiceName)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto nextservice;
+ }
+ ret = SetupGetStringFieldW(
+ &ContextService,
+ 1, /* Field index */
+ ServiceName, RequiredSize,
+ &RequiredSize);
+ if (!ret)
+ goto nextservice;
+ }
+ ret = SetupGetIntField(
+ &ContextService,
+ 2, /* Field index */
+ &Flags);
+ if (!ret)
+ {
+ /* The field may be empty. Ignore the error */
+ Flags = 0;
+ }
+ ret = SetupGetStringFieldW(
+ &ContextService,
+ 3, /* Field index */
+ NULL, 0,
+ &RequiredSize);
+ if (!ret)
+ {
+ if (GetLastError() == ERROR_INVALID_PARAMETER)
+ {
+ /* This first is probably missing. It is not
+ * required, so ignore the error */
+ RequiredSize = 0;
+ ret = TRUE;
+ }
+ else
+ goto nextservice;
+ }
+ if (RequiredSize > 0)
+ {
+ /* We got the needed size for the buffer */
+ ServiceSection = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
+ if (!ServiceSection)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto nextservice;
+ }
+ ret = SetupGetStringFieldW(
+ &ContextService,
+ 3, /* Field index */
+ ServiceSection, RequiredSize,
+ &RequiredSize);
+ if (!ret)
+ goto nextservice;
- if ((Flags & DI_NOVCP) && (FileQueue == NULL || FileQueue == INVALID_HANDLE_VALUE))
- {
- SetLastError(ERROR_INVALID_PARAMETER);
- return FALSE;
+ SetLastError(ERROR_SUCCESS);
+ ret = SetupInstallServicesFromInfSectionExW(
+ hInf,
+ ServiceSection, Flags, DeviceInfoSet, DeviceInfoData, ServiceName, NULL);
+ }
+ if (ret && (Flags & SPSVCINST_ASSOCSERVICE))
+ {
+ if (pAssociatedService)
+ {
+ *pAssociatedService = ServiceName;
+ ServiceName = NULL;
+ }
+ if (pRebootRequired && GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED)
+ *pRebootRequired = TRUE;
+ }
+nextservice:
+ HeapFree(GetProcessHeap(), 0, ServiceName);
+ HeapFree(GetProcessHeap(), 0, ServiceSection);
+ if (!ret)
+ goto done;
+ ret = SetupFindNextLine(&ContextService, &ContextService);
}
- /* Open the .inf file */
- hInf = SetupOpenInfFileW(InfFileName,
- NULL,
- INF_STYLE_WIN4,
- NULL);
- if (hInf == INVALID_HANDLE_VALUE)
- {
+ ret = TRUE;
- return FALSE;
- }
+done:
+ return ret;
+}
+
+/***********************************************************************
+ * SetupDiInstallClassExW (SETUPAPI.@)
+ */
+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)
+{
+ BOOL ret = FALSE;
+
+ TRACE("%p %s 0x%lx %p %s %p %p\n", hwndParent, debugstr_w(InfFileName), Flags,
+ FileQueue, debugstr_guid(InterfaceClassGuid), Reserved1, Reserved2);
- /* Create or open the class registry key 'HKLM\\CurrentControlSet\\Class\\{GUID}' */
- hClassKey = CreateClassKey(hInf);
- if (hClassKey == INVALID_HANDLE_VALUE)
+ if (!InfFileName && !InterfaceClassGuid)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else if (Flags & ~(DI_NOVCP | DI_NOBROWSE | DI_FORCECOPY | DI_QUIETINSTALL))
{
- SetupCloseInfFile(hInf);
- return FALSE;
+ TRACE("Unknown flags: 0x%08lx\n", Flags & ~(DI_NOVCP | DI_NOBROWSE | DI_FORCECOPY | DI_QUIETINSTALL));
+ SetLastError(ERROR_INVALID_FLAGS);
}
+ 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
+ {
+ 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 */
-#if 0
- SetupOpenAppendInfFileW(NULL, hInf, NULL);
-#endif
+ /* Try to append a layout file */
+ ret = SetupOpenAppendInfFileW(NULL, hInf, NULL);
+ if (!ret)
+ goto cleanup;
- /* Retrieve the actual section name */
- SetupDiGetActualSectionToInstallW(hInf,
- ClassInstall32,
- SectionName,
- MAX_PATH,
- &SectionNameLength,
- NULL);
+ /* Retrieve the actual section name */
+ ret = SetupDiGetActualSectionToInstallW(
+ hInf,
+ ClassInstall32,
+ SectionName,
+ MAX_PATH - wcslen(DotServices),
+ NULL,
+ NULL);
+ if (!ret)
+ goto cleanup;
-#if 0
- if (!(Flags & DI_NOVCP))
- {
- FileQueue = SetupOpenFileQueue();
- if (FileQueue == INVALID_HANDLE_VALUE)
- {
- SetupCloseInfFile(hInf);
- RegCloseKey(hClassKey);
- return FALSE;
- }
-
- bFileQueueCreated = TRUE;
-
- }
-#endif
+ callback_context = SetupInitDefaultQueueCallback(hwndParent);
+ if (!callback_context)
+ goto cleanup;
- SetupInstallFromInfSectionW(NULL,
- hInf,
- SectionName,
- SPINST_REGISTRY,
- hClassKey,
- NULL,
- 0,
- NULL,
- NULL,
- INVALID_HANDLE_VALUE,
- NULL);
+ 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;
- /* FIXME: More code! */
+ /* Install .Services section */
+ lstrcatW(SectionName, DotServices);
+ ret = InstallServicesSection(hInf, SectionName, NULL, NULL, NULL, NULL);
+ if (!ret)
+ goto cleanup;
- if (bFileQueueCreated)
- SetupCloseFileQueue(FileQueue);
+ ret = TRUE;
+ }
- SetupCloseInfFile(hInf);
+cleanup:
+ if (hInf != INVALID_HANDLE_VALUE)
+ SetupCloseInfFile(hInf);
+ if (hClassKey != INVALID_HANDLE_VALUE)
+ RegCloseKey(hClassKey);
+ SetupTermDefaultQueueCallback(callback_context);
+ }
- RegCloseKey(hClassKey);
- return TRUE;
+ TRACE("Returning %d\n", ret);
+ return ret;
}
if (Flags == DIOCR_INSTALLER)
{
- lpKeyName = ControlClass;
+ lpKeyName = REGSTR_PATH_CLASS_NT;
}
else if (Flags == DIOCR_INTERFACE)
{
- lpKeyName = DeviceClasses;
+ lpKeyName = REGSTR_PATH_DEVICE_CLASSES;
}
else
{
rc = RegOpenKeyExW(HKLM,
lpKeyName,
0,
- ClassGuid ? KEY_ENUMERATE_SUB_KEYS : samDesired,
+ ClassGuid ? 0 : samDesired,
&hClassesKey);
if (MachineName != NULL) RegCloseKey(HKLM);
if (rc != ERROR_SUCCESS)
* SetupDiSetClassInstallParamsW (SETUPAPI.@)
*/
BOOL WINAPI SetupDiSetClassInstallParamsW(
- HDEVINFO DeviceInfoSet,
- PSP_DEVINFO_DATA DeviceInfoData,
- PSP_CLASSINSTALL_HEADER ClassInstallParams,
- DWORD ClassInstallParamsSize)
+ IN HDEVINFO DeviceInfoSet,
+ IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
+ IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL,
+ IN DWORD ClassInstallParamsSize)
{
- FIXME("%p %p %x %lu\n",DeviceInfoSet, DeviceInfoData,
- ClassInstallParams->InstallFunction, ClassInstallParamsSize);
- return FALSE;
+ struct DeviceInfoSet *list;
+ BOOL ret = FALSE;
+
+ TRACE("%p %p %p %lu\n", DeviceInfoSet, DeviceInfoData,
+ ClassInstallParams, ClassInstallParamsSize);
+
+ 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;
+
+ InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
+ Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
+ if (!Result)
+ goto done;
+
+ if (ClassInstallParams)
+ {
+ /* 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;
+ }
+
+ ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
+ }
+
+done:
+ TRACE("Returning %d\n", ret);
+ return ret;
+}
+
+static BOOL PropertyChangeHandler(
+ IN HDEVINFO DeviceInfoSet,
+ IN PSP_DEVINFO_DATA DeviceInfoData,
+ IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL,
+ IN DWORD ClassInstallParamsSize)
+{
+ PSP_PROPCHANGE_PARAMS PropChangeParams = (PSP_PROPCHANGE_PARAMS)ClassInstallParams;
+ BOOL ret = FALSE;
+
+ if (!DeviceInfoData)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ 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
+ {
+ PSP_PROPCHANGE_PARAMS *CurrentPropChangeParams;
+ if (!DeviceInfoData)
+ {
+ struct DeviceInfoSet *list = (struct DeviceInfoSet *)DeviceInfoSet;
+ CurrentPropChangeParams = &list->ClassInstallParams.PropChange;
+ }
+ else
+ {
+ 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)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto done;
+ }
+ memcpy(*CurrentPropChangeParams, PropChangeParams, sizeof(SP_PROPCHANGE_PARAMS));
+ }
+ ret = TRUE;
+ }
+
+done:
+ return ret;
}
static DWORD
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;
hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_QUERY_VALUE);
if (hKey != INVALID_HANDLE_VALUE)
{
- rc = RegQueryValueExW(hKey, L"CoInstallers32", NULL, &dwRegType, NULL, &dwLength);
+ 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, L"CoInstallers32", NULL, NULL, (LPBYTE)KeyBuffer, &dwLength);
+ rc = RegQueryValueExW(hKey, REGSTR_VAL_COINSTALLERS_32, NULL, NULL, (LPBYTE)KeyBuffer, &dwLength);
if (rc == ERROR_SUCCESS)
{
LPWSTR ptr;
{
rc = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
- L"SYSTEM\\CurrentControlSet\\Control\\CoDeviceInstallers",
+ REGSTR_PATH_CODEVICEINSTALLERS,
0, /* Options */
KEY_QUERY_VALUE,
&hKey);
hKey = SetupDiOpenClassRegKey(&DeviceInfoData->ClassGuid, KEY_QUERY_VALUE);
if (hKey != INVALID_HANDLE_VALUE)
{
- rc = RegQueryValueExW(hKey, L"Installer32", NULL, &dwRegType, NULL, &dwLength);
+ 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, L"Installer32", NULL, NULL, (LPBYTE)KeyBuffer, &dwLength);
+ rc = RegQueryValueExW(hKey, REGSTR_VAL_INSTALLER_32, NULL, NULL, (LPBYTE)KeyBuffer, &dwLength);
if (rc == ERROR_SUCCESS)
{
/* Get ClassInstaller function pointer */
if (hKey == INVALID_HANDLE_VALUE)
goto cleanup;
- rc = RegQueryValueExW(hKey, L"EnumPropPages32", NULL, &dwRegType, NULL, &dwLength);
+ 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 */
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto cleanup;
}
- rc = RegQueryValueExW(hKey, L"EnumPropPages32", NULL, NULL, (LPBYTE)PropPageProvider, &dwLength);
+ rc = RegQueryValueExW(hKey, REGSTR_VAL_ENUMPROPPAGES_32, NULL, NULL, (LPBYTE)PropPageProvider, &dwLength);
if (rc != ERROR_SUCCESS)
{
SetLastError(rc);
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.@)
*/
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_CONFIGSPECIFIC)
+ if (Scope == DICS_FLAG_GLOBAL)
+ RootKey = list->HKLM;
+ else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
{
- FIXME("DICS_FLAG_CONFIGSPECIFIC case unimplemented\n");
- goto cleanup;
+ hHWProfileKey = OpenHardwareProfileKey(list->HKLM, HwProfile, KEY_CREATE_SUB_KEY);
+ if (hHWProfileKey == INVALID_HANDLE_VALUE)
+ goto cleanup;
+ RootKey = hHWProfileKey;
}
if (KeyType == DIREG_DEV)
{
- FIXME("DIREG_DEV case unimplemented\n");
+ 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 HKLM\System\CurrentControlSet\Control\Class\{GUID}\Index */
+ /* 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)
{
wcscat(DriverKey, lpGuidString);
wcscat(DriverKey, L"}\\");
pDeviceInstance = &DriverKey[wcslen(DriverKey)];
- rc = RegOpenKeyExW(list->HKLM,
- ControlClass,
+ rc = RegOpenKeyExW(RootKey,
+ REGSTR_PATH_CLASS_NT,
0,
KEY_CREATE_SUB_KEY,
&hClassKey);
hDeviceKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, Scope, HwProfile, DIREG_DEV, KEY_SET_VALUE);
if (hDeviceKey == INVALID_HANDLE_VALUE)
goto cleanup;
- rc = RegSetValueEx(hDeviceKey, L"Driver", 0, REG_SZ, (const BYTE *)DriverKey, (wcslen(DriverKey) + 1) * sizeof(WCHAR));
+ rc = RegSetValueEx(hDeviceKey, REGSTR_VAL_DRIVER, 0, REG_SZ, (const BYTE *)DriverKey, (wcslen(DriverKey) + 1) * sizeof(WCHAR));
if (rc != ERROR_SUCCESS)
{
SetLastError(rc);
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)
SetLastError(ERROR_INVALID_PARAMETER);
else
{
- HKEY hKey = INVALID_HANDLE_VALUE;
- HKEY hRootKey = INVALID_HANDLE_VALUE;
struct DeviceInfoElement *deviceInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
LPWSTR DriverKey = NULL;
DWORD dwLength = 0;
DWORD dwRegType;
DWORD rc;
+ HKEY hHWProfileKey = INVALID_HANDLE_VALUE;
+ HKEY hEnumKey = INVALID_HANDLE_VALUE;
+ HKEY hKey = INVALID_HANDLE_VALUE;
+ HKEY RootKey;
- if (Scope == DICS_FLAG_CONFIGSPECIFIC)
+ if (Scope == DICS_FLAG_GLOBAL)
+ RootKey = list->HKLM;
+ else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
{
- FIXME("DICS_FLAG_CONFIGSPECIFIC case unimplemented\n");
+ hHWProfileKey = OpenHardwareProfileKey(list->HKLM, HwProfile, 0);
+ if (hHWProfileKey == INVALID_HANDLE_VALUE)
+ goto cleanup;
+ RootKey = hHWProfileKey;
}
- else /* Scope == DICS_FLAG_GLOBAL */
+
+ rc = RegOpenKeyExW(
+ RootKey,
+ REGSTR_PATH_SYSTEMENUM,
+ 0, /* Options */
+ 0,
+ &hEnumKey);
+ if (rc != ERROR_SUCCESS)
{
- rc = RegOpenKeyExW(
- list->HKLM,
- EnumKeyName,
- 0, /* Options */
- KEY_ENUMERATE_SUB_KEYS,
- &hRootKey);
- if (rc != ERROR_SUCCESS)
- {
- SetLastError(rc);
- goto cleanup;
- }
- rc = RegOpenKeyExW(
- hRootKey,
- deviceInfo->DeviceName,
- 0, /* Options */
- KeyType == DIREG_DEV ? samDesired : KEY_QUERY_VALUE,
- &hKey);
- RegCloseKey(hRootKey);
- hRootKey = INVALID_HANDLE_VALUE;
- if (rc != ERROR_SUCCESS)
- {
- SetLastError(rc);
- goto cleanup;
- }
- if (KeyType == DIREG_DEV)
- {
- /* We're done. Just return the hKey handle */
- ret = hKey;
- goto cleanup;
- }
- /* Read the 'Driver' key */
- rc = RegQueryValueExW(hKey, L"Driver", NULL, &dwRegType, NULL, &dwLength);
- if (rc != ERROR_SUCCESS)
- {
- SetLastError(rc);
- goto cleanup;
- }
- if (dwRegType != REG_SZ)
- {
- SetLastError(ERROR_GEN_FAILURE);
- goto cleanup;
- }
- DriverKey = HeapAlloc(GetProcessHeap(), 0, dwLength);
- if (!DriverKey)
- {
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- goto cleanup;
- }
- rc = RegQueryValueExW(hKey, L"Driver", NULL, &dwRegType, (LPBYTE)DriverKey, &dwLength);
- if (rc != ERROR_SUCCESS)
- {
- SetLastError(rc);
- goto cleanup;
- }
- RegCloseKey(hKey);
- hKey = INVALID_HANDLE_VALUE;
- /* Need to open the driver key */
- rc = RegOpenKeyExW(
- list->HKLM,
- ControlClass,
- 0, /* Options */
- KEY_ENUMERATE_SUB_KEYS,
- &hRootKey);
- if (rc != ERROR_SUCCESS)
- {
- SetLastError(rc);
- goto cleanup;
- }
- rc = RegOpenKeyExW(
- hRootKey,
- DriverKey,
- 0, /* Options */
- samDesired,
- &hKey);
- if (rc != ERROR_SUCCESS)
- {
- SetLastError(rc);
- goto cleanup;
- }
+ 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 (hRootKey != INVALID_HANDLE_VALUE)
- RegCloseKey(hRootKey);
+ if (hHWProfileKey != INVALID_HANDLE_VALUE)
+ RegCloseKey(hHWProfileKey);
+ if (hEnumKey != INVALID_HANDLE_VALUE)
+ RegCloseKey(hEnumKey);
if (hKey != INVALID_HANDLE_VALUE && hKey != ret)
RegCloseKey(hKey);
}
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;
PreviousEntry = DriverListHead->Flink;
while (PreviousEntry != DriverListHead)
{
- if (((struct DriverInfoElement *)PreviousEntry)->DriverRank >= Rank)
+ 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);
}
/* Get driver version. Invalid version = 0.0.0.0 */
*DriverVersion = 0;
- /* FIXME: use pVersion to fill DriverVersion variable */
+ 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;
/* Open supposed registry key */
rc = RegOpenKeyExW(
list->HKLM,
- EnumKeyName,
+ REGSTR_PATH_SYSTEMENUM,
0, /* Options */
- KEY_ENUMERATE_SUB_KEYS,
+ 0,
&hEnumKey);
if (rc != ERROR_SUCCESS)
{
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) ||
}
DriverInfoDataW.DriverType = DriverInfoData->DriverType;
DriverInfoDataW.Reserved = DriverInfoData->Reserved;
-
+
/* convert the strings to unicode */
if (MultiByteToWideChar(CP_ACP,
0,
}
}
}
-
+
Cleanup:
if (DriverInfoDetailDataW != NULL)
{
return ret;
}
+/* Return the current hardware profile id, or -1 if error */
+static DWORD
+GetCurrentHwProfile(
+ IN HDEVINFO DeviceInfoSet)
+{
+ 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;
+ }
+
+ 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;
+
+cleanup:
+ if (hKey != INVALID_HANDLE_VALUE)
+ RegCloseKey(hKey);
+
+ return hwProfile;
+}
+
+static BOOL
+ResetDevice(
+ IN HDEVINFO DeviceInfoSet,
+ IN PSP_DEVINFO_DATA DeviceInfoData)
+{
+ PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData;
+ struct DeviceInfoElement *deviceInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
+ NTSTATUS Status;
+
+ 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;
+ }
+
+ 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;
+}
+
+/***********************************************************************
+ * SetupDiChangeState (SETUPAPI.@)
+ */
+BOOL WINAPI
+SetupDiChangeState(
+ IN HDEVINFO DeviceInfoSet,
+ IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
+{
+ PSP_PROPCHANGE_PARAMS PropChange;
+ HKEY hKey = INVALID_HANDLE_VALUE;
+ LPCWSTR RegistryValueName;
+ DWORD dwConfigFlags, dwLength, dwRegType;
+ LONG rc;
+ BOOL ret = FALSE;
+
+ TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
+
+ if (!DeviceInfoData)
+ PropChange = ((struct DeviceInfoSet *)DeviceInfoSet)->ClassInstallParams.PropChange;
+ else
+ PropChange = ((struct DeviceInfoElement *)DeviceInfoData->Reserved)->ClassInstallParams.PropChange;
+ if (!PropChange)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ goto cleanup;
+ }
+
+ if (PropChange->Scope == DICS_FLAG_GLOBAL)
+ RegistryValueName = REGSTR_VAL_CONFIGFLAGS;
+ else
+ RegistryValueName = REGSTR_VAL_CSCONFIGFLAGS;
+
+ switch (PropChange->StateChange)
+ {
+ case DICS_ENABLE:
+ case DICS_DISABLE:
+ {
+ /* 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)
+ {
+ SetLastError(rc);
+ goto cleanup;
+ }
+ else if (dwRegType != REG_DWORD || dwLength != sizeof(DWORD))
+ {
+ SetLastError(ERROR_GEN_FAILURE);
+ goto cleanup;
+ }
+ 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);
+ goto cleanup;
+ }
+
+ /* Enable/disable device if needed */
+ if (PropChange->Scope == DICS_FLAG_GLOBAL
+ || PropChange->HwProfile == 0
+ || PropChange->HwProfile == GetCurrentHwProfile(DeviceInfoSet))
+ {
+ if (PropChange->StateChange == DICS_ENABLE)
+ ret = ResetDevice(DeviceInfoSet, DeviceInfoData);
+ else
+ ret = StopDevice(DeviceInfoSet, DeviceInfoData);
+ }
+ else
+ ret = TRUE;
+ break;
+ }
+ case DICS_PROPCHANGE:
+ {
+ ret = ResetDevice(DeviceInfoSet, DeviceInfoData);
+ break;
+ }
+ default:
+ {
+ FIXME("Unknown StateChange 0x%lx\n", PropChange->StateChange);
+ SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ }
+ }
+
+cleanup:
+ if (hKey != INVALID_HANDLE_VALUE)
+ RegCloseKey(hKey);
+
+ TRACE("Returning %d\n", ret);
+ return ret;
+}
+
/***********************************************************************
* SetupDiSelectBestCompatDrv (SETUPAPI.@)
*/
IN HDEVINFO DeviceInfoSet,
IN PSP_DEVINFO_DATA DeviceInfoData)
{
- struct DeviceInfoElement *DevInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
SP_DEVINSTALL_PARAMS_W InstallParams;
struct DriverInfoElement *SelectedDriver;
SYSTEMTIME DriverDate;
WCHAR Buffer[32];
DWORD SectionNameLength = 0;
BOOL Result = FALSE;
- INFCONTEXT ContextService;
- INT Flags;
ULONG DoAction;
DWORD RequiredSize;
LPCWSTR AssociatedService = NULL;
HKEY hKey = INVALID_HANDLE_VALUE;
HKEY hClassKey = INVALID_HANDLE_VALUE;
BOOL NeedtoCopyFile;
+ LARGE_INTEGER fullVersion;
LONG rc;
BOOL ret = FALSE; /* Return value */
SelectedDriver->InfFileDetails->hInf,
SelectedDriver->Details.SectionName,
SectionName, MAX_PATH, &SectionNameLength, NULL);
- if (!Result || SectionNameLength > MAX_PATH - 9)
+ if (!Result || SectionNameLength > MAX_PATH - wcslen(DotServices))
goto cleanup;
pSectionName = &SectionName[wcslen(SectionName)];
/* 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", SelectedDriver->Info.DriverVersion & 0xff, (SelectedDriver->Info.DriverVersion >> 8) & 0xff, (SelectedDriver->Info.DriverVersion >> 16) & 0xff, (SelectedDriver->Info.DriverVersion >> 24) & 0xff);
+ 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)]);
rc = RegSetValueEx(hKey, L"DriverDesc", 0, REG_SZ, (const BYTE *)SelectedDriver->Info.Description, (wcslen(SelectedDriver->Info.Description) + 1) * sizeof(WCHAR));
if (rc == ERROR_SUCCESS)
{
- swprintf(Buffer, L"%u.%u.%u.%u", SelectedDriver->Info.DriverVersion & 0xff, (SelectedDriver->Info.DriverVersion >> 8) & 0xff, (SelectedDriver->Info.DriverVersion >> 16) & 0xff, (SelectedDriver->Info.DriverVersion >> 24) & 0xff);
+ 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)
/* FIXME: Process .LogConfigOverride section */
/* Install .Services section */
- wcscpy(pSectionName, L".Services");
- Result = SetupFindFirstLineW(SelectedDriver->InfFileDetails->hInf, SectionName, NULL, &ContextService);
- while (Result)
- {
- LPWSTR ServiceName = NULL;
- LPWSTR ServiceSection = NULL;
-
- Result = SetupGetStringFieldW(
- &ContextService,
- 1, /* Field index */
- NULL, 0,
- &RequiredSize);
- if (!Result)
- goto nextfile;
- if (RequiredSize > 0)
- {
- /* We got the needed size for the buffer */
- ServiceName = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
- if (!ServiceName)
- {
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- goto nextfile;
- }
- Result = SetupGetStringFieldW(
- &ContextService,
- 1, /* Field index */
- ServiceName, RequiredSize,
- &RequiredSize);
- if (!Result)
- goto nextfile;
- }
- Result = SetupGetIntField(
- &ContextService,
- 2, /* Field index */
- &Flags);
- if (!Result)
- {
- /* The field may be empty. Ignore the error */
- Flags = 0;
- }
- Result = SetupGetStringFieldW(
- &ContextService,
- 3, /* Field index */
- NULL, 0,
- &RequiredSize);
- if (!Result)
- {
- if (GetLastError() == ERROR_INVALID_PARAMETER)
- {
- /* This first is probably missing. It is not
- * required, so ignore the error */
- RequiredSize = 0;
- Result = TRUE;
- }
- else
- goto nextfile;
- }
- if (RequiredSize > 0)
- {
- /* We got the needed size for the buffer */
- ServiceSection = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
- if (!ServiceSection)
- {
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- goto nextfile;
- }
- Result = SetupGetStringFieldW(
- &ContextService,
- 3, /* Field index */
- ServiceSection, RequiredSize,
- &RequiredSize);
- if (!Result)
- goto nextfile;
-
- SetLastError(ERROR_SUCCESS);
- Result = SetupInstallServicesFromInfSectionExW(
- SelectedDriver->InfFileDetails->hInf,
- ServiceSection, Flags, DeviceInfoSet, DeviceInfoData, ServiceName, NULL);
- }
- if (Result && (Flags & SPSVCINST_ASSOCSERVICE))
- {
- AssociatedService = ServiceName;
- ServiceName = NULL;
- if (GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED)
- RebootRequired = TRUE;
- }
-nextfile:
- HeapFree(GetProcessHeap(), 0, ServiceName);
- HeapFree(GetProcessHeap(), 0, ServiceSection);
- if (!Result)
- goto cleanup;
- Result = SetupFindNextLine(&ContextService, &ContextService);
- }
+ wcscpy(pSectionName, DotServices);
+ Result = InstallServicesSection(
+ SelectedDriver->InfFileDetails->hInf,
+ SectionName,
+ DeviceInfoSet,
+ DeviceInfoData,
+ &AssociatedService,
+ &RebootRequired);
+ if (!Result)
+ goto cleanup;
/* Copy .inf file to Inf\ directory (if needed) */
Result = InfIsFromOEMLocation(SelectedDriver->InfFileDetails->FullInfFileName, &NeedtoCopyFile);
TRACE("DeviceDesc : '%S'\n", SelectedDriver->Info.Description);
TRACE("Mfg : '%S'\n", SelectedDriver->Info.MfgName);
TRACE("Service : '%S'\n", AssociatedService);
- rc = RegSetValueEx(hKey, L"Class", 0, REG_SZ, (const BYTE *)ClassName, (wcslen(ClassName) + 1) * sizeof(WCHAR));
+ rc = RegSetValueEx(hKey, REGSTR_VAL_CLASS, 0, REG_SZ, (const BYTE *)ClassName, (wcslen(ClassName) + 1) * sizeof(WCHAR));
if (rc == ERROR_SUCCESS)
- rc = RegSetValueEx(hKey, L"ClassGUID", 0, REG_SZ, (const BYTE *)lpFullGuidString, (wcslen(lpFullGuidString) + 1) * sizeof(WCHAR));
+ rc = RegSetValueEx(hKey, REGSTR_VAL_CLASSGUID, 0, REG_SZ, (const BYTE *)lpFullGuidString, (wcslen(lpFullGuidString) + 1) * sizeof(WCHAR));
if (rc == ERROR_SUCCESS)
- rc = RegSetValueEx(hKey, L"DeviceDesc", 0, REG_SZ, (const BYTE *)SelectedDriver->Info.Description, (wcslen(SelectedDriver->Info.Description) + 1) * sizeof(WCHAR));
+ 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, L"Mfg", 0, REG_SZ, (const BYTE *)SelectedDriver->Info.MfgName, (wcslen(SelectedDriver->Info.MfgName) + 1) * sizeof(WCHAR));
- if (rc == ERROR_SUCCESS && *AssociatedService)
- rc = RegSetValueEx(hKey, L"Service", 0, REG_SZ, (const BYTE *)AssociatedService, (wcslen(AssociatedService) + 1) * sizeof(WCHAR));
+ 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 && AssociatedService && *AssociatedService)
+ rc = RegSetValueEx(hKey, REGSTR_VAL_SERVICE, 0, REG_SZ, (const BYTE *)AssociatedService, (wcslen(AssociatedService) + 1) * sizeof(WCHAR));
if (rc != ERROR_SUCCESS)
{
SetLastError(rc);
/* Start the device */
if (!RebootRequired && !(InstallParams.Flags & (DI_NEEDRESTART | DI_NEEDREBOOT | DI_DONOTCALLCONFIGMG)))
- {
- PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData;
- NTSTATUS Status;
- RtlInitUnicodeString(&ResetDeviceData.DeviceInstance, DevInfo->DeviceName);
- Status = NtPlugPlayControl(PlugPlayControlResetDevice, &ResetDeviceData, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA));
- ret = NT_SUCCESS(Status);
- }
+ ret = ResetDevice(DeviceInfoSet, DeviceInfoData);
else
ret = TRUE;