Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

1904 lines
54 KiB

/*++
Copyright (c) 1995-2001 Microsoft Corporation
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"
#include "cfgi.h"
#include "setupapi.h"
#include "spapip.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, 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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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 HdrDiff = offsetof(IRQ_RESOURCE_64,IRQ_Data) - offsetof(IRQ_RESOURCE_32,IRQ_Data);
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 HdrDiff = offsetof(IRQ_RESOURCE_64,IRQ_Data) - offsetof(IRQ_RESOURCE_32,IRQ_Data);
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;
}
}