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.
1962 lines
58 KiB
1962 lines
58 KiB
/*++
|
|
|
|
Copyright (c) Microsoft Corporation. All rights reserved.
|
|
|
|
Module Name:
|
|
|
|
resdes.c
|
|
|
|
Abstract:
|
|
|
|
This module contains the API routines that operate directly on resource
|
|
descriptions.
|
|
|
|
CM_Add_Res_Des
|
|
CM_Free_Res_Des
|
|
CM_Get_Next_Res_Des
|
|
CM_Get_Res_Des_Data
|
|
CM_Get_Res_Des_Data_Size
|
|
CM_Modify_Res_Des
|
|
CM_Detect_Resource_Conflict
|
|
CM_Free_Res_Des_Handle
|
|
|
|
Author:
|
|
|
|
Paula Tomlinson (paulat) 9-26-1995
|
|
|
|
Environment:
|
|
|
|
User mode only.
|
|
|
|
Revision History:
|
|
|
|
26-Sept-1995 paulat
|
|
|
|
Creation and initial implementation.
|
|
|
|
--*/
|
|
|
|
|
|
//
|
|
// includes
|
|
//
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
#include "cfgi.h"
|
|
|
|
|
|
//
|
|
// Private prototypes
|
|
//
|
|
CONFIGRET
|
|
CreateResDesHandle(
|
|
PRES_DES prdResDes,
|
|
DEVINST dnDevInst,
|
|
ULONG ulLogType,
|
|
ULONG ulLogTag,
|
|
ULONG ulResType,
|
|
ULONG ulResTag
|
|
);
|
|
|
|
BOOL
|
|
ValidateResDesHandle(
|
|
PPrivate_Res_Des_Handle pResDes
|
|
);
|
|
|
|
CONFIGRET
|
|
Get32bitResDesFrom64bitResDes(
|
|
IN RESOURCEID ResourceID,
|
|
IN PCVOID ResData64,
|
|
IN ULONG ResLen64,
|
|
OUT PVOID * ResData32,
|
|
OUT ULONG * ResLen32
|
|
);
|
|
|
|
CONFIGRET
|
|
Convert32bitResDesTo64bitResDes(
|
|
IN RESOURCEID ResourceID,
|
|
IN OUT PVOID ResData,
|
|
IN ULONG ResLen
|
|
);
|
|
|
|
CONFIGRET
|
|
Convert32bitResDesSizeTo64bitResDesSize(
|
|
IN RESOURCEID ResourceID,
|
|
IN OUT PULONG ResLen
|
|
);
|
|
|
|
//
|
|
// private prototypes from logconf.c
|
|
//
|
|
CONFIGRET
|
|
CreateLogConfHandle(
|
|
PLOG_CONF plcLogConf,
|
|
DEVINST dnDevInst,
|
|
ULONG ulLogType,
|
|
ULONG ulLogTag
|
|
);
|
|
|
|
BOOL
|
|
ValidateLogConfHandle(
|
|
PPrivate_Log_Conf_Handle pLogConf
|
|
);
|
|
|
|
|
|
|
|
|
|
CONFIGRET
|
|
CM_Add_Res_Des_Ex(
|
|
OUT PRES_DES prdResDes,
|
|
IN LOG_CONF lcLogConf,
|
|
IN RESOURCEID ResourceID,
|
|
IN PCVOID ResourceData,
|
|
IN ULONG ResourceLen,
|
|
IN ULONG ulFlags,
|
|
IN HMACHINE hMachine
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine adds a resource descriptor to a logical configuration.
|
|
|
|
Parameters:
|
|
|
|
prdResDes Address of a variable that receives a handle for the new
|
|
resource descriptor.
|
|
|
|
lcLogConf Supplies the handle of the logical configuration to which
|
|
the resource descriptor is added.
|
|
|
|
ResourceID Specifies the type of the resource. Can be one of the
|
|
ResType values defined in Section 2.1..
|
|
|
|
ResourceData Supplies the address of an IO_DES, MEM_DES, DMA_DES, or
|
|
IRQ_DES structure, depending on the given resource type.
|
|
|
|
ResourceLen Supplies the size, in bytes, of the structure pointed to
|
|
by ResourceData.
|
|
|
|
ulFlags Specifies the width of certain variable-size resource
|
|
descriptor structure fields, where applicable.
|
|
|
|
Currently, the following flags are defined:
|
|
|
|
CM_RESDES_WIDTH_32 or
|
|
CM_RESDES_WIDTH_64
|
|
|
|
If no flags are specified, the width of the variable-sized
|
|
resource data supplied is assumed to be that native to the
|
|
platform of the caller.
|
|
|
|
hMachine Machine handle returned from CM_Connect_Machine or NULL.
|
|
|
|
Return Value:
|
|
|
|
If the function succeeds, the return value is CR_SUCCESS.
|
|
If the function fails, the return value is one of the following:
|
|
CR_INVALID_LOG_CONF,
|
|
CR_INVALID_FLAG,
|
|
CR_INVALID_POINTER,
|
|
CR_INVALID_RESOURCE_ID,
|
|
CR_OUT_OF_MEMORY.
|
|
|
|
--*/
|
|
|
|
|
|
{
|
|
CONFIGRET Status = CR_SUCCESS;
|
|
DEVINST dnDevInst;
|
|
WCHAR pDeviceID [MAX_DEVICE_ID_LEN];
|
|
ULONG ulResTag = 0, ulLogTag, ulLogType,ulLen = MAX_DEVICE_ID_LEN;
|
|
PVOID hStringTable = NULL;
|
|
handle_t hBinding = NULL;
|
|
BOOL Success;
|
|
PVOID ResourceData32 = NULL;
|
|
ULONG ResourceLen32 = 0;
|
|
|
|
|
|
try {
|
|
//
|
|
// validate parameters
|
|
//
|
|
if (!ValidateLogConfHandle((PPrivate_Log_Conf_Handle)lcLogConf)) {
|
|
Status = CR_INVALID_LOG_CONF;
|
|
goto Clean0;
|
|
}
|
|
|
|
if (INVALID_FLAGS(ulFlags, CM_RESDES_WIDTH_BITS)) {
|
|
Status = CR_INVALID_FLAG;
|
|
goto Clean0;
|
|
}
|
|
|
|
if ((ulFlags & CM_RESDES_WIDTH_32) && (ulFlags & CM_RESDES_WIDTH_64)) {
|
|
Status = CR_INVALID_FLAG;
|
|
goto Clean0;
|
|
}
|
|
|
|
#ifdef _WIN64
|
|
if ((ulFlags & CM_RESDES_WIDTH_BITS) == CM_RESDES_WIDTH_DEFAULT) {
|
|
ulFlags |= CM_RESDES_WIDTH_64;
|
|
}
|
|
#endif // _WIN64
|
|
|
|
if (ulFlags & CM_RESDES_WIDTH_32) {
|
|
ulFlags &= ~CM_RESDES_WIDTH_BITS;
|
|
}
|
|
|
|
if (ResourceData == NULL || ResourceLen == 0) {
|
|
Status = CR_INVALID_POINTER;
|
|
goto Clean0;
|
|
}
|
|
|
|
#if 0
|
|
if (ResourceID > ResType_MAX && ResourceID != ResType_ClassSpecific) {
|
|
Status = CR_INVALID_RESOURCEID;
|
|
goto Clean0;
|
|
}
|
|
#endif
|
|
|
|
if (ResourceID == ResType_All) {
|
|
Status = CR_INVALID_RESOURCEID; // can't specify All on an add
|
|
}
|
|
|
|
//
|
|
// Initialize parameters
|
|
//
|
|
if (prdResDes != NULL) { // prdResDes is optional param
|
|
*prdResDes = 0;
|
|
}
|
|
|
|
//
|
|
// extract info from the log conf handle
|
|
//
|
|
dnDevInst = ((PPrivate_Log_Conf_Handle)lcLogConf)->LC_DevInst;
|
|
ulLogType = ((PPrivate_Log_Conf_Handle)lcLogConf)->LC_LogConfType;
|
|
ulLogTag = ((PPrivate_Log_Conf_Handle)lcLogConf)->LC_LogConfTag;
|
|
|
|
//
|
|
// setup rpc binding handle and string table handle
|
|
//
|
|
if (!PnPGetGlobalHandles(hMachine, &hStringTable, &hBinding)) {
|
|
Status = CR_FAILURE;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// Make sure the server can support the client's 64-bit resdes request.
|
|
// Only server versions 0x0501 and greater support CM_RESDES_WIDTH_64.
|
|
//
|
|
if (ulFlags & CM_RESDES_WIDTH_64) {
|
|
if (!CM_Is_Version_Available_Ex((WORD)0x0501,
|
|
hMachine)) {
|
|
//
|
|
// Server can only support 32-bit resdes. Have the client
|
|
// convert the caller's 64-bit resdes to a 32-bit resdes for the
|
|
// server.
|
|
//
|
|
ulFlags &= ~CM_RESDES_WIDTH_BITS;
|
|
|
|
Status = Get32bitResDesFrom64bitResDes(ResourceID,ResourceData,ResourceLen,&ResourceData32,&ResourceLen32);
|
|
if(Status != CR_SUCCESS) {
|
|
goto Clean0;
|
|
}
|
|
if(ResourceData32) {
|
|
ResourceData = ResourceData32;
|
|
ResourceLen = ResourceLen32;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// retreive device instance string that corresponds to dnDevInst
|
|
//
|
|
Success = pSetupStringTableStringFromIdEx(hStringTable, dnDevInst,pDeviceID,&ulLen);
|
|
if (Success == FALSE || INVALID_DEVINST(pDeviceID)) {
|
|
Status = CR_INVALID_LOG_CONF;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// Special privileges are no longer required by the server.
|
|
//
|
|
// Note that with previous versions of the PlugPlay RPC server,
|
|
// SE_LOAD_DRIVER_PRIVILEGE was required for this operation. We do not
|
|
// need to enable the privilege for local callers, since this version of
|
|
// CFGMGR32 should match a local version of UMPNPMGR that does not
|
|
// require the privilege. For remote calls, it's not always possible
|
|
// for us to enable the privilege anyways, since the client may not have
|
|
// the privilege on the local machine, but may as authenticated on the
|
|
// server. The server typically sees all privileges that a remote
|
|
// caller has as "enabled by default", so we are not required to enable
|
|
// the privilege here either.
|
|
//
|
|
|
|
RpcTryExcept {
|
|
//
|
|
// call rpc service entry point
|
|
//
|
|
Status = PNP_AddResDes(
|
|
hBinding, // rpc binding handle
|
|
pDeviceID, // device id string
|
|
ulLogTag, // log conf tag
|
|
ulLogType, // log conf type
|
|
ResourceID, // resource type
|
|
&ulResTag, // resource tag
|
|
(LPBYTE)ResourceData, // actual res des data
|
|
ResourceLen, // size in bytes of ResourceData
|
|
ulFlags); // currently zero
|
|
}
|
|
RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
|
|
KdPrintEx((DPFLTR_PNPMGR_ID,
|
|
DBGF_ERRORS,
|
|
"PNP_AddResDes caused an exception (%d)\n",
|
|
RpcExceptionCode()));
|
|
|
|
Status = MapRpcExceptionToCR(RpcExceptionCode());
|
|
}
|
|
RpcEndExcept
|
|
|
|
if ((Status == CR_SUCCESS) && (prdResDes != NULL)) {
|
|
|
|
Status = CreateResDesHandle(prdResDes,
|
|
dnDevInst,
|
|
ulLogType,
|
|
ulLogTag,
|
|
ResourceID,
|
|
ulResTag);
|
|
}
|
|
|
|
Clean0:
|
|
NOTHING;
|
|
|
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|
Status = CR_FAILURE;
|
|
}
|
|
|
|
if(ResourceData32) {
|
|
pSetupFree(ResourceData32);
|
|
}
|
|
|
|
return Status;
|
|
|
|
} // CM_Add_Res_Des_Ex
|
|
|
|
|
|
|
|
|
|
CONFIGRET
|
|
CM_Free_Res_Des_Ex(
|
|
OUT PRES_DES prdResDes,
|
|
IN RES_DES rdResDes,
|
|
IN ULONG ulFlags,
|
|
IN HMACHINE hMachine
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine destroys a resource descriptor. This API returns
|
|
CR_NO_MORE_RES_DES if rdResDes specifies the last resource descriptor.
|
|
|
|
Parameters:
|
|
|
|
prdResDes Supplies the address of the variable that receives the
|
|
handle of the previous resource descriptor. If rdResDes
|
|
is the handle of the first resource descriptor, this
|
|
address receives the handle of the logical configuration.
|
|
|
|
rdResDes Supplies the handle of the resource descriptor to be destroyed.
|
|
|
|
ulFlags Must be zero.
|
|
|
|
hMachine Machine handle returned from CM_Connect_Machine or NULL.
|
|
|
|
Return Value:
|
|
|
|
If the function succeeds, the return value is CR_SUCCESS.
|
|
If the function fails, the return value is one of the following:
|
|
CR_INVALID_FLAG,
|
|
CR_INVALID_POINTER,
|
|
CR_INVALID_RES_DES,
|
|
CR_NO_MORE_RES_DES.
|
|
|
|
--*/
|
|
|
|
{
|
|
CONFIGRET Status = CR_SUCCESS;
|
|
DEVINST dnDevInst;
|
|
WCHAR pDeviceID[MAX_DEVICE_ID_LEN];
|
|
ULONG ulLogType, ulLogTag, ulResType, ulResTag,ulLen=MAX_DEVICE_ID_LEN;
|
|
ULONG ulPreviousResType = 0, ulPreviousResTag = 0;
|
|
PVOID hStringTable = NULL;
|
|
handle_t hBinding = NULL;
|
|
BOOL Success;
|
|
|
|
|
|
try {
|
|
//
|
|
// validate parameters
|
|
//
|
|
if (!ValidateResDesHandle((PPrivate_Res_Des_Handle)rdResDes)) {
|
|
Status = CR_INVALID_RES_DES;
|
|
goto Clean0;
|
|
}
|
|
|
|
if (INVALID_FLAGS(ulFlags, 0)) {
|
|
Status = CR_INVALID_FLAG;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// Initialize parameters
|
|
//
|
|
if (prdResDes != NULL) { // optional parameter
|
|
*prdResDes = 0;
|
|
}
|
|
|
|
//
|
|
// extract info from the res des handle
|
|
//
|
|
dnDevInst = ((PPrivate_Res_Des_Handle)rdResDes)->RD_DevInst;
|
|
ulLogType = ((PPrivate_Res_Des_Handle)rdResDes)->RD_LogConfType;
|
|
ulLogTag = ((PPrivate_Res_Des_Handle)rdResDes)->RD_LogConfTag;
|
|
ulResType = ((PPrivate_Res_Des_Handle)rdResDes)->RD_ResourceType;
|
|
ulResTag = ((PPrivate_Res_Des_Handle)rdResDes)->RD_ResDesTag;
|
|
|
|
//
|
|
// setup rpc binding handle and string table handle
|
|
//
|
|
if (!PnPGetGlobalHandles(hMachine, &hStringTable, &hBinding)) {
|
|
Status = CR_FAILURE;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// retreive device instance string that corresponds to dnDevInst
|
|
//
|
|
Success = pSetupStringTableStringFromIdEx(hStringTable, dnDevInst,pDeviceID,&ulLen);
|
|
if (Success == FALSE || INVALID_DEVINST(pDeviceID)) {
|
|
Status = CR_INVALID_RES_DES;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// Special privileges are no longer required by the server.
|
|
//
|
|
// Note that with previous versions of the PlugPlay RPC server,
|
|
// SE_LOAD_DRIVER_PRIVILEGE was required for this operation. We do not
|
|
// need to enable the privilege for local callers, since this version of
|
|
// CFGMGR32 should match a local version of UMPNPMGR that does not
|
|
// require the privilege. For remote calls, it's not always possible
|
|
// for us to enable the privilege anyways, since the client may not have
|
|
// the privilege on the local machine, but may as authenticated on the
|
|
// server. The server typically sees all privileges that a remote
|
|
// caller has as "enabled by default", so we are not required to enable
|
|
// the privilege here either.
|
|
//
|
|
|
|
RpcTryExcept {
|
|
//
|
|
// call rpc service entry point
|
|
//
|
|
Status = PNP_FreeResDes(
|
|
hBinding, // rpc binding handle
|
|
pDeviceID, // device id string
|
|
ulLogTag, // log conf tag
|
|
ulLogType, // log conf type
|
|
ulResType, // resource type
|
|
ulResTag, // resource tag
|
|
&ulPreviousResType, // resource type of previous res des
|
|
&ulPreviousResTag, // tag of previous res des
|
|
ulFlags); // currently zero
|
|
}
|
|
RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
|
|
KdPrintEx((DPFLTR_PNPMGR_ID,
|
|
DBGF_ERRORS,
|
|
"PNP_FreeResDes caused an exception (%d)\n",
|
|
RpcExceptionCode()));
|
|
|
|
Status = MapRpcExceptionToCR(RpcExceptionCode());
|
|
}
|
|
RpcEndExcept
|
|
|
|
if ((Status != CR_SUCCESS) &&
|
|
(Status != CR_NO_MORE_RES_DES)) {
|
|
goto Clean0; // quit for any other error
|
|
}
|
|
|
|
//
|
|
// if prdResDes supplied, fill in with previous res des or
|
|
// the log conf info
|
|
//
|
|
if (prdResDes != NULL) {
|
|
//
|
|
// if the previous tag value is set to 0xFFFFFFFF, then
|
|
// there are no previous tages so return the log conf
|
|
// info instead
|
|
//
|
|
if (Status == CR_NO_MORE_RES_DES) {
|
|
|
|
CONFIGRET Status1;
|
|
|
|
Status1 = CreateLogConfHandle(prdResDes, dnDevInst,
|
|
ulLogType, ulLogTag);
|
|
|
|
if (Status1 != CR_SUCCESS) {
|
|
Status = Status1;
|
|
}
|
|
}
|
|
|
|
else {
|
|
//
|
|
// allocate a res des handle
|
|
//
|
|
Status = CreateResDesHandle(prdResDes, dnDevInst,
|
|
ulLogType, ulLogTag,
|
|
ulPreviousResType,
|
|
ulPreviousResTag);
|
|
}
|
|
}
|
|
|
|
|
|
Clean0:
|
|
NOTHING;
|
|
|
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|
Status = CR_FAILURE;
|
|
}
|
|
|
|
return Status;
|
|
|
|
} // CM_Free_Res_Des_Ex
|
|
|
|
|
|
|
|
CONFIGRET
|
|
CM_Get_Next_Res_Des_Ex(
|
|
OUT PRES_DES prdResDes,
|
|
IN RES_DES rdResDes,
|
|
IN RESOURCEID ForResource,
|
|
OUT PRESOURCEID pResourceID,
|
|
IN ULONG ulFlags,
|
|
IN HMACHINE hMachine
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine returns the handle of the next resource descriptor in
|
|
a logical configuration.
|
|
|
|
Parameters:
|
|
|
|
prdResDes Supplies the address of the variable that receives the
|
|
handle of the next resource descriptor.
|
|
|
|
rdResDes Supplies the handle of the current resource
|
|
descriptor or the handle of a logical configuration.
|
|
(Both are 32-bit numbers--Configuration Manager must can
|
|
distinguish between them.)
|
|
|
|
ForResource Specifies the type of the resource to retrieve. Can be
|
|
one of the ResType values listed in Section 2.1..
|
|
|
|
pResourceID Supplies the address of the variable that receives the
|
|
resource type, when ForResource specifies ResType_All.
|
|
(When ForResource is not ResType_All, this parameter can
|
|
be NULL.)
|
|
|
|
ulFlags Must be zero.
|
|
|
|
hMachine Machine handle returned from CM_Connect_Machine or NULL.
|
|
|
|
Return Value:
|
|
|
|
If the function succeeds, the return value is CR_SUCCESS.
|
|
If the function fails, the return value is one of the following:
|
|
CR_INVALID_LOG_CONF,
|
|
CR_INVALID_FLAG,
|
|
CR_INVALID_POINTER,
|
|
CR_INVALID_RES_DES,
|
|
CR_NO_MORE_RES_DES.
|
|
|
|
--*/
|
|
|
|
{
|
|
CONFIGRET Status = CR_SUCCESS;
|
|
DEVINST dnDevInst;
|
|
WCHAR pDeviceID [MAX_DEVICE_ID_LEN];
|
|
ULONG ulLogTag, ulLogType, ulResTag,ulLen = MAX_DEVICE_ID_LEN;
|
|
ULONG ulNextResType = 0, ulNextResTag = 0;
|
|
PVOID hStringTable = NULL;
|
|
handle_t hBinding = NULL;
|
|
BOOL Success;
|
|
|
|
|
|
try {
|
|
//
|
|
// validate parameters
|
|
//
|
|
if (prdResDes == NULL) {
|
|
Status = CR_INVALID_POINTER;
|
|
goto Clean0;
|
|
}
|
|
#if 0
|
|
if (ForResource > ResType_MAX &&
|
|
ForResource != ResType_ClassSpecific) {
|
|
|
|
Status = CR_INVALID_RESOURCEID;
|
|
goto Clean0;
|
|
}
|
|
#endif
|
|
if (ForResource == ResType_All && pResourceID == NULL) {
|
|
Status = CR_INVALID_POINTER;
|
|
goto Clean0;
|
|
}
|
|
|
|
if (INVALID_FLAGS(ulFlags, 0)) {
|
|
Status = CR_INVALID_FLAG;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// this handle could be a res des or a log conf, determine
|
|
// which and extract info handle
|
|
//
|
|
if (ValidateResDesHandle((PPrivate_Res_Des_Handle)rdResDes)) {
|
|
//
|
|
// it was a valid res des handle
|
|
//
|
|
dnDevInst = ((PPrivate_Res_Des_Handle)rdResDes)->RD_DevInst;
|
|
ulLogType = ((PPrivate_Res_Des_Handle)rdResDes)->RD_LogConfType;
|
|
ulLogTag = ((PPrivate_Res_Des_Handle)rdResDes)->RD_LogConfTag;
|
|
ulResTag = ((PPrivate_Res_Des_Handle)rdResDes)->RD_ResDesTag;
|
|
}
|
|
|
|
else if (ValidateLogConfHandle((PPrivate_Log_Conf_Handle)rdResDes)) {
|
|
//
|
|
// it was a valid log conf handle, so assume it's the first
|
|
// res des we want
|
|
//
|
|
dnDevInst = ((PPrivate_Log_Conf_Handle)rdResDes)->LC_DevInst;
|
|
ulLogType = ((PPrivate_Log_Conf_Handle)rdResDes)->LC_LogConfType;
|
|
ulLogTag = ((PPrivate_Log_Conf_Handle)rdResDes)->LC_LogConfTag;
|
|
ulResTag = MAX_RESDES_TAG;
|
|
}
|
|
|
|
else {
|
|
//
|
|
// it was neither a valid log conf nor a valid res des handle
|
|
//
|
|
Status = CR_INVALID_RES_DES;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// setup rpc binding handle and string table handle
|
|
//
|
|
if (!PnPGetGlobalHandles(hMachine, &hStringTable, &hBinding)) {
|
|
Status = CR_FAILURE;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// retreive device instance string that corresponds to dnDevInst
|
|
//
|
|
Success = pSetupStringTableStringFromIdEx(hStringTable, dnDevInst,pDeviceID,&ulLen);
|
|
if (Success == FALSE || INVALID_DEVINST(pDeviceID)) {
|
|
Status = CR_INVALID_LOG_CONF;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// No special privileges are required by the server
|
|
//
|
|
|
|
RpcTryExcept {
|
|
//
|
|
// call rpc service entry point
|
|
//
|
|
Status = PNP_GetNextResDes(
|
|
hBinding, // rpc binding handle
|
|
pDeviceID, // device id string
|
|
ulLogTag, // log conf tag
|
|
ulLogType, // log conf type
|
|
ForResource, // resource type
|
|
ulResTag, // resource tag
|
|
&ulNextResTag, // next res des of type ForResource
|
|
&ulNextResType, // type of next res des
|
|
ulFlags); // 32/64 bit data
|
|
}
|
|
RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
|
|
KdPrintEx((DPFLTR_PNPMGR_ID,
|
|
DBGF_ERRORS,
|
|
"PNP_GetNextResDes caused an exception (%d)\n",
|
|
RpcExceptionCode()));
|
|
|
|
Status = MapRpcExceptionToCR(RpcExceptionCode());
|
|
}
|
|
RpcEndExcept
|
|
|
|
if (Status != CR_SUCCESS) {
|
|
goto Clean0;
|
|
}
|
|
|
|
if (ForResource == ResType_All) {
|
|
*pResourceID = ulNextResType;
|
|
}
|
|
|
|
Status = CreateResDesHandle(prdResDes,
|
|
dnDevInst,
|
|
ulLogType,
|
|
ulLogTag,
|
|
ulNextResType,
|
|
ulNextResTag);
|
|
|
|
Clean0:
|
|
NOTHING;
|
|
|
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|
Status = CR_FAILURE;
|
|
}
|
|
|
|
return Status;
|
|
|
|
} // CM_Get_Next_Res_Des_Ex
|
|
|
|
|
|
|
|
CONFIGRET
|
|
CM_Get_Res_Des_Data_Ex(
|
|
IN RES_DES rdResDes,
|
|
OUT PVOID Buffer,
|
|
IN ULONG BufferLen,
|
|
IN ULONG ulFlags,
|
|
IN HMACHINE hMachine
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine copies the data from a specified resource descriptor
|
|
into a buffer. Use the CM_Get_Res_Des_Data_Size API to determine
|
|
the buffer size needed to receive the data. Alternately, set a
|
|
size that is at least as large as the maximum possible size of the
|
|
resource. If the size given is too small, the data is truncated and
|
|
the API returns CR_BUFFER_SMALL.
|
|
|
|
Parameters:
|
|
|
|
rdResDes Supplies the handle of the resource descriptor from which
|
|
data is to be copied.
|
|
|
|
Buffer Supplies the address of the buffer that receives the data.
|
|
|
|
BufferLen Supplies the size of the buffer, in bytes.
|
|
|
|
ulFlags Specifies the width of certain variable-size resource
|
|
descriptor structure fields, where applicable.
|
|
|
|
Currently, the following flags are defined:
|
|
|
|
CM_RESDES_WIDTH_32 or
|
|
CM_RESDES_WIDTH_64
|
|
|
|
If no flags are specified, the width of the variable-sized
|
|
resource data expected is assumed to be that native to the
|
|
platform of the caller.
|
|
|
|
hMachine Machine handle returned from CM_Connect_Machine or NULL.
|
|
|
|
Return Value:
|
|
|
|
If the function succeeds, the return value is CR_SUCCESS.
|
|
If the function fails, the return value is one of the following:
|
|
CR_INVALID_FLAG,
|
|
CR_INVALID_POINTER,
|
|
CR_INVALID_RES_DES,
|
|
CR_BUFFER_SMALL.
|
|
|
|
--*/
|
|
|
|
{
|
|
CONFIGRET Status = CR_SUCCESS;
|
|
DEVINST dnDevInst;
|
|
WCHAR pDeviceID [MAX_DEVICE_ID_LEN];
|
|
ULONG ulLogType, ulLogTag, ulResType, ulResTag,ulLen = MAX_DEVICE_ID_LEN;
|
|
PVOID hStringTable = NULL;
|
|
handle_t hBinding = NULL;
|
|
BOOL Success;
|
|
BOOL ConvertResDes = FALSE;
|
|
|
|
try {
|
|
//
|
|
// validate parameters
|
|
//
|
|
if (!ValidateResDesHandle((PPrivate_Res_Des_Handle)rdResDes)) {
|
|
Status = CR_INVALID_RES_DES;
|
|
goto Clean0;
|
|
}
|
|
|
|
if (Buffer == NULL || BufferLen == 0) {
|
|
Status = CR_INVALID_POINTER;
|
|
goto Clean0;
|
|
}
|
|
|
|
if (INVALID_FLAGS(ulFlags, CM_RESDES_WIDTH_BITS)) {
|
|
Status = CR_INVALID_FLAG;
|
|
goto Clean0;
|
|
}
|
|
|
|
if ((ulFlags & CM_RESDES_WIDTH_32) && (ulFlags & CM_RESDES_WIDTH_64)) {
|
|
Status = CR_INVALID_FLAG;
|
|
goto Clean0;
|
|
}
|
|
|
|
#ifdef _WIN64
|
|
if ((ulFlags & CM_RESDES_WIDTH_BITS) == CM_RESDES_WIDTH_DEFAULT) {
|
|
ulFlags |= CM_RESDES_WIDTH_64;
|
|
}
|
|
#endif // _WIN64
|
|
|
|
if (ulFlags & CM_RESDES_WIDTH_32) {
|
|
ulFlags &= ~CM_RESDES_WIDTH_BITS;
|
|
}
|
|
|
|
//
|
|
// extract info from the res des handle
|
|
//
|
|
dnDevInst = ((PPrivate_Res_Des_Handle)rdResDes)->RD_DevInst;
|
|
ulLogType = ((PPrivate_Res_Des_Handle)rdResDes)->RD_LogConfType;
|
|
ulLogTag = ((PPrivate_Res_Des_Handle)rdResDes)->RD_LogConfTag;
|
|
ulResType = ((PPrivate_Res_Des_Handle)rdResDes)->RD_ResourceType;
|
|
ulResTag = ((PPrivate_Res_Des_Handle)rdResDes)->RD_ResDesTag;
|
|
|
|
//
|
|
// setup rpc binding handle and string table handle
|
|
//
|
|
if (!PnPGetGlobalHandles(hMachine, &hStringTable, &hBinding)) {
|
|
Status = CR_FAILURE;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// Make sure the server can support the client's 64-bit resdes request.
|
|
// Only server versions 0x0501 and greater support CM_RESDES_WIDTH_64.
|
|
//
|
|
if (ulFlags & CM_RESDES_WIDTH_64) {
|
|
if (!CM_Is_Version_Available_Ex((WORD)0x0501,
|
|
hMachine)) {
|
|
//
|
|
// Client will only give us 32-bit resdes. Request a 32-bit
|
|
// resdes from the server, and we'll convert it to 64-bit here
|
|
// on the client.
|
|
//
|
|
ulFlags &= ~CM_RESDES_WIDTH_BITS;
|
|
ConvertResDes = TRUE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// retreive device instance string that corresponds to dnDevInst
|
|
//
|
|
Success = pSetupStringTableStringFromIdEx(hStringTable, dnDevInst,pDeviceID,&ulLen);
|
|
if (Success == FALSE || INVALID_DEVINST(pDeviceID)) {
|
|
Status = CR_INVALID_RES_DES;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// No special privileges are required by the server
|
|
//
|
|
|
|
RpcTryExcept {
|
|
//
|
|
// call rpc service entry point
|
|
//
|
|
Status = PNP_GetResDesData(
|
|
hBinding, // rpc binding handle
|
|
pDeviceID, // device id string
|
|
ulLogTag, // log conf tag
|
|
ulLogType, // log conf type
|
|
ulResType, // resource type
|
|
ulResTag, // resource tag
|
|
Buffer, // return res des data
|
|
BufferLen, // size in bytes of Buffer
|
|
ulFlags); // 32/64 bit data
|
|
}
|
|
RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
|
|
KdPrintEx((DPFLTR_PNPMGR_ID,
|
|
DBGF_ERRORS,
|
|
"PNP_GetResDesData caused an exception (%d)\n",
|
|
RpcExceptionCode()));
|
|
|
|
Status = MapRpcExceptionToCR(RpcExceptionCode());
|
|
}
|
|
RpcEndExcept
|
|
|
|
if((Status == CR_SUCCESS) && ConvertResDes) {
|
|
Status = Convert32bitResDesTo64bitResDes(ulResType,Buffer,BufferLen);
|
|
}
|
|
|
|
Clean0:
|
|
NOTHING;
|
|
|
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|
Status = CR_FAILURE;
|
|
}
|
|
|
|
return Status;
|
|
|
|
} // CM_Get_Res_Des_Data_Ex
|
|
|
|
|
|
|
|
CONFIGRET
|
|
CM_Get_Res_Des_Data_Size_Ex(
|
|
OUT PULONG pulSize,
|
|
IN RES_DES rdResDes,
|
|
IN ULONG ulFlags,
|
|
IN HMACHINE hMachine
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine retrieves the size of a resource descriptor, not
|
|
including the resource descriptor header.
|
|
|
|
Parameters:
|
|
|
|
pulSize Supplies the address of the variable that receives the
|
|
size, in bytes, of the resource descriptor data.
|
|
|
|
rdResDes Supplies the handle of the resource descriptor for which
|
|
to retrieve the size.
|
|
|
|
ulFlags Specifies the width of certain variable-size resource
|
|
descriptor structure fields, where applicable.
|
|
|
|
Currently, the following flags are defined:
|
|
|
|
CM_RESDES_WIDTH_32 or
|
|
CM_RESDES_WIDTH_64
|
|
|
|
If no flags are specified, the width of the variable-sized
|
|
resource data expected is assumed to be that native to the
|
|
platform of the caller.
|
|
|
|
hMachine Machine handle returned from CM_Connect_Machine or NULL.
|
|
|
|
Return Value:
|
|
|
|
If the function succeeds, the return value is CR_SUCCESS.
|
|
If the function fails, the return value is one of the following:
|
|
CR_INVALID_RES_DES,
|
|
CR_INVALID_FLAG,
|
|
CR_INVALID_POINTER.
|
|
|
|
--*/
|
|
|
|
{
|
|
CONFIGRET Status = CR_SUCCESS;
|
|
DEVINST dnDevInst;
|
|
WCHAR pDeviceID [MAX_DEVICE_ID_LEN];
|
|
ULONG ulLogType, ulLogTag, ulResType, ulResTag,ulLen = MAX_DEVICE_ID_LEN;
|
|
PVOID hStringTable = NULL;
|
|
handle_t hBinding = NULL;
|
|
BOOL Success;
|
|
BOOL ConvertResDesSize = FALSE;
|
|
|
|
|
|
try {
|
|
//
|
|
// validate parameters
|
|
//
|
|
if (!ValidateResDesHandle((PPrivate_Res_Des_Handle)rdResDes)) {
|
|
Status = CR_INVALID_RES_DES;
|
|
goto Clean0;
|
|
}
|
|
|
|
if (pulSize == NULL) {
|
|
Status = CR_INVALID_POINTER;
|
|
goto Clean0;
|
|
}
|
|
|
|
if (INVALID_FLAGS(ulFlags, CM_RESDES_WIDTH_BITS)) {
|
|
Status = CR_INVALID_FLAG;
|
|
goto Clean0;
|
|
}
|
|
|
|
if ((ulFlags & CM_RESDES_WIDTH_32) && (ulFlags & CM_RESDES_WIDTH_64)) {
|
|
Status = CR_INVALID_FLAG;
|
|
goto Clean0;
|
|
}
|
|
|
|
#ifdef _WIN64
|
|
if ((ulFlags & CM_RESDES_WIDTH_BITS) == CM_RESDES_WIDTH_DEFAULT) {
|
|
ulFlags |= CM_RESDES_WIDTH_64;
|
|
}
|
|
#endif // _WIN64
|
|
|
|
if (ulFlags & CM_RESDES_WIDTH_32) {
|
|
ulFlags &= ~CM_RESDES_WIDTH_BITS;
|
|
}
|
|
|
|
//
|
|
// Initialize output parameters
|
|
//
|
|
*pulSize = 0;
|
|
|
|
//
|
|
// extract info from the res des handle
|
|
//
|
|
dnDevInst = ((PPrivate_Res_Des_Handle)rdResDes)->RD_DevInst;
|
|
ulLogType = ((PPrivate_Res_Des_Handle)rdResDes)->RD_LogConfType;
|
|
ulLogTag = ((PPrivate_Res_Des_Handle)rdResDes)->RD_LogConfTag;
|
|
ulResType = ((PPrivate_Res_Des_Handle)rdResDes)->RD_ResourceType;
|
|
ulResTag = ((PPrivate_Res_Des_Handle)rdResDes)->RD_ResDesTag;
|
|
|
|
//
|
|
// setup rpc binding handle and string table handle
|
|
//
|
|
if (!PnPGetGlobalHandles(hMachine, &hStringTable, &hBinding)) {
|
|
Status = CR_FAILURE;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// Make sure the server can support the client's 64-bit resdes request.
|
|
// Only server versions 0x0501 and greater support CM_RESDES_WIDTH_64.
|
|
//
|
|
if (ulFlags & CM_RESDES_WIDTH_64) {
|
|
if (!CM_Is_Version_Available_Ex((WORD)0x0501,
|
|
hMachine)) {
|
|
//
|
|
// Server only supports 32-bit resdes. Request a 32-bit
|
|
// resdes size from the server, and we'll convert it to 64-bit here
|
|
// on the client.
|
|
//
|
|
ulFlags &= ~CM_RESDES_WIDTH_BITS;
|
|
ConvertResDesSize = TRUE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// retreive device instance string that corresponds to dnDevInst
|
|
//
|
|
Success = pSetupStringTableStringFromIdEx(hStringTable, dnDevInst,pDeviceID,&ulLen);
|
|
if (Success == FALSE || INVALID_DEVINST(pDeviceID)) {
|
|
Status = CR_INVALID_RES_DES;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// No special privileges are required by the server
|
|
//
|
|
|
|
RpcTryExcept {
|
|
//
|
|
// call rpc service entry point
|
|
//
|
|
Status = PNP_GetResDesDataSize(
|
|
hBinding, // rpc binding handle
|
|
pDeviceID, // device id string
|
|
ulLogTag, // log conf tag
|
|
ulLogType, // log conf type
|
|
ulResType, // resource type
|
|
ulResTag, // resource tag
|
|
pulSize, // returns size of res des data
|
|
ulFlags); // currently zero
|
|
}
|
|
RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
|
|
KdPrintEx((DPFLTR_PNPMGR_ID,
|
|
DBGF_ERRORS,
|
|
"PNP_GetResDesDataSize caused an exception (%d)\n",
|
|
RpcExceptionCode()));
|
|
|
|
Status = MapRpcExceptionToCR(RpcExceptionCode());
|
|
}
|
|
RpcEndExcept
|
|
|
|
if(Status == CR_SUCCESS) {
|
|
Status = Convert32bitResDesSizeTo64bitResDesSize(ulResType,pulSize);
|
|
}
|
|
|
|
Clean0:
|
|
NOTHING;
|
|
|
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|
Status = CR_FAILURE;
|
|
}
|
|
|
|
return Status;
|
|
|
|
} // CM_Get_Res_Des_Data_Size_Ex
|
|
|
|
|
|
|
|
CONFIGRET
|
|
CM_Modify_Res_Des_Ex(
|
|
OUT PRES_DES prdResDes,
|
|
IN RES_DES rdResDes,
|
|
IN RESOURCEID ResourceID,
|
|
IN PCVOID ResourceData,
|
|
IN ULONG ResourceLen,
|
|
IN ULONG ulFlags,
|
|
IN HMACHINE hMachine
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine modifies a resource descriptor. This API retrieves a
|
|
handle to the new resource descriptor. This may or may not be the
|
|
handle of the original resource descriptor. The original resource
|
|
descriptor handle is invalid after calling this API.
|
|
|
|
Parameters:
|
|
|
|
prdResDes Supplies the address of the variable that receives the
|
|
handle of the modified resource descriptor.
|
|
|
|
rdResDes Supplies the handle of the resource descriptor to be
|
|
modified.
|
|
|
|
ResourceID Specifies the type of resource to modify. Can be one
|
|
of the ResType values described in Section 2.1..
|
|
|
|
ResourceData Supplies the address of a resource data structure.
|
|
|
|
ResourceLen Supplies the size, in bytes, of the new resource data
|
|
structure. This size can be different from the size of
|
|
the original resource data.
|
|
|
|
ulFlags Specifies the width of certain variable-size resource
|
|
descriptor structure fields, where applicable.
|
|
|
|
Currently, the following flags are defined:
|
|
|
|
CM_RESDES_WIDTH_32 or
|
|
CM_RESDES_WIDTH_64
|
|
|
|
If no flags are specified, the width of the variable-sized
|
|
resource data supplied is assumed to be that native to the
|
|
platform of the caller.
|
|
|
|
hMachine Machine handle returned from CM_Connect_Machine or NULL.
|
|
|
|
Return Value:
|
|
|
|
If the function succeeds, the return value is CR_SUCCESS.
|
|
If the function fails, the return value is one of the following:
|
|
CR_INVALID_RES_DES,
|
|
CR_INVALID_FLAG,
|
|
CR_INVALID_POINTER,
|
|
CR_OUT_OF_MEMORY.
|
|
|
|
--*/
|
|
|
|
{
|
|
CONFIGRET Status = CR_SUCCESS;
|
|
DEVINST dnDevInst;
|
|
WCHAR pDeviceID [MAX_DEVICE_ID_LEN];
|
|
ULONG ulLogType, ulLogTag, ulResType, ulResTag,ulLen = MAX_DEVICE_ID_LEN;
|
|
PVOID hStringTable = NULL;
|
|
handle_t hBinding = NULL;
|
|
BOOL Success;
|
|
PVOID ResourceData32 = NULL;
|
|
ULONG ResourceLen32 = 0;
|
|
|
|
|
|
try {
|
|
//
|
|
// validate parameters
|
|
//
|
|
if (!ValidateResDesHandle((PPrivate_Res_Des_Handle)rdResDes)) {
|
|
Status = CR_INVALID_RES_DES;
|
|
goto Clean0;
|
|
}
|
|
|
|
if (prdResDes == NULL) {
|
|
Status = CR_INVALID_POINTER;
|
|
goto Clean0;
|
|
}
|
|
#if 0
|
|
if (ResourceID > ResType_MAX && ResourceID != ResType_ClassSpecific) {
|
|
Status = CR_INVALID_RESOURCEID;
|
|
goto Clean0;
|
|
}
|
|
#endif
|
|
if (ResourceData == NULL || ResourceLen == 0) {
|
|
Status = CR_INVALID_POINTER;
|
|
goto Clean0;
|
|
}
|
|
|
|
if (INVALID_FLAGS(ulFlags, CM_RESDES_WIDTH_BITS)) {
|
|
Status = CR_INVALID_FLAG;
|
|
goto Clean0;
|
|
}
|
|
|
|
if ((ulFlags & CM_RESDES_WIDTH_32) && (ulFlags & CM_RESDES_WIDTH_64)) {
|
|
Status = CR_INVALID_FLAG;
|
|
goto Clean0;
|
|
}
|
|
|
|
#ifdef _WIN64
|
|
if ((ulFlags & CM_RESDES_WIDTH_BITS) == CM_RESDES_WIDTH_DEFAULT) {
|
|
ulFlags |= CM_RESDES_WIDTH_64;
|
|
}
|
|
#endif // _WIN64
|
|
|
|
if (ulFlags & CM_RESDES_WIDTH_32) {
|
|
ulFlags &= ~CM_RESDES_WIDTH_BITS;
|
|
}
|
|
|
|
//
|
|
// initialize output parameters
|
|
//
|
|
*prdResDes = 0;
|
|
|
|
//
|
|
// extract info from the res des handle
|
|
//
|
|
dnDevInst = ((PPrivate_Res_Des_Handle)rdResDes)->RD_DevInst;
|
|
ulLogType = ((PPrivate_Res_Des_Handle)rdResDes)->RD_LogConfType;
|
|
ulLogTag = ((PPrivate_Res_Des_Handle)rdResDes)->RD_LogConfTag;
|
|
ulResType = ((PPrivate_Res_Des_Handle)rdResDes)->RD_ResourceType;
|
|
ulResTag = ((PPrivate_Res_Des_Handle)rdResDes)->RD_ResDesTag;
|
|
|
|
//
|
|
// setup rpc binding handle and string table handle
|
|
//
|
|
if (!PnPGetGlobalHandles(hMachine, &hStringTable, &hBinding)) {
|
|
Status = CR_FAILURE;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// Make sure the server can support the client's 64-bit resdes request.
|
|
// Only server versions 0x0501 and greater support CM_RESDES_WIDTH_64.
|
|
//
|
|
if (ulFlags & CM_RESDES_WIDTH_64) {
|
|
if (!CM_Is_Version_Available_Ex((WORD)0x0501,
|
|
hMachine)) {
|
|
//
|
|
// Server can only support 32-bit resdes. Have the client
|
|
// convert the caller's 64-bit resdes to a 32-bit resdes for the
|
|
// server.
|
|
//
|
|
ulFlags &= ~CM_RESDES_WIDTH_BITS;
|
|
|
|
Status = Get32bitResDesFrom64bitResDes(ResourceID,ResourceData,ResourceLen,&ResourceData32,&ResourceLen32);
|
|
if(Status != CR_SUCCESS) {
|
|
goto Clean0;
|
|
}
|
|
if(ResourceData32) {
|
|
ResourceData = ResourceData32;
|
|
ResourceLen = ResourceLen32;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// retreive device instance string that corresponds to dnDevInst
|
|
//
|
|
Success = pSetupStringTableStringFromIdEx(hStringTable, dnDevInst,pDeviceID,&ulLen);
|
|
if (Success == FALSE || INVALID_DEVINST(pDeviceID)) {
|
|
Status = CR_INVALID_LOG_CONF;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// Special privileges are no longer required by the server.
|
|
//
|
|
// Note that with previous versions of the PlugPlay RPC server,
|
|
// SE_LOAD_DRIVER_PRIVILEGE was required for this operation. We do not
|
|
// need to enable the privilege for local callers, since this version of
|
|
// CFGMGR32 should match a local version of UMPNPMGR that does not
|
|
// require the privilege. For remote calls, it's not always possible
|
|
// for us to enable the privilege anyways, since the client may not have
|
|
// the privilege on the local machine, but may as authenticated on the
|
|
// server. The server typically sees all privileges that a remote
|
|
// caller has as "enabled by default", so we are not required to enable
|
|
// the privilege here either.
|
|
//
|
|
|
|
RpcTryExcept {
|
|
//
|
|
// call rpc service entry point
|
|
//
|
|
Status = PNP_ModifyResDes(
|
|
hBinding, // rpc binding handle
|
|
pDeviceID, // device id string
|
|
ulLogTag, // log conf tag
|
|
ulLogType, // log conf type
|
|
ulResType, // current resource type
|
|
ResourceID, // new resource type
|
|
ulResTag, // resource tag
|
|
(LPBYTE)ResourceData, // actual res des data
|
|
ResourceLen, // size in bytes of ResourceData
|
|
ulFlags); // currently zero
|
|
}
|
|
RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
|
|
KdPrintEx((DPFLTR_PNPMGR_ID,
|
|
DBGF_ERRORS,
|
|
"PNP_ModifyResDes caused an exception (%d)\n",
|
|
RpcExceptionCode()));
|
|
|
|
Status = MapRpcExceptionToCR(RpcExceptionCode());
|
|
}
|
|
RpcEndExcept
|
|
|
|
if (Status == CR_SUCCESS) {
|
|
//
|
|
// The resource type may change so a new handle is required and
|
|
// returned to caller.
|
|
//
|
|
Status = CreateResDesHandle(prdResDes,
|
|
dnDevInst,
|
|
ulLogType,
|
|
ulLogTag,
|
|
ResourceID,
|
|
ulResTag);
|
|
}
|
|
|
|
Clean0:
|
|
NOTHING;
|
|
|
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|
Status = CR_FAILURE;
|
|
}
|
|
|
|
if(ResourceData32) {
|
|
pSetupFree(ResourceData32);
|
|
}
|
|
return Status;
|
|
|
|
} // CM_Modify_Res_Des_Ex
|
|
|
|
|
|
|
|
CMAPI
|
|
CONFIGRET
|
|
WINAPI
|
|
CM_Detect_Resource_Conflict_Ex(
|
|
IN DEVINST dnDevInst,
|
|
IN RESOURCEID ResourceID, OPTIONAL
|
|
IN PCVOID ResourceData, OPTIONAL
|
|
IN ULONG ResourceLen, OPTIONAL
|
|
OUT PBOOL pbConflictDetected,
|
|
IN ULONG ulFlags,
|
|
IN HMACHINE hMachine
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This depreciated routine calls CM_Query_Resource_Conflict_List to see if
|
|
dnDevInst is conflicting with any other devices. It is used for a simple
|
|
"has a conflict" check. CM_Query_Resource_Conflict_List returns more
|
|
details of the conflicts.
|
|
|
|
Parameters:
|
|
|
|
dnDevInst DEVINST we're doing the test for (ie, that resource belongs to)
|
|
|
|
ResourceID,ResourceData,ResourceLen
|
|
See if this resource conflicts with a device other than dnDevInst
|
|
|
|
pbConflictDetected
|
|
Set to TRUE on conflict, FALSE if no conflict
|
|
|
|
ulFlags Specifies the width of certain variable-size resource
|
|
descriptor structure fields, where applicable.
|
|
|
|
Currently, the following flags are defined:
|
|
|
|
CM_RESDES_WIDTH_32 or
|
|
CM_RESDES_WIDTH_64
|
|
|
|
If no flags are specified, the width of the variable-sized
|
|
resource data supplied is assumed to be that native to the
|
|
platform of the caller.
|
|
|
|
hMachine Machine handle returned from CM_Connect_Machine or NULL.
|
|
|
|
Return Value:
|
|
|
|
If the function succeeds, the return value is CR_SUCCESS.
|
|
If the function fails, the return value is one of the following:
|
|
CR_INVALID_RES_DES,
|
|
CR_INVALID_FLAG,
|
|
CR_INVALID_POINTER,
|
|
CR_OUT_OF_MEMORY.
|
|
|
|
--*/
|
|
{
|
|
CONFIGRET Status = CR_SUCCESS;
|
|
CONFLICT_LIST ConflictList = 0;
|
|
ULONG ConflictCount = 0;
|
|
WCHAR pDeviceID [MAX_DEVICE_ID_LEN]; // )
|
|
PVOID hStringTable = NULL; // > for validation only
|
|
handle_t hBinding = NULL; // )
|
|
ULONG ulLen = MAX_DEVICE_ID_LEN; // )
|
|
|
|
try {
|
|
//
|
|
// validate parameters - must maintain compatability with original implementation
|
|
// even though some of the error codes don't make sense
|
|
// don't change any of the parameters here, as they are needed for
|
|
// CM_Query_Resource_Conflict_List
|
|
//
|
|
if (dnDevInst == 0) {
|
|
Status = CR_INVALID_DEVINST;
|
|
goto Clean0;
|
|
}
|
|
|
|
if (INVALID_FLAGS(ulFlags, CM_RESDES_WIDTH_BITS)) {
|
|
Status = CR_INVALID_FLAG;
|
|
goto Clean0;
|
|
}
|
|
|
|
if ((ulFlags & CM_RESDES_WIDTH_32) && (ulFlags & CM_RESDES_WIDTH_64)) {
|
|
Status = CR_INVALID_FLAG;
|
|
goto Clean0;
|
|
}
|
|
|
|
if (pbConflictDetected == NULL) {
|
|
Status = CR_INVALID_POINTER;
|
|
goto Clean0;
|
|
}
|
|
if (ResourceData == NULL || ResourceLen == 0) {
|
|
Status = CR_INVALID_POINTER;
|
|
goto Clean0;
|
|
}
|
|
if (ResourceID == ResType_All) {
|
|
Status = CR_INVALID_RESOURCEID; // can't specify All on a detect
|
|
goto Clean0;
|
|
}
|
|
//
|
|
// setup rpc binding handle and string table handle - for validation only
|
|
//
|
|
if (!PnPGetGlobalHandles(hMachine, &hStringTable, &hBinding)) {
|
|
Status = CR_FAILURE;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// retreive device instance string that corresponds to dnDevInst
|
|
// stupid status code for this check, but someone may rely on it
|
|
//
|
|
if ((pSetupStringTableStringFromIdEx(hStringTable,dnDevInst,pDeviceID,&ulLen) == FALSE)
|
|
|| INVALID_DEVINST(pDeviceID)) {
|
|
Status = CR_INVALID_LOG_CONF;
|
|
goto Clean0;
|
|
}
|
|
//
|
|
// now implement via CM_Query_Resource_Conflict_List
|
|
// the only difference here is that this new implementation should return
|
|
// only valid conflicts
|
|
//
|
|
Status = CM_Query_Resource_Conflict_List(&ConflictList,
|
|
dnDevInst,
|
|
ResourceID,
|
|
ResourceData,
|
|
ResourceLen,
|
|
ulFlags,
|
|
hMachine);
|
|
|
|
if (Status != CR_SUCCESS) {
|
|
goto Clean0;
|
|
}
|
|
|
|
Status = CM_Get_Resource_Conflict_Count(ConflictList,&ConflictCount);
|
|
|
|
if (Status != CR_SUCCESS) {
|
|
goto Clean0;
|
|
}
|
|
|
|
*pbConflictDetected = ConflictCount ? TRUE : FALSE;
|
|
|
|
Clean0:
|
|
NOTHING;
|
|
|
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|
Status = CR_FAILURE;
|
|
}
|
|
|
|
if (ConflictList) {
|
|
CM_Free_Resource_Conflict_Handle(ConflictList);
|
|
}
|
|
|
|
return Status;
|
|
|
|
} // CM_Detect_Resource_Conflict
|
|
|
|
|
|
|
|
CONFIGRET
|
|
CM_Free_Res_Des_Handle(
|
|
IN RES_DES rdResDes
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine frees the handle to the specified res des and frees and
|
|
memory associated with that res des handle.
|
|
|
|
Parameters:
|
|
|
|
|
|
rdResDes Supplies the handle of the resource descriptor.
|
|
|
|
Return Value:
|
|
|
|
If the function succeeds, the return value is CR_SUCCESS.
|
|
If the function fails, the return value is one of the following:
|
|
CR_INVALID_RES_DES.
|
|
|
|
--*/
|
|
|
|
{
|
|
CONFIGRET Status = CR_SUCCESS;
|
|
|
|
|
|
try {
|
|
//
|
|
// Validate parameters
|
|
//
|
|
if (!ValidateResDesHandle((PPrivate_Res_Des_Handle)rdResDes)) {
|
|
Status = CR_INVALID_RES_DES;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// It's a valid log conf handle, which is a pointer to memory
|
|
// allocated when the log conf was created or retrieved using
|
|
// the first/next routines. Free the associated memory.
|
|
//
|
|
((PPrivate_Res_Des_Handle)rdResDes)->RD_Signature = 0;
|
|
pSetupFree((PPrivate_Res_Des_Handle)rdResDes);
|
|
|
|
Clean0:
|
|
NOTHING;
|
|
|
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|
Status = CR_FAILURE;
|
|
}
|
|
|
|
return Status;
|
|
|
|
} // CM_Free_Res_Des_Handle
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
// Local Stubs
|
|
//-------------------------------------------------------------------
|
|
|
|
|
|
CONFIGRET
|
|
CM_Add_Res_Des(
|
|
OUT PRES_DES prdResDes,
|
|
IN LOG_CONF lcLogConf,
|
|
IN RESOURCEID ResourceID,
|
|
IN PCVOID ResourceData,
|
|
IN ULONG ResourceLen,
|
|
IN ULONG ulFlags
|
|
)
|
|
{
|
|
return CM_Add_Res_Des_Ex(prdResDes, lcLogConf, ResourceID, ResourceData,
|
|
ResourceLen, ulFlags, NULL);
|
|
}
|
|
|
|
|
|
CONFIGRET
|
|
CM_Free_Res_Des(
|
|
OUT PRES_DES prdResDes,
|
|
IN RES_DES rdResDes,
|
|
IN ULONG ulFlags
|
|
)
|
|
{
|
|
return CM_Free_Res_Des_Ex(prdResDes, rdResDes, ulFlags, NULL);
|
|
}
|
|
|
|
|
|
CONFIGRET
|
|
CM_Get_Next_Res_Des(
|
|
OUT PRES_DES prdResDes,
|
|
IN RES_DES rdResDes,
|
|
IN RESOURCEID ForResource,
|
|
OUT PRESOURCEID pResourceID,
|
|
IN ULONG ulFlags
|
|
)
|
|
{
|
|
return CM_Get_Next_Res_Des_Ex(prdResDes, rdResDes, ForResource,
|
|
pResourceID, ulFlags, NULL);
|
|
}
|
|
|
|
|
|
CONFIGRET
|
|
CM_Get_Res_Des_Data(
|
|
IN RES_DES rdResDes,
|
|
OUT PVOID Buffer,
|
|
IN ULONG BufferLen,
|
|
IN ULONG ulFlags
|
|
)
|
|
{
|
|
return CM_Get_Res_Des_Data_Ex(rdResDes, Buffer, BufferLen, ulFlags, NULL);
|
|
}
|
|
|
|
|
|
CONFIGRET
|
|
CM_Get_Res_Des_Data_Size(
|
|
OUT PULONG pulSize,
|
|
IN RES_DES rdResDes,
|
|
IN ULONG ulFlags
|
|
)
|
|
{
|
|
return CM_Get_Res_Des_Data_Size_Ex(pulSize, rdResDes, ulFlags, NULL);
|
|
}
|
|
|
|
|
|
CONFIGRET
|
|
CM_Modify_Res_Des(
|
|
OUT PRES_DES prdResDes,
|
|
IN RES_DES rdResDes,
|
|
IN RESOURCEID ResourceID,
|
|
IN PCVOID ResourceData,
|
|
IN ULONG ResourceLen,
|
|
IN ULONG ulFlags
|
|
)
|
|
{
|
|
return CM_Modify_Res_Des_Ex(prdResDes, rdResDes, ResourceID, ResourceData,
|
|
ResourceLen, ulFlags, NULL);
|
|
}
|
|
|
|
|
|
CONFIGRET
|
|
WINAPI
|
|
CM_Detect_Resource_Conflict(
|
|
IN DEVINST dnDevInst,
|
|
IN RESOURCEID ResourceID, OPTIONAL
|
|
IN PCVOID ResourceData, OPTIONAL
|
|
IN ULONG ResourceLen, OPTIONAL
|
|
OUT PBOOL pbConflictDetected,
|
|
IN ULONG ulFlags
|
|
)
|
|
{
|
|
return CM_Detect_Resource_Conflict_Ex(dnDevInst, ResourceID, ResourceData,
|
|
ResourceLen, pbConflictDetected,
|
|
ulFlags, NULL);
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
// Local Utility Routines
|
|
//-------------------------------------------------------------------
|
|
|
|
|
|
CONFIGRET
|
|
CreateResDesHandle(
|
|
PRES_DES prdResDes,
|
|
DEVINST dnDevInst,
|
|
ULONG ulLogType,
|
|
ULONG ulLogTag,
|
|
ULONG ulResType,
|
|
ULONG ulResTag
|
|
)
|
|
{
|
|
PPrivate_Res_Des_Handle pResDesHandle;
|
|
|
|
//
|
|
// allocate memory for the res des handle data
|
|
//
|
|
pResDesHandle = (PPrivate_Res_Des_Handle)pSetupMalloc(
|
|
sizeof(Private_Res_Des_Handle));
|
|
|
|
if (pResDesHandle == NULL) {
|
|
return CR_OUT_OF_MEMORY;
|
|
}
|
|
|
|
//
|
|
// fill in the private res des info and return as handle
|
|
//
|
|
pResDesHandle->RD_Signature = CM_PRIVATE_RESDES_SIGNATURE;
|
|
pResDesHandle->RD_DevInst = dnDevInst;
|
|
pResDesHandle->RD_LogConfType = ulLogType;
|
|
pResDesHandle->RD_LogConfTag = ulLogTag;
|
|
pResDesHandle->RD_ResourceType = ulResType;
|
|
pResDesHandle->RD_ResDesTag = ulResTag;
|
|
|
|
*prdResDes = (RES_DES)pResDesHandle;
|
|
|
|
return CR_SUCCESS;
|
|
|
|
} // CreateResDesHandle
|
|
|
|
|
|
|
|
BOOL
|
|
ValidateResDesHandle(
|
|
PPrivate_Res_Des_Handle pResDes
|
|
)
|
|
{
|
|
//
|
|
// validate parameters
|
|
//
|
|
if (pResDes == NULL || pResDes == 0) {
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// check for the private log conf signature
|
|
//
|
|
if (pResDes->RD_Signature != CM_PRIVATE_RESDES_SIGNATURE) {
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
} // ValidateResDesHandle
|
|
|
|
|
|
|
|
CONFIGRET
|
|
Convert32bitResDesSizeTo64bitResDesSize(
|
|
IN RESOURCEID ResourceID,
|
|
IN OUT PULONG ResLen
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine resizes ResLen for ResourceID
|
|
old structure: [DES32][RANGE32][RANGE32]...
|
|
new structure: [DES64 ][RANGE64 ][RANGE 64]...
|
|
#elements = (len-sizeof(DES32))/sizeof(RANGE32)
|
|
new len = sizeof(DES64)+#elements*sizeof(RANGE64)
|
|
(+ allow for alignment issues)
|
|
|
|
Parameters:
|
|
|
|
ResourceID - type of resource to adjust
|
|
ResLen - adjusted resource length
|
|
|
|
Return Value:
|
|
|
|
If the function succeeds, the return value is CR_SUCCESS.
|
|
|
|
--*/
|
|
{
|
|
switch(ResourceID) {
|
|
case ResType_All:
|
|
case ResType_Mem:
|
|
case ResType_IO:
|
|
case ResType_DMA:
|
|
case ResType_BusNumber:
|
|
//
|
|
// no change in resource size
|
|
//
|
|
return CR_SUCCESS;
|
|
|
|
case ResType_IRQ:
|
|
//
|
|
// header only
|
|
// use offsetof to handle non-obvious structure alignment padding
|
|
//
|
|
*ResLen += offsetof(IRQ_RESOURCE_64,IRQ_Data)-offsetof(IRQ_RESOURCE_32,IRQ_Data);
|
|
return CR_SUCCESS;
|
|
|
|
default:
|
|
//
|
|
// unknown resource
|
|
// shouldn't be a problem as this is for downlevel platforms
|
|
//
|
|
ASSERT(ResourceID & ResType_Ignored_Bit);
|
|
return CR_SUCCESS;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
CONFIGRET
|
|
Get32bitResDesFrom64bitResDes(
|
|
IN RESOURCEID ResourceID,
|
|
IN PCVOID ResData64,
|
|
IN ULONG ResLen64,
|
|
OUT PVOID * ResData32,
|
|
OUT ULONG * ResLen32
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine allocates ResData32 and converts ResData64 into ResData32 if needed
|
|
In the cases where no conversion is required, CR_SUCCESS is returned and
|
|
ResData32 is NULL.
|
|
In the cases where conversion is required, ResData32 holds new data
|
|
|
|
old structure: [DES64 ][RANGE64 ][RANGE 64]...
|
|
new structure: [DES32][RANGE32][RANGE32]...
|
|
#elements from 64-bit structure
|
|
new len = sizeof(DES32)+#elements*sizeof(RANGE32)
|
|
(+ allow for alignment issues)
|
|
|
|
Parameters:
|
|
|
|
ResourceID - type of resource to adjust
|
|
ResData64 - incoming data to convert (constant buffer)
|
|
ResLen64 - incoming length of data
|
|
ResData32 - converted data (if non-NULL)
|
|
ResLen32 - converted length
|
|
|
|
Return Value:
|
|
|
|
If the function succeeds, the return value is CR_SUCCESS.
|
|
|
|
--*/
|
|
{
|
|
*ResData32 = NULL;
|
|
*ResLen32 = ResLen64;
|
|
|
|
switch(ResourceID) {
|
|
case ResType_All:
|
|
case ResType_Mem:
|
|
case ResType_IO:
|
|
case ResType_DMA:
|
|
case ResType_BusNumber:
|
|
//
|
|
// no change in resource structure
|
|
//
|
|
return CR_SUCCESS;
|
|
|
|
case ResType_IRQ:
|
|
{
|
|
PIRQ_RESOURCE_64 pIrq64 = (PIRQ_RESOURCE_64)ResData64;
|
|
ULONG DataSize = ResLen64-offsetof(IRQ_RESOURCE_64,IRQ_Data);
|
|
ULONG NewResSize = DataSize+offsetof(IRQ_RESOURCE_32,IRQ_Data);
|
|
PVOID NewResData = pSetupMalloc(NewResSize);
|
|
PIRQ_RESOURCE_32 pIrq32 = (PIRQ_RESOURCE_32)NewResData;
|
|
|
|
if(NewResData == NULL) {
|
|
return CR_OUT_OF_MEMORY;
|
|
}
|
|
//
|
|
// copy header
|
|
//
|
|
MoveMemory(pIrq32,pIrq64,offsetof(IRQ_RESOURCE_32,IRQ_Data));
|
|
//
|
|
// copy/truncate Affinity (to ensure it's correct)
|
|
//
|
|
pIrq32->IRQ_Header.IRQD_Affinity = (ULONG32)pIrq64->IRQ_Header.IRQD_Affinity;
|
|
//
|
|
// copy data (trivial in this case)
|
|
//
|
|
MoveMemory(pIrq32->IRQ_Data,pIrq64->IRQ_Data,DataSize);
|
|
|
|
*ResLen32 = NewResSize;
|
|
*ResData32 = NewResData;
|
|
}
|
|
return CR_SUCCESS;
|
|
|
|
default:
|
|
//
|
|
// unknown resource
|
|
// shouldn't be a problem as this is for downlevel platforms
|
|
//
|
|
ASSERT(ResourceID & ResType_Ignored_Bit);
|
|
return CR_SUCCESS;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
CONFIGRET
|
|
Convert32bitResDesTo64bitResDes(
|
|
IN RESOURCEID ResourceID,
|
|
IN OUT PVOID ResData,
|
|
IN ULONG ResLen
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine reuses ResData and ResLen converting the 32-bit data provided
|
|
into 64-bit. Return error if buffer (reslen) isn't big enough
|
|
|
|
old structure: [DES32][RANGE32][RANGE32]...
|
|
new structure: [DES64 ][RANGE64 ][RANGE 64]...
|
|
#elements from 32-bit structure
|
|
(+ allow for alignment issues)
|
|
|
|
Parameters:
|
|
|
|
ResourceID - type of resource to adjust
|
|
ResData - in, 32-bit, out, 64-bit
|
|
ResData32 - size of ResData buffer
|
|
|
|
Return Value:
|
|
|
|
If the function succeeds, the return value is CR_SUCCESS.
|
|
|
|
--*/
|
|
{
|
|
switch(ResourceID) {
|
|
case ResType_All:
|
|
case ResType_Mem:
|
|
case ResType_IO:
|
|
case ResType_DMA:
|
|
case ResType_BusNumber:
|
|
//
|
|
// no change in resource structure
|
|
//
|
|
return CR_SUCCESS;
|
|
|
|
case ResType_IRQ:
|
|
{
|
|
PIRQ_RESOURCE_64 pIrq64 = (PIRQ_RESOURCE_64)ResData;
|
|
PIRQ_RESOURCE_32 pIrq32 = (PIRQ_RESOURCE_32)ResData;
|
|
ULONG DataSize = pIrq32->IRQ_Header.IRQD_Count * sizeof(IRQ_RANGE);
|
|
ULONG NewResSize = DataSize+offsetof(IRQ_RESOURCE_64,IRQ_Data);
|
|
|
|
if(NewResSize > ResLen) {
|
|
return CR_BUFFER_SMALL;
|
|
}
|
|
//
|
|
// work top to bottom
|
|
// copy data (trivial in this case)
|
|
// MoveMemory handles overlap
|
|
//
|
|
MoveMemory(pIrq64->IRQ_Data,pIrq32->IRQ_Data,DataSize);
|
|
|
|
//
|
|
// header is in correct position
|
|
// but we need to deal with affinity... copy only low 32-bits
|
|
//
|
|
pIrq64->IRQ_Header.IRQD_Affinity = pIrq32->IRQ_Header.IRQD_Affinity;
|
|
}
|
|
return CR_SUCCESS;
|
|
|
|
default:
|
|
//
|
|
// unknown resource
|
|
// shouldn't be a problem as this is for downlevel platforms
|
|
//
|
|
ASSERT(ResourceID & ResType_Ignored_Bit);
|
|
return CR_SUCCESS;
|
|
}
|
|
}
|
|
|
|
|