1476 lines
42 KiB
C
1476 lines
42 KiB
C
/*++
|
||
|
||
Copyright (c) 1995-2000 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
rlogconf.c
|
||
|
||
Abstract:
|
||
|
||
This module contains the server-side logical configuration APIs.
|
||
|
||
PNP_AddEmptyLogConf
|
||
PNP_FreeLogConf
|
||
PNP_GetFirstLogConf
|
||
PNP_GetNextLogConf
|
||
PNP_GetLogConfPriority
|
||
|
||
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 "umpnpi.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
|
||
);
|
||
|
||
//
|
||
// Prototypes from rresdes.c
|
||
//
|
||
|
||
BOOL
|
||
FindLogConf(
|
||
IN LPBYTE pList,
|
||
OUT LPBYTE *ppLogConf,
|
||
IN ULONG RegDataType,
|
||
IN ULONG ulTag
|
||
);
|
||
|
||
PIO_RESOURCE_DESCRIPTOR
|
||
AdvanceRequirementsDescriptorPtr(
|
||
IN PIO_RESOURCE_DESCRIPTOR pReqDesStart,
|
||
IN ULONG ulIncrement,
|
||
IN ULONG ulRemainingRanges,
|
||
OUT PULONG pulRangeCount
|
||
);
|
||
|
||
//
|
||
// private prototypes
|
||
//
|
||
|
||
BOOL
|
||
MigrateObsoleteDetectionInfo(
|
||
IN LPWSTR pszDeviceID,
|
||
IN HKEY hLogConfKey
|
||
);
|
||
|
||
|
||
//
|
||
// global data
|
||
//
|
||
extern HKEY ghEnumKey; // Key to HKLM\CCC\System\Enum - DO NOT MODIFY
|
||
|
||
|
||
|
||
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 RPC binding handle.
|
||
|
||
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;
|
||
ULONG Index = 0, ulListSize = 0, ulAddListSize = 0;
|
||
ULONG RegDataType = 0;
|
||
|
||
//------------------------------------------------------------------
|
||
// 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.
|
||
// - 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 {
|
||
//
|
||
// verify client access
|
||
//
|
||
if (!VerifyClientAccess(hBinding, &gLuidLoadDriverPrivilege)) {
|
||
Status = CR_ACCESS_DENIED;
|
||
goto Clean0;
|
||
}
|
||
|
||
//
|
||
// initialize output parameters
|
||
//
|
||
if (!ARGUMENT_PRESENT(pulTag)) {
|
||
Status = CR_INVALID_POINTER;
|
||
goto Clean0;
|
||
} else {
|
||
*pulTag = 0;
|
||
}
|
||
|
||
//
|
||
// validate parameters
|
||
//
|
||
if (INVALID_FLAGS(ulFlags, LOG_CONF_BITS | PRIORITY_BIT)) {
|
||
Status = CR_INVALID_FLAG;
|
||
goto Clean0;
|
||
}
|
||
|
||
//
|
||
// make sure original caller didn't specify root devnode
|
||
//
|
||
if (!IsLegalDeviceId(pDeviceID) || IsRootDeviceID(pDeviceID)) {
|
||
Status = CR_INVALID_DEVNODE;
|
||
goto Clean0;
|
||
}
|
||
|
||
//
|
||
// open a key to the device's LogConf subkey
|
||
//
|
||
Status = OpenLogConfKey(pDeviceID, ulFlags & LOG_CONF_BITS, &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) {
|
||
//
|
||
// This is the first log conf of this type: create a new
|
||
// log conf with an empty res des.
|
||
//
|
||
PCM_RESOURCE_LIST pResList = NULL;
|
||
|
||
Status = CR_SUCCESS;
|
||
ulListSize = sizeof(CM_RESOURCE_LIST) -
|
||
sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
|
||
|
||
pList = HeapAlloc(ghPnPHeap, HEAP_ZERO_MEMORY, ulListSize);
|
||
if (pList == NULL) {
|
||
Status = CR_OUT_OF_MEMORY;
|
||
goto Clean0;
|
||
}
|
||
|
||
//
|
||
// initialize the config list header info
|
||
//
|
||
pResList = (PCM_RESOURCE_LIST)pList;
|
||
pResList->Count = 1;
|
||
pResList->List[0].InterfaceType = InterfaceTypeUndefined;
|
||
pResList->List[0].BusNumber = 0;
|
||
pResList->List[0].PartialResourceList.Version = NT_RESLIST_VERSION;
|
||
pResList->List[0].PartialResourceList.Revision = NT_RESLIST_REVISION;
|
||
pResList->List[0].PartialResourceList.Count = 0;
|
||
|
||
} else {
|
||
//
|
||
// There is already at least one log conf of this type, so add
|
||
// a new empty log conf to the log conf list (priority ignored)
|
||
//
|
||
PCM_RESOURCE_LIST pResList = (PCM_RESOURCE_LIST)pList;
|
||
PCM_FULL_RESOURCE_DESCRIPTOR pRes = NULL;
|
||
|
||
//
|
||
// 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)HeapReAlloc(ghPnPHeap, 0, pResList,
|
||
ulListSize + ulAddListSize);
|
||
if (pResList == NULL) {
|
||
Status = CR_OUT_OF_MEMORY;
|
||
goto Clean0;
|
||
}
|
||
pList = (LPBYTE)pResList;
|
||
|
||
//
|
||
// Priorities are ignored for resource lists, so just add any
|
||
// subsequent log confs to the end (they will be ignored by the
|
||
// system anyway).
|
||
//
|
||
pRes = (PCM_FULL_RESOURCE_DESCRIPTOR)(&pResList->List[0]); // first lc
|
||
for (Index = 0; Index < pResList->Count; Index++) {
|
||
pRes = AdvanceResourcePtr(pRes); // next lc
|
||
}
|
||
|
||
//
|
||
// initialize the new empty log config
|
||
//
|
||
pResList->Count++;
|
||
pRes->InterfaceType = InterfaceTypeUndefined;
|
||
pRes->BusNumber = 0;
|
||
pRes->PartialResourceList.Version = NT_RESLIST_VERSION;
|
||
pRes->PartialResourceList.Revision = NT_RESLIST_REVISION;
|
||
pRes->PartialResourceList.Count = 0;
|
||
|
||
*pulTag = Index;
|
||
}
|
||
}
|
||
|
||
//-----------------------------------------------------------
|
||
// Specified log conf type contains requirements data only
|
||
//-----------------------------------------------------------
|
||
else if (RegDataType == REG_RESOURCE_REQUIREMENTS_LIST) {
|
||
|
||
if (Status != CR_SUCCESS || ulListSize == 0) {
|
||
//
|
||
// This is the first log conf of this type: create a new
|
||
// log conf (IO_RESOURCE_LIST) with a single res des
|
||
// (IO_RESOURCE_DESCRIPTOR) for the config data.
|
||
//
|
||
PIO_RESOURCE_REQUIREMENTS_LIST pReqList = NULL;
|
||
PIO_RESOURCE_LIST pReq = NULL;
|
||
|
||
Status = CR_SUCCESS;
|
||
ulListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST);
|
||
|
||
pReqList = HeapAlloc(ghPnPHeap, HEAP_ZERO_MEMORY, ulListSize);
|
||
if (pReqList == NULL) {
|
||
Status = CR_OUT_OF_MEMORY;
|
||
goto Clean0;
|
||
}
|
||
pList = (LPBYTE)pReqList;
|
||
|
||
//
|
||
// initialize the config list header info
|
||
//
|
||
// There's room for one IO_RESOURCE_DESCRIPTOR embedded in
|
||
// the IO_RESOURCE_LIST structure and by definition the first
|
||
// one is a ConfigData type descriptor (user-mode always
|
||
// specifies a priority value so we always have a ConfigData
|
||
// struct).
|
||
//
|
||
pReqList->ListSize = ulListSize;
|
||
pReqList->InterfaceType = InterfaceTypeUndefined;
|
||
pReqList->BusNumber = 0;
|
||
pReqList->SlotNumber = 0;
|
||
pReqList->AlternativeLists = 1;
|
||
|
||
pReq = (PIO_RESOURCE_LIST)(&pReqList->List[0]); // first lc
|
||
pReq->Version = NT_REQLIST_VERSION;
|
||
pReq->Revision = NT_REQLIST_REVISION;
|
||
pReq->Count = 1;
|
||
|
||
pReq->Descriptors[0].Option = IO_RESOURCE_PREFERRED;
|
||
pReq->Descriptors[0].Type = CmResourceTypeConfigData;
|
||
pReq->Descriptors[0].u.ConfigData.Priority = ulPriority;
|
||
|
||
} else {
|
||
//
|
||
// There is already at least one log conf of this type, so add
|
||
// a new empty log conf to the log conf list (always at the end)
|
||
//
|
||
PIO_RESOURCE_REQUIREMENTS_LIST pReqList = (PIO_RESOURCE_REQUIREMENTS_LIST)pList;
|
||
PIO_RESOURCE_LIST pReq = NULL;
|
||
|
||
//
|
||
// realloc the existing log conf list structs to hold another
|
||
// log conf
|
||
//
|
||
ulAddListSize = sizeof(IO_RESOURCE_LIST);
|
||
|
||
pReqList = (PIO_RESOURCE_REQUIREMENTS_LIST)HeapReAlloc(ghPnPHeap, 0, pReqList,
|
||
ulListSize + ulAddListSize);
|
||
if (pReqList == NULL) {
|
||
Status = CR_OUT_OF_MEMORY;
|
||
goto Clean0;
|
||
}
|
||
pList = (LPBYTE)pReqList;
|
||
|
||
//
|
||
// Skip past all the existing log confs to the new space at the
|
||
// end of the reallocated buffer.
|
||
//
|
||
pReq = (PIO_RESOURCE_LIST)(&pReqList->List[0]); // first lc
|
||
for (Index = 0; Index < pReqList->AlternativeLists; Index++) {
|
||
pReq = AdvanceRequirementsPtr(pReq); // next lc
|
||
}
|
||
|
||
//
|
||
// initialize the new empty log config (including the embedded
|
||
// ConfigData structure).
|
||
//
|
||
pReqList->AlternativeLists++;
|
||
pReqList->ListSize = ulListSize + ulAddListSize;
|
||
|
||
pReq->Version = NT_REQLIST_VERSION;
|
||
pReq->Revision = NT_REQLIST_REVISION;
|
||
pReq->Count = 1;
|
||
|
||
memset(&pReq->Descriptors[0], 0, sizeof(IO_RESOURCE_DESCRIPTOR));
|
||
pReq->Descriptors[0].Option = IO_RESOURCE_PREFERRED;
|
||
pReq->Descriptors[0].Type = CmResourceTypeConfigData;
|
||
pReq->Descriptors[0].u.ConfigData.Priority = ulPriority;
|
||
|
||
*pulTag = Index;
|
||
}
|
||
|
||
} 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:
|
||
NOTHING;
|
||
|
||
} except(EXCEPTION_EXECUTE_HANDLER) {
|
||
Status = CR_FAILURE;
|
||
}
|
||
|
||
if (hKey != NULL) {
|
||
RegCloseKey(hKey);
|
||
}
|
||
if (pList != NULL) {
|
||
HeapFree(ghPnPHeap, 0, pList);
|
||
}
|
||
|
||
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 RPC binding handle.
|
||
|
||
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, must be zero.
|
||
|
||
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, pTemp = NULL, pNext = NULL;
|
||
ULONG RegDataType = 0, Index = 0, ulListSize = 0, ulSize = 0;
|
||
|
||
try {
|
||
//
|
||
// verify client access
|
||
//
|
||
if (!VerifyClientAccess(hBinding, &gLuidLoadDriverPrivilege)) {
|
||
Status = CR_ACCESS_DENIED;
|
||
goto Clean0;
|
||
}
|
||
|
||
//
|
||
// validate parameters
|
||
//
|
||
if (INVALID_FLAGS(ulFlags, 0)) {
|
||
Status = CR_INVALID_FLAG;
|
||
goto Clean0;
|
||
}
|
||
|
||
//
|
||
// make sure original caller didn't specify root devnode (this
|
||
// can't happen but Win95 does the check anyway)
|
||
//
|
||
if (!IsLegalDeviceId(pDeviceID) || IsRootDeviceID(pDeviceID)) {
|
||
Status = CR_INVALID_DEVNODE;
|
||
goto Clean0;
|
||
}
|
||
|
||
//
|
||
// open a key to the device's LogConf subkey
|
||
//
|
||
Status = OpenLogConfKey(pDeviceID, ulType, &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)) {
|
||
|
||
KdPrintEx((DPFLTR_PNPMGR_ID,
|
||
DBGF_REGISTRY,
|
||
"PNP_FreeLogConf: Deleting Value %ws from Device %ws\r\n",
|
||
szValueName,
|
||
pDeviceID));
|
||
|
||
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
|
||
//
|
||
|
||
//-----------------------------------------------------------
|
||
// 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 = NULL;
|
||
|
||
if (ulTag >= pResList->Count) {
|
||
Status = CR_INVALID_LOG_CONF;
|
||
goto Clean0;
|
||
}
|
||
|
||
//
|
||
// skip to the log conf to be deleted
|
||
//
|
||
pRes = (PCM_FULL_RESOURCE_DESCRIPTOR)(&pResList->List[0]); // first lc
|
||
for (Index = 0; Index < ulTag; Index++) {
|
||
pRes = AdvanceResourcePtr(pRes); // next lc
|
||
}
|
||
|
||
if (ulTag == pResList->Count-1) {
|
||
//
|
||
// If deleting the last log conf in the list, just truncate it
|
||
//
|
||
ulListSize = (ULONG)((ULONG_PTR)pRes - (ULONG_PTR)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)((ULONG_PTR)pNext - (ULONG_PTR)pResList);
|
||
|
||
pTemp = HeapAlloc(ghPnPHeap, 0, 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)((ULONG_PTR)pNext - (ULONG_PTR)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 = NULL;
|
||
|
||
if (ulTag >= pReqList->AlternativeLists) {
|
||
Status = CR_INVALID_LOG_CONF;
|
||
goto Clean0;
|
||
}
|
||
|
||
//
|
||
// skip to the log conf to be deleted
|
||
//
|
||
pReq = (PIO_RESOURCE_LIST)(&pReqList->List[0]); // first lc
|
||
for (Index = 0; Index < ulTag; Index++) {
|
||
pReq = AdvanceRequirementsPtr(pReq); // next lc
|
||
}
|
||
|
||
//
|
||
// If there's any log confs after the log conf that will be deleted,
|
||
// then write them over the top of the log conf we're deleting and
|
||
// truncate any left over data.
|
||
//
|
||
pNext = (LPBYTE)AdvanceRequirementsPtr(pReq);
|
||
if (ulListSize > ((DWORD_PTR)pNext - (DWORD_PTR)pReqList)) {
|
||
|
||
ulSize = ulListSize - (DWORD)((ULONG_PTR)pNext - (ULONG_PTR)pReqList);
|
||
|
||
pTemp = HeapAlloc(ghPnPHeap, 0, 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)((ULONG_PTR)pNext - (ULONG_PTR)pReq);
|
||
|
||
} else {
|
||
//
|
||
// No log confs trailing the log conf to be deleted so just
|
||
// truncate it.
|
||
//
|
||
ulListSize = (ULONG)((ULONG_PTR)pReq - (ULONG_PTR)pReqList);
|
||
}
|
||
|
||
//
|
||
// 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:
|
||
NOTHING;
|
||
|
||
} except(EXCEPTION_EXECUTE_HANDLER) {
|
||
Status = CR_FAILURE;
|
||
}
|
||
|
||
if (hKey != NULL) {
|
||
RegCloseKey(hKey);
|
||
}
|
||
if (pList != NULL) {
|
||
HeapFree(ghPnPHeap, 0, pList);
|
||
}
|
||
if (pTemp != NULL) {
|
||
HeapFree(ghPnPHeap, 0, 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 RPC binding handle, 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 (but may specify LOG_CONF_BITS).
|
||
|
||
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);
|
||
|
||
try {
|
||
//
|
||
// Initialize output parameters. The index of the "first" lc will always
|
||
// be zero as long as at least one lc exists.
|
||
//
|
||
if (!ARGUMENT_PRESENT(pulTag)) {
|
||
Status = CR_INVALID_POINTER;
|
||
} else {
|
||
*pulTag = 0;
|
||
}
|
||
|
||
//
|
||
// validate parameters
|
||
//
|
||
if (INVALID_FLAGS(ulFlags, LOG_CONF_BITS)) {
|
||
Status = CR_INVALID_FLAG;
|
||
goto Clean0;
|
||
}
|
||
|
||
if (!IsLegalDeviceId(pDeviceID)) {
|
||
Status = CR_INVALID_DEVNODE;
|
||
goto Clean0;
|
||
}
|
||
|
||
//
|
||
// 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, ulType, &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) {
|
||
|
||
PCM_RESOURCE_LIST pResList = (PCM_RESOURCE_LIST)pList;
|
||
|
||
if (pResList->Count == 0) {
|
||
Status = CR_NO_MORE_LOG_CONF;
|
||
goto Clean0;
|
||
}
|
||
}
|
||
|
||
//
|
||
// 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;
|
||
|
||
if (pReqList->AlternativeLists == 0) {
|
||
Status = CR_NO_MORE_LOG_CONF;
|
||
goto Clean0;
|
||
}
|
||
}
|
||
|
||
Clean0:
|
||
NOTHING;
|
||
|
||
} except(EXCEPTION_EXECUTE_HANDLER) {
|
||
Status = CR_FAILURE;
|
||
}
|
||
|
||
if (hKey != NULL) {
|
||
RegCloseKey(hKey);
|
||
}
|
||
if (pList != NULL) {
|
||
HeapFree(ghPnPHeap, 0, 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 RPC binding handle, 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, must be zero.
|
||
|
||
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;
|
||
LPBYTE pList = NULL;
|
||
|
||
UNREFERENCED_PARAMETER(hBinding);
|
||
|
||
try {
|
||
//
|
||
// Initialize output parameters
|
||
//
|
||
if (!ARGUMENT_PRESENT(pulNextTag)) {
|
||
Status = CR_INVALID_POINTER;
|
||
goto Clean0;
|
||
} else {
|
||
*pulNextTag = 0;
|
||
}
|
||
|
||
//
|
||
// validate parameters
|
||
//
|
||
if (INVALID_FLAGS(ulFlags, 0)) {
|
||
Status = CR_INVALID_FLAG;
|
||
goto Clean0;
|
||
}
|
||
|
||
if (!IsLegalDeviceId(pDeviceID)) {
|
||
Status = CR_INVALID_DEVNODE;
|
||
goto Clean0;
|
||
}
|
||
|
||
//
|
||
// 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, ulType, &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;
|
||
}
|
||
|
||
//
|
||
// Specified log conf type contains Resource Data only
|
||
//
|
||
if (RegDataType == REG_RESOURCE_LIST) {
|
||
|
||
PCM_RESOURCE_LIST pResList = (PCM_RESOURCE_LIST)pList;
|
||
|
||
if (ulCurrentTag >= pResList->Count) {
|
||
Status = CR_INVALID_LOG_CONF;
|
||
goto Clean0;
|
||
}
|
||
|
||
//
|
||
// Is the "current" log conf the last log conf?
|
||
//
|
||
if (ulCurrentTag == pResList->Count - 1) {
|
||
Status = CR_NO_MORE_LOG_CONF;
|
||
goto Clean0;
|
||
}
|
||
}
|
||
|
||
//
|
||
// 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;
|
||
|
||
if (ulCurrentTag >= pReqList->AlternativeLists) {
|
||
Status = CR_INVALID_LOG_CONF;
|
||
goto Clean0;
|
||
}
|
||
|
||
//
|
||
// Is the "current" log conf the last log conf?
|
||
//
|
||
if (ulCurrentTag == pReqList->AlternativeLists - 1) {
|
||
Status = CR_NO_MORE_LOG_CONF;
|
||
goto Clean0;
|
||
}
|
||
}
|
||
|
||
//
|
||
// There's at least one more log conf, return the next index value
|
||
//
|
||
*pulNextTag = ulCurrentTag + 1;
|
||
|
||
Clean0:
|
||
NOTHING;
|
||
|
||
} except(EXCEPTION_EXECUTE_HANDLER) {
|
||
Status = CR_FAILURE;
|
||
}
|
||
|
||
if (hKey != NULL) {
|
||
RegCloseKey(hKey);
|
||
}
|
||
if (pList != NULL) {
|
||
HeapFree(ghPnPHeap, 0, pList);
|
||
}
|
||
|
||
return Status;
|
||
|
||
} // PNP_GetNextLogConf
|
||
|
||
|
||
|
||
CONFIGRET
|
||
PNP_GetLogConfPriority(
|
||
IN handle_t hBinding,
|
||
IN LPWSTR pDeviceID,
|
||
IN ULONG ulType,
|
||
IN ULONG ulTag,
|
||
OUT PULONG pPriority,
|
||
IN ULONG ulFlags
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This the server-side of an RPC remote call. This routine returns the
|
||
priority value assigned to the specified log config.
|
||
|
||
Arguments:
|
||
|
||
hBinding RPC binding handle, not used.
|
||
|
||
pDeviceID Null-terminated device instance id string.
|
||
|
||
ulType Specifies what type of log conf to retrieve priority for.
|
||
|
||
ulCurrent Specifies current log conf in the enumeration.
|
||
|
||
pulNext Returns priority value of specified log conf.
|
||
|
||
ulFlags Not used, must be zero.
|
||
|
||
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, index, count;
|
||
LPBYTE pList = NULL, pLogConf = NULL, pRD = NULL;
|
||
PIO_RESOURCE_REQUIREMENTS_LIST pReqList = NULL;
|
||
PIO_RESOURCE_LIST pReq = NULL;
|
||
PIO_RESOURCE_DESCRIPTOR pReqDes = NULL;
|
||
|
||
UNREFERENCED_PARAMETER(hBinding);
|
||
|
||
try {
|
||
//
|
||
// Initialize output parameters
|
||
//
|
||
if (!ARGUMENT_PRESENT(pPriority)) {
|
||
Status = CR_INVALID_POINTER;
|
||
goto Clean0;
|
||
} else {
|
||
*pPriority = 0;
|
||
}
|
||
|
||
//
|
||
// validate parameters
|
||
//
|
||
if (INVALID_FLAGS(ulFlags, 0)) {
|
||
Status = CR_INVALID_FLAG;
|
||
goto Clean0;
|
||
}
|
||
|
||
if (!IsLegalDeviceId(pDeviceID)) {
|
||
Status = CR_INVALID_DEVNODE;
|
||
goto Clean0;
|
||
}
|
||
|
||
//
|
||
// 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, ulType, &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_INVALID_LOG_CONF;
|
||
goto Clean0;
|
||
}
|
||
|
||
//
|
||
// Priority values are only stored in requirements lists
|
||
//
|
||
if (RegDataType != REG_RESOURCE_REQUIREMENTS_LIST) {
|
||
Status = CR_INVALID_LOG_CONF;
|
||
goto Clean0;
|
||
}
|
||
|
||
//
|
||
// Seek to the log conf that matches the log conf tag
|
||
//
|
||
if (!FindLogConf(pList, &pLogConf, RegDataType, ulTag)) {
|
||
Status = CR_NO_SUCH_VALUE;
|
||
goto Clean0;
|
||
}
|
||
|
||
//
|
||
// Seek to the ConfigData res des, if any.
|
||
//
|
||
pReq = (PIO_RESOURCE_LIST)pLogConf;
|
||
pReqDes = &pReq->Descriptors[0]; // first rd
|
||
|
||
index = 0;
|
||
count = 0;
|
||
while (index < pReq->Count && pReqDes != NULL &&
|
||
pReqDes->Type != CmResourceTypeConfigData) {
|
||
|
||
pReqDes = AdvanceRequirementsDescriptorPtr(pReqDes, 1, pReq->Count - index, &count);
|
||
index += count; // index of actual rd's in the struct
|
||
}
|
||
|
||
if (pReqDes == NULL || pReqDes->Type != CmResourceTypeConfigData) {
|
||
//
|
||
// No config data so we can't determine the priority.
|
||
//
|
||
Status = CR_NO_SUCH_VALUE;
|
||
goto Clean0;
|
||
|
||
}
|
||
|
||
*pPriority = pReqDes->u.ConfigData.Priority;
|
||
|
||
Clean0:
|
||
NOTHING;
|
||
|
||
} except(EXCEPTION_EXECUTE_HANDLER) {
|
||
Status = CR_FAILURE;
|
||
}
|
||
|
||
if (hKey != NULL) {
|
||
RegCloseKey(hKey);
|
||
}
|
||
if (pList != NULL) {
|
||
HeapFree(ghPnPHeap, 0, pList);
|
||
}
|
||
|
||
return Status;
|
||
|
||
} // PNP_GetLogConfPriority
|
||
|
||
|
||
|
||
|
||
//------------------------------------------------------------------------
|
||
// 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 = HeapAlloc(ghPnPHeap, 0, *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
|
||
MigrateObsoleteDetectionInfo(
|
||
IN LPWSTR pszDeviceID,
|
||
IN HKEY hLogConfKey
|
||
)
|
||
{
|
||
LONG RegStatus = ERROR_SUCCESS;
|
||
HKEY hKey = NULL;
|
||
ULONG ulSize = 0;
|
||
LPBYTE ptr = NULL;
|
||
PCM_RESOURCE_LIST pResList = NULL;
|
||
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
|
||
//
|
||
if (RegOpenKeyEx(ghEnumKey, pszDeviceID, 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)HeapAlloc(ghPnPHeap, 0, 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 = HeapAlloc(ghPnPHeap, HEAP_ZERO_MEMORY, sizeof(CM_RESOURCE_LIST) + ulSize);
|
||
|
||
if (pResList == NULL) {
|
||
goto Clean0; // insufficient memory
|
||
}
|
||
|
||
//
|
||
// initialize resource list
|
||
//
|
||
pResList->Count = 1;
|
||
pResList->List[0].InterfaceType = InterfaceTypeUndefined;
|
||
pResList->List[0].BusNumber = 0;
|
||
pResList->List[0].PartialResourceList.Version = NT_RESLIST_VERSION;
|
||
pResList->List[0].PartialResourceList.Revision = NT_RESLIST_REVISION;
|
||
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) {
|
||
HeapFree(ghPnPHeap, 0, pDetectData);
|
||
}
|
||
if (pResList != NULL) {
|
||
HeapFree(ghPnPHeap, 0, pResList);
|
||
}
|
||
|
||
return TRUE;
|
||
|
||
} // MigrateObsoleteDetectionInfo
|
||
|
||
|