925 lines
26 KiB
C
925 lines
26 KiB
C
/*++
|
||
|
||
Copyright (c) 1995-2000 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
rhwprof.c
|
||
|
||
Abstract:
|
||
|
||
This module contains the server-side hardware profile APIs.
|
||
|
||
PNP_IsDockStationPresent
|
||
PNP_RequestEjectPC
|
||
PNP_HwProfFlags
|
||
PNP_GetHwProfInfo
|
||
PNP_SetHwProf
|
||
|
||
Author:
|
||
|
||
Paula Tomlinson (paulat) 7-18-1995
|
||
|
||
Environment:
|
||
|
||
User-mode only.
|
||
|
||
Revision History:
|
||
|
||
18-July-1995 paulat
|
||
|
||
Creation and initial implementation.
|
||
|
||
--*/
|
||
|
||
|
||
//
|
||
// includes
|
||
//
|
||
|
||
#include "precomp.h"
|
||
#include "umpnpi.h"
|
||
#include "umpnpdat.h"
|
||
|
||
#include <profiles.h>
|
||
|
||
|
||
//
|
||
// private prototypes
|
||
//
|
||
BOOL
|
||
IsCurrentProfile(
|
||
ULONG ulProfile
|
||
);
|
||
|
||
|
||
|
||
CONFIGRET
|
||
PNP_IsDockStationPresent(
|
||
IN handle_t hBinding,
|
||
OUT PBOOL Present
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
This routine determines whether a docking station is currently present.
|
||
|
||
Parameters:
|
||
|
||
hBinding RPC binding handle, not used.
|
||
|
||
Present Supplies the address of a boolean variable that is set
|
||
upon successful return to indicate whether or not a
|
||
docking station is currently present.
|
||
|
||
Return Value:
|
||
|
||
If the function succeeds, the return value is CR_SUCCESS.
|
||
If the function fails, the return value is a CR failure code.
|
||
|
||
--*/
|
||
|
||
{
|
||
CONFIGRET status = CR_SUCCESS;
|
||
ULONG regStatus = ERROR_SUCCESS;
|
||
HKEY hCurrentDockInfo = NULL, hIDConfigDB = NULL;
|
||
DWORD dataType;
|
||
ULONG dockingState;
|
||
ULONG ejectableDocks;
|
||
ULONG size;
|
||
|
||
UNREFERENCED_PARAMETER(hBinding);
|
||
|
||
try {
|
||
//
|
||
// Validate parameters.
|
||
//
|
||
if (!ARGUMENT_PRESENT(Present)) {
|
||
status = CR_FAILURE;
|
||
goto Clean0;
|
||
}
|
||
|
||
*Present = FALSE;
|
||
|
||
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
||
pszRegPathIDConfigDB,
|
||
0,
|
||
KEY_READ,
|
||
&hIDConfigDB) != ERROR_SUCCESS) {
|
||
status = CR_REGISTRY_ERROR;
|
||
hIDConfigDB = NULL;
|
||
goto Clean0;
|
||
}
|
||
|
||
if (RegOpenKeyEx(hIDConfigDB,
|
||
pszRegKeyCurrentDockInfo,
|
||
0,
|
||
KEY_READ,
|
||
&hCurrentDockInfo) != ERROR_SUCCESS) {
|
||
status = CR_REGISTRY_ERROR;
|
||
hCurrentDockInfo = NULL;
|
||
goto Clean0;
|
||
}
|
||
|
||
size = sizeof (dockingState);
|
||
|
||
if ((RegQueryValueEx(hCurrentDockInfo,
|
||
pszRegValueDockingState,
|
||
0,
|
||
&dataType,
|
||
(PUCHAR) &dockingState,
|
||
&size) != ERROR_SUCCESS) ||
|
||
(dataType != REG_DWORD) ||
|
||
(size != sizeof (ULONG))) {
|
||
status = CR_REGISTRY_ERROR;
|
||
goto Clean0;
|
||
}
|
||
|
||
if ((dockingState & HW_PROFILE_DOCKSTATE_UNKNOWN) ==
|
||
HW_PROFILE_DOCKSTATE_DOCKED) {
|
||
|
||
size = sizeof(ejectableDocks);
|
||
|
||
if ((RegQueryValueEx(hCurrentDockInfo,
|
||
pszRegValueEjectableDocks,
|
||
0,
|
||
&dataType,
|
||
(PUCHAR) &ejectableDocks,
|
||
&size) == ERROR_SUCCESS) &&
|
||
(dataType == REG_DWORD) &&
|
||
(size == sizeof(ULONG)) &&
|
||
(ejectableDocks > 0)) {
|
||
*Present = TRUE;
|
||
}
|
||
}
|
||
|
||
Clean0:
|
||
NOTHING;
|
||
|
||
} except(EXCEPTION_EXECUTE_HANDLER) {
|
||
status = CR_FAILURE;
|
||
}
|
||
|
||
if (hIDConfigDB) {
|
||
RegCloseKey(hIDConfigDB);
|
||
}
|
||
|
||
if (hCurrentDockInfo) {
|
||
RegCloseKey(hCurrentDockInfo);
|
||
}
|
||
|
||
return status;
|
||
|
||
} // PNP_IsDockStationPresent
|
||
|
||
|
||
|
||
CONFIGRET
|
||
PNP_RequestEjectPC(
|
||
IN handle_t hBinding
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine requests that the PC be ejected (i.e., undocked).
|
||
|
||
Parameters:
|
||
|
||
hBinding RPC binding handle.
|
||
|
||
Return Value:
|
||
|
||
If the function succeeds, the return value is CR_SUCCESS.
|
||
If the function fails, the return value is a CR failure code.
|
||
|
||
--*/
|
||
|
||
{
|
||
CONFIGRET Status = CR_SUCCESS;
|
||
NTSTATUS ntStatus;
|
||
WCHAR szDockDevInst[MAX_DEVICE_ID_LEN + 1];
|
||
PLUGPLAY_CONTROL_RETRIEVE_DOCK_DATA dockData;
|
||
|
||
try {
|
||
dockData.DeviceInstance = szDockDevInst;
|
||
dockData.DeviceInstanceLength = MAX_DEVICE_ID_LEN;
|
||
|
||
ntStatus = NtPlugPlayControl(PlugPlayControlRetrieveDock,
|
||
&dockData,
|
||
sizeof(PLUGPLAY_CONTROL_RETRIEVE_DOCK_DATA));
|
||
|
||
if (NT_SUCCESS(ntStatus)) {
|
||
Status = PNP_RequestDeviceEject(hBinding,
|
||
szDockDevInst,
|
||
NULL, // pVetoType
|
||
NULL, // pszVetoName
|
||
0, // ulNameLength
|
||
0); // ulFlags
|
||
} else {
|
||
Status = MapNtStatusToCmError(ntStatus);
|
||
}
|
||
|
||
} except(EXCEPTION_EXECUTE_HANDLER) {
|
||
Status = CR_FAILURE;
|
||
}
|
||
|
||
return Status;
|
||
|
||
} // PNP_RequestEjectPC
|
||
|
||
|
||
|
||
CONFIGRET
|
||
PNP_HwProfFlags(
|
||
IN handle_t hBinding,
|
||
IN ULONG ulAction,
|
||
IN LPCWSTR pDeviceID,
|
||
IN ULONG ulConfig,
|
||
IN OUT PULONG pulValue,
|
||
OUT PPNP_VETO_TYPE pVetoType,
|
||
OUT LPWSTR pszVetoName,
|
||
IN ULONG ulNameLength,
|
||
IN ULONG ulFlags
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This is the RPC server entry point for the ConfigManager routines that
|
||
get and set the hardware profile flags.
|
||
|
||
Arguments:
|
||
|
||
hBinding RPC binding handle.
|
||
|
||
ulAction Specified whether to get or set the flag. Can be one
|
||
of the PNP_*_HWPROFFLAGS values.
|
||
|
||
pDeviceID Device instance to get/set the hw profile flag for.
|
||
|
||
ulConfig Specifies which profile to get/set the flag for. A
|
||
value of zero indicates to use the current profile.
|
||
|
||
pulValue If setting the flag, then this value on entry contains
|
||
the value to set the hardware profile flag to. If
|
||
getting the flag, then this value will return the
|
||
current hardware profile flag.
|
||
|
||
pVetoType Buffer to receive the type of veto. If this is NULL
|
||
then no veto information will be received and the OS wil
|
||
display the veto information.
|
||
|
||
pszVetoName Buffer to receive the veto information. If this is NULL
|
||
then no veto information will be received and the OS will
|
||
display the veto information.
|
||
|
||
ulNameLength Size of the pszVetoName buffer.
|
||
|
||
ulFlags Depends on the action being performed.
|
||
For PNP_GET_HWPROFFLAGS, no flags are valid.
|
||
For PNP_SET_HWPROFFLAGS, may be CM_SET_HW_PROF_FLAGS_BITS.
|
||
|
||
Return Value:
|
||
|
||
If the function succeeds it returns CR_SUCCESS. Otherwise it returns one
|
||
of the CR_* values.
|
||
|
||
--*/
|
||
|
||
{
|
||
CONFIGRET Status = CR_SUCCESS;
|
||
ULONG RegStatus = ERROR_SUCCESS;
|
||
WCHAR RegStr[MAX_CM_PATH];
|
||
HKEY hKey = NULL, hDevKey = NULL;
|
||
ULONG ulValueSize = sizeof(ULONG);
|
||
ULONG ulCurrentValue, ulChange, ulDisposition;
|
||
BOOL AffectsCurrentProfile;
|
||
|
||
//
|
||
// NOTE: The device is not checked for presense or not, this flag is
|
||
// always just set or retrieved directly from the registry, as it is
|
||
// done on Windows 95
|
||
//
|
||
|
||
try {
|
||
//
|
||
// validate parameters
|
||
//
|
||
if ((ulAction != PNP_GET_HWPROFFLAGS) &&
|
||
(ulAction != PNP_SET_HWPROFFLAGS)) {
|
||
Status = CR_INVALID_DATA;
|
||
goto Clean0;
|
||
}
|
||
|
||
if (!ARGUMENT_PRESENT(pulValue)) {
|
||
Status = CR_INVALID_POINTER;
|
||
goto Clean0;
|
||
}
|
||
|
||
if (ulAction == PNP_GET_HWPROFFLAGS) {
|
||
//
|
||
// Validate flags for PNP_GET_HWPROFFLAGS
|
||
//
|
||
if (INVALID_FLAGS(ulFlags, 0)) {
|
||
Status = CR_INVALID_FLAG;
|
||
goto Clean0;
|
||
}
|
||
|
||
} else if (ulAction == PNP_SET_HWPROFFLAGS) {
|
||
//
|
||
// Validate flags and value for PNP_SET_HWPROFFLAGS
|
||
//
|
||
if (INVALID_FLAGS(ulFlags, CM_SET_HW_PROF_FLAGS_BITS)) {
|
||
Status = CR_INVALID_FLAG;
|
||
goto Clean0;
|
||
}
|
||
if (INVALID_FLAGS(*pulValue, CSCONFIGFLAG_BITS)) {
|
||
Status = CR_INVALID_DATA;
|
||
goto Clean0;
|
||
}
|
||
}
|
||
|
||
if (!IsLegalDeviceId(pDeviceID)) {
|
||
Status = CR_INVALID_DEVNODE;
|
||
goto Clean0;
|
||
}
|
||
|
||
//
|
||
// a configuration value of zero implies to use the current config
|
||
//
|
||
if (ulConfig == 0) {
|
||
wsprintf(RegStr, TEXT("%s\\%s\\%s"),
|
||
pszRegPathHwProfiles, // System\CCC\Hardware Profiles
|
||
pszRegKeyCurrent, // Current
|
||
pszRegPathEnum); // System\Enum
|
||
} else {
|
||
wsprintf(RegStr, TEXT("%s\\%04u\\%s"),
|
||
pszRegPathHwProfiles, // System\CCC\Hardware Profiles
|
||
ulConfig, // xxxx (profile id)
|
||
pszRegPathEnum); // System\Enum
|
||
}
|
||
|
||
//----------------------------------------------------
|
||
// caller wants to retrieve the hw profile flag value
|
||
//----------------------------------------------------
|
||
|
||
if (ulAction == PNP_GET_HWPROFFLAGS) {
|
||
|
||
//
|
||
// open the profile specific enum key
|
||
//
|
||
RegStatus = RegOpenKeyEx( HKEY_LOCAL_MACHINE, RegStr, 0,
|
||
KEY_QUERY_VALUE, &hKey);
|
||
|
||
if (RegStatus != ERROR_SUCCESS) {
|
||
*pulValue = 0; // success,this is what Win95 does
|
||
goto Clean0;
|
||
}
|
||
|
||
//
|
||
// open the enum\device-instance key under the profile key
|
||
//
|
||
RegStatus = RegOpenKeyEx( hKey, pDeviceID, 0, KEY_QUERY_VALUE, &hDevKey);
|
||
|
||
if (RegStatus != ERROR_SUCCESS) {
|
||
*pulValue = 0; // success,this is what Win95 does
|
||
goto Clean0;
|
||
}
|
||
|
||
//
|
||
// query the profile flag
|
||
//
|
||
ulValueSize = sizeof(ULONG);
|
||
RegStatus = RegQueryValueEx( hDevKey, pszRegValueCSConfigFlags,
|
||
NULL, NULL, (LPBYTE)pulValue,
|
||
&ulValueSize);
|
||
|
||
if (RegStatus != ERROR_SUCCESS) {
|
||
|
||
*pulValue = 0;
|
||
|
||
if (RegStatus != ERROR_CANTREAD && RegStatus != ERROR_FILE_NOT_FOUND) {
|
||
Status = CR_REGISTRY_ERROR;
|
||
goto Clean0;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
//----------------------------------------------
|
||
// caller wants to set the hw profile flag value
|
||
//----------------------------------------------
|
||
|
||
else if (ulAction == PNP_SET_HWPROFFLAGS) {
|
||
|
||
if (!VerifyClientAccess(hBinding, &gLuidLoadDriverPrivilege)) {
|
||
Status = CR_ACCESS_DENIED;
|
||
goto Clean0;
|
||
}
|
||
|
||
//
|
||
// open the profile specific enum key.
|
||
//
|
||
// note that we may actually end up creating a Hardware Profile key
|
||
// here for the specified profile id, even if no such profile
|
||
// exists. ideally, we should check that such a profile exists, but
|
||
// we've been doing this for too long to change it now. the
|
||
// consolation here is that the client must have appropriate
|
||
// privilege to actually do this.
|
||
//
|
||
RegStatus = RegCreateKeyEx( HKEY_LOCAL_MACHINE, RegStr, 0, NULL,
|
||
REG_OPTION_NON_VOLATILE, KEY_QUERY_VALUE,
|
||
NULL, &hKey, &ulDisposition);
|
||
|
||
if (RegStatus != ERROR_SUCCESS) {
|
||
Status = CR_REGISTRY_ERROR;
|
||
goto Clean0;
|
||
}
|
||
|
||
//
|
||
// open the enum\device-instance key under the profile key
|
||
//
|
||
RegStatus = RegCreateKeyEx( hKey, pDeviceID, 0, NULL,
|
||
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
|
||
NULL, &hDevKey, NULL);
|
||
|
||
if (RegStatus != ERROR_SUCCESS) {
|
||
Status = CR_REGISTRY_ERROR;
|
||
goto Clean0;
|
||
}
|
||
|
||
//
|
||
// before setting, query the current profile flag
|
||
//
|
||
ulValueSize = sizeof(ulCurrentValue);
|
||
RegStatus = RegQueryValueEx( hDevKey, pszRegValueCSConfigFlags,
|
||
NULL, NULL, (LPBYTE)&ulCurrentValue,
|
||
&ulValueSize);
|
||
|
||
if (RegStatus == ERROR_CANTREAD || RegStatus == ERROR_FILE_NOT_FOUND) {
|
||
|
||
ulCurrentValue = 0; // success,this is what Win95 does
|
||
|
||
} else if (RegStatus != ERROR_SUCCESS) {
|
||
|
||
Status = CR_REGISTRY_ERROR;
|
||
goto Clean0;
|
||
}
|
||
|
||
//
|
||
// if requested flags different than current, write out to registry
|
||
//
|
||
ulChange = ulCurrentValue ^ *pulValue;
|
||
|
||
if (ulChange) {
|
||
|
||
AffectsCurrentProfile = (BOOL)(ulConfig == 0 || IsCurrentProfile(ulConfig));
|
||
|
||
//
|
||
// we're about to change the disable bit on the current profile,
|
||
// try and disable the device in the process
|
||
//
|
||
if ((ulChange & CSCONFIGFLAG_DISABLED) &&
|
||
(*pulValue & CSCONFIGFLAG_DISABLED) && AffectsCurrentProfile) {
|
||
//
|
||
// disable the devnode
|
||
//
|
||
Status = DisableDevInst(pDeviceID,
|
||
pVetoType,
|
||
pszVetoName,
|
||
ulNameLength);
|
||
if (Status != CR_SUCCESS) {
|
||
if (Status == CR_NOT_DISABLEABLE) {
|
||
//
|
||
// we got refused!
|
||
// (note that this error also implies *NO* changes to the registry entry)
|
||
//
|
||
goto Clean0;
|
||
|
||
} else {
|
||
//
|
||
// we can go ahead and disable after restart
|
||
//
|
||
Status = CR_NEED_RESTART;
|
||
}
|
||
}
|
||
}
|
||
//
|
||
// assume Status is valid and typically CR_SUCCESS or CR_NEED_RESTART
|
||
//
|
||
|
||
//
|
||
// now update the registry
|
||
//
|
||
RegStatus = RegSetValueEx( hDevKey, pszRegValueCSConfigFlags, 0,
|
||
REG_DWORD, (LPBYTE)pulValue,
|
||
sizeof(ULONG));
|
||
|
||
if (RegStatus != ERROR_SUCCESS) {
|
||
Status = CR_REGISTRY_ERROR;
|
||
goto Clean0;
|
||
}
|
||
|
||
if (Status == CR_NEED_RESTART) {
|
||
//
|
||
// we have to RESTART due to not being able to disable device immediately
|
||
//
|
||
goto Clean0;
|
||
}
|
||
|
||
//
|
||
// If this doesn't effect the current config, then we're done.
|
||
//
|
||
if (!AffectsCurrentProfile) {
|
||
goto Clean0;
|
||
}
|
||
|
||
//
|
||
// are we enabling the device?
|
||
//
|
||
|
||
if ((ulChange & CSCONFIGFLAG_DISABLED) && !(*pulValue & CSCONFIGFLAG_DISABLED)) {
|
||
//
|
||
// enable the devnode
|
||
//
|
||
EnableDevInst(pDeviceID);
|
||
}
|
||
|
||
//
|
||
// did the do-not-create bit change?
|
||
//
|
||
if (ulChange & CSCONFIGFLAG_DO_NOT_CREATE) {
|
||
if (*pulValue & CSCONFIGFLAG_DO_NOT_CREATE) {
|
||
//
|
||
// if subtree can be removed, remove it now
|
||
//
|
||
if (QueryAndRemoveSubTree( pDeviceID,
|
||
pVetoType,
|
||
pszVetoName,
|
||
ulNameLength,
|
||
PNP_QUERY_AND_REMOVE_NO_RESTART) != CR_SUCCESS) {
|
||
|
||
Status = CR_NEED_RESTART;
|
||
goto Clean0;
|
||
}
|
||
}
|
||
else {
|
||
//
|
||
// The DO_NOT_CREATE flag was turned off, reenumerate the devnode
|
||
//
|
||
ReenumerateDevInst(pDeviceID, TRUE, 0);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
Clean0:
|
||
NOTHING;
|
||
|
||
} except(EXCEPTION_EXECUTE_HANDLER) {
|
||
Status = CR_FAILURE;
|
||
}
|
||
|
||
if (hKey != NULL) {
|
||
RegCloseKey(hKey);
|
||
}
|
||
if (hDevKey != NULL) {
|
||
RegCloseKey(hDevKey);
|
||
}
|
||
|
||
return Status;
|
||
|
||
} // PNP_HwProfFlags
|
||
|
||
|
||
|
||
CONFIGRET
|
||
PNP_GetHwProfInfo(
|
||
IN handle_t hBinding,
|
||
IN ULONG ulIndex,
|
||
OUT PHWPROFILEINFO pHWProfileInfo,
|
||
IN ULONG ulProfileInfoSize,
|
||
IN ULONG ulFlags
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This is the RPC server entry point for the ConfigManager routine
|
||
CM_Get_Hardware_Profile_Info. It returns a structure of info for
|
||
the specified hardware profile.
|
||
|
||
Arguments:
|
||
|
||
hBinding RPC binding handle, not used.
|
||
|
||
ulIndex Specifies which profile to use. A value of 0xFFFFFFFF
|
||
indicates to use the current profile.
|
||
|
||
pHWProfileInfo Pointer to HWPROFILEINFO struct, returns profile info
|
||
|
||
ulProfileInfoSize Specifies the size of the HWPROFILEINFO struct
|
||
|
||
ulFlags Not used, must be zero.
|
||
|
||
Return Value:
|
||
|
||
If the function succeeds it returns CR_SUCCESS. Otherwise it returns one
|
||
of the CR_* values.
|
||
|
||
--*/
|
||
|
||
{
|
||
CONFIGRET Status = CR_SUCCESS;
|
||
ULONG RegStatus = ERROR_SUCCESS;
|
||
WCHAR RegStr[MAX_CM_PATH];
|
||
HKEY hKey = NULL, hDockKey = NULL, hCfgKey = NULL;
|
||
ULONG ulSize, ulDisposition;
|
||
ULONG enumIndex, targetIndex;
|
||
|
||
UNREFERENCED_PARAMETER(hBinding);
|
||
|
||
try {
|
||
//
|
||
// validate parameters
|
||
//
|
||
if (INVALID_FLAGS(ulFlags, 0)) {
|
||
Status = CR_INVALID_FLAG;
|
||
goto Clean0;
|
||
}
|
||
|
||
//
|
||
// validate the size of the HWPROFILEINFO struct
|
||
//
|
||
if (ulProfileInfoSize != sizeof(HWPROFILEINFO)) {
|
||
Status = CR_INVALID_DATA;
|
||
goto Clean0;
|
||
}
|
||
|
||
//
|
||
// initialize the HWPROFILEINFO struct fields
|
||
//
|
||
pHWProfileInfo->HWPI_ulHWProfile = 0;
|
||
pHWProfileInfo->HWPI_szFriendlyName[0] = '\0';
|
||
pHWProfileInfo->HWPI_dwFlags = 0;
|
||
|
||
//
|
||
// open a key to IDConfigDB (create if it doesn't already exist
|
||
//
|
||
RegStatus = RegCreateKeyEx(HKEY_LOCAL_MACHINE, pszRegPathIDConfigDB, 0,
|
||
NULL, REG_OPTION_NON_VOLATILE, KEY_QUERY_VALUE,
|
||
NULL, &hKey, &ulDisposition);
|
||
|
||
if (RegStatus != ERROR_SUCCESS) {
|
||
Status = CR_REGISTRY_ERROR;
|
||
goto Clean0;
|
||
}
|
||
|
||
//
|
||
// open a key to Hardware Profiles (create if it doesn't already exist)
|
||
//
|
||
RegStatus = RegCreateKeyEx(hKey, pszRegKeyKnownDockingStates, 0,
|
||
NULL, REG_OPTION_NON_VOLATILE,
|
||
KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, NULL,
|
||
&hDockKey, &ulDisposition);
|
||
|
||
if (RegStatus != ERROR_SUCCESS) {
|
||
Status = CR_REGISTRY_ERROR;
|
||
goto Clean0;
|
||
}
|
||
|
||
|
||
//
|
||
// a configuration value of 0xFFFFFFFF implies to use the current config
|
||
//
|
||
if (ulIndex == 0xFFFFFFFF) {
|
||
//
|
||
// get the current profile index stored under IDConfigDB
|
||
//
|
||
ulSize = sizeof(ULONG);
|
||
RegStatus = RegQueryValueEx(
|
||
hKey, pszRegValueCurrentConfig, NULL, NULL,
|
||
(LPBYTE)&pHWProfileInfo->HWPI_ulHWProfile, &ulSize);
|
||
|
||
if (RegStatus != ERROR_SUCCESS) {
|
||
Status = CR_REGISTRY_ERROR;
|
||
pHWProfileInfo->HWPI_ulHWProfile = 0;
|
||
goto Clean0;
|
||
}
|
||
|
||
}
|
||
|
||
//
|
||
// values other than 0xFFFFFFFF mean that we're essentially
|
||
// enumerating profiles (the value is an enumeration index)
|
||
//
|
||
else {
|
||
//
|
||
// enumerate the profile keys under Known Docking States
|
||
//
|
||
Status = CR_SUCCESS;
|
||
enumIndex = 0;
|
||
targetIndex = ulIndex;
|
||
while(enumIndex <= targetIndex) {
|
||
ulSize = MAX_CM_PATH;
|
||
RegStatus = RegEnumKeyEx(hDockKey,
|
||
enumIndex,
|
||
RegStr,
|
||
&ulSize,
|
||
NULL,
|
||
NULL,
|
||
NULL,
|
||
NULL);
|
||
if (RegStatus == ERROR_NO_MORE_ITEMS) {
|
||
Status = CR_NO_MORE_HW_PROFILES;
|
||
goto Clean0;
|
||
} else if (RegStatus != ERROR_SUCCESS) {
|
||
Status = CR_REGISTRY_ERROR;
|
||
goto Clean0;
|
||
}
|
||
|
||
if (_wtoi(RegStr) == 0) {
|
||
//
|
||
// we found the pristine amidst the profiles we're enumerating.
|
||
// enumerate one extra key to make up for it.
|
||
//
|
||
targetIndex++;
|
||
}
|
||
if (enumIndex == targetIndex) {
|
||
//
|
||
// this is the one we want.
|
||
//
|
||
pHWProfileInfo->HWPI_ulHWProfile = _wtoi(RegStr);
|
||
Status = CR_SUCCESS;
|
||
break;
|
||
}
|
||
enumIndex++;
|
||
}
|
||
}
|
||
|
||
//
|
||
// open the key for this profile
|
||
//
|
||
wsprintf(RegStr, TEXT("%04u"),
|
||
pHWProfileInfo->HWPI_ulHWProfile);
|
||
|
||
RegStatus = RegOpenKeyEx(
|
||
hDockKey, RegStr, 0, KEY_QUERY_VALUE, &hCfgKey);
|
||
|
||
if (RegStatus != ERROR_SUCCESS) {
|
||
Status = CR_REGISTRY_ERROR;
|
||
goto Clean0;
|
||
}
|
||
|
||
//
|
||
// retrieve the friendly name
|
||
//
|
||
ulSize = MAX_PROFILE_LEN * sizeof(WCHAR);
|
||
RegStatus = RegQueryValueEx(
|
||
hCfgKey, pszRegValueFriendlyName, NULL, NULL,
|
||
(LPBYTE)(pHWProfileInfo->HWPI_szFriendlyName),
|
||
&ulSize);
|
||
|
||
//
|
||
// retrieve the DockState
|
||
//
|
||
#if 0
|
||
//
|
||
// KENRAY
|
||
// This is the wrong way to determine docking state caps
|
||
// You must instead check the alias tables
|
||
//
|
||
wsprintf(RegStr, TEXT("%04u"), pHWProfileInfo->HWPI_ulHWProfile);
|
||
|
||
ulSize = sizeof(SYSTEM_DOCK_STATE);
|
||
RegStatus = RegQueryValueEx(
|
||
hCfgKey, pszRegValueDockState, NULL, NULL,
|
||
(LPBYTE)&DockState, &ulSize);
|
||
|
||
if (RegStatus != ERROR_SUCCESS) {
|
||
pHWProfileInfo->HWPI_dwFlags = CM_HWPI_NOT_DOCKABLE;
|
||
}
|
||
else {
|
||
//
|
||
// map SYSTEM_DOCK_STATE enumerated types into CM_HWPI_ flags
|
||
//
|
||
if (DockState == SystemDocked) {
|
||
pHWProfileInfo->HWPI_dwFlags = CM_HWPI_DOCKED;
|
||
}
|
||
else if (DockState == SystemUndocked) {
|
||
pHWProfileInfo->HWPI_dwFlags = CM_HWPI_UNDOCKED;
|
||
}
|
||
else {
|
||
pHWProfileInfo->HWPI_dwFlags = CM_HWPI_NOT_DOCKABLE;
|
||
}
|
||
}
|
||
#endif
|
||
|
||
Clean0:
|
||
NOTHING;
|
||
|
||
} except(EXCEPTION_EXECUTE_HANDLER) {
|
||
Status = CR_FAILURE;
|
||
}
|
||
|
||
if (hKey != NULL) {
|
||
RegCloseKey(hKey);
|
||
}
|
||
if (hDockKey != NULL) {
|
||
RegCloseKey(hDockKey);
|
||
}
|
||
if (hCfgKey != NULL) {
|
||
RegCloseKey(hCfgKey);
|
||
}
|
||
|
||
return Status;
|
||
|
||
} // PNP_GetHwProfInfo
|
||
|
||
|
||
|
||
CONFIGRET
|
||
PNP_SetHwProf(
|
||
IN handle_t hBinding,
|
||
IN ULONG ulHardwareProfile,
|
||
IN ULONG ulFlags
|
||
)
|
||
{
|
||
UNREFERENCED_PARAMETER(hBinding);
|
||
UNREFERENCED_PARAMETER(ulHardwareProfile);
|
||
UNREFERENCED_PARAMETER(ulFlags);
|
||
|
||
return CR_CALL_NOT_IMPLEMENTED;
|
||
|
||
} // PNP_SetHwProf
|
||
|
||
|
||
|
||
//-------------------------------------------------------------------
|
||
// Private utility routines
|
||
//-------------------------------------------------------------------
|
||
|
||
BOOL
|
||
IsCurrentProfile(
|
||
ULONG ulProfile
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine determines if the specified profile matches the current
|
||
profile.
|
||
|
||
Arguments:
|
||
|
||
ulProfile Profile id value (value from 1 - 9999).
|
||
|
||
Return Value:
|
||
|
||
Return TRUE if this is the current profile, FALSE if it isn't.
|
||
|
||
--*/
|
||
|
||
{
|
||
HKEY hKey;
|
||
ULONG ulSize, ulCurrentProfile;
|
||
|
||
//
|
||
// open a key to IDConfigDB
|
||
//
|
||
if (RegOpenKeyEx(
|
||
HKEY_LOCAL_MACHINE, pszRegPathIDConfigDB, 0,
|
||
KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS) {
|
||
return FALSE;
|
||
}
|
||
|
||
//
|
||
// get the current profile index stored under IDConfigDB
|
||
//
|
||
ulSize = sizeof(ULONG);
|
||
if (RegQueryValueEx(
|
||
hKey, pszRegValueCurrentConfig, NULL, NULL,
|
||
(LPBYTE)&ulCurrentProfile, &ulSize) != ERROR_SUCCESS) {
|
||
RegCloseKey(hKey);
|
||
return FALSE;
|
||
}
|
||
|
||
RegCloseKey(hKey);
|
||
|
||
if (ulCurrentProfile == ulProfile) {
|
||
return TRUE;
|
||
}
|
||
|
||
return FALSE;
|
||
|
||
} // IsCurrentProfile
|
||
|
||
|
||
|