Implement DICS_FLAG_CONFIGSPECIFIC and DIREG_DEV cases in SetupDiCreateDevRegKeyW

Implement SetupDiChangeState

svn path=/trunk/; revision=20201
This commit is contained in:
Hervé Poussineau 2005-12-15 21:21:38 +00:00
parent 11dcbab404
commit 89bf2a6dcd
2 changed files with 231 additions and 13 deletions

View file

@ -3397,14 +3397,16 @@ done:
static BOOL PropertyChangeHandler(
IN HDEVINFO DeviceInfoSet,
IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
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 (ClassInstallParamsSize != sizeof(SP_PROPCHANGE_PARAMS))
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
@ -4362,25 +4364,101 @@ HKEY WINAPI SetupDiCreateDevRegKeyW(
LPWSTR pDeviceInstance; /* Points into DriverKey, on the Index field */
DWORD Index; /* Index used in the DriverKey name */
DWORD rc;
HKEY hHWProfilesKey = INVALID_HANDLE_VALUE;
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;
rc = RegOpenKeyExW(list->HKLM,
L"SYSTEM\\CurrentControlSet\\Hardware Profiles",
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;
}
RootKey = hHWProfileKey;
}
if (KeyType == DIREG_DEV)
{
FIXME("DIREG_DEV case unimplemented\n");
struct DeviceInfoElement *deviceInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
rc = RegCreateKeyExW(
RootKey,
EnumKeyName,
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)
{
@ -4391,7 +4469,7 @@ HKEY WINAPI SetupDiCreateDevRegKeyW(
wcscat(DriverKey, lpGuidString);
wcscat(DriverKey, L"}\\");
pDeviceInstance = &DriverKey[wcslen(DriverKey)];
rc = RegOpenKeyExW(list->HKLM,
rc = RegOpenKeyExW(RootKey,
ControlClass,
0,
KEY_CREATE_SUB_KEY,
@ -4463,6 +4541,12 @@ cleanup:
if (lpGuidString)
RpcStringFreeW(&lpGuidString);
HeapFree(GetProcessHeap(), 0, DriverKey);
if (hHWProfilesKey != INVALID_HANDLE_VALUE)
RegCloseKey(hHWProfilesKey);
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)
@ -6346,15 +6430,71 @@ SetupDiGetDriverInfoDetailW(
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;
}
/***********************************************************************
* SetupDiChangeState (SETUPAPI.@)
*/
static BOOL StartDevice(VOID) { FIXME("Stub"); return TRUE; }
static BOOL StopDevice(VOID) { FIXME("Stub"); return TRUE; }
BOOL WINAPI
SetupDiChangeState(
IN HDEVINFO DeviceInfoSet,
IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
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);
@ -6366,13 +6506,90 @@ SetupDiChangeState(
if (!PropChange)
{
SetLastError(ERROR_INVALID_PARAMETER);
goto done;
goto cleanup;
}
FIXME("Stub %p %p\n", DeviceInfoSet, DeviceInfoData);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
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 = SetupDiCreateDevRegKey(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 = StartDevice();
else
ret = StopDevice();
}
else
ret = TRUE;
break;
}
case DICS_PROPCHANGE:
{
ret = StopDevice() && StartDevice();
break;
}
default:
{
FIXME("Unknown StateChange 0x%lx\n", PropChange->StateChange);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
}
}
cleanup:
if (hKey != INVALID_HANDLE_VALUE)
RegCloseKey(hKey);
done:
TRACE("Returning %d\n", ret);
return ret;
}

View file

@ -29,6 +29,7 @@
#include <windows.h>
#include <cfgmgr32.h>
#include <fdi.h>
#include <regstr.h>
#include <setupapi.h>
#include <shlobj.h>
#include <wine/debug.h>