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.
1512 lines
45 KiB
1512 lines
45 KiB
/*++
|
|
|
|
Copyright (c) Microsoft Corporation. All rights reserved.
|
|
|
|
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"
|
|
#pragma hdrstop
|
|
#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 "write" access
|
|
//
|
|
if (!VerifyClientAccess(hBinding,
|
|
PLUGPLAY_WRITE)) {
|
|
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, pList,
|
|
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, pList,
|
|
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 "write" access
|
|
//
|
|
if (!VerifyClientAccess(hBinding,
|
|
PLUGPLAY_WRITE)) {
|
|
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;
|
|
goto Clean0;
|
|
} 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;
|
|
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
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
|
|
switch (ulLogConfType) {
|
|
//
|
|
// BOOT, ALLOC, FORCED only have a Config value
|
|
//
|
|
case BOOT_LOG_CONF:
|
|
hr = StringCchCopyEx(pszValueName,
|
|
64, // as defined by callers of GetLogConfData
|
|
pszRegValueBootConfig,
|
|
NULL, NULL,
|
|
STRSAFE_NULL_ON_FAILURE);
|
|
ASSERT(SUCCEEDED(hr));
|
|
*pulRegDataType = REG_RESOURCE_LIST;
|
|
break;
|
|
|
|
case ALLOC_LOG_CONF:
|
|
hr = StringCchCopyEx(pszValueName,
|
|
64, // as defined by callers of GetLogConfData
|
|
pszRegValueAllocConfig,
|
|
NULL, NULL,
|
|
STRSAFE_NULL_ON_FAILURE);
|
|
ASSERT(SUCCEEDED(hr));
|
|
*pulRegDataType = REG_RESOURCE_LIST;
|
|
break;
|
|
|
|
case FORCED_LOG_CONF:
|
|
hr = StringCchCopyEx(pszValueName,
|
|
64, // as defined by callers of GetLogConfData
|
|
pszRegValueForcedConfig,
|
|
NULL, NULL,
|
|
STRSAFE_NULL_ON_FAILURE);
|
|
ASSERT(SUCCEEDED(hr));
|
|
*pulRegDataType = REG_RESOURCE_LIST;
|
|
break;
|
|
|
|
//
|
|
// FILTERED, BASIC, OVERRIDE only have a Vector value
|
|
//
|
|
case FILTERED_LOG_CONF:
|
|
hr = StringCchCopyEx(pszValueName,
|
|
64, // as defined by callers of GetLogConfData
|
|
pszRegValueFilteredVector,
|
|
NULL, NULL,
|
|
STRSAFE_NULL_ON_FAILURE);
|
|
ASSERT(SUCCEEDED(hr));
|
|
*pulRegDataType = REG_RESOURCE_REQUIREMENTS_LIST;
|
|
break;
|
|
|
|
case BASIC_LOG_CONF:
|
|
hr = StringCchCopyEx(pszValueName,
|
|
64, // as defined by callers of GetLogConfData
|
|
pszRegValueBasicVector,
|
|
NULL, NULL,
|
|
STRSAFE_NULL_ON_FAILURE);
|
|
ASSERT(SUCCEEDED(hr));
|
|
*pulRegDataType = REG_RESOURCE_REQUIREMENTS_LIST;
|
|
break;
|
|
|
|
case OVERRIDE_LOG_CONF:
|
|
hr = StringCchCopyEx(pszValueName,
|
|
64, // as defined by callers of GetLogConfData
|
|
pszRegValueOverrideVector,
|
|
NULL, NULL,
|
|
STRSAFE_NULL_ON_FAILURE);
|
|
ASSERT(SUCCEEDED(hr));
|
|
*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) {
|
|
HeapFree(ghPnPHeap, 0, *ppBuffer);
|
|
*ppBuffer = NULL;
|
|
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
|
|
|
|
|