Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1765 lines
47 KiB

/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
rlogconf.c
Abstract:
This module contains the server-side logical configuration APIs.
PNP_AddEmptyLogConf
PNP_FreeLogConf
PNP_GetFirstLogConf
PNP_GetNextLogConf
Author:
Paula Tomlinson (paulat) 9-27-1995
Environment:
User-mode only.
Revision History:
27-Sept-1995 paulat
Creation and initial implementation.
--*/
//
// includes
//
#include "precomp.h"
#include "umpnpdat.h"
//
// Prototypes used in this routine and in rresdes.c
//
CONFIGRET
GetLogConfData(
IN HKEY hKey,
IN ULONG ulLogConfType,
OUT PULONG pulRegDataType,
OUT LPWSTR pszValueName,
OUT LPBYTE *ppBuffer,
OUT PULONG pulBufferSize
);
PCM_FULL_RESOURCE_DESCRIPTOR
AdvanceResourcePtr(
IN PCM_FULL_RESOURCE_DESCRIPTOR pRes
);
PIO_RESOURCE_LIST
AdvanceRequirementsPtr(
IN PIO_RESOURCE_LIST pReq
);
BOOL
FindLogConf(
IN PVOID pList,
OUT PVOID *ppLogConf,
IN ULONG RegDataType,
IN ULONG ulTag,
OUT PULONG pulIndex
);
//
// private prototypes
//
BOOL
InitLogConfRes(
IN OUT PCM_FULL_RESOURCE_DESCRIPTOR pRes,
IN ULONG ulPriority,
IN ULONG ulTag
);
BOOL
InitLogConfReq(
IN OUT PIO_RESOURCE_LIST pReq,
IN ULONG ulPriority,
IN ULONG ulTag
);
BOOL
InitReqList(
IN OUT PIO_RESOURCE_REQUIREMENTS_LIST pReqList,
IN ULONG ulReqSize
);
ULONG
GetFreeLogConfTag(
IN ULONG RegDataType,
IN LPBYTE pList
);
ULONG
LC_RES_TAG(
IN PCM_FULL_RESOURCE_DESCRIPTOR pRes
);
ULONG
LC_REQ_TAG(
IN PIO_RESOURCE_LIST pReq
);
ULONG
LC_RES_PRIORITY(
IN PCM_FULL_RESOURCE_DESCRIPTOR pRes
);
ULONG
LC_REQ_PRIORITY(
IN PIO_RESOURCE_LIST pReq
);
BYTE
CmToNtPriority(
IN ULONG CmPriority
);
ULONG
NtToCmPriority(
IN BYTE NtPriority
);
BOOL
MigrateObsoleteDetectionInfo(
IN LPWSTR pszDeviceID,
IN HKEY hLogConfKey
);
//
// global data
//
CONFIGRET
PNP_AddEmptyLogConf(
IN handle_t hBinding,
IN LPWSTR pDeviceID,
IN ULONG ulPriority,
OUT PULONG pulTag,
IN ULONG ulFlags
)
/*++
Routine Description:
This the server-side of an RPC remote call. This routine adds
an empty logical configuration.
Arguments:
hBinding Not used.
pDeviceID Null-terminated device instance id string.
ulPriority Priority for new log conf.
pulTag Returns tag that identifies which log config this is.
ulFlags Describes type of log conf to add.
Return Value:
If the specified device instance is valid, it returns CR_SUCCESS,
otherwise it returns CR_ error code.
--*/
{
CONFIGRET Status = CR_SUCCESS;
HKEY hKey = NULL;
WCHAR szValueName[64];
LPBYTE pList = NULL, pLogConf = NULL, pTemp = NULL, pNext = NULL;
ULONG Index = 0, ulListSize = 0, ulAddListSize = 0, ulSize = 0;
ULONG RegDataType = 0;
UNREFERENCED_PARAMETER(hBinding);
//------------------------------------------------------------------
// NOTE: The log confs are stored in priority order in the registry.
// The BOOT, ALLOC, and FORCED config types are stored in a registry
// value name of the format XxxConfig and the BASIC, FILTERED, and
// OVERRIDE configs are stored in a registr value name of the format
// XxxConfigVector. XxxConfig values contain the actual resource
// description (REG_RESOURCE_LIST, CM_RESOURCE_LIST) while
// XxxConfigVector values contain a list of resource requirements
// (REG_RESOURCE_REQUIREMENTS_LIST, IO_RESOURCE_REQUIREMENTS_LIST).
//
// The policy for using the log conf and res des APIs is:
// - BOOT, ALLOC, and FORCED are defined to only have one log conf.
// You can add additional log confs, but only the first (highest
// priority log conf will ever be used internally).
// - Although callers always specify a complete XXX_RESOURCE type
// structure for the data when adding resource descriptors to
// a log conf, I will ignore the resource specific portion of
// the XXX_DES structure for FILTERED, BASIC, and OVERRIDE.
// Likewise I will ignore any XXX_RANGE structures for ALLOC,
// BOOT or FORCED log config types.
//------------------------------------------------------------------
try {
//
// make sure original caller didn't specify root devnode
//
if (IsRootDeviceID(pDeviceID)) {
Status = CR_INVALID_DEVNODE;
goto Clean0;
}
//
// open a key to the device's LogConf subkey
//
Status = OpenLogConfKey(pDeviceID, &hKey);
if (Status != CR_SUCCESS) {
goto Clean0;
}
MigrateObsoleteDetectionInfo(pDeviceID, hKey);
//
// Retrieve log conf data from the registry
//
Status = GetLogConfData(hKey, ulFlags & LOG_CONF_BITS,
&RegDataType, szValueName,
&pList, &ulListSize);
//-----------------------------------------------------------
// Specified log conf type contains Resource Data only
//-----------------------------------------------------------
if (RegDataType == REG_RESOURCE_LIST) {
if (Status != CR_SUCCESS || ulListSize == 0) {
//
// If this is the first log conf of this type, create a new
// log conf list structure with a single empty log conf entry
//
PCM_RESOURCE_LIST pResList = NULL;
Status = CR_SUCCESS;
ulListSize = sizeof(CM_RESOURCE_LIST) -
sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
pList = malloc(ulListSize);
if (pList == NULL) {
Status = CR_OUT_OF_MEMORY;
goto Clean0;
}
//
// initialize the config list header info
//
*pulTag = 0;
memset(pList, 0, ulListSize);
pResList = (PCM_RESOURCE_LIST)pList;
pResList->Count = 1;
InitLogConfRes(&pResList->List[0], ulPriority, *pulTag);
} else {
//
// There is already at least one log conf of this type, so add
// a new empty log conf to the log conf list (in priority order)
//
PCM_RESOURCE_LIST pResList = (PCM_RESOURCE_LIST)pList;
PCM_FULL_RESOURCE_DESCRIPTOR pRes = (PCM_FULL_RESOURCE_DESCRIPTOR)pLogConf;
//
// verify there is room for another log conf
//
if (pResList->Count >= MAX_LOG_CONF-1) {
Status = CR_NO_MORE_LOG_CONF;
goto Clean0;
}
*pulTag = GetFreeLogConfTag(RegDataType, pList);
if (*pulTag == MAX_LOGCONF_TAG) {
Status = CR_NO_MORE_LOG_CONF; // no more available log confs
goto Clean0;
}
//
// realloc the existing log conf list structs to hold another
// log conf
//
ulAddListSize = sizeof(CM_FULL_RESOURCE_DESCRIPTOR) -
sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
pResList = (PCM_RESOURCE_LIST)realloc(pResList,
ulListSize + ulAddListSize);
if (pResList == NULL) {
Status = CR_OUT_OF_MEMORY;
goto Clean0;
}
pList = (LPBYTE)pResList;
//
// walk the Resource data looking for where the new log conf
// fits in the list of log confs in terms of priority.
//
pRes = (PCM_FULL_RESOURCE_DESCRIPTOR)(&pResList->List[0]); // first lc
Index = 0;
while (Index < pResList->Count) {
if ((LC_RES_PRIORITY(pRes) > ulPriority) ||
((LC_RES_PRIORITY(pRes) == ulPriority) &&
((ulFlags & PRIORITY_BIT) == PRIORITY_EQUAL_FIRST))) {
break; // this is the spot
}
pRes = AdvanceResourcePtr(pRes); // next lc
Index++;
}
if (Index != pResList->Count) {
//
// we're going to insert the new log conf somewhere besides
// at the end, so move any remaining log confs down one
// spot in the list to make room for the new log conf at
// this spot
//
ulSize = ulListSize - ((DWORD)pRes - (DWORD)pResList);
pTemp = malloc(ulSize);
if (pTemp == NULL) {
Status = CR_OUT_OF_MEMORY;
goto Clean0;
}
pNext = (LPBYTE)((LPBYTE)pRes + ulAddListSize);
memcpy(pTemp, pRes, ulSize); // save in temp buffer
memcpy(pNext, pTemp, ulSize); // copy to next lc
}
//
// initialize the new empty log config
//
pResList->Count++;
InitLogConfRes(pRes, ulPriority, *pulTag);
}
}
//-----------------------------------------------------------
// Specified log conf type contains requirements data only
//-----------------------------------------------------------
else if (RegDataType == REG_RESOURCE_REQUIREMENTS_LIST) {
if (Status != CR_SUCCESS || ulListSize == 0) {
//
// If this is the first log conf of this type, create a new
// log conf list structure with a single empty log conf entry
//
PIO_RESOURCE_REQUIREMENTS_LIST pReqList = NULL;
Status = CR_SUCCESS;
ulListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) -
sizeof(IO_RESOURCE_DESCRIPTOR);
pList = malloc(ulListSize);
if (pList == NULL) {
Status = CR_OUT_OF_MEMORY;
goto Clean0;
}
//
// initialize the config list header info
//
*pulTag = 0;
memset(pList, 0, ulListSize);
pReqList = (PIO_RESOURCE_REQUIREMENTS_LIST)pList;
InitReqList(pReqList, ulListSize);
pReqList->AlternativeLists = 1;
InitLogConfReq(&pReqList->List[0], ulPriority, *pulTag);
} else {
//
// There is already at least one log conf of this type, so add
// a new empty log conf to the log conf list (in priority order)
//
PIO_RESOURCE_REQUIREMENTS_LIST pReqList = (PIO_RESOURCE_REQUIREMENTS_LIST)pList;
PIO_RESOURCE_LIST pReq = (PIO_RESOURCE_LIST)pLogConf;
//
// verify there is room for another log conf
//
if (pReqList->AlternativeLists >= MAX_LOG_CONF-1) {
Status = CR_NO_MORE_LOG_CONF;
goto Clean0;
}
*pulTag = GetFreeLogConfTag(RegDataType, pList);
if (*pulTag == MAX_LOGCONF_TAG) {
Status = CR_NO_MORE_LOG_CONF; // no more available log confs
goto Clean0;
}
//
// realloc the existing log conf list structs to hold another
// log conf
//
ulAddListSize = sizeof(IO_RESOURCE_LIST) -
sizeof(IO_RESOURCE_DESCRIPTOR);
pReqList = (PIO_RESOURCE_REQUIREMENTS_LIST)realloc(pReqList,
ulListSize + ulAddListSize);
if (pReqList == NULL) {
Status = CR_OUT_OF_MEMORY;
goto Clean0;
}
pList = (LPBYTE)pReqList;
//
// walk the pReqList struct (it contains priority value), looking
// for where the new log conf fits in the list of log confs in
// terms of priority.
//
pReq = (PIO_RESOURCE_LIST)(&pReqList->List[0]); // first lc
Index = 0;
while (Index < pReqList->AlternativeLists) {
if ((LC_REQ_PRIORITY(pReq) > ulPriority) ||
((LC_REQ_PRIORITY(pReq) == ulPriority) &&
((ulFlags & PRIORITY_BIT) == PRIORITY_EQUAL_FIRST))) {
break; // this is the spot
}
pReq = AdvanceRequirementsPtr(pReq); // next lc
Index++;
}
if (Index != pReqList->AlternativeLists) {
//
// we're going to insert the new log conf somewhere besides
// at the end, so move any remaining log confs down one
// spot in the list to make room for the new log conf at
// this spot
//
ulSize = ulListSize - ((DWORD)pReq - (DWORD)pReqList);
pTemp = malloc(ulSize);
if (pTemp == NULL) {
Status = CR_OUT_OF_MEMORY;
goto Clean0;
}
pNext = (LPBYTE)((LPBYTE)pReq + ulAddListSize);
memcpy(pTemp, pReq, ulSize); // save in temp buffer
memcpy(pNext, pTemp, ulSize); // copy to next lc
}
//
// initialize the new empty log config
//
InitLogConfReq(pReq, ulPriority, *pulTag);
pReqList->AlternativeLists++;
pReqList->ListSize = ulListSize + ulAddListSize;
}
} else {
Status = CR_FAILURE;
goto Clean0;
}
//
// Write out the new/updated log conf list to the registry
//
if (RegSetValueEx(hKey, szValueName, 0, RegDataType,
pList, ulListSize + ulAddListSize)
!= ERROR_SUCCESS) {
Status = CR_REGISTRY_ERROR;
goto Clean0;
}
Clean0:
;
} except(EXCEPTION_EXECUTE_HANDLER) {
Status = CR_FAILURE;
}
if (hKey != NULL) {
RegCloseKey(hKey);
}
if (pList != NULL) {
free(pList);
}
if (pTemp != NULL) {
free(pTemp);
}
return Status;
} // PNP_AddEmptyLogConf
CONFIGRET
PNP_FreeLogConf(
IN handle_t hBinding,
IN LPWSTR pDeviceID,
IN ULONG ulType,
IN ULONG ulTag,
IN ULONG ulFlags
)
/*++
Routine Description:
This the server-side of an RPC remote call. This routine frees a
logical configuration.
Arguments:
hBinding Not used.
pDeviceID Null-terminated device instance id string.
ulType Identifies which type of log conf is requested.
ulTag Identifies which log conf from the specified type
of log conf we want.
ulFlags Not used.
Return Value:
If the specified device instance is valid, it returns CR_SUCCESS,
otherwise it returns CR_ error code.
--*/
{
CONFIGRET Status = CR_SUCCESS;
HKEY hKey = NULL;
WCHAR szValueName[64];
LPBYTE pList = NULL, pLogConf = NULL, pTemp = NULL, pNext = NULL;
ULONG RegDataType = 0, ulIndex = 0, ulListSize = 0, ulSize = 0;
UNREFERENCED_PARAMETER(hBinding);
UNREFERENCED_PARAMETER(ulFlags);
try {
//
// make sure original caller didn't specify root devnode (this
// can't happen but Win95 does the check anyway)
//
if (IsRootDeviceID(pDeviceID)) {
Status = CR_INVALID_DEVNODE;
goto Clean0;
}
//
// Validate the specified tag
//
if (ulTag >= MAX_LOGCONF_TAG) {
Status = CR_INVALID_LOG_CONF;
goto Clean0;
}
//
// open a key to the device's LogConf subkey
//
Status = OpenLogConfKey(pDeviceID, &hKey);
if (Status != CR_SUCCESS) {
//
// if the device id or LogConf subkey is not in registry,
// that's okay, by definition the log conf is freed since it
// doesn't exist
//
goto Clean0;
}
//
// Retrieve log conf data from the registry
//
Status = GetLogConfData(hKey, ulType,
&RegDataType, szValueName,
&pList, &ulListSize);
if (Status != CR_SUCCESS) {
Status = CR_INVALID_LOG_CONF;
goto Clean0;
}
//
// If the log conf to free is the one and only log conf of this
// type then delete the corresponding registry values
//
if ((RegDataType == REG_RESOURCE_LIST &&
((PCM_RESOURCE_LIST)pList)->Count <= 1) ||
(RegDataType == REG_RESOURCE_REQUIREMENTS_LIST &&
((PIO_RESOURCE_REQUIREMENTS_LIST)pList)->AlternativeLists <= 1)) {
RegDeleteValue(hKey, szValueName);
goto Clean0;
}
//
// There are other log confs besides the one to delete, so I'll
// have to remove the log conf from the data structs and resave
// to the registry
//
//
// Seek to the log conf that matches the log conf tag
//
if (!FindLogConf(pList, &pLogConf, RegDataType, ulTag, &ulIndex)) {
Status = CR_INVALID_LOG_CONF;
goto Clean0;
}
//
// Specified log conf type contains Resource Data only
//
if (RegDataType == REG_RESOURCE_LIST) {
PCM_RESOURCE_LIST pResList = (PCM_RESOURCE_LIST)pList;
PCM_FULL_RESOURCE_DESCRIPTOR pRes = (PCM_FULL_RESOURCE_DESCRIPTOR)pLogConf;
if (ulIndex == pResList->Count-1) {
//
// If deleting the last log conf in the list, just truncate it
//
ulListSize = (ULONG)pRes - (ULONG)pResList;
} else {
//
// Shift remaining log confs (after the log conf to be deleted)
// up in the list, writing over the log conf to be deleted
//
pNext = (LPBYTE)AdvanceResourcePtr(pRes);
ulSize = ulListSize - ((DWORD)pNext - (DWORD)pResList);
pTemp = malloc(ulSize);
if (pTemp == NULL) {
Status = CR_OUT_OF_MEMORY;
goto Clean0;
}
memcpy(pTemp, pNext, ulSize); // save in temp buffer
memcpy(pRes, pTemp, ulSize); // copy to deleted lc
ulListSize -= ((DWORD)pNext - (DWORD)pRes);
}
//
// update the log conf list header
//
pResList->Count--;
}
//
// Specified log conf type contains requirements data only
//
else if (RegDataType == REG_RESOURCE_REQUIREMENTS_LIST) {
PIO_RESOURCE_REQUIREMENTS_LIST pReqList = (PIO_RESOURCE_REQUIREMENTS_LIST)pList;
PIO_RESOURCE_LIST pReq = (PIO_RESOURCE_LIST)pLogConf;
if (ulIndex == pReqList->AlternativeLists-1) {
//
// If deleting the last log conf in the list, just truncate it
//
ulListSize = (ULONG)pReq - (ULONG)pReqList;
}
else {
//
// Shift remaining log confs (after the log conf to be deleted)
// up in the list, writing over the log conf to be deleted
//
pNext = (LPBYTE)AdvanceRequirementsPtr(pReq);
ulSize = ulListSize - ((DWORD)pNext - (DWORD)pReqList);
pTemp = malloc(ulSize);
if (pTemp == NULL) {
Status = CR_OUT_OF_MEMORY;
goto Clean0;
}
memcpy(pTemp, pNext, ulSize); // save in temp buffer
memcpy(pReq, pTemp, ulSize); // copy to deleted lc
ulListSize -= ((DWORD)pNext - (DWORD)pReq);
}
//
// update the log conf list header
//
pReqList->AlternativeLists--;
pReqList->ListSize = ulListSize;
}
//
// Write out the updated log conf list to the registry
//
if (RegSetValueEx(hKey, szValueName, 0, RegDataType, pList,
ulListSize) != ERROR_SUCCESS) {
Status = CR_REGISTRY_ERROR;
goto Clean0;
}
Clean0:
;
} except(EXCEPTION_EXECUTE_HANDLER) {
Status = CR_FAILURE;
}
if (hKey != NULL) {
RegCloseKey(hKey);
}
if (pList != NULL) {
free(pList);
}
if (pTemp != NULL) {
free(pTemp);
}
return Status;
} // PNP_FreeLogConf
CONFIGRET
PNP_GetFirstLogConf(
IN handle_t hBinding,
IN LPWSTR pDeviceID,
IN ULONG ulType,
OUT PULONG pulTag,
IN ULONG ulFlags
)
/*++
Routine Description:
This the server-side of an RPC remote call. This routine finds the
first log conf of this type for this devnode.
Arguments:
hBinding Not used.
pDeviceID Null-terminated device instance id string.
ulType Describes the type of log conf to find.
pulTag Returns tag that identifies which log config this is.
ulFlags Not used.
Return Value:
If the specified device instance is valid, it returns CR_SUCCESS,
otherwise it returns CR_ error code.
--*/
{
CONFIGRET Status = CR_SUCCESS;
HKEY hKey = NULL;
LPBYTE pList = NULL;
WCHAR szValueName[64];
ULONG RegDataType = 0, ulListSize = 0;
UNREFERENCED_PARAMETER(hBinding);
UNREFERENCED_PARAMETER(ulFlags);
try {
//
// Initialize output parameters
//
*pulTag = MAX_LOGCONF_TAG;
//
// open a key to the device's LogConf subkey. If the device id is not
// in the registry, the devnode doesn't exist and therefore neither
// does the log conf
//
Status = OpenLogConfKey(pDeviceID, &hKey);
if (Status != CR_SUCCESS) {
Status = CR_NO_MORE_LOG_CONF;
goto Clean0;
}
//
// Migrate any log conf data that might have been written to
// registry by NT 4.0 Beta I code.
//
MigrateObsoleteDetectionInfo(pDeviceID, hKey);
//
// Retrieve log conf data from the registry
//
Status = GetLogConfData(hKey, ulType,
&RegDataType, szValueName,
&pList, &ulListSize);
if (Status != CR_SUCCESS) {
Status = CR_NO_MORE_LOG_CONF;
goto Clean0;
}
//
// Specified log conf type contains Resource Data only
//
if (RegDataType == REG_RESOURCE_LIST) {
//
// retrieve log conf tag value
//
*pulTag = LC_RES_TAG(&((PCM_RESOURCE_LIST)pList)->List[0]);
}
//
// Specified log conf type contains requirements data only
//
else if (RegDataType == REG_RESOURCE_REQUIREMENTS_LIST) {
//
// retreive log conf tag value
//
*pulTag = LC_REQ_TAG(&((PIO_RESOURCE_REQUIREMENTS_LIST)pList)->List[0]);
}
Clean0:
;
} except(EXCEPTION_EXECUTE_HANDLER) {
Status = CR_FAILURE;
}
if (hKey != NULL) {
RegCloseKey(hKey);
}
if (pList != NULL) {
free(pList);
}
return Status;
} // PNP_GetFirstLogConf
CONFIGRET
PNP_GetNextLogConf(
IN handle_t hBinding,
IN LPWSTR pDeviceID,
IN ULONG ulType,
IN ULONG ulCurrentTag,
OUT PULONG pulNextTag,
IN ULONG ulFlags
)
/*++
Routine Description:
This the server-side of an RPC remote call. This routine finds the
next log conf of this type for this devnode.
Arguments:
hBinding Not used.
pDeviceID Null-terminated device instance id string.
ulType Specifies what type of log conf to retrieve.
ulCurrent Specifies current log conf in the enumeration.
pulNext Returns next log conf of this type for this device id.
ulFlags Not used.
Return Value:
If the specified device instance is valid, it returns CR_SUCCESS,
otherwise it returns CR_ error code.
--*/
{
CONFIGRET Status = CR_SUCCESS;
HKEY hKey = NULL;
WCHAR szValueName[64];
ULONG RegDataType = 0, ulListSize = 0, ulIndex = 0;
LPBYTE pList = NULL, pLogConf = NULL;
UNREFERENCED_PARAMETER(hBinding);
UNREFERENCED_PARAMETER(ulFlags);
try {
//
// Initialize output parameters
//
*pulNextTag = MAX_LOGCONF_TAG;
//
// open a key to the device's LogConf subkey. If the device id is not
// in the registry, the devnode doesn't exist and therefore neither
// does the log conf
//
Status = OpenLogConfKey(pDeviceID, &hKey);
if (Status != CR_SUCCESS) {
Status = CR_INVALID_LOG_CONF;
goto Clean0;
}
//
// Retrieve log conf data from the registry
//
Status = GetLogConfData(hKey, ulType,
&RegDataType, szValueName,
&pList, &ulListSize);
if (Status != CR_SUCCESS) {
Status = CR_NO_MORE_LOG_CONF;
goto Clean0;
}
//
// Seek to the log conf that matches the "current" tag
//
if (!FindLogConf(pList, &pLogConf, RegDataType, ulCurrentTag, &ulIndex)) {
Status = CR_INVALID_LOG_CONF;
goto Clean0;
}
//
// Specified log conf type contains Resource Data only
//
if (RegDataType == REG_RESOURCE_LIST) {
PCM_RESOURCE_LIST pResList = (PCM_RESOURCE_LIST)pList;
PCM_FULL_RESOURCE_DESCRIPTOR pRes = (PCM_FULL_RESOURCE_DESCRIPTOR)pLogConf;
//
// Is the "current" log conf the last log conf?
//
if (ulIndex == pResList->Count - 1) {
Status = CR_NO_MORE_LOG_CONF;
goto Clean0;
}
//
// Skip to the "next" log conf and return the tag for that log conf
//
pRes = AdvanceResourcePtr(pRes); // next lc
*pulNextTag = LC_RES_TAG(pRes);
}
//
// Specified log conf type contains requirements data only
//
else if (RegDataType == REG_RESOURCE_REQUIREMENTS_LIST) {
PIO_RESOURCE_REQUIREMENTS_LIST pReqList = (PIO_RESOURCE_REQUIREMENTS_LIST)pList;
PIO_RESOURCE_LIST pReq = (PIO_RESOURCE_LIST)pLogConf;
//
// Is the "current" log conf the last log conf?
//
if (ulIndex == pReqList->AlternativeLists - 1) {
Status = CR_NO_MORE_LOG_CONF;
goto Clean0;
}
//
// Skip to the "next" log conf and return the tag for that log conf
//
pReq = AdvanceRequirementsPtr(pReq); // next lc
*pulNextTag = LC_REQ_TAG(pReq);
}
Clean0:
;
} except(EXCEPTION_EXECUTE_HANDLER) {
Status = CR_FAILURE;
}
if (hKey != NULL) {
RegCloseKey(hKey);
}
if (pList != NULL) {
free(pList);
}
return Status;
} // PNP_GetNextLogConf
//------------------------------------------------------------------------
// Private Utility Routines
//------------------------------------------------------------------------
CONFIGRET
GetLogConfData(
IN HKEY hKey,
IN ULONG ulLogConfType,
OUT PULONG pulRegDataType,
OUT LPWSTR pszValueName,
OUT LPBYTE *ppBuffer,
OUT PULONG pulBufferSize
)
{
switch (ulLogConfType) {
//
// BOOT, ALLOC, FORCED only have a Config value
//
case BOOT_LOG_CONF:
lstrcpy(pszValueName, pszRegValueBootConfig);
*pulRegDataType = REG_RESOURCE_LIST;
break;
case ALLOC_LOG_CONF:
lstrcpy(pszValueName, pszRegValueAllocConfig);
*pulRegDataType = REG_RESOURCE_LIST;
break;
case FORCED_LOG_CONF:
lstrcpy(pszValueName, pszRegValueForcedConfig);
*pulRegDataType = REG_RESOURCE_LIST;
break;
//
// FILTERED, BASIC, OVERRIDE only have a Vector value
//
case FILTERED_LOG_CONF:
lstrcpy(pszValueName, pszRegValueFilteredVector);
*pulRegDataType = REG_RESOURCE_REQUIREMENTS_LIST;
break;
case BASIC_LOG_CONF:
lstrcpy(pszValueName, pszRegValueBasicVector);
*pulRegDataType = REG_RESOURCE_REQUIREMENTS_LIST;
break;
case OVERRIDE_LOG_CONF:
lstrcpy(pszValueName, pszRegValueOverrideVector);
*pulRegDataType = REG_RESOURCE_REQUIREMENTS_LIST;
break;
default:
return CR_FAILURE;
}
//
// retrieve the Log Conf registry data
//
if (RegQueryValueEx(hKey, pszValueName, NULL, NULL, NULL,
pulBufferSize) != ERROR_SUCCESS) {
return CR_INVALID_LOG_CONF;
}
*ppBuffer = malloc(*pulBufferSize);
if (*ppBuffer == NULL) {
return CR_OUT_OF_MEMORY;
}
if (RegQueryValueEx(hKey, pszValueName, NULL, NULL,
(LPBYTE)*ppBuffer, pulBufferSize) != ERROR_SUCCESS) {
return CR_INVALID_LOG_CONF;
}
return CR_SUCCESS;
} // GetLogConfData
PCM_FULL_RESOURCE_DESCRIPTOR
AdvanceResourcePtr(
IN PCM_FULL_RESOURCE_DESCRIPTOR pRes
)
{
// Given a resource pointer, this routine advances to the beginning
// of the next resource and returns a pointer to it. I assume that
// at least one more resource exists in the resource list.
LPBYTE p = NULL;
ULONG LastResIndex = 0;
if (pRes == NULL) {
return NULL;
}
//
// account for the size of the CM_FULL_RESOURCE_DESCRIPTOR
// (includes the header plus a single imbedded
// CM_PARTIAL_RESOURCE_DESCRIPTOR struct)
//
p = (LPBYTE)pRes + sizeof(CM_FULL_RESOURCE_DESCRIPTOR);
//
// account for any resource descriptors in addition to the single
// imbedded one I've already accounted for (if there aren't any,
// then I'll end up subtracting off the extra imbedded descriptor
// from the previous step)
//
p += (pRes->PartialResourceList.Count - 1) *
sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
//
// finally, account for any extra device specific data at the end of
// the last partial resource descriptor (if any)
//
if (pRes->PartialResourceList.Count > 0) {
LastResIndex = pRes->PartialResourceList.Count - 1;
if (pRes->PartialResourceList.PartialDescriptors[LastResIndex].Type ==
CmResourceTypeDeviceSpecific) {
p += pRes->PartialResourceList.PartialDescriptors[LastResIndex].
u.DeviceSpecificData.DataSize;
}
}
return (PCM_FULL_RESOURCE_DESCRIPTOR)p;
} // AdvanceResourcePtr
PIO_RESOURCE_LIST
AdvanceRequirementsPtr(
IN PIO_RESOURCE_LIST pReq
)
{
LPBYTE p = NULL;
if (pReq == NULL) {
return NULL;
}
//
// account for the size of the IO_RESOURCE_LIST (includes header plus
// a single imbedded IO_RESOURCE_DESCRIPTOR struct)
//
p = (LPBYTE)pReq + sizeof(IO_RESOURCE_LIST);
//
// account for any requirements descriptors in addition to the single
// imbedded one I've already accounted for (if there aren't any,
// then I'll end up subtracting off the extra imbedded descriptor
// from the previous step)
//
p += (pReq->Count - 1) * sizeof(IO_RESOURCE_DESCRIPTOR);
return (PIO_RESOURCE_LIST)p;
} // AdvanceRequirementsPtr
BOOL
FindLogConf(
IN LPBYTE pList,
OUT LPBYTE *ppLogConf,
IN ULONG RegDataType,
IN ULONG ulTag,
OUT PULONG pulIndex
)
{
ULONG Index = 0, i = 0;
//
// Input data is a Resource List
//
if (RegDataType == REG_RESOURCE_LIST) {
PCM_RESOURCE_LIST pResList = (PCM_RESOURCE_LIST)pList;
PCM_FULL_RESOURCE_DESCRIPTOR pRes = NULL;
//
// seek to the log conf that matches the log conf tag
// Req first.
//
pRes = (PCM_FULL_RESOURCE_DESCRIPTOR)(&pResList->List[0]); // first lc
while ((Index < pResList->Count) &&
(ulTag != LC_RES_TAG(pRes))) {
Index++;
if (Index < pResList->Count) {
pRes = AdvanceResourcePtr(pRes); // next lc
}
}
if (Index >= pResList->Count) {
*ppLogConf = NULL;
return FALSE; // tag not found
}
//
// return index if specified
//
if (pulIndex) {
*pulIndex = Index;
}
*ppLogConf = (LPBYTE)pRes;
}
//
// Input data is a Requirments List
//
else if (RegDataType == REG_RESOURCE_REQUIREMENTS_LIST) {
PIO_RESOURCE_REQUIREMENTS_LIST pReqList = (PIO_RESOURCE_REQUIREMENTS_LIST)pList;
PIO_RESOURCE_LIST pReq = NULL;
//
// seek to the log conf that matches the log conf tag
// Req first.
//
pReq = (PIO_RESOURCE_LIST)(&pReqList->List[0]); // first lc
while ((Index < pReqList->AlternativeLists) &&
(ulTag != LC_REQ_TAG(pReq))) {
Index++;
if (Index < pReqList->AlternativeLists) {
pReq = AdvanceRequirementsPtr(pReq); // next lc
}
}
if (Index >= pReqList->AlternativeLists) {
*ppLogConf = NULL;
return FALSE; // tag not found
}
//
// return index if specified
//
if (pulIndex) {
*pulIndex = Index;
}
*ppLogConf = (LPBYTE)pReq;
} else {
return FALSE;
}
return TRUE;
} // FindLogConf
BOOL
InitLogConfRes(
IN OUT PCM_FULL_RESOURCE_DESCRIPTOR pRes,
IN ULONG ulPriority,
IN ULONG ulTag
)
{
pRes->InterfaceType = Isa; // BUGBUG
pRes->BusNumber = 0; // BUGBUG
pRes->PartialResourceList.Version = 1;
pRes->PartialResourceList.Revision =
(USHORT)MAKEWORD(ulTag, CmToNtPriority(ulPriority));
pRes->PartialResourceList.Count = 0;
return TRUE;
} // InitLogConfRes
BOOL
InitLogConfReq(
IN OUT PIO_RESOURCE_LIST pReq,
IN ULONG ulPriority,
IN ULONG ulTag
)
{
pReq->Version = 1;
pReq->Revision = (USHORT)MAKEWORD(ulTag, CmToNtPriority(ulPriority));
pReq->Count = 0;
return TRUE;
} // InitLogConfReq
BOOL
InitReqList(
IN OUT PIO_RESOURCE_REQUIREMENTS_LIST pReqList,
IN ULONG ulReqSize
)
{
pReqList->ListSize = ulReqSize;
pReqList->InterfaceType = Isa; // BUGBUG
pReqList->BusNumber = 0; // BUGBUG
pReqList->SlotNumber = 0; // BUGBUG
pReqList->Reserved[0] = 0;
pReqList->Reserved[1] = 0;
pReqList->Reserved[2] = 0;
pReqList->AlternativeLists = 0;
return TRUE;
} // InitReqList
ULONG
GetFreeLogConfTag(
IN ULONG RegDataType,
IN LPBYTE pList
)
{
ULONG ulTag = 0, i = 0;
//
// Input data is a Resource List
//
if (RegDataType == REG_RESOURCE_LIST) {
PCM_RESOURCE_LIST pResList = (PCM_RESOURCE_LIST)pList;
PCM_FULL_RESOURCE_DESCRIPTOR pRes = NULL;
//
// find an unused log conf tag value
//
while (ulTag < MAX_LOGCONF_TAG) {
for (i = 0; i < pResList->Count; i++) { // check each rd
if (i == 0) {
pRes = (PCM_FULL_RESOURCE_DESCRIPTOR)(&pResList->List[0]);
} else {
pRes = AdvanceResourcePtr(pRes); // next lc
}
if (ulTag == LC_RES_TAG(pRes)) {
goto NextResTag; // match, try next tag
}
}
break; // made it thru whole list without a hit, use this tag
NextResTag:
ulTag++;
}
}
//
// Input data is a Requirments List
//
else if (RegDataType == REG_RESOURCE_REQUIREMENTS_LIST) {
PIO_RESOURCE_REQUIREMENTS_LIST pReqList = (PIO_RESOURCE_REQUIREMENTS_LIST)pList;
PIO_RESOURCE_LIST pReq = NULL;
//
// find an unused log conf tag value
//
while (ulTag < MAX_LOGCONF_TAG) {
for (i = 0; i < pReqList->AlternativeLists; i++) { // check each rd
if (i == 0) {
pReq = (PIO_RESOURCE_LIST)(&pReqList->List[0]); // first lc
} else {
pReq = AdvanceRequirementsPtr(pReq); // next lc
}
if (ulTag == LC_REQ_TAG(pReq)) {
goto NextReqTag; // match, try next tag
}
}
break; // made it thru whole list without a hit, use this tag
NextReqTag:
ulTag++;
}
} else {
ulTag = MAX_LOGCONF_TAG;
}
return ulTag;
} // GetFreeLogConfTag
ULONG
LC_RES_TAG(
IN PCM_FULL_RESOURCE_DESCRIPTOR pRes
)
{
//
// Abstract the notion of where the tag value is stored
//
if (pRes != NULL) {
return (ULONG)LOBYTE(pRes->PartialResourceList.Revision);
} else {
return MAX_LOGCONF_TAG;
}
} // LC_RES_TAG
ULONG
LC_REQ_TAG(
IN PIO_RESOURCE_LIST pReq
)
{
//
// Abstract the notion of where the tag value is stored
//
if (pReq != NULL) {
return (ULONG)LOBYTE(pReq->Revision);
} else {
return MAX_LOGCONF_TAG;
}
} // LC_REQ_TAG
ULONG
LC_RES_PRIORITY(
IN PCM_FULL_RESOURCE_DESCRIPTOR pRes
)
{
//
// Abstract the notion of where the priority value is stored
//
if (pRes != NULL) {
return NtToCmPriority(HIBYTE(pRes->PartialResourceList.Revision));
} else {
return 0;
}
} // LC_RES_PRIORITY
ULONG
LC_REQ_PRIORITY(
IN PIO_RESOURCE_LIST pReq
)
{
//
// Abstract the notion of where the priority value is stored
//
if (pReq != NULL) {
return NtToCmPriority(HIBYTE(pReq->Revision));
} else {
return 0;
}
} // LC_REQ_PRIORITY
BYTE
CmToNtPriority(
IN ULONG CmPriority
)
{
switch (CmPriority) {
case LCPRI_FORCECONFIG:
return NT_FORCECONFIG;
case LCPRI_BOOTCONFIG:
return NT_BOOTCONFIG;
case LCPRI_DESIRED:
return NT_DESIRED;
case LCPRI_NORMAL:
return NT_NORMAL;
case LCPRI_LASTBESTCONFIG:
return NT_LASTBESTCONFIG;
case LCPRI_SUBOPTIMAL:
return NT_SUBOPTIMAL;
case LCPRI_LASTSOFTCONFIG:
return NT_LASTSOFTCONFIG;
case LCPRI_RESTART:
return NT_RESTART;
case LCPRI_REBOOT:
return NT_REBOOT;
case LCPRI_POWEROFF:
return NT_POWEROFF;
case LCPRI_HARDRECONFIG:
return NT_HARDRECONFIG;
case LCPRI_HARDWIRED:
return NT_HARDWIRED;
case LCPRI_IMPOSSIBLE:
return NT_IMPOSSIBLE;
case LCPRI_DISABLED:
return NT_DISABLED;
default:
return NT_NORMAL;
}
} // CmToNtPriority
ULONG
NtToCmPriority(
IN BYTE NtPriority
)
{
switch (NtPriority) {
case NT_FORCECONFIG:
return LCPRI_FORCECONFIG;
case NT_BOOTCONFIG:
return LCPRI_BOOTCONFIG;
case NT_DESIRED:
return LCPRI_DESIRED;
case NT_NORMAL:
return LCPRI_NORMAL;
case NT_LASTBESTCONFIG:
return LCPRI_LASTBESTCONFIG;
case NT_SUBOPTIMAL:
return LCPRI_SUBOPTIMAL;
case NT_LASTSOFTCONFIG:
return LCPRI_LASTSOFTCONFIG;
case NT_RESTART:
return LCPRI_RESTART;
case NT_REBOOT:
return LCPRI_REBOOT;
case NT_POWEROFF:
return LCPRI_POWEROFF;
case NT_HARDRECONFIG:
return LCPRI_HARDRECONFIG;
case NT_HARDWIRED:
return LCPRI_HARDWIRED;
case NT_IMPOSSIBLE:
return LCPRI_IMPOSSIBLE;
case NT_DISABLED:
return LCPRI_DISABLED;
default:
return LCPRI_NORMAL;
}
} // NtToCmPriority
BOOL
MigrateObsoleteDetectionInfo(
IN LPWSTR pszDeviceID,
IN HKEY hLogConfKey
)
{
LONG RegStatus = ERROR_SUCCESS;
WCHAR RegStr[MAX_PATH];
HKEY hKey = NULL;
ULONG ulSize = 0;
LPBYTE ptr = NULL;
PCM_RESOURCE_LIST pResList = NULL;
IO_RESOURCE_REQUIREMENTS_LIST ReqList;
PPrivate_Log_Conf pDetectData = NULL;
//
// First, delete any of the log conf pairs that aren't valid any more
//
RegDeleteValue(hLogConfKey, TEXT("BootConfigVector"));
RegDeleteValue(hLogConfKey, TEXT("AllocConfigVector"));
RegDeleteValue(hLogConfKey, TEXT("ForcedConfigVector"));
RegDeleteValue(hLogConfKey, TEXT("BasicConfig"));
RegDeleteValue(hLogConfKey, TEXT("FilteredConfig"));
RegDeleteValue(hLogConfKey, TEXT("OverrideConfig"));
//
// open the device instance key in the registry
//
wsprintf(RegStr, TEXT("%s\\%s"),
pszRegPathEnum,
pszDeviceID);
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, RegStr, 0,
KEY_READ | KEY_WRITE, &hKey) != ERROR_SUCCESS) {
goto Clean0; // nothing to migrate
}
//
// If there is already a boot log config value then we can't
// migrate any old detect info
//
RegStatus = RegQueryValueEx(hLogConfKey, pszRegValueBootConfig,
NULL, NULL, NULL, &ulSize);
if (RegStatus == ERROR_SUCCESS && ulSize > 0) {
goto Clean0; // can't migrate
}
//
// retrieve any old detect signature info
//
RegStatus = RegQueryValueEx(hKey, pszRegValueDetectSignature,
NULL, NULL, NULL, &ulSize);
if ((RegStatus != ERROR_SUCCESS) || (ulSize == 0)) {
goto Clean0; // nothing to migrate
}
pDetectData = (PPrivate_Log_Conf)malloc(ulSize);
if (pDetectData == NULL) {
goto Clean0; // insufficient memory
}
RegStatus = RegQueryValueEx(hKey, pszRegValueDetectSignature,
NULL, NULL, (LPBYTE)pDetectData, &ulSize);
if ((RegStatus != ERROR_SUCCESS) || (ulSize == 0)) {
goto Clean0; // nothing to migrate
}
//
// Create an empty boot log conf and add this class specific data
// to it
//
ulSize = pDetectData->LC_CS.CS_Header.CSD_SignatureLength +
pDetectData->LC_CS.CS_Header.CSD_LegacyDataSize +
sizeof(GUID);
pResList = malloc(sizeof(CM_RESOURCE_LIST) + ulSize);
if (pResList == NULL) {
goto Clean0; // insufficient memory
}
//
// initialize resource list
//
memset(pResList, 0, ulSize);
pResList->Count = 1;
pResList->List[0].InterfaceType = Isa; // BUGBUG
pResList->List[0].BusNumber = 0; // BUGBUG
pResList->List[0].PartialResourceList.Version = 1;
pResList->List[0].PartialResourceList.Revision =
(USHORT)pDetectData->LC_Priority;
pResList->List[0].PartialResourceList.Count = 1;
pResList->List[0].PartialResourceList.PartialDescriptors[0].Type =
CmResourceTypeDeviceSpecific;
pResList->List[0].PartialResourceList.PartialDescriptors[0].ShareDisposition =
CmResourceShareUndetermined;
pResList->List[0].PartialResourceList.PartialDescriptors[0].Flags =
(USHORT)pDetectData->LC_CS.CS_Header.CSD_Flags;
pResList->List[0].PartialResourceList.PartialDescriptors[0].
u.DeviceSpecificData.DataSize = ulSize;
pResList->List[0].PartialResourceList.PartialDescriptors[0].
u.DeviceSpecificData.Reserved1 =
pDetectData->LC_CS.CS_Header.CSD_LegacyDataSize;
pResList->List[0].PartialResourceList.PartialDescriptors[0].
u.DeviceSpecificData.Reserved2 =
pDetectData->LC_CS.CS_Header.CSD_SignatureLength;
//
// copy the legacy and class-specific signature data
//
ptr = (LPBYTE)(&pResList->List[0].PartialResourceList.PartialDescriptors[1]);
memcpy(ptr,
pDetectData->LC_CS.CS_Header.CSD_Signature +
pDetectData->LC_CS.CS_Header.CSD_LegacyDataOffset,
pDetectData->LC_CS.CS_Header.CSD_LegacyDataSize); // legacy data
ptr += pDetectData->LC_CS.CS_Header.CSD_LegacyDataSize;
memcpy(ptr,
pDetectData->LC_CS.CS_Header.CSD_Signature,
pDetectData->LC_CS.CS_Header.CSD_SignatureLength); // signature
ptr += pDetectData->LC_CS.CS_Header.CSD_SignatureLength;
memcpy(ptr,
&pDetectData->LC_CS.CS_Header.CSD_ClassGuid,
sizeof(GUID)); // GUID
//
// Write out the new/updated log conf list to the registry
//
RegSetValueEx(hLogConfKey, pszRegValueBootConfig, 0,
REG_RESOURCE_LIST, (LPBYTE)pResList,
ulSize + sizeof(CM_RESOURCE_LIST));
//
// Delete the old detect signature info
//
RegDeleteValue(hKey, pszRegValueDetectSignature);
Clean0:
if (hKey != NULL) {
RegCloseKey(hKey);
}
if (pDetectData != NULL) {
free(pDetectData);
}
if (pResList != NULL) {
free(pResList);
}
return TRUE;
} // MigrateObsoleteDetectionInfo