mirror of https://github.com/tongzx/nt5src
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.
4959 lines
158 KiB
4959 lines
158 KiB
/*++
|
|
|
|
Copyright (c) 1995-2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
rresdes.c
|
|
|
|
Abstract:
|
|
|
|
This module contains the server-side resource description APIs.
|
|
|
|
PNP_AddResDes
|
|
PNP_FreeResDes
|
|
PNP_GetNextResDes
|
|
PNP_GetResDesData
|
|
PNP_GetResDesDataSize
|
|
PNP_ModifyResDes
|
|
PNP_DetectResourceConflict
|
|
|
|
Author:
|
|
|
|
Paula Tomlinson (paulat) 9-27-1995
|
|
|
|
Environment:
|
|
|
|
User-mode only.
|
|
|
|
Revision History:
|
|
|
|
27-Sept-1995 paulat
|
|
|
|
Creation and initial implementation.
|
|
|
|
--*/
|
|
|
|
|
|
//
|
|
// includes
|
|
//
|
|
#include "precomp.h"
|
|
#include "umpnpi.h"
|
|
|
|
|
|
//
|
|
// private prototypes
|
|
//
|
|
|
|
BOOL
|
|
FindLogConf(
|
|
IN LPBYTE pList,
|
|
OUT LPBYTE *ppLogConf,
|
|
IN ULONG RegDataType,
|
|
IN ULONG ulTag
|
|
);
|
|
|
|
BOOL
|
|
FindResDes(
|
|
IN LPBYTE pList,
|
|
IN ULONG RegDataType,
|
|
IN ULONG ulLogConfTag,
|
|
IN ULONG ulResTag,
|
|
IN RESOURCEID ResType,
|
|
OUT LPBYTE *ppRD,
|
|
OUT LPBYTE *ppLogConf,
|
|
OUT PULONG pulSubIndex OPTIONAL
|
|
);
|
|
|
|
PIO_RESOURCE_DESCRIPTOR
|
|
AdvanceRequirementsDescriptorPtr(
|
|
IN PIO_RESOURCE_DESCRIPTOR pReqDesStart,
|
|
IN ULONG ulIncrement,
|
|
IN ULONG ulRemainingRanges,
|
|
OUT PULONG pulRangeCount
|
|
);
|
|
|
|
ULONG
|
|
RANGE_COUNT(
|
|
IN PIO_RESOURCE_DESCRIPTOR pReqDes,
|
|
IN LPBYTE pLastReqAddr
|
|
);
|
|
|
|
ULONG
|
|
GetResDesSize(
|
|
IN ULONG ResourceID,
|
|
IN ULONG ulFlags
|
|
);
|
|
|
|
ULONG
|
|
GetReqDesSize(
|
|
IN ULONG ResourceID,
|
|
IN PIO_RESOURCE_DESCRIPTOR pReqDes,
|
|
IN LPBYTE pLastReqAddr,
|
|
IN ULONG ulFlags
|
|
);
|
|
|
|
CONFIGRET
|
|
ResDesToNtResource(
|
|
IN PCVOID ResourceData,
|
|
IN RESOURCEID ResourceID,
|
|
IN ULONG ResourceLen,
|
|
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pResDes,
|
|
IN ULONG ulTag,
|
|
IN ULONG ulFlags
|
|
);
|
|
|
|
CONFIGRET
|
|
ResDesToNtRequirements(
|
|
IN PCVOID ResourceData,
|
|
IN RESOURCEID ResourceType,
|
|
IN ULONG ResourceLen,
|
|
IN PIO_RESOURCE_DESCRIPTOR pReqDes,
|
|
IN OUT PULONG pulResCount,
|
|
IN ULONG ulTag,
|
|
IN ULONG ulFlags
|
|
);
|
|
|
|
CONFIGRET
|
|
NtResourceToResDes(
|
|
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pResDes,
|
|
IN OUT LPBYTE Buffer,
|
|
IN ULONG BufferLen,
|
|
IN LPBYTE pLastAddr,
|
|
IN ULONG ulFlags
|
|
);
|
|
|
|
CONFIGRET
|
|
NtRequirementsToResDes(
|
|
IN PIO_RESOURCE_DESCRIPTOR pReqDes,
|
|
IN OUT LPBYTE Buffer,
|
|
IN ULONG BufferLen,
|
|
IN LPBYTE pLastAddr,
|
|
IN ULONG ulFlags
|
|
);
|
|
|
|
UCHAR
|
|
NT_RES_TYPE(
|
|
IN RESOURCEID ResourceID
|
|
);
|
|
|
|
ULONG
|
|
CM_RES_TYPE(
|
|
IN UCHAR ResourceType
|
|
);
|
|
|
|
USHORT MapToNtMemoryFlags(IN DWORD);
|
|
DWORD MapFromNtMemoryFlags(IN USHORT);
|
|
USHORT MapToNtPortFlags(IN DWORD, IN DWORD);
|
|
DWORD MapFromNtPortFlags(IN USHORT);
|
|
DWORD MapAliasFromNtPortFlags(IN USHORT);
|
|
ULONG MapToNtAlignment(IN DWORDLONG);
|
|
DWORDLONG MapFromNtAlignment(IN ULONG);
|
|
USHORT MapToNtDmaFlags(IN DWORD);
|
|
DWORD MapFromNtDmaFlags(IN USHORT);
|
|
USHORT MapToNtIrqFlags(IN DWORD);
|
|
DWORD MapFromNtIrqFlags(IN USHORT);
|
|
UCHAR MapToNtIrqShare(IN DWORD);
|
|
DWORD MapFromNtIrqShare(IN UCHAR);
|
|
|
|
//
|
|
// prototypes from rlogconf.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
|
|
);
|
|
|
|
|
|
//
|
|
// global data
|
|
//
|
|
#define HIDWORD(x) ((DWORD)(((DWORDLONG)(x) >> 32) & 0xFFFFFFFF))
|
|
#define LODWORD(x) ((DWORD)(x))
|
|
#define MAKEDWORDLONG(x,y) ((DWORDLONG)(((DWORD)(x)) | ((DWORDLONG)((DWORD)(y))) << 32))
|
|
|
|
|
|
|
|
CONFIGRET
|
|
PNP_AddResDes(
|
|
IN handle_t hBinding,
|
|
IN LPWSTR pDeviceID,
|
|
IN ULONG LogConfTag,
|
|
IN ULONG LogConfType,
|
|
IN RESOURCEID ResourceID,
|
|
OUT PULONG pResourceTag,
|
|
IN LPBYTE ResourceData,
|
|
IN ULONG ResourceLen,
|
|
IN ULONG ulFlags
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This the server-side of an RPC remote call. This routine adds
|
|
a res des to the specified log conf.
|
|
|
|
Arguments:
|
|
|
|
hBinding RPC binding handle.
|
|
|
|
pDeviceID Null-terminated device instance id string.
|
|
|
|
LogConfTag Specifies the log conf within a given type.
|
|
|
|
LogConfType Specifies the log conf type.
|
|
|
|
ResourceID Specifies the resource type.
|
|
|
|
ResourceTag Returns with resource within a given type.
|
|
|
|
ResourceData Resource data (of ResourceID type) to add to log conf.
|
|
|
|
ResourceLen Size of ResourceData 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 supplied is assumed to be that native to the
|
|
platform of the caller.
|
|
|
|
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, i = 0, ulSize = 0, ulOffset = 0,
|
|
ulAddListSize = 0;
|
|
LPBYTE pList = NULL, pLogConf = NULL, pTemp = NULL;
|
|
|
|
//
|
|
// Always add the res des to the end, except in the case where a
|
|
// class-specific res des has already been added. The class-specific
|
|
// res des always MUST be last so add any new (non-class specific)
|
|
// res des just before the class specific. Note that there can be
|
|
// only one class-specific res des.
|
|
//
|
|
|
|
try {
|
|
//
|
|
// verify client access
|
|
//
|
|
if (!VerifyClientAccess(hBinding, &gLuidLoadDriverPrivilege)) {
|
|
Status = CR_ACCESS_DENIED;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// validate/initialize output parameters
|
|
//
|
|
if (!ARGUMENT_PRESENT(pResourceTag)) {
|
|
Status = CR_INVALID_POINTER;
|
|
goto Clean0;
|
|
} else {
|
|
*pResourceTag = 0;
|
|
}
|
|
|
|
//
|
|
// validate parameters
|
|
//
|
|
if (INVALID_FLAGS(ulFlags, CM_RESDES_WIDTH_BITS)) {
|
|
Status = CR_INVALID_FLAG;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// validate res des size
|
|
//
|
|
if (ResourceLen < GetResDesSize(ResourceID, ulFlags)) {
|
|
Status = CR_INVALID_DATA;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// make sure original caller didn't specify root devnode
|
|
//
|
|
if (!IsLegalDeviceId(pDeviceID) || IsRootDeviceID(pDeviceID)) {
|
|
Status = CR_INVALID_LOG_CONF;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// open a key to the device's LogConf subkey
|
|
//
|
|
Status = OpenLogConfKey(pDeviceID, LogConfType, &hKey);
|
|
if (Status != CR_SUCCESS) {
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// Retrieve log conf data from the registry
|
|
//
|
|
Status = GetLogConfData(hKey, LogConfType,
|
|
&RegDataType, szValueName,
|
|
&pList, &ulListSize);
|
|
|
|
if (Status != CR_SUCCESS) {
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// Seek to the log conf that matches the log conf tag
|
|
//
|
|
if (!FindLogConf(pList, &pLogConf, RegDataType, LogConfTag)) {
|
|
Status = CR_INVALID_LOG_CONF;
|
|
goto Clean0;
|
|
}
|
|
|
|
|
|
//-------------------------------------------------------------
|
|
// Specified log conf type contains Resource Data only
|
|
//-------------------------------------------------------------
|
|
|
|
if (RegDataType == REG_RESOURCE_LIST) {
|
|
|
|
PCM_RESOURCE_LIST pResList = (PCM_RESOURCE_LIST)pList;
|
|
PCM_FULL_RESOURCE_DESCRIPTOR pRes = (PCM_FULL_RESOURCE_DESCRIPTOR)pLogConf;
|
|
PCM_PARTIAL_RESOURCE_DESCRIPTOR pResDes = NULL;
|
|
|
|
//
|
|
// determine size required to hold the new res des
|
|
//
|
|
ulAddListSize = sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
|
|
|
|
if (ResourceID == ResType_ClassSpecific) {
|
|
|
|
PCS_RESOURCE pCsRes = (PCS_RESOURCE)ResourceData;
|
|
|
|
//
|
|
// first make sure there isn't already a cs (only one per lc)
|
|
//
|
|
if (pRes->PartialResourceList.Count != 0 &&
|
|
pRes->PartialResourceList.PartialDescriptors[pRes->PartialResourceList.Count-1].Type
|
|
== CmResourceTypeDeviceSpecific) {
|
|
Status = CR_INVALID_RES_DES;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// account for any extra class specific data in res list
|
|
//
|
|
ulAddListSize += sizeof(GUID) +
|
|
pCsRes->CS_Header.CSD_SignatureLength +
|
|
pCsRes->CS_Header.CSD_LegacyDataSize;
|
|
}
|
|
|
|
//
|
|
// reallocate the resource buffers to hold the new res des
|
|
//
|
|
ulOffset = (DWORD)((ULONG_PTR)pRes - (ULONG_PTR)pResList); // for restoring later
|
|
|
|
pResList = HeapReAlloc(ghPnPHeap, 0, pResList, ulListSize + ulAddListSize);
|
|
if (pResList == NULL) {
|
|
Status = CR_OUT_OF_MEMORY;
|
|
goto Clean0;
|
|
}
|
|
pList = (LPBYTE)pResList;
|
|
pRes = (PCM_FULL_RESOURCE_DESCRIPTOR)((LPBYTE)pResList + ulOffset);
|
|
|
|
//
|
|
// Find location for new res des (make a hole if necessary)
|
|
//
|
|
// If the following conditions are true, then can just append the
|
|
// new data to the end of the rsource list:
|
|
// - The selected LogConf is the last LogConf, and
|
|
// - No ClassSpecific resource has been added yet (or no resource period)
|
|
//
|
|
i = pRes->PartialResourceList.Count;
|
|
|
|
if ((LogConfTag == pResList->Count - 1) &&
|
|
(i == 0 ||
|
|
pRes->PartialResourceList.PartialDescriptors[i-1].Type !=
|
|
CmResourceTypeDeviceSpecific)) {
|
|
|
|
*pResourceTag = i;
|
|
pResDes = &pRes->PartialResourceList.PartialDescriptors[i];
|
|
|
|
} else {
|
|
//
|
|
// Need to make a hole for the new data before copying it.
|
|
// Find the spot to add the new res des data at - either as the
|
|
// last res des for this log conf or just before the class
|
|
// specific res des if it exists.
|
|
//
|
|
if (i == 0) {
|
|
*pResourceTag = 0;
|
|
pResDes = &pRes->PartialResourceList.PartialDescriptors[0];
|
|
|
|
} else if (pRes->PartialResourceList.PartialDescriptors[i-1].Type ==
|
|
CmResourceTypeDeviceSpecific) {
|
|
|
|
*pResourceTag = i-1;
|
|
pResDes = &pRes->PartialResourceList.PartialDescriptors[i-1];
|
|
|
|
} else {
|
|
*pResourceTag = i;
|
|
pResDes = &pRes->PartialResourceList.PartialDescriptors[i];
|
|
}
|
|
|
|
//
|
|
// Move any data after this point down a notch to make room for
|
|
// the new res des
|
|
//
|
|
ulSize = ulListSize - (DWORD)((ULONG_PTR)pResDes - (ULONG_PTR)pResList);
|
|
|
|
pTemp = HeapAlloc(ghPnPHeap, 0, ulSize);
|
|
if (pTemp == NULL) {
|
|
Status = CR_OUT_OF_MEMORY;
|
|
goto Clean0;
|
|
}
|
|
|
|
memcpy(pTemp, pResDes, ulSize);
|
|
memcpy((LPBYTE)((LPBYTE)pResDes + ulAddListSize), pTemp, ulSize);
|
|
}
|
|
|
|
if (ResourceID == ResType_ClassSpecific) {
|
|
*pResourceTag = RESDES_CS_TAG;
|
|
}
|
|
|
|
//
|
|
// Add res des to the log conf
|
|
//
|
|
Status = ResDesToNtResource(ResourceData, ResourceID, ResourceLen,
|
|
pResDes, *pResourceTag, ulFlags);
|
|
|
|
//
|
|
// update the lc and res header
|
|
//
|
|
pRes->PartialResourceList.Count += 1; // added a single res des (_DES)
|
|
}
|
|
|
|
//-------------------------------------------------------------
|
|
// Specified log conf type contains requirements data only
|
|
//-------------------------------------------------------------
|
|
|
|
else if (RegDataType == REG_RESOURCE_REQUIREMENTS_LIST) {
|
|
|
|
PIO_RESOURCE_REQUIREMENTS_LIST pReqList = (PIO_RESOURCE_REQUIREMENTS_LIST)pList;
|
|
PIO_RESOURCE_LIST pReq = (PIO_RESOURCE_LIST)pLogConf;
|
|
PIO_RESOURCE_DESCRIPTOR pReqDes = NULL;
|
|
PGENERIC_RESOURCE pGenRes = (PGENERIC_RESOURCE)ResourceData;
|
|
|
|
//
|
|
// validate res des type - ClassSpecific not allowed in
|
|
// requirements list (only resource list)
|
|
//
|
|
if (ResourceID == ResType_ClassSpecific ||
|
|
pGenRes->GENERIC_Header.GENERIC_Count == 0) {
|
|
|
|
Status = CR_INVALID_RES_DES;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// determine size required to hold the new res des
|
|
//
|
|
ulAddListSize = pGenRes->GENERIC_Header.GENERIC_Count *
|
|
sizeof(IO_RESOURCE_DESCRIPTOR);
|
|
|
|
//
|
|
// reallocate the resource buffers to hold the new res des
|
|
//
|
|
ulOffset = (DWORD)((ULONG_PTR)pReq - (ULONG_PTR)pReqList); // for restoring later
|
|
|
|
pReqList = HeapReAlloc(ghPnPHeap, 0, pReqList, ulListSize + ulAddListSize);
|
|
if (pReqList == NULL) {
|
|
Status = CR_OUT_OF_MEMORY;
|
|
goto Clean0;
|
|
}
|
|
pList = (LPBYTE)pReqList;
|
|
pReq = (PIO_RESOURCE_LIST)((LPBYTE)pReqList + ulOffset);
|
|
|
|
//
|
|
// Find location for new res des - the new res des always ends
|
|
// up being added as the last res des for this log conf.
|
|
//
|
|
*pResourceTag = pReq->Count;
|
|
pReqDes = &pReq->Descriptors[*pResourceTag];
|
|
|
|
//
|
|
// If the selected LogConf is the last LogConf then can just
|
|
// append the new res des data to the end of the requirements
|
|
// list. Otherwise, need to make a whole for the new data
|
|
// before copying it.
|
|
//
|
|
if (LogConfTag != pReqList->AlternativeLists - 1) {
|
|
|
|
ulSize = ulListSize - (DWORD)((ULONG_PTR)pReqDes - (ULONG_PTR)pReqList);
|
|
|
|
pTemp = HeapAlloc(ghPnPHeap, 0, ulSize);
|
|
if (pTemp == NULL) {
|
|
Status = CR_OUT_OF_MEMORY;
|
|
goto Clean0;
|
|
}
|
|
|
|
memcpy(pTemp, pReqDes, ulSize);
|
|
memcpy((LPBYTE)((LPBYTE)pReqDes + ulAddListSize), pTemp, ulSize);
|
|
}
|
|
|
|
//
|
|
// Add res des to the log conf.
|
|
//
|
|
Status = ResDesToNtRequirements(ResourceData, ResourceID, ResourceLen,
|
|
pReqDes, &i, *pResourceTag, ulFlags);
|
|
|
|
//
|
|
// update the lc and res header
|
|
//
|
|
pReq->Count += i; // _RANGES added
|
|
pReqList->ListSize = ulListSize + ulAddListSize;
|
|
}
|
|
|
|
//
|
|
// 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 (pList != NULL) {
|
|
HeapFree(ghPnPHeap, 0, pList);
|
|
}
|
|
if (pTemp != NULL) {
|
|
HeapFree(ghPnPHeap, 0, pTemp);
|
|
}
|
|
if (hKey != NULL) {
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
return Status;
|
|
|
|
} // PNP_AddResDes
|
|
|
|
|
|
|
|
CONFIGRET
|
|
PNP_FreeResDes(
|
|
IN handle_t hBinding,
|
|
IN LPWSTR pDeviceID,
|
|
IN ULONG LogConfTag,
|
|
IN ULONG LogConfType,
|
|
IN RESOURCEID ResourceID,
|
|
IN ULONG ResourceTag,
|
|
OUT PULONG pulPreviousResType,
|
|
OUT PULONG pulPreviousResTag,
|
|
IN ULONG ulFlags
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This the server-side of an RPC remote call. This routine frees
|
|
a res des to the specified log conf.
|
|
|
|
Arguments:
|
|
|
|
hBinding RPC binding handle.
|
|
|
|
pDeviceID Null-terminated device instance id string.
|
|
|
|
LogConfTag Specifies the log conf within a given type.
|
|
|
|
LogConfType Specifies the log conf type.
|
|
|
|
ResourceID Specifies the resource type.
|
|
|
|
ResourceTag Specifies the resource within a given type.
|
|
|
|
pulPreviousResType Receives the previous resource type.
|
|
|
|
pulPreviousResTag Receives the previous resource within a given type.
|
|
|
|
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, RdCount=0, ulCount=0, ulListSize=0, ulSize=0;
|
|
LPBYTE pList=NULL, pLogConf=NULL, pRD=NULL, pTemp=NULL, pNext=NULL;
|
|
|
|
try {
|
|
//
|
|
// verify client access
|
|
//
|
|
if (!VerifyClientAccess(hBinding, &gLuidLoadDriverPrivilege)) {
|
|
Status = CR_ACCESS_DENIED;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// validate parameters
|
|
//
|
|
if (INVALID_FLAGS(ulFlags, 0)) {
|
|
Status = CR_INVALID_FLAG;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// make sure original caller didn't specify root devnode
|
|
//
|
|
if (!IsLegalDeviceId(pDeviceID) || IsRootDeviceID(pDeviceID)) {
|
|
Status = CR_INVALID_LOG_CONF;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// open a key to the device's LogConf subkey
|
|
//
|
|
Status = OpenLogConfKey(pDeviceID, LogConfType, &hKey);
|
|
if (Status != CR_SUCCESS) {
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// Retrieve log conf data from the registry
|
|
//
|
|
Status = GetLogConfData(hKey, LogConfType,
|
|
&RegDataType, szValueName,
|
|
&pList, &ulListSize);
|
|
|
|
if (Status != CR_SUCCESS) {
|
|
Status = CR_INVALID_RES_DES; // log conf doesn't exist
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// seek to the res des that matches the resource tag.
|
|
//
|
|
if (!FindResDes(pList, RegDataType, LogConfTag,
|
|
ResourceTag, ResourceID, &pRD, &pLogConf, &ulCount)) {
|
|
|
|
Status = CR_INVALID_RES_DES;
|
|
goto Clean0;
|
|
}
|
|
|
|
|
|
//-------------------------------------------------------------
|
|
// Specified log conf type contains Resource Data only
|
|
//-------------------------------------------------------------
|
|
|
|
if (RegDataType == REG_RESOURCE_LIST) {
|
|
|
|
PCM_RESOURCE_LIST pResList = (PCM_RESOURCE_LIST)pList;
|
|
PCM_FULL_RESOURCE_DESCRIPTOR pRes = (PCM_FULL_RESOURCE_DESCRIPTOR)pLogConf;
|
|
PCM_PARTIAL_RESOURCE_DESCRIPTOR pResDes = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)pRD;
|
|
|
|
//
|
|
// If this is the last log conf and last res des, then don't
|
|
// need to do anything except truncate it by writing less data
|
|
// back into the registry.
|
|
//
|
|
if ((LogConfTag == pResList->Count - 1) &&
|
|
((ResourceTag == pRes->PartialResourceList.Count - 1) ||
|
|
(ResourceTag == RESDES_CS_TAG))) {
|
|
|
|
pRes->PartialResourceList.Count -= 1;
|
|
ulListSize = (DWORD)((ULONG_PTR)(pResDes) - (ULONG_PTR)(pResList));
|
|
|
|
} else {
|
|
//
|
|
// If the res des is not at the end of the structure, then
|
|
// migrate the remainder of the structure up to keep the
|
|
// struct contiguous when removing a res des.
|
|
//
|
|
// pResDes points to the beginning of the res des to remove,
|
|
// pNext points to the byte just after the res des to remove
|
|
//
|
|
pNext = (LPBYTE)((LPBYTE)pResDes + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
|
|
|
|
if (pResDes->Type == CmResourceTypeDeviceSpecific) {
|
|
pNext += pResDes->u.DeviceSpecificData.DataSize;
|
|
}
|
|
|
|
ulSize = ulListSize - (DWORD)((ULONG_PTR)pNext - (ULONG_PTR)pResList);
|
|
ulListSize -= (DWORD)((ULONG_PTR)pNext - (ULONG_PTR)pResDes); // new lc list size
|
|
|
|
pTemp = HeapAlloc(ghPnPHeap, 0, ulSize);
|
|
if (pTemp == NULL) {
|
|
Status = CR_OUT_OF_MEMORY;
|
|
goto Clean0;
|
|
}
|
|
|
|
memcpy(pTemp, pNext, ulSize);
|
|
memcpy((LPBYTE)pResDes, pTemp, ulSize);
|
|
|
|
pRes->PartialResourceList.Count -= 1;
|
|
}
|
|
|
|
//
|
|
// if no more res des's in this log conf, then return that
|
|
// status (the client side will return a handle to the lc)
|
|
//
|
|
if (pRes->PartialResourceList.Count == 0) {
|
|
Status = CR_NO_MORE_RES_DES;
|
|
} else {
|
|
//
|
|
// return the previous res des type and tag
|
|
//
|
|
*pulPreviousResType =
|
|
CM_RES_TYPE(pRes->PartialResourceList.PartialDescriptors[ResourceTag-1].Type);
|
|
|
|
if (*pulPreviousResType == ResType_ClassSpecific) {
|
|
*pulPreviousResTag = RESDES_CS_TAG; // special tag for cs
|
|
} else {
|
|
*pulPreviousResTag = ResourceTag - 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------
|
|
// Specified log conf type contains requirements data only
|
|
//-------------------------------------------------------------
|
|
|
|
else if (RegDataType == REG_RESOURCE_REQUIREMENTS_LIST) {
|
|
|
|
PIO_RESOURCE_REQUIREMENTS_LIST pReqList = (PIO_RESOURCE_REQUIREMENTS_LIST)pList;
|
|
PIO_RESOURCE_LIST pReq = (PIO_RESOURCE_LIST)pLogConf;
|
|
PIO_RESOURCE_DESCRIPTOR pReqDes = (PIO_RESOURCE_DESCRIPTOR)pRD;
|
|
|
|
//
|
|
// If this is the last log conf and last res des, then don't
|
|
// need to do anything except truncate it by writing less data
|
|
// back into the registry.
|
|
//
|
|
RdCount = RANGE_COUNT(pReqDes, (LPBYTE)pReqList + ulListSize - 1);
|
|
|
|
if ((LogConfTag == pReqList->AlternativeLists - 1) &&
|
|
(RdCount + ulCount == pReq->Count - 1)) {
|
|
|
|
ulListSize = (DWORD)((ULONG_PTR)(pReqDes) - (ULONG_PTR)pReqList);
|
|
|
|
} else {
|
|
//
|
|
// If the res des is not at the end of the structure, then
|
|
// migrate the remainder of the structure up to keep the
|
|
// struct contiguous when removing a res des.
|
|
//
|
|
// pReqDes points to the beginning of the res des(s) to remove,
|
|
// pNext points to the byte just after the res des(s) to remove
|
|
//
|
|
pNext = (LPBYTE)((LPBYTE)pReqDes +
|
|
RdCount * sizeof(IO_RESOURCE_DESCRIPTOR));
|
|
|
|
ulSize = ulListSize - (DWORD)((ULONG_PTR)pNext - (ULONG_PTR)pReqList);
|
|
ulListSize -= (DWORD)((ULONG_PTR)pNext - (ULONG_PTR)pReqDes); // new lc list size
|
|
|
|
pTemp = HeapAlloc(ghPnPHeap, 0, ulSize);
|
|
if (pTemp == NULL) {
|
|
Status = CR_OUT_OF_MEMORY;
|
|
goto Clean0;
|
|
}
|
|
|
|
memcpy(pTemp, pNext, ulSize);
|
|
memcpy((LPBYTE)pReqDes, pTemp, ulSize);
|
|
}
|
|
|
|
pReqList->ListSize = ulListSize;
|
|
pReq->Count -= RdCount;
|
|
|
|
//
|
|
// if no more res des's in this log conf, then return that status
|
|
// (the client side will return a handle to the log conf)
|
|
//
|
|
if (pReq->Count == 0) {
|
|
Status = CR_NO_MORE_RES_DES;
|
|
} else {
|
|
//
|
|
// return the previous res des type and tag
|
|
//
|
|
pReqDes = AdvanceRequirementsDescriptorPtr(&pReq->Descriptors[0],
|
|
ResourceTag-1, pReq->Count, NULL);
|
|
|
|
//
|
|
// Double check whether this is the first ConfigData res des,
|
|
// skip it if so.
|
|
//
|
|
if (pReqDes == NULL || pReqDes->Type == CmResourceTypeConfigData) {
|
|
Status = CR_NO_MORE_RES_DES;
|
|
} else {
|
|
*pulPreviousResType = CM_RES_TYPE(pReqDes->Type);
|
|
*pulPreviousResTag = ResourceTag - 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// 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_INVALID_RES_DES; // mostly likely reason we got here
|
|
}
|
|
|
|
if (pList != NULL) {
|
|
HeapFree(ghPnPHeap, 0, pList);
|
|
}
|
|
if (pTemp != NULL) {
|
|
HeapFree(ghPnPHeap, 0, pTemp);
|
|
}
|
|
if (hKey != NULL) {
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
return Status;
|
|
|
|
} // PNP_FreeResDes
|
|
|
|
|
|
|
|
CONFIGRET
|
|
PNP_GetNextResDes(
|
|
IN handle_t hBinding,
|
|
IN LPWSTR pDeviceID,
|
|
IN ULONG LogConfTag,
|
|
IN ULONG LogConfType,
|
|
IN RESOURCEID ResourceID,
|
|
IN ULONG ResourceTag,
|
|
OUT PULONG pulNextResDesTag,
|
|
OUT PULONG pulNextResDesType,
|
|
IN ULONG ulFlags
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This the server-side of an RPC remote call. This routine gets the
|
|
next res des in the specified log conf.
|
|
|
|
Arguments:
|
|
|
|
hBinding RPC binding handle, not used.
|
|
|
|
pDeviceID Null-terminated device instance id string.
|
|
|
|
LogConfTag Specifies the log conf within a given type.
|
|
|
|
LogConfType Specifies the log conf type.
|
|
|
|
ResourceID Specifies the resource type.
|
|
|
|
ResourceTag Specifies current resource descriptor (if any).
|
|
|
|
pulNextResDesTag Receives the next resource type.
|
|
|
|
pulNextResDesType Receives the next resource within a given type.
|
|
|
|
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, i = 0, ulCount = 0;
|
|
LPBYTE pList = NULL, pLogConf = NULL;
|
|
|
|
UNREFERENCED_PARAMETER(hBinding);
|
|
|
|
try {
|
|
//
|
|
// validate/initialize output parameters
|
|
//
|
|
if (!ARGUMENT_PRESENT(pulNextResDesTag)) {
|
|
Status = CR_INVALID_POINTER;
|
|
goto Clean0;
|
|
} else {
|
|
*pulNextResDesTag = 0;
|
|
}
|
|
|
|
//
|
|
// validate parameters
|
|
//
|
|
if (INVALID_FLAGS(ulFlags, 0)) {
|
|
Status = CR_INVALID_FLAG;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// make sure original caller didn't specify root devnode
|
|
//
|
|
if (!IsLegalDeviceId(pDeviceID) || IsRootDeviceID(pDeviceID)) {
|
|
Status = CR_INVALID_LOG_CONF;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// open a key to the device's LogConf subkey
|
|
//
|
|
Status = OpenLogConfKey(pDeviceID, LogConfType, &hKey);
|
|
if (Status != CR_SUCCESS) {
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// Retrieve log conf data from the registry
|
|
//
|
|
Status = GetLogConfData(hKey, LogConfType,
|
|
&RegDataType, szValueName,
|
|
&pList, &ulListSize);
|
|
if (Status != CR_SUCCESS) {
|
|
Status = CR_INVALID_RES_DES; // log conf doesn't exist
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// Seek to the log conf that matches the log conf tag
|
|
//
|
|
if (!FindLogConf(pList, &pLogConf, RegDataType, LogConfTag)) {
|
|
Status = CR_INVALID_LOG_CONF;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// find the next res des. A resource tag of max indicates that we want
|
|
// a find first operation.
|
|
//
|
|
if (ResourceTag == MAX_RESDES_TAG) {
|
|
//
|
|
// This is essentially a Get-First operation
|
|
//
|
|
*pulNextResDesTag = 0;
|
|
|
|
} else if (ResourceTag == RESDES_CS_TAG) {
|
|
//
|
|
// By definition, if the resource type is classspecific, it's last,
|
|
// so there aren't any more after this.
|
|
//
|
|
Status = CR_NO_MORE_RES_DES;
|
|
goto Clean0;
|
|
|
|
} else {
|
|
*pulNextResDesTag = ResourceTag + 1; // we want the "next" res des
|
|
}
|
|
|
|
|
|
//-------------------------------------------------------------
|
|
// Specified log conf type contains Resource Data only
|
|
//-------------------------------------------------------------
|
|
|
|
if (RegDataType == REG_RESOURCE_LIST) {
|
|
|
|
PCM_RESOURCE_LIST pResList = (PCM_RESOURCE_LIST)pList;
|
|
PCM_FULL_RESOURCE_DESCRIPTOR pRes = (PCM_FULL_RESOURCE_DESCRIPTOR)pLogConf;
|
|
ULONG ulTmpResDesTag, ulTmpLogConfTag;
|
|
|
|
ulTmpResDesTag = *pulNextResDesTag;
|
|
ulTmpLogConfTag = LogConfTag;
|
|
|
|
for ( ; ; ) {
|
|
|
|
while (ulTmpResDesTag >= pRes->PartialResourceList.Count) {
|
|
|
|
ulTmpResDesTag -= pRes->PartialResourceList.Count;
|
|
ulTmpLogConfTag++;
|
|
|
|
//
|
|
// Seek to the log conf that matches the log conf tag
|
|
//
|
|
if (!FindLogConf(pList, &pLogConf, RegDataType, ulTmpLogConfTag)) {
|
|
|
|
Status = CR_NO_MORE_RES_DES; // there is no "next"
|
|
goto Clean0;
|
|
}
|
|
|
|
pRes = (PCM_FULL_RESOURCE_DESCRIPTOR)pLogConf;
|
|
}
|
|
|
|
//
|
|
// Not done yet, if a specific resource type was specified, then
|
|
// we may need to keep looking.
|
|
//
|
|
if (ResourceID != ResType_All) {
|
|
|
|
UCHAR NtResType = NT_RES_TYPE(ResourceID);
|
|
|
|
if (pRes->PartialResourceList.PartialDescriptors[ulTmpResDesTag].Type
|
|
!= NtResType) {
|
|
|
|
(*pulNextResDesTag)++;
|
|
ulTmpResDesTag++;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Return the type and tag of the "next" res des
|
|
//
|
|
*pulNextResDesType = CM_RES_TYPE(pRes->PartialResourceList.
|
|
PartialDescriptors[ulTmpResDesTag].Type);
|
|
|
|
if (*pulNextResDesType == ResType_ClassSpecific) {
|
|
*pulNextResDesTag = RESDES_CS_TAG; // special tag for cs
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------
|
|
// Specified log conf type contains requirements data only
|
|
//-------------------------------------------------------------
|
|
|
|
else if (RegDataType == REG_RESOURCE_REQUIREMENTS_LIST) {
|
|
|
|
PIO_RESOURCE_REQUIREMENTS_LIST pReqList = (PIO_RESOURCE_REQUIREMENTS_LIST)pList;
|
|
PIO_RESOURCE_LIST pReq = (PIO_RESOURCE_LIST)pLogConf;
|
|
PIO_RESOURCE_DESCRIPTOR pReqDes;
|
|
|
|
//
|
|
// Point pResDes at the first possible "next" res des
|
|
//
|
|
|
|
if (*pulNextResDesTag == 0) {
|
|
if (pReq->Count == 0) {
|
|
Status = CR_NO_MORE_RES_DES; // there is no "next"
|
|
goto Clean0;
|
|
}
|
|
|
|
if (pReq->Descriptors[0].Type == CmResourceTypeConfigData) {
|
|
//
|
|
// This one doesn't count, it's privately created and maintained,
|
|
// skip to the next rd
|
|
//
|
|
*pulNextResDesTag = 1;
|
|
}
|
|
}
|
|
|
|
if (*pulNextResDesTag > 0) {
|
|
pReqDes = AdvanceRequirementsDescriptorPtr(&pReq->Descriptors[0], *pulNextResDesTag, pReq->Count, &ulCount); // current
|
|
|
|
if (pReqDes == NULL) {
|
|
Status = CR_NO_MORE_RES_DES; // there is no "next"
|
|
goto Clean0;
|
|
}
|
|
} else {
|
|
ulCount = 0;
|
|
pReqDes = &pReq->Descriptors[0];
|
|
}
|
|
|
|
//
|
|
// Not done yet, if a specific resource type was specified, then
|
|
// we may need to keep looking.
|
|
//
|
|
if (ResourceID != ResType_All) {
|
|
|
|
UCHAR NtResType = NT_RES_TYPE(ResourceID);
|
|
|
|
while (pReqDes->Type != NtResType) {
|
|
|
|
if (ulCount >= pReq->Count) {
|
|
Status = CR_NO_MORE_RES_DES;
|
|
goto Clean0;
|
|
}
|
|
pReqDes = AdvanceRequirementsDescriptorPtr(pReqDes, 1, pReq->Count - ulCount, &i);
|
|
|
|
if (pReqDes == NULL) {
|
|
Status = CR_NO_MORE_RES_DES;
|
|
goto Clean0;
|
|
}
|
|
|
|
ulCount += i;
|
|
*pulNextResDesTag += 1;
|
|
}
|
|
}
|
|
|
|
*pulNextResDesType = CM_RES_TYPE(pReqDes->Type);
|
|
}
|
|
|
|
Clean0:
|
|
NOTHING;
|
|
|
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|
Status = CR_FAILURE;
|
|
}
|
|
|
|
if (pList != NULL) {
|
|
HeapFree(ghPnPHeap, 0, pList);
|
|
}
|
|
if (hKey != NULL) {
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
return Status;
|
|
|
|
} // PNP_GetNextResDes
|
|
|
|
|
|
|
|
CONFIGRET
|
|
PNP_GetResDesData(
|
|
IN handle_t hBinding,
|
|
IN LPWSTR pDeviceID,
|
|
IN ULONG LogConfTag,
|
|
IN ULONG LogConfType,
|
|
IN RESOURCEID ResourceID,
|
|
IN ULONG ResourceTag,
|
|
OUT LPBYTE Buffer,
|
|
IN ULONG BufferLen,
|
|
IN ULONG ulFlags
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This the server-side of an RPC remote call. This routine retrieves
|
|
the data for the specified res des.
|
|
|
|
Arguments:
|
|
|
|
hBinding RPC binding handle, not used.
|
|
|
|
pDeviceID Null-terminated device instance id string.
|
|
|
|
LogConfTag Specifies the log conf within a given type.
|
|
|
|
LogConfType Specifies the log conf type.
|
|
|
|
ResourceID Specifies the resource type.
|
|
|
|
ResourceTag Returns with resource within a given type.
|
|
|
|
Buffer Returns resource data (of ResourceID type) from log conf.
|
|
|
|
BufferLen Size of 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.
|
|
|
|
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, ulCount = 0;
|
|
LPBYTE pList = NULL, pLogConf = NULL, pRD = NULL;
|
|
|
|
UNREFERENCED_PARAMETER(hBinding);
|
|
|
|
try {
|
|
//
|
|
// validate parameters
|
|
//
|
|
if (INVALID_FLAGS(ulFlags, CM_RESDES_WIDTH_BITS)) {
|
|
Status = CR_INVALID_FLAG;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// make sure original caller didn't specify root devnode
|
|
//
|
|
if (!IsLegalDeviceId(pDeviceID) || IsRootDeviceID(pDeviceID)) {
|
|
Status = CR_INVALID_LOG_CONF;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// open a key to the device's LogConf subkey
|
|
//
|
|
Status = OpenLogConfKey(pDeviceID, LogConfType, &hKey);
|
|
if (Status != CR_SUCCESS) {
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// Retrieve log conf data from the registry
|
|
//
|
|
Status = GetLogConfData(hKey, LogConfType,
|
|
&RegDataType, szValueName,
|
|
&pList, &ulListSize);
|
|
|
|
if (Status != CR_SUCCESS) {
|
|
Status = CR_INVALID_RES_DES; // log conf doesn't exist
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// seek to the res des that matches the resource tag.
|
|
//
|
|
if (!FindResDes(pList, RegDataType, LogConfTag,
|
|
ResourceTag, ResourceID, &pRD, &pLogConf, &ulCount)) {
|
|
|
|
Status = CR_INVALID_RES_DES;
|
|
goto Clean0;
|
|
}
|
|
|
|
//-------------------------------------------------------------
|
|
// Specified log conf type contains Resource Data only
|
|
//-------------------------------------------------------------
|
|
|
|
if (RegDataType == REG_RESOURCE_LIST) {
|
|
|
|
PCM_RESOURCE_LIST pResList = (PCM_RESOURCE_LIST)pList;
|
|
PCM_PARTIAL_RESOURCE_DESCRIPTOR pResDes = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)pRD;
|
|
|
|
//
|
|
// map the NT-style info into ConfigMgr-style structures
|
|
//
|
|
Status = NtResourceToResDes(pResDes, Buffer, BufferLen,
|
|
(LPBYTE)pResList + ulListSize - 1, ulFlags);
|
|
}
|
|
|
|
//-------------------------------------------------------------
|
|
// 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_DESCRIPTOR pReqDes = (PIO_RESOURCE_DESCRIPTOR)pRD;
|
|
|
|
//
|
|
// map the NT-style info into ConfigMgr-style structures
|
|
//
|
|
Status = NtRequirementsToResDes(pReqDes, Buffer, BufferLen,
|
|
(LPBYTE)pReqList + ulListSize - 1, ulFlags);
|
|
}
|
|
|
|
Clean0:
|
|
NOTHING;
|
|
|
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|
Status = CR_FAILURE;
|
|
}
|
|
|
|
if (hKey != NULL) {
|
|
RegCloseKey(hKey);
|
|
}
|
|
if (pList != NULL) {
|
|
HeapFree(ghPnPHeap, 0, pList);
|
|
}
|
|
|
|
return Status;
|
|
|
|
} // PNP_GetResDesData
|
|
|
|
|
|
|
|
CONFIGRET
|
|
PNP_GetResDesDataSize(
|
|
IN handle_t hBinding,
|
|
IN LPWSTR pDeviceID,
|
|
IN ULONG LogConfTag,
|
|
IN ULONG LogConfType,
|
|
IN RESOURCEID ResourceID,
|
|
IN ULONG ResourceTag,
|
|
OUT PULONG pulSize,
|
|
IN ULONG ulFlags
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This the server-side of an RPC remote call. This routine retrieves
|
|
the data size for the specified res des.
|
|
|
|
Arguments:
|
|
|
|
hBinding RPC binding handle, not used.
|
|
|
|
pDeviceID Null-terminated device instance id string.
|
|
|
|
LogConfTag Specifies the log conf within a given type.
|
|
|
|
LogConfType Specifies the log conf type.
|
|
|
|
ResourceID Specifies the resource type.
|
|
|
|
ResourceTag Returns with resource within a given type.
|
|
|
|
pulSize Returns size of buffer in bytes required to hold the
|
|
resource data (of ResourceID type) from log conf.
|
|
|
|
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.
|
|
|
|
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, ulCount = 0;
|
|
LPBYTE pList = NULL, pLogConf = NULL, pRD = NULL;
|
|
|
|
UNREFERENCED_PARAMETER(hBinding);
|
|
|
|
try {
|
|
//
|
|
// validate/initialize output parameters
|
|
//
|
|
if (!ARGUMENT_PRESENT(pulSize)) {
|
|
Status = CR_INVALID_POINTER;
|
|
goto Clean0;
|
|
} else {
|
|
*pulSize = 0;
|
|
}
|
|
|
|
//
|
|
// validate parameters
|
|
//
|
|
if (INVALID_FLAGS(ulFlags, CM_RESDES_WIDTH_BITS)) {
|
|
Status = CR_INVALID_FLAG;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// make sure original caller didn't specify root devnode
|
|
//
|
|
if (!IsLegalDeviceId(pDeviceID) || IsRootDeviceID(pDeviceID)) {
|
|
Status = CR_INVALID_LOG_CONF;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// open a key to the device's LogConf subkey
|
|
//
|
|
Status = OpenLogConfKey(pDeviceID, LogConfType, &hKey);
|
|
if (Status != CR_SUCCESS) {
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// Retrieve log conf data from the registry
|
|
//
|
|
Status = GetLogConfData(hKey, LogConfType,
|
|
&RegDataType, szValueName,
|
|
&pList, &ulListSize);
|
|
if (Status != CR_SUCCESS) {
|
|
Status = CR_INVALID_RES_DES; // log conf doesn't exist
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// seek to the res des that matches the resource tag.
|
|
//
|
|
if (!FindResDes(pList, RegDataType, LogConfTag,
|
|
ResourceTag, ResourceID, &pRD, &pLogConf, &ulCount)) {
|
|
|
|
Status = CR_INVALID_RES_DES;
|
|
goto Clean0;
|
|
}
|
|
|
|
//-------------------------------------------------------------
|
|
// Specified log conf type contains Resource Data only
|
|
//-------------------------------------------------------------
|
|
|
|
if (RegDataType == REG_RESOURCE_LIST) {
|
|
|
|
PCM_PARTIAL_RESOURCE_DESCRIPTOR pResDes = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)pRD;
|
|
|
|
//
|
|
// calculate data size required (in terms of ConfigMgr structures)
|
|
//
|
|
*pulSize = GetResDesSize(ResourceID, ulFlags);
|
|
|
|
if (ResourceID == ResType_ClassSpecific) {
|
|
//
|
|
// the Reserved fields should not exceed DataSize. if so, they
|
|
// may have been incorrectly initialized, so set them 0.
|
|
// we expect DataSize to be correct in all cases.
|
|
//
|
|
if (pResDes->u.DeviceSpecificData.Reserved1 > pResDes->u.DeviceSpecificData.DataSize) {
|
|
pResDes->u.DeviceSpecificData.Reserved1 = 0;
|
|
}
|
|
|
|
if (pResDes->u.DeviceSpecificData.Reserved2 > pResDes->u.DeviceSpecificData.DataSize) {
|
|
pResDes->u.DeviceSpecificData.Reserved2 = 0;
|
|
}
|
|
|
|
//
|
|
// add space for legacy and signature data but not the
|
|
// GUID - it's already included in the CM structures
|
|
//
|
|
if (pResDes->u.DeviceSpecificData.DataSize == 0) {
|
|
//
|
|
// no legacy data or class-specific data
|
|
//
|
|
;
|
|
} else if (pResDes->u.DeviceSpecificData.Reserved2 == 0) {
|
|
//
|
|
// add space for legacy data
|
|
//
|
|
*pulSize += pResDes->u.DeviceSpecificData.DataSize - 1;
|
|
} else {
|
|
//
|
|
// add space for class-specific data and/or legacy data
|
|
//
|
|
*pulSize += pResDes->u.DeviceSpecificData.Reserved1 +
|
|
pResDes->u.DeviceSpecificData.Reserved2 - 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------
|
|
// Specified log conf type contains requirements data only
|
|
//-------------------------------------------------------------
|
|
|
|
else if (RegDataType == REG_RESOURCE_REQUIREMENTS_LIST) {
|
|
|
|
PIO_RESOURCE_DESCRIPTOR pReqDes = (PIO_RESOURCE_DESCRIPTOR)pRD;
|
|
LPBYTE pLastReqAddr = (LPBYTE)pList + ulListSize - 1;
|
|
|
|
//
|
|
// calculate data size required (in terms of ConfigMgr structures)
|
|
//
|
|
*pulSize = GetReqDesSize(ResourceID, pReqDes, pLastReqAddr, ulFlags);
|
|
}
|
|
|
|
Clean0:
|
|
NOTHING;
|
|
|
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|
Status = CR_FAILURE;
|
|
}
|
|
|
|
if (hKey != NULL) {
|
|
RegCloseKey(hKey);
|
|
}
|
|
if (pList != NULL) {
|
|
HeapFree(ghPnPHeap, 0, pList);
|
|
}
|
|
|
|
return Status;
|
|
|
|
} // PNP_GetResDesDataSize
|
|
|
|
|
|
|
|
CONFIGRET
|
|
PNP_ModifyResDes(
|
|
IN handle_t hBinding,
|
|
IN LPWSTR pDeviceID,
|
|
IN ULONG LogConfTag,
|
|
IN ULONG LogConfType,
|
|
IN RESOURCEID CurrentResourceID,
|
|
IN RESOURCEID NewResourceID,
|
|
IN ULONG ResourceTag,
|
|
IN LPBYTE ResourceData,
|
|
IN ULONG ResourceLen,
|
|
IN ULONG ulFlags
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This the server-side of an RPC remote call. This routine modifies
|
|
the specified res des.
|
|
|
|
Arguments:
|
|
|
|
hBinding RPC binding handle.
|
|
|
|
pDeviceID Null-terminated device instance id string.
|
|
|
|
LogConfTag Specifies the log conf within a given type.
|
|
|
|
LogConfType Specifies the log conf type.
|
|
|
|
ResourceID Specifies the resource type.
|
|
|
|
ResourceIndex Returns with resource within a given type.
|
|
|
|
ResourceData New resource data (of ResourceID type).
|
|
|
|
ResourceLen Size of ResourceData 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 supplied is assumed to be that native to the
|
|
platform of the caller.
|
|
|
|
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 ulListSize = 0, ulOldSize = 0, ulNewSize = 0, ulSize = 0,
|
|
ulOldCount = 0, ulNewCount = 0, RegDataType = 0, ulCount = 0;
|
|
LONG AddSize = 0;
|
|
LPBYTE pList = NULL, pRD = NULL, pLogConf = NULL,
|
|
pTemp = NULL, pNext = NULL;
|
|
|
|
|
|
try {
|
|
//
|
|
// verify client access
|
|
//
|
|
if (!VerifyClientAccess(hBinding, &gLuidLoadDriverPrivilege)) {
|
|
Status = CR_ACCESS_DENIED;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// validate parameters
|
|
//
|
|
if (INVALID_FLAGS(ulFlags, CM_RESDES_WIDTH_BITS)) {
|
|
Status = CR_INVALID_FLAG;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// validate res des size
|
|
//
|
|
if (ResourceLen < GetResDesSize(NewResourceID, ulFlags)) {
|
|
Status = CR_INVALID_DATA;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// make sure original caller didn't specify root devnode
|
|
//
|
|
if (!IsLegalDeviceId(pDeviceID) || IsRootDeviceID(pDeviceID)) {
|
|
Status = CR_INVALID_LOG_CONF;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// open a key to the device's LogConf subkey
|
|
//
|
|
Status = OpenLogConfKey(pDeviceID, LogConfType, &hKey);
|
|
if (Status != CR_SUCCESS) {
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// Retrieve log conf data from the registry
|
|
//
|
|
Status = GetLogConfData(hKey, LogConfType,
|
|
&RegDataType, szValueName,
|
|
&pList, &ulListSize);
|
|
if (Status != CR_SUCCESS) {
|
|
Status = CR_INVALID_RES_DES; // log conf doesn't exist
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// seek to the res des that matches the resource tag.
|
|
//
|
|
if (!FindResDes(pList, RegDataType, LogConfTag,
|
|
ResourceTag, CurrentResourceID, &pRD, &pLogConf, &ulCount)) {
|
|
|
|
Status = CR_INVALID_RES_DES;
|
|
goto Clean0;
|
|
}
|
|
|
|
//-------------------------------------------------------------
|
|
// Specified log conf type contains Resource Data only
|
|
//-------------------------------------------------------------
|
|
|
|
if (RegDataType == REG_RESOURCE_LIST) {
|
|
|
|
PCM_RESOURCE_LIST pResList = (PCM_RESOURCE_LIST)pList;
|
|
PCM_FULL_RESOURCE_DESCRIPTOR pRes = (PCM_FULL_RESOURCE_DESCRIPTOR)pLogConf;
|
|
PCM_PARTIAL_RESOURCE_DESCRIPTOR pResDes = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)pRD;
|
|
|
|
//
|
|
// If new res des type is ClassSpecific, then it must be the last
|
|
// res des that is attempting to be modified (only last res des can
|
|
// be class specific).
|
|
//
|
|
if (NewResourceID == ResType_ClassSpecific &&
|
|
ResourceTag != RESDES_CS_TAG) {
|
|
|
|
Status = CR_INVALID_RES_DES;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// calculate the current size and the new size of the res des data
|
|
//
|
|
ulNewSize = ulOldSize = sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
|
|
|
|
if (CurrentResourceID == ResType_ClassSpecific) {
|
|
ulOldSize += pResDes->u.DeviceSpecificData.DataSize;
|
|
}
|
|
|
|
if (NewResourceID == ResType_ClassSpecific) {
|
|
|
|
PCS_RESOURCE pCsRes = (PCS_RESOURCE)ResourceData;
|
|
|
|
ulNewSize += sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) +
|
|
sizeof(GUID) +
|
|
pCsRes->CS_Header.CSD_SignatureLength +
|
|
pCsRes->CS_Header.CSD_LegacyDataSize;
|
|
}
|
|
|
|
//
|
|
// How much does data need to grow/shrink to accomodate the change?
|
|
//
|
|
AddSize = ulNewSize - ulOldSize;
|
|
|
|
//
|
|
// reallocate the buffers and shrink/expand the contents as
|
|
// necessary
|
|
//
|
|
if (AddSize != 0) {
|
|
|
|
if (AddSize > 0) {
|
|
//
|
|
// only bother reallocating if the buffer size is growing
|
|
//
|
|
ULONG ulOffset = (ULONG)((ULONG_PTR)pResDes - (ULONG_PTR)pResList);
|
|
|
|
pResList = HeapReAlloc(ghPnPHeap, 0, pResList, ulListSize + AddSize);
|
|
if (pResList == NULL) {
|
|
Status = CR_OUT_OF_MEMORY;
|
|
goto Clean0;
|
|
}
|
|
pList = (LPBYTE)pResList;
|
|
pResDes = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)((LPBYTE)pResList + ulOffset);
|
|
}
|
|
|
|
//
|
|
// if not the last lc and rd, then need to move the following data
|
|
// either up or down to account for changed res des data size
|
|
//
|
|
if ((LogConfTag != pResList->Count - 1) ||
|
|
((ResourceTag != pRes->PartialResourceList.Count - 1) &&
|
|
ResourceTag != RESDES_CS_TAG)) {
|
|
|
|
pNext = (LPBYTE)((LPBYTE)pResDes + ulOldSize);
|
|
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);
|
|
memcpy((LPBYTE)((LPBYTE)pResDes + ulNewSize), pTemp, ulSize);
|
|
}
|
|
}
|
|
|
|
//
|
|
// write out modified data
|
|
//
|
|
Status = ResDesToNtResource(ResourceData, NewResourceID, ResourceLen,
|
|
pResDes, ResourceTag, ulFlags);
|
|
}
|
|
|
|
//-------------------------------------------------------------
|
|
// Specified log conf type contains requirements data only
|
|
//-------------------------------------------------------------
|
|
|
|
else if (RegDataType == REG_RESOURCE_REQUIREMENTS_LIST) {
|
|
|
|
PIO_RESOURCE_REQUIREMENTS_LIST pReqList = (PIO_RESOURCE_REQUIREMENTS_LIST)pList;
|
|
PIO_RESOURCE_LIST pReq = (PIO_RESOURCE_LIST)pLogConf;
|
|
PIO_RESOURCE_DESCRIPTOR pReqDes = (PIO_RESOURCE_DESCRIPTOR)pRD;
|
|
LPBYTE pLastReqAddr = (LPBYTE)pReqList + ulListSize - 1;
|
|
PGENERIC_RESOURCE pGenRes = (PGENERIC_RESOURCE)ResourceData;
|
|
|
|
//
|
|
// Can't add class specific resdes to this type of log conf
|
|
//
|
|
if (NewResourceID == ResType_ClassSpecific) {
|
|
Status = CR_INVALID_RES_DES;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// calculate the current size and the new size of the res des data
|
|
//
|
|
ulOldCount = RANGE_COUNT(pReqDes, pLastReqAddr);
|
|
ulOldSize = sizeof(IO_RESOURCE_DESCRIPTOR) * ulOldCount;
|
|
|
|
ulNewSize = sizeof(IO_RESOURCE_DESCRIPTOR) *
|
|
pGenRes->GENERIC_Header.GENERIC_Count;
|
|
|
|
//
|
|
// How much does data need to grow/shrink to accomodate the change?
|
|
//
|
|
AddSize = ulNewSize - ulOldSize;
|
|
|
|
//
|
|
// reallocate the buffers and shrink/expand the contents as
|
|
// necessary
|
|
//
|
|
if (AddSize != 0) {
|
|
|
|
if (AddSize > 0) {
|
|
//
|
|
// only bother reallocating if the buffer size is growing
|
|
//
|
|
ULONG ulOffset = (ULONG)((ULONG_PTR)pReqDes - (ULONG_PTR)pReqList);
|
|
|
|
pReqList = HeapReAlloc(ghPnPHeap, 0, pReqList, ulListSize + AddSize);
|
|
if (pReqList == NULL) {
|
|
Status = CR_OUT_OF_MEMORY;
|
|
goto Clean0;
|
|
}
|
|
pList = (LPBYTE)pReqList;
|
|
pReqDes = (PIO_RESOURCE_DESCRIPTOR)((LPBYTE)pReqList + ulOffset);
|
|
}
|
|
|
|
//
|
|
// set to last index for this res des (whole)
|
|
//
|
|
ulCount += RANGE_COUNT(pReqDes, (LPBYTE)((ULONG_PTR)pList + ulListSize));
|
|
|
|
//
|
|
// if not the last lc and rd, then need to move the following data
|
|
// either up or down to account for changed res des data size
|
|
//
|
|
if (LogConfTag != pReqList->AlternativeLists - 1 ||
|
|
ulCount != pReq->Count - 1) {
|
|
|
|
pNext = (LPBYTE)((LPBYTE)pReqDes + ulOldSize);
|
|
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);
|
|
memcpy((LPBYTE)((LPBYTE)pReqDes + ulNewSize), pTemp, ulSize);
|
|
}
|
|
}
|
|
|
|
//
|
|
// write out modified data
|
|
//
|
|
Status = ResDesToNtRequirements(ResourceData, NewResourceID, ResourceLen,
|
|
pReqDes, &ulNewCount, ResourceTag, ulFlags);
|
|
|
|
if (Status == CR_SUCCESS) {
|
|
//
|
|
// update the requirements header (changes will be zero if CS)
|
|
//
|
|
pReq->Count += ulNewCount - ulOldCount;
|
|
pReqList->ListSize = ulListSize + AddSize;
|
|
}
|
|
}
|
|
|
|
if (Status == CR_SUCCESS) {
|
|
|
|
//
|
|
// Write out the new/updated log conf list to the registry
|
|
//
|
|
if (RegSetValueEx(hKey, szValueName, 0, RegDataType, pList,
|
|
ulListSize + AddSize) != 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_ModifyResDes
|
|
|
|
|
|
|
|
CONFIGRET
|
|
PNP_DetectResourceConflict(
|
|
IN handle_t hBinding,
|
|
IN LPWSTR pDeviceID,
|
|
IN RESOURCEID ResourceID,
|
|
IN LPBYTE ResourceData,
|
|
IN ULONG ResourceLen,
|
|
OUT PBOOL pbConflictDetected,
|
|
IN ULONG ulFlags
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This the server-side of an RPC remote call. This routine detects
|
|
conflicts with the specified res des.
|
|
|
|
Arguments:
|
|
|
|
hBinding RPC binding handle, not used.
|
|
|
|
pDeviceID Null-terminated device instance id string.
|
|
|
|
ResourceID Specifies the resource type.
|
|
|
|
ResourceData Specifies resource data (of ResourceID type).
|
|
|
|
ResourceLen Size of ResourceData in bytes.
|
|
|
|
pbConflictDetected Returns whether a conflict was detected.
|
|
|
|
ulFlags Not used, must be zero.
|
|
|
|
Return Value:
|
|
|
|
** PRESENTLY, ALWAYS RETURNS CR_CALL_NOT_IMPLEMENTED **
|
|
|
|
Note:
|
|
|
|
This routine is currently not implemented. It initializes
|
|
pbConflictDetected to FALSE, and returns CR_CALL_NOT_IMPLEMENTED.
|
|
|
|
--*/
|
|
|
|
{
|
|
UNREFERENCED_PARAMETER(hBinding);
|
|
UNREFERENCED_PARAMETER(pDeviceID);
|
|
UNREFERENCED_PARAMETER(ResourceID);
|
|
UNREFERENCED_PARAMETER(ResourceData);
|
|
UNREFERENCED_PARAMETER(ResourceLen);
|
|
UNREFERENCED_PARAMETER(ulFlags);
|
|
|
|
try {
|
|
//
|
|
// initialize output parameters
|
|
//
|
|
if (ARGUMENT_PRESENT(pbConflictDetected)) {
|
|
*pbConflictDetected = FALSE;
|
|
}
|
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|
NOTHING;
|
|
}
|
|
|
|
return CR_CALL_NOT_IMPLEMENTED;
|
|
|
|
} // PNP_DetectResourceConflict
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
// Private Utility Functions
|
|
//------------------------------------------------------------------------
|
|
|
|
BOOL
|
|
FindLogConf(
|
|
IN LPBYTE pList,
|
|
OUT LPBYTE *ppLogConf,
|
|
IN ULONG RegDataType,
|
|
IN ULONG ulTag
|
|
)
|
|
{
|
|
|
|
ULONG Index = 0;
|
|
|
|
//
|
|
// Input data is a Resource List
|
|
//
|
|
if (RegDataType == REG_RESOURCE_LIST) {
|
|
|
|
PCM_RESOURCE_LIST pResList = (PCM_RESOURCE_LIST)pList;
|
|
PCM_FULL_RESOURCE_DESCRIPTOR pRes = NULL;
|
|
|
|
if (ulTag >= pResList->Count) {
|
|
return FALSE;
|
|
}
|
|
|
|
pRes = (PCM_FULL_RESOURCE_DESCRIPTOR)(&pResList->List[0]); // first lc
|
|
for (Index = 0; Index < ulTag; Index++) {
|
|
pRes = AdvanceResourcePtr(pRes); // next lc
|
|
}
|
|
|
|
*ppLogConf = (LPBYTE)pRes;
|
|
}
|
|
|
|
//
|
|
// Input data is a Requirments List
|
|
//
|
|
else if (RegDataType == REG_RESOURCE_REQUIREMENTS_LIST) {
|
|
|
|
PIO_RESOURCE_REQUIREMENTS_LIST pReqList = (PIO_RESOURCE_REQUIREMENTS_LIST)pList;
|
|
PIO_RESOURCE_LIST pReq = NULL;
|
|
|
|
if (ulTag >= pReqList->AlternativeLists) {
|
|
return FALSE;
|
|
}
|
|
|
|
pReq = (PIO_RESOURCE_LIST)(&pReqList->List[0]); // first lc
|
|
for (Index = 0; Index < ulTag; Index++) {
|
|
pReq = AdvanceRequirementsPtr(pReq); // next lc
|
|
}
|
|
|
|
*ppLogConf = (LPBYTE)pReq;
|
|
|
|
} else {
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
} // FindLogConf
|
|
|
|
|
|
|
|
BOOL
|
|
FindResDes(
|
|
IN LPBYTE pList,
|
|
IN ULONG RegDataType,
|
|
IN ULONG ulLogConfTag,
|
|
IN ULONG ulResTag,
|
|
IN RESOURCEID ResType,
|
|
OUT LPBYTE *ppRD,
|
|
OUT LPBYTE *ppLogConf,
|
|
OUT PULONG pulSubIndex OPTIONAL
|
|
)
|
|
{
|
|
ULONG ulIndex;
|
|
|
|
//
|
|
// Input data is a Resource List
|
|
//
|
|
if (RegDataType == REG_RESOURCE_LIST) {
|
|
|
|
PCM_RESOURCE_LIST pResList = (PCM_RESOURCE_LIST)pList;
|
|
PCM_FULL_RESOURCE_DESCRIPTOR pRes = NULL;
|
|
PCM_PARTIAL_RESOURCE_DESCRIPTOR pResDes = NULL;
|
|
ULONG ulSubIndex;
|
|
ULONG ulResTagOffset;
|
|
|
|
if (ulLogConfTag != 0) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (pResList->Count == 0) {
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// The tag is just the res des index with the exception of a
|
|
// DeviceSpecificData type which has a unique tag. This is
|
|
// necessary because new res des's will always get placed at
|
|
// the end unless there's already a device specific res des,
|
|
// in which case new res des get added just before it.
|
|
//
|
|
if (ulResTag == RESDES_CS_TAG) {
|
|
//
|
|
// If there is a devicespecific res des, it will be the last.
|
|
//
|
|
pRes = (PCM_FULL_RESOURCE_DESCRIPTOR)&pResList->List[0]; // first lc
|
|
|
|
ulSubIndex = 0;
|
|
|
|
for (ulIndex = 0; ulIndex < (pResList->Count - 1); ulIndex++) {
|
|
ulSubIndex += pRes->PartialResourceList.Count;
|
|
pRes = AdvanceResourcePtr(pRes); // next lc
|
|
}
|
|
|
|
ulResTagOffset = pRes->PartialResourceList.Count - 1;
|
|
pResDes = &pRes->PartialResourceList.PartialDescriptors[ulResTagOffset];
|
|
|
|
if (pResDes->Type != CmResourceTypeDeviceSpecific) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (pulSubIndex) {
|
|
*pulSubIndex = ulSubIndex + ulResTagOffset; // for res list, subindex = index
|
|
}
|
|
|
|
} else {
|
|
|
|
pRes = (PCM_FULL_RESOURCE_DESCRIPTOR)&pResList->List[0]; // first lc
|
|
|
|
ulResTagOffset = ulResTag;
|
|
|
|
for (ulIndex = 0; ulIndex < pResList->Count; ulIndex++) {
|
|
|
|
if (ulResTagOffset >= pRes->PartialResourceList.Count) {
|
|
|
|
ulResTagOffset -= pRes->PartialResourceList.Count;
|
|
pRes = AdvanceResourcePtr(pRes); // next lc
|
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
if (ulResTagOffset >= pRes->PartialResourceList.Count) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (pulSubIndex) {
|
|
*pulSubIndex = ulResTag; // for res list, subindex = index = tag
|
|
}
|
|
pResDes = &pRes->PartialResourceList.PartialDescriptors[ulResTagOffset];
|
|
}
|
|
|
|
//
|
|
// Validate against res des type
|
|
//
|
|
if (pResDes->Type != NT_RES_TYPE(ResType)) {
|
|
return FALSE;
|
|
}
|
|
|
|
*ppLogConf = (LPBYTE)pRes;
|
|
*ppRD = (LPBYTE)pResDes;
|
|
}
|
|
|
|
//
|
|
// Input data is a Requirments List
|
|
//
|
|
else if (RegDataType == REG_RESOURCE_REQUIREMENTS_LIST) {
|
|
|
|
LPBYTE pLogConf = NULL;
|
|
PIO_RESOURCE_LIST pReq = NULL;
|
|
PIO_RESOURCE_DESCRIPTOR pReqDes = NULL;
|
|
ULONG Index, i = 0, Count = 0;
|
|
|
|
|
|
if (!FindLogConf(pList, &pLogConf, RegDataType, ulLogConfTag)) {
|
|
return FALSE;
|
|
}
|
|
|
|
pReq = (PIO_RESOURCE_LIST)pLogConf;
|
|
|
|
if (pReq == NULL || pReq->Count == 0 || ulResTag >= pReq->Count) {
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Find the res des that matches the specified tag. In this case the
|
|
// tag is the index based on res des groupings.
|
|
//
|
|
pReqDes = AdvanceRequirementsDescriptorPtr(&pReq->Descriptors[0], ulResTag, pReq->Count, &Count);
|
|
|
|
if (pReqDes == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (pulSubIndex) {
|
|
*pulSubIndex = Count;
|
|
}
|
|
|
|
//
|
|
// Validate against res des type
|
|
//
|
|
if (pReqDes->Type != NT_RES_TYPE(ResType)) {
|
|
return FALSE;
|
|
}
|
|
|
|
*ppLogConf = (LPBYTE)pReq;
|
|
*ppRD = (LPBYTE)pReqDes;
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
} // FindResDes
|
|
|
|
|
|
|
|
PIO_RESOURCE_DESCRIPTOR
|
|
AdvanceRequirementsDescriptorPtr(
|
|
IN PIO_RESOURCE_DESCRIPTOR pReqDesStart,
|
|
IN ULONG ulIncrement,
|
|
IN ULONG ulRemainingRanges,
|
|
OUT PULONG pulRangeCount
|
|
)
|
|
{
|
|
PIO_RESOURCE_DESCRIPTOR pReqDes = NULL;
|
|
ULONG i = 0, Count = 0;
|
|
|
|
//
|
|
// Advance requirements descriptor pointer by number passed
|
|
// in ulIncrement parameter. Return the actual index to the
|
|
// first range in this descriptor list and range count if
|
|
// desired. This routine assumes there is at least one more
|
|
// requirements descriptor in the list.
|
|
//
|
|
|
|
if (pReqDesStart == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
try {
|
|
|
|
pReqDes = pReqDesStart;
|
|
|
|
for (i = 0; i < ulIncrement; i++) {
|
|
//
|
|
// skip to next "whole" res des
|
|
//
|
|
if (Count < ulRemainingRanges &&
|
|
(pReqDes->Option == 0 ||
|
|
pReqDes->Option == IO_RESOURCE_PREFERRED ||
|
|
pReqDes->Option == IO_RESOURCE_DEFAULT)) {
|
|
//
|
|
// This is a valid Option, there may be one or more alternate
|
|
// descriptor in the set associated with this descriptor,
|
|
// treat the set as "one" descriptor. (loop through the
|
|
// descriptors until I find another non-alternative descriptor)
|
|
//
|
|
pReqDes++; // next range
|
|
Count++;
|
|
|
|
while (Count < ulRemainingRanges &&
|
|
(pReqDes->Option == IO_RESOURCE_ALTERNATIVE ||
|
|
pReqDes->Option == IO_RESOURCE_ALTERNATIVE + IO_RESOURCE_PREFERRED ||
|
|
pReqDes->Option == IO_RESOURCE_ALTERNATIVE + IO_RESOURCE_DEFAULT)) {
|
|
pReqDes++; // next range
|
|
Count++;
|
|
}
|
|
|
|
if (Count >= ulRemainingRanges) {
|
|
pReqDes = NULL;
|
|
Count = 0;
|
|
break;
|
|
}
|
|
} else {
|
|
|
|
//
|
|
// invalid Option value
|
|
//
|
|
pReqDes = NULL;
|
|
Count = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|
pReqDes = NULL;
|
|
Count = 0;
|
|
}
|
|
|
|
if (pulRangeCount) {
|
|
*pulRangeCount = Count;
|
|
}
|
|
|
|
return pReqDes;
|
|
} // AdvanceRequirementsDescriptorPtr
|
|
|
|
|
|
|
|
ULONG
|
|
RANGE_COUNT(
|
|
IN PIO_RESOURCE_DESCRIPTOR pReqDes,
|
|
IN LPBYTE pLastReqAddr
|
|
)
|
|
{
|
|
ULONG ulRangeCount = 0;
|
|
|
|
try {
|
|
|
|
if (pReqDes == NULL) {
|
|
goto Clean0;
|
|
}
|
|
|
|
ulRangeCount++;
|
|
|
|
if (pReqDes->Option == 0 ||
|
|
pReqDes->Option == IO_RESOURCE_PREFERRED ||
|
|
pReqDes->Option == IO_RESOURCE_DEFAULT) {
|
|
|
|
PIO_RESOURCE_DESCRIPTOR p = pReqDes;
|
|
p++;
|
|
|
|
while (((LPBYTE)p < pLastReqAddr) &&
|
|
(p->Option == IO_RESOURCE_ALTERNATIVE ||
|
|
p->Option == IO_RESOURCE_ALTERNATIVE + IO_RESOURCE_PREFERRED ||
|
|
p->Option == IO_RESOURCE_ALTERNATIVE + IO_RESOURCE_DEFAULT)) {
|
|
|
|
ulRangeCount++;
|
|
p++; // skip to next res des
|
|
}
|
|
}
|
|
|
|
Clean0:
|
|
NOTHING;
|
|
|
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|
ulRangeCount = 0;
|
|
}
|
|
|
|
return ulRangeCount;
|
|
|
|
} // RANGE_COUNT
|
|
|
|
|
|
|
|
ULONG
|
|
GetResDesSize(
|
|
IN ULONG ResourceID,
|
|
IN ULONG ulFlags
|
|
)
|
|
{
|
|
switch (ResourceID) {
|
|
|
|
case ResType_Mem:
|
|
return sizeof(MEM_RESOURCE);
|
|
|
|
case ResType_IO:
|
|
return sizeof(IO_RESOURCE);
|
|
|
|
case ResType_DMA:
|
|
return sizeof(DMA_RESOURCE);
|
|
|
|
case ResType_IRQ:
|
|
if (ulFlags & CM_RESDES_WIDTH_64) {
|
|
return sizeof(IRQ_RESOURCE_64);
|
|
} else {
|
|
return sizeof(IRQ_RESOURCE_32);
|
|
}
|
|
|
|
case ResType_ClassSpecific:
|
|
return sizeof(CS_RESOURCE);
|
|
|
|
case ResType_DevicePrivate:
|
|
return sizeof(DEVPRIVATE_RESOURCE);
|
|
|
|
case ResType_BusNumber:
|
|
return sizeof(BUSNUMBER_RESOURCE);
|
|
|
|
case ResType_PcCardConfig:
|
|
return sizeof(PCCARD_RESOURCE);
|
|
|
|
case ResType_MfCardConfig:
|
|
return sizeof(MFCARD_RESOURCE);
|
|
|
|
default:
|
|
return 0;
|
|
}
|
|
|
|
} // GetResDesSize
|
|
|
|
|
|
|
|
ULONG
|
|
GetReqDesSize(
|
|
IN ULONG ResourceID,
|
|
IN PIO_RESOURCE_DESCRIPTOR pReqDes,
|
|
IN LPBYTE pLastReqAddr,
|
|
IN ULONG ulFlags
|
|
)
|
|
{
|
|
ULONG ulSize = 0;
|
|
|
|
switch (ResourceID) {
|
|
|
|
case ResType_Mem:
|
|
ulSize = sizeof(MEM_RESOURCE);
|
|
ulSize += (RANGE_COUNT(pReqDes, pLastReqAddr) - 1) * sizeof(MEM_RANGE);
|
|
break;
|
|
|
|
case ResType_IO:
|
|
ulSize = sizeof(IO_RESOURCE);
|
|
ulSize += (RANGE_COUNT(pReqDes, pLastReqAddr) - 1) * sizeof(IO_RANGE);
|
|
break;
|
|
|
|
case ResType_DMA:
|
|
ulSize = sizeof(DMA_RESOURCE);
|
|
ulSize += (RANGE_COUNT(pReqDes, pLastReqAddr) - 1) * sizeof(DMA_RANGE);
|
|
break;
|
|
|
|
case ResType_IRQ:
|
|
if (ulFlags & CM_RESDES_WIDTH_64) {
|
|
ulSize = sizeof(IRQ_RESOURCE_64);
|
|
} else {
|
|
ulSize = sizeof(IRQ_RESOURCE_32);
|
|
}
|
|
ulSize += (RANGE_COUNT(pReqDes, pLastReqAddr) - 1) * sizeof(IRQ_RANGE);
|
|
break;
|
|
|
|
case ResType_DevicePrivate:
|
|
ulSize = sizeof(DEVPRIVATE_RESOURCE);
|
|
ulSize += (RANGE_COUNT(pReqDes, pLastReqAddr) - 1) * sizeof(DEVPRIVATE_RANGE);
|
|
break;
|
|
|
|
case ResType_BusNumber:
|
|
ulSize = sizeof(BUSNUMBER_RESOURCE);
|
|
ulSize += (RANGE_COUNT(pReqDes, pLastReqAddr) - 1) * sizeof(BUSNUMBER_RANGE);
|
|
break;
|
|
|
|
case ResType_PcCardConfig:
|
|
//
|
|
// Non-arbitrated types don't have a range side in the user-mode structs
|
|
//
|
|
ulSize = sizeof(PCCARD_RESOURCE);
|
|
break;
|
|
|
|
case ResType_MfCardConfig:
|
|
//
|
|
// Non-arbitrated types don't have a range side in the user-mode structs
|
|
//
|
|
ulSize = sizeof(MFCARD_RESOURCE);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return ulSize;
|
|
|
|
} // GetReqDesSize
|
|
|
|
|
|
|
|
UCHAR
|
|
NT_RES_TYPE(
|
|
IN RESOURCEID ResourceID
|
|
)
|
|
{
|
|
ULONG resid = 0;
|
|
|
|
if ((ResourceID < 0x06)) {
|
|
|
|
//
|
|
// First handle the divergent cases that can only be mapped
|
|
// on a case by case basis. These are the values from zero
|
|
// through five plus the special class specific case.
|
|
//
|
|
switch(ResourceID) {
|
|
|
|
case ResType_None:
|
|
return CmResourceTypeNull;
|
|
break;
|
|
|
|
case ResType_Mem:
|
|
return CmResourceTypeMemory;
|
|
|
|
case ResType_IO:
|
|
return CmResourceTypePort;
|
|
|
|
case ResType_DMA:
|
|
return CmResourceTypeDma;
|
|
|
|
case ResType_IRQ:
|
|
return CmResourceTypeInterrupt;
|
|
|
|
case ResType_DoNotUse:
|
|
return (UCHAR)-1;
|
|
|
|
DEFAULT_UNREACHABLE;
|
|
}
|
|
|
|
} else if (ResourceID == ResType_ClassSpecific) {
|
|
|
|
//
|
|
// ResType_ClassSpecific is another special case.
|
|
//
|
|
return CmResourceTypeDeviceSpecific;
|
|
|
|
} else {
|
|
|
|
//
|
|
// For all other cases, rules apply as to how to map a kernel-mode
|
|
// resource type id to a user-mode resource type id.
|
|
//
|
|
|
|
if (ResourceID >= 0x8080) {
|
|
|
|
//
|
|
// Anything larger this can't be mapped to the kernel-mode USHORT
|
|
// values so it's invalid.
|
|
//
|
|
|
|
return (UCHAR)-1;
|
|
|
|
} else if (!(ResourceID & ResType_Ignored_Bit)) {
|
|
|
|
//
|
|
// Values in the range [0x6,0x8000] use the same values
|
|
// for ConfigMgr as for kernel-mode.
|
|
//
|
|
return (UCHAR)ResourceID;
|
|
|
|
} else if (ResourceID & ResType_Ignored_Bit) {
|
|
|
|
//
|
|
// For the non arbitrated types (0x8000 bit set), do special
|
|
// mapping to get the kernel-mode resource id type.
|
|
//
|
|
|
|
resid = ResourceID;
|
|
resid &= ~(ResType_Ignored_Bit); // clear um non-arbitrated bit
|
|
resid |= CmResourceTypeNonArbitrated; // set km non-arbitrated bit
|
|
return (UCHAR)resid;
|
|
|
|
} else {
|
|
return (CHAR)-1;
|
|
}
|
|
}
|
|
|
|
} // NT_RES_TYPE
|
|
|
|
|
|
|
|
ULONG
|
|
CM_RES_TYPE(
|
|
IN UCHAR ResourceType
|
|
)
|
|
{
|
|
ULONG resid = 0;
|
|
|
|
if ((ResourceType < 0x06)) {
|
|
|
|
//
|
|
// First handle the divergent cases that can only be mapped
|
|
// on a case by case basis. These are the values from zero
|
|
// through five plus the special class specific case.
|
|
//
|
|
|
|
switch(ResourceType) {
|
|
|
|
case CmResourceTypeNull:
|
|
return ResType_None;
|
|
|
|
case CmResourceTypePort:
|
|
return ResType_IO;
|
|
|
|
case CmResourceTypeInterrupt:
|
|
return ResType_IRQ;
|
|
|
|
case CmResourceTypeMemory:
|
|
return ResType_Mem;
|
|
|
|
case CmResourceTypeDma:
|
|
return ResType_DMA;
|
|
|
|
case CmResourceTypeDeviceSpecific:
|
|
return ResType_ClassSpecific;
|
|
|
|
DEFAULT_UNREACHABLE;
|
|
}
|
|
|
|
} else {
|
|
|
|
//
|
|
// For all other cases, rules apply as to how to map a kernel-mode
|
|
// resource type id to a user-mode resource type id.
|
|
//
|
|
|
|
if (!(ResourceType & CmResourceTypeNonArbitrated)) {
|
|
|
|
//
|
|
// Values in the range [0x6,0x80] use the same values
|
|
// for ConfigMgr as for kernel-mode.
|
|
//
|
|
return (ULONG)ResourceType;
|
|
|
|
} else if (ResourceType & CmResourceTypeNonArbitrated) {
|
|
|
|
//
|
|
// For the non arbitrated types (0x80 bit set), do special
|
|
// mapping to get the user-mode resource id type.
|
|
//
|
|
|
|
resid = (ULONG)ResourceType;
|
|
resid &= ~(CmResourceTypeNonArbitrated); // clear km non-arbitrated bit
|
|
resid |= ResType_Ignored_Bit; // set um non-arbitrated bit
|
|
return resid;
|
|
|
|
} else {
|
|
return (ULONG)-1;
|
|
}
|
|
}
|
|
|
|
} // NT_RES_TYPE
|
|
|
|
|
|
|
|
CONFIGRET
|
|
ResDesToNtResource(
|
|
IN PCVOID ResourceData,
|
|
IN RESOURCEID ResourceType,
|
|
IN ULONG ResourceLen,
|
|
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pResDes,
|
|
IN ULONG ulTag,
|
|
IN ULONG ulFlags
|
|
)
|
|
{
|
|
CONFIGRET Status = CR_SUCCESS;
|
|
|
|
UNREFERENCED_PARAMETER(ulTag);
|
|
|
|
//
|
|
// fill in resource type specific info
|
|
//
|
|
switch (ResourceType) {
|
|
|
|
case ResType_Mem: {
|
|
|
|
//-------------------------------------------------------
|
|
// Memory Resource Type
|
|
//-------------------------------------------------------
|
|
|
|
//
|
|
// NOTE: pMemData->MEM_Header.MD_Reserved is not mapped
|
|
// pMemData->MEM_Data.MR_Reserved is not mapped
|
|
//
|
|
|
|
PMEM_RESOURCE pMemData = (PMEM_RESOURCE)ResourceData;
|
|
|
|
//
|
|
// validate resource data
|
|
//
|
|
if (ResourceLen < sizeof(MEM_RESOURCE)) {
|
|
Status = CR_INVALID_RES_DES;
|
|
goto Clean0;
|
|
}
|
|
|
|
if (pMemData->MEM_Header.MD_Type != MType_Range) {
|
|
Status = CR_INVALID_RES_DES;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// copy MEM_DES info to CM_PARTIAL_RESOURCE_DESCRIPTOR format
|
|
//
|
|
pResDes->Type = CmResourceTypeMemory;
|
|
pResDes->ShareDisposition = CmResourceShareUndetermined;
|
|
//pResDes->ShareDisposition = MapToNtDisposition(pMemData->MEM_Header.MD_Flags, 0);
|
|
pResDes->Flags = MapToNtMemoryFlags(pMemData->MEM_Header.MD_Flags);
|
|
|
|
pResDes->u.Memory.Start.HighPart = HIDWORD(pMemData->MEM_Header.MD_Alloc_Base);
|
|
pResDes->u.Memory.Start.LowPart = LODWORD(pMemData->MEM_Header.MD_Alloc_Base);
|
|
|
|
pResDes->u.Memory.Length = (DWORD)(pMemData->MEM_Header.MD_Alloc_End -
|
|
pMemData->MEM_Header.MD_Alloc_Base + 1);
|
|
break;
|
|
}
|
|
|
|
|
|
case ResType_IO: {
|
|
|
|
//-------------------------------------------------------
|
|
// IO Port Resource Type
|
|
//
|
|
// NOTE: alias info lost during this conversion process
|
|
//-------------------------------------------------------
|
|
|
|
PIO_RESOURCE pIoData = (PIO_RESOURCE)ResourceData;
|
|
|
|
//
|
|
// validate resource data
|
|
//
|
|
if (ResourceLen < sizeof(IO_RESOURCE)) {
|
|
Status = CR_FAILURE;
|
|
goto Clean0;
|
|
}
|
|
|
|
if (pIoData->IO_Header.IOD_Type != IOType_Range) {
|
|
Status = CR_INVALID_RES_DES;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// copy IO_DES info to CM_PARTIAL_RESOURCE_DESCRIPTOR format
|
|
//
|
|
pResDes->Type = CmResourceTypePort;
|
|
pResDes->ShareDisposition = CmResourceShareUndetermined;
|
|
//pResDes->ShareDisposition = MapToNtDisposition(pIoData->IO_Header.IOD_DesFlags, 0);
|
|
pResDes->Flags = MapToNtPortFlags(pIoData->IO_Header.IOD_DesFlags, 0);
|
|
|
|
pResDes->u.Port.Start.HighPart = HIDWORD(pIoData->IO_Header.IOD_Alloc_Base);
|
|
pResDes->u.Port.Start.LowPart = LODWORD(pIoData->IO_Header.IOD_Alloc_Base);
|
|
|
|
pResDes->u.Port.Length = (DWORD)(pIoData->IO_Header.IOD_Alloc_End -
|
|
pIoData->IO_Header.IOD_Alloc_Base + 1);
|
|
break;
|
|
}
|
|
|
|
|
|
case ResType_DMA: {
|
|
|
|
//-------------------------------------------------------
|
|
// DMA Resource Type
|
|
//-------------------------------------------------------
|
|
|
|
//
|
|
// Note: u.Dma.Port is not mapped
|
|
// u.Dma.Reserved is not mapped
|
|
//
|
|
|
|
PDMA_RESOURCE pDmaData = (PDMA_RESOURCE)ResourceData;
|
|
|
|
//
|
|
// validate resource data
|
|
//
|
|
if (ResourceLen < sizeof(DMA_RESOURCE)) {
|
|
Status = CR_FAILURE;
|
|
goto Clean0;
|
|
}
|
|
|
|
if (pDmaData->DMA_Header.DD_Type != DType_Range) {
|
|
Status = CR_INVALID_RES_DES;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// copy DMA_DES info to CM_PARTIAL_RESOURCE_DESCRIPTOR format
|
|
//
|
|
pResDes->Type = CmResourceTypeDma;
|
|
pResDes->ShareDisposition = CmResourceShareUndetermined;
|
|
//pResDes->ShareDisposition = MapToNtDisposition(pDmaData->DMA_Header.DD_Flags, 0);
|
|
pResDes->Flags = MapToNtDmaFlags(pDmaData->DMA_Header.DD_Flags);
|
|
|
|
pResDes->u.Dma.Channel = pDmaData->DMA_Header.DD_Alloc_Chan;
|
|
pResDes->u.Dma.Port = 0;
|
|
pResDes->u.Dma.Reserved1 = 0;
|
|
|
|
break;
|
|
}
|
|
|
|
|
|
case ResType_IRQ: {
|
|
|
|
//-------------------------------------------------------
|
|
// IRQ Resource Type
|
|
//-------------------------------------------------------
|
|
|
|
if (ulFlags & CM_RESDES_WIDTH_64) {
|
|
//
|
|
// CM_RESDES_WIDTH_64
|
|
//
|
|
|
|
PIRQ_RESOURCE_64 pIrqData = (PIRQ_RESOURCE_64)ResourceData;
|
|
|
|
//
|
|
// validate resource data
|
|
//
|
|
if (ResourceLen < GetResDesSize(ResourceType, ulFlags)) {
|
|
Status = CR_FAILURE;
|
|
goto Clean0;
|
|
}
|
|
|
|
if (pIrqData->IRQ_Header.IRQD_Type != IRQType_Range) {
|
|
Status = CR_INVALID_RES_DES;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// copy IRQ_DES info to CM_PARTIAL_RESOURCE_DESCRIPTOR format
|
|
//
|
|
pResDes->Type = CmResourceTypeInterrupt;
|
|
pResDes->ShareDisposition = MapToNtIrqShare(pIrqData->IRQ_Header.IRQD_Flags);
|
|
//pResDes->ShareDisposition = MapToNtDisposition(pIrqData->IRQ_Header.IRQD_Flags, 1);
|
|
pResDes->Flags = MapToNtIrqFlags(pIrqData->IRQ_Header.IRQD_Flags);
|
|
|
|
pResDes->u.Interrupt.Level = pIrqData->IRQ_Header.IRQD_Alloc_Num;
|
|
pResDes->u.Interrupt.Vector = pIrqData->IRQ_Header.IRQD_Alloc_Num;
|
|
|
|
#ifdef _WIN64
|
|
pResDes->u.Interrupt.Affinity = pIrqData->IRQ_Header.IRQD_Affinity;
|
|
#else // !_WIN64
|
|
pResDes->u.Interrupt.Affinity = (ULONG)pIrqData->IRQ_Header.IRQD_Affinity;
|
|
#endif // !_WIN64
|
|
|
|
} else {
|
|
//
|
|
// CM_RESDES_WIDTH_32
|
|
//
|
|
|
|
PIRQ_RESOURCE_32 pIrqData = (PIRQ_RESOURCE_32)ResourceData;
|
|
|
|
//
|
|
// validate resource data
|
|
//
|
|
if (ResourceLen < GetResDesSize(ResourceType, ulFlags)) {
|
|
Status = CR_FAILURE;
|
|
goto Clean0;
|
|
}
|
|
|
|
if (pIrqData->IRQ_Header.IRQD_Type != IRQType_Range) {
|
|
Status = CR_INVALID_RES_DES;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// copy IRQ_DES info to CM_PARTIAL_RESOURCE_DESCRIPTOR format
|
|
//
|
|
pResDes->Type = CmResourceTypeInterrupt;
|
|
pResDes->ShareDisposition = MapToNtIrqShare(pIrqData->IRQ_Header.IRQD_Flags);
|
|
//pResDes->ShareDisposition = MapToNtDisposition(pIrqData->IRQ_Header.IRQD_Flags, 1);
|
|
pResDes->Flags = MapToNtIrqFlags(pIrqData->IRQ_Header.IRQD_Flags);
|
|
|
|
pResDes->u.Interrupt.Level = pIrqData->IRQ_Header.IRQD_Alloc_Num;
|
|
pResDes->u.Interrupt.Vector = pIrqData->IRQ_Header.IRQD_Alloc_Num;
|
|
|
|
pResDes->u.Interrupt.Affinity = pIrqData->IRQ_Header.IRQD_Affinity;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case ResType_DevicePrivate: {
|
|
|
|
//-------------------------------------------------------
|
|
// Device Private Resource Type
|
|
//-------------------------------------------------------
|
|
|
|
PDEVPRIVATE_RESOURCE pPrvData = (PDEVPRIVATE_RESOURCE)ResourceData;
|
|
|
|
//
|
|
// validate resource data
|
|
//
|
|
if (ResourceLen < sizeof(DEVPRIVATE_RESOURCE)) {
|
|
Status = CR_INVALID_RES_DES;
|
|
goto Clean0;
|
|
}
|
|
|
|
if (pPrvData->PRV_Header.PD_Type != PType_Range) {
|
|
Status = CR_INVALID_RES_DES;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// copy DEVICEPRIVATE_DES info to CM_PARTIAL_RESOURCE_DESCRIPTOR format
|
|
//
|
|
pResDes->Type = CmResourceTypeDevicePrivate;
|
|
pResDes->ShareDisposition = CmResourceShareUndetermined;
|
|
pResDes->Flags = (USHORT)pPrvData->PRV_Header.PD_Flags;
|
|
|
|
pResDes->u.DevicePrivate.Data[0] = pPrvData->PRV_Header.PD_Data1;
|
|
pResDes->u.DevicePrivate.Data[1] = pPrvData->PRV_Header.PD_Data2;
|
|
pResDes->u.DevicePrivate.Data[2] = pPrvData->PRV_Header.PD_Data3;
|
|
break;
|
|
}
|
|
|
|
|
|
case ResType_BusNumber: {
|
|
|
|
//-------------------------------------------------------
|
|
// Bus Number Resource Type
|
|
//-------------------------------------------------------
|
|
|
|
PBUSNUMBER_RESOURCE pBusData = (PBUSNUMBER_RESOURCE)ResourceData;
|
|
|
|
//
|
|
// validate resource data
|
|
//
|
|
if (ResourceLen < sizeof(BUSNUMBER_RESOURCE)) {
|
|
Status = CR_INVALID_RES_DES;
|
|
goto Clean0;
|
|
}
|
|
|
|
if (pBusData->BusNumber_Header.BUSD_Type != BusNumberType_Range) {
|
|
Status = CR_INVALID_RES_DES;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// copy BUSNUMBER_DES info to CM_PARTIAL_RESOURCE_DESCRIPTOR format
|
|
//
|
|
pResDes->Type = CmResourceTypeBusNumber;
|
|
pResDes->ShareDisposition = CmResourceShareUndetermined;
|
|
pResDes->Flags = (USHORT)pBusData->BusNumber_Header.BUSD_Flags;
|
|
|
|
pResDes->u.BusNumber.Start = pBusData->BusNumber_Header.BUSD_Alloc_Base;
|
|
pResDes->u.BusNumber.Length = pBusData->BusNumber_Header.BUSD_Alloc_End;
|
|
pResDes->u.BusNumber.Reserved = 0;
|
|
break;
|
|
}
|
|
|
|
|
|
case ResType_PcCardConfig: {
|
|
|
|
//-------------------------------------------------------
|
|
// PcCarConfig Resource Type
|
|
//-------------------------------------------------------
|
|
|
|
PPCCARD_RESOURCE pPcData = (PPCCARD_RESOURCE)ResourceData;
|
|
ULONG index;
|
|
ULONG flags;
|
|
ULONG waitstate[2];
|
|
|
|
//
|
|
// validate resource data
|
|
//
|
|
if (ResourceLen < sizeof(PCCARD_RESOURCE)) {
|
|
Status = CR_INVALID_RES_DES;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// The following macros use bit manipulation, initialize data
|
|
// fields first.
|
|
//
|
|
|
|
pResDes->u.DevicePrivate.Data[0] = 0;
|
|
pResDes->u.DevicePrivate.Data[1] = 0;
|
|
pResDes->u.DevicePrivate.Data[2] = 0;
|
|
|
|
//
|
|
// copy PCCARD_DES info to CM_PARTIAL_RESOURCE_DESCRIPTOR format
|
|
//
|
|
PCMRES_SET_DESCRIPTOR_TYPE(pResDes, DPTYPE_PCMCIA_CONFIGURATION);
|
|
PCMRES_SET_CONFIG_INDEX(pResDes, pPcData->PcCard_Header.PCD_ConfigIndex);
|
|
PCMRES_SET_MEMORY_CARDBASE(pResDes, 0, pPcData->PcCard_Header.PCD_MemoryCardBase1);
|
|
PCMRES_SET_MEMORY_CARDBASE(pResDes, 1, pPcData->PcCard_Header.PCD_MemoryCardBase2);
|
|
|
|
flags = pPcData->PcCard_Header.PCD_Flags;
|
|
|
|
if (flags & (fPCD_MEM_16 | fPCD_MEM1_16)) {
|
|
PCMRES_SET_MEMORY_FLAG(pResDes, 0, PCMRESF_MEM_16BIT_ACCESS);
|
|
}
|
|
if (flags & (fPCD_MEM_16 | fPCD_MEM2_16)) {
|
|
PCMRES_SET_MEMORY_FLAG(pResDes, 1, PCMRESF_MEM_16BIT_ACCESS);
|
|
}
|
|
|
|
if (flags & fPCD_MEM1_A) {
|
|
PCMRES_SET_MEMORY_FLAG(pResDes, 0, PCMRESF_MEM_ATTRIBUTE);
|
|
}
|
|
if (flags & fPCD_MEM2_A) {
|
|
PCMRES_SET_MEMORY_FLAG(pResDes, 1, PCMRESF_MEM_ATTRIBUTE);
|
|
}
|
|
|
|
if (flags & fPCD_ATTRIBUTES_PER_WINDOW) {
|
|
waitstate[0] = flags & mPCD_MEM1_WS;
|
|
waitstate[1] = flags & mPCD_MEM2_WS;
|
|
} else {
|
|
waitstate[0] = waitstate[1] = flags & mPCD_MEM_WS;
|
|
}
|
|
|
|
for (index = 0; index < 2; index++) {
|
|
switch (waitstate[index]) {
|
|
|
|
case fPCD_MEM_WS_ONE:
|
|
case fPCD_MEM1_WS_ONE:
|
|
case fPCD_MEM2_WS_ONE:
|
|
PCMRES_SET_MEMORY_WAITSTATES(pResDes, index, PCMRESF_MEM_WAIT_1);
|
|
break;
|
|
|
|
case fPCD_MEM_WS_TWO:
|
|
case fPCD_MEM1_WS_TWO:
|
|
case fPCD_MEM2_WS_TWO:
|
|
PCMRES_SET_MEMORY_WAITSTATES(pResDes, index, PCMRESF_MEM_WAIT_2);
|
|
break;
|
|
|
|
case fPCD_MEM_WS_THREE:
|
|
case fPCD_MEM1_WS_THREE:
|
|
case fPCD_MEM2_WS_THREE:
|
|
PCMRES_SET_MEMORY_WAITSTATES(pResDes, index, PCMRESF_MEM_WAIT_3);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (flags & (fPCD_IO_16 | fPCD_IO1_16)) {
|
|
PCMRES_SET_IO_FLAG(pResDes, 0, PCMRESF_IO_16BIT_ACCESS);
|
|
}
|
|
if (flags & (fPCD_IO_16 | fPCD_IO2_16)) {
|
|
PCMRES_SET_IO_FLAG(pResDes, 1, PCMRESF_IO_16BIT_ACCESS);
|
|
}
|
|
if (flags & (fPCD_IO_ZW_8 | fPCD_IO1_ZW_8)) {
|
|
PCMRES_SET_IO_FLAG(pResDes, 0, PCMRESF_IO_ZERO_WAIT_8);
|
|
}
|
|
if (flags & (fPCD_IO_ZW_8 | fPCD_IO2_ZW_8)) {
|
|
PCMRES_SET_IO_FLAG(pResDes, 1, PCMRESF_IO_ZERO_WAIT_8);
|
|
}
|
|
if (flags & (fPCD_IO_SRC_16 | fPCD_IO1_SRC_16)) {
|
|
PCMRES_SET_IO_FLAG(pResDes, 0, PCMRESF_IO_SOURCE_16);
|
|
}
|
|
if (flags & (fPCD_IO_SRC_16 | fPCD_IO2_SRC_16)) {
|
|
PCMRES_SET_IO_FLAG(pResDes, 1, PCMRESF_IO_SOURCE_16);
|
|
}
|
|
if (flags & (fPCD_IO_WS_16 | fPCD_IO1_WS_16)) {
|
|
PCMRES_SET_IO_FLAG(pResDes, 0, PCMRESF_IO_WAIT_16);
|
|
}
|
|
if (flags & (fPCD_IO_WS_16 | fPCD_IO2_WS_16)) {
|
|
PCMRES_SET_IO_FLAG(pResDes, 1, PCMRESF_IO_WAIT_16);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case ResType_MfCardConfig: {
|
|
|
|
//-------------------------------------------------------
|
|
// MfCardConfig Resource Type
|
|
//-------------------------------------------------------
|
|
|
|
PMFCARD_RESOURCE pMfData = (PMFCARD_RESOURCE)ResourceData;
|
|
|
|
//
|
|
// validate resource data
|
|
//
|
|
if (ResourceLen < sizeof(MFCARD_RESOURCE)) {
|
|
Status = CR_INVALID_RES_DES;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// The following macros use bit manipulation, initialize data
|
|
// fields first.
|
|
//
|
|
|
|
pResDes->u.DevicePrivate.Data[0] = 0;
|
|
pResDes->u.DevicePrivate.Data[1] = 0;
|
|
pResDes->u.DevicePrivate.Data[2] = 0;
|
|
|
|
//
|
|
// copy MFCARD_DES info to CM_PARTIAL_RESOURCE_DESCRIPTOR format
|
|
//
|
|
PCMRES_SET_DESCRIPTOR_TYPE(pResDes, DPTYPE_PCMCIA_MF_CONFIGURATION);
|
|
PCMRES_SET_CONFIG_OPTIONS(pResDes, pMfData->MfCard_Header.PMF_ConfigOptions);
|
|
PCMRES_SET_PORT_RESOURCE_INDEX(pResDes, pMfData->MfCard_Header.PMF_IoResourceIndex);
|
|
PCMRES_SET_CONFIG_REGISTER_BASE(pResDes, pMfData->MfCard_Header.PMF_ConfigRegisterBase);
|
|
|
|
if ((pMfData->MfCard_Header.PMF_Flags & mPMF_AUDIO_ENABLE) == fPMF_AUDIO_ENABLE) {
|
|
PCMRES_SET_AUDIO_ENABLE(pResDes);
|
|
}
|
|
break;
|
|
}
|
|
|
|
|
|
case ResType_ClassSpecific: {
|
|
|
|
//-------------------------------------------------------
|
|
// Class Specific Resource Type
|
|
//-------------------------------------------------------
|
|
|
|
PCS_RESOURCE pCsData = (PCS_RESOURCE)ResourceData;
|
|
LPBYTE ptr = NULL;
|
|
|
|
//
|
|
// validate resource data
|
|
//
|
|
if (ResourceLen < sizeof(CS_RESOURCE)) {
|
|
Status = CR_FAILURE;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// copy CS_DES info to CM_PARTIAL_RESOURCE_DESCRIPTOR format
|
|
//
|
|
pResDes->Type = CmResourceTypeDeviceSpecific;
|
|
pResDes->ShareDisposition = CmResourceShareUndetermined;
|
|
pResDes->Flags = (USHORT)pCsData->CS_Header.CSD_Flags; // none defined
|
|
|
|
pResDes->u.DeviceSpecificData.DataSize = pCsData->CS_Header.CSD_LegacyDataSize +
|
|
sizeof(GUID) +
|
|
pCsData->CS_Header.CSD_SignatureLength;
|
|
|
|
pResDes->u.DeviceSpecificData.Reserved1 = pCsData->CS_Header.CSD_LegacyDataSize;
|
|
pResDes->u.DeviceSpecificData.Reserved2 = pCsData->CS_Header.CSD_SignatureLength;
|
|
|
|
//
|
|
// copy the legacy and class-specific signature data
|
|
//
|
|
ptr = (LPBYTE)((LPBYTE)pResDes + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
|
|
|
|
memcpy(ptr,
|
|
pCsData->CS_Header.CSD_Signature + pCsData->CS_Header.CSD_LegacyDataOffset,
|
|
pCsData->CS_Header.CSD_LegacyDataSize); // copy legacy data first...
|
|
|
|
ptr += pCsData->CS_Header.CSD_LegacyDataSize;
|
|
|
|
memcpy(ptr,
|
|
pCsData->CS_Header.CSD_Signature,
|
|
pCsData->CS_Header.CSD_SignatureLength); // then copy signature...
|
|
|
|
ptr += pCsData->CS_Header.CSD_SignatureLength;
|
|
|
|
memcpy(ptr,
|
|
&pCsData->CS_Header.CSD_ClassGuid,
|
|
sizeof(GUID)); // then copy GUID
|
|
break;
|
|
}
|
|
|
|
default:
|
|
Status = CR_INVALID_RESOURCEID;
|
|
break;
|
|
}
|
|
|
|
Clean0:
|
|
|
|
return Status;
|
|
|
|
} // ResDesToNtResource
|
|
|
|
|
|
|
|
CONFIGRET
|
|
ResDesToNtRequirements(
|
|
IN PCVOID ResourceData,
|
|
IN RESOURCEID ResourceType,
|
|
IN ULONG ResourceLen,
|
|
IN PIO_RESOURCE_DESCRIPTOR pReqDes,
|
|
IN OUT PULONG pulResCount,
|
|
IN ULONG ulTag,
|
|
IN ULONG ulFlags
|
|
)
|
|
{
|
|
CONFIGRET Status = CR_SUCCESS;
|
|
ULONG i = 0;
|
|
PIO_RESOURCE_DESCRIPTOR pCurrent = NULL;
|
|
|
|
UNREFERENCED_PARAMETER(ulTag);
|
|
|
|
//
|
|
// fill in resource type specific info
|
|
//
|
|
switch (ResourceType) {
|
|
|
|
case ResType_Mem: {
|
|
|
|
//-------------------------------------------------------
|
|
// Memory Resource Type
|
|
//-------------------------------------------------------
|
|
|
|
//
|
|
// NOTE: pMemData->MEM_Header.MD_Reserved is not mapped
|
|
// pMemData->MEM_Data.MR_Reserved is not mapped
|
|
//
|
|
|
|
PMEM_RESOURCE pMemData = (PMEM_RESOURCE)ResourceData;
|
|
|
|
//
|
|
// validate resource data
|
|
//
|
|
if (ResourceLen < sizeof(MEM_RESOURCE)) {
|
|
Status = CR_INVALID_RES_DES;
|
|
goto Clean0;
|
|
}
|
|
|
|
if (pMemData->MEM_Header.MD_Type != MType_Range) {
|
|
Status = CR_INVALID_RES_DES;
|
|
goto Clean0;
|
|
}
|
|
|
|
*pulResCount = pMemData->MEM_Header.MD_Count;
|
|
|
|
//
|
|
// copy MEM_RANGE info to IO_RESOURCE_DESCRIPTOR format
|
|
//
|
|
for (i = 0, pCurrent = pReqDes;
|
|
i < *pulResCount;
|
|
i++, pCurrent++) {
|
|
|
|
if (i == 0) {
|
|
pCurrent->Option = 0;
|
|
} else {
|
|
pCurrent->Option = IO_RESOURCE_ALTERNATIVE;
|
|
}
|
|
|
|
pCurrent->Type = CmResourceTypeMemory;
|
|
pCurrent->ShareDisposition = CmResourceShareUndetermined;
|
|
//pCurrent->ShareDisposition = MapToNtDisposition(pMemData->MEM_Data[i].MR_Flags, 0);
|
|
pCurrent->Spare1 = 0;
|
|
pCurrent->Spare2 = 0;
|
|
|
|
pCurrent->Flags = MapToNtMemoryFlags(pMemData->MEM_Data[i].MR_Flags);
|
|
|
|
pCurrent->u.Memory.Length = pMemData->MEM_Data[i].MR_nBytes;
|
|
pCurrent->u.Memory.Alignment = MapToNtAlignment(pMemData->MEM_Data[i].MR_Align);
|
|
|
|
pCurrent->u.Memory.MinimumAddress.HighPart = HIDWORD(pMemData->MEM_Data[i].MR_Min);
|
|
pCurrent->u.Memory.MinimumAddress.LowPart = LODWORD(pMemData->MEM_Data[i].MR_Min);
|
|
|
|
pCurrent->u.Memory.MaximumAddress.HighPart = HIDWORD(pMemData->MEM_Data[i].MR_Max);
|
|
pCurrent->u.Memory.MaximumAddress.LowPart = LODWORD(pMemData->MEM_Data[i].MR_Max);
|
|
}
|
|
break;
|
|
}
|
|
|
|
|
|
case ResType_IO: {
|
|
|
|
//-------------------------------------------------------
|
|
// IO Port Resource Type
|
|
//-------------------------------------------------------
|
|
|
|
PIO_RESOURCE pIoData = (PIO_RESOURCE)ResourceData;
|
|
|
|
//
|
|
// validate resource data
|
|
//
|
|
if (ResourceLen < sizeof(IO_RESOURCE)) {
|
|
Status = CR_FAILURE;
|
|
goto Clean0;
|
|
}
|
|
|
|
if (pIoData->IO_Header.IOD_Type != IOType_Range) {
|
|
Status = CR_INVALID_RES_DES;
|
|
goto Clean0;
|
|
}
|
|
|
|
*pulResCount = pIoData->IO_Header.IOD_Count;
|
|
|
|
//
|
|
// copy IO_RANGE info to IO_RESOURCE_DESCRIPTOR format
|
|
//
|
|
for (i = 0, pCurrent = pReqDes;
|
|
i < *pulResCount;
|
|
i++, pCurrent++) {
|
|
|
|
if (i == 0) {
|
|
pCurrent->Option = 0;
|
|
} else {
|
|
pCurrent->Option = IO_RESOURCE_ALTERNATIVE;
|
|
}
|
|
|
|
pCurrent->Type = CmResourceTypePort;
|
|
pCurrent->ShareDisposition = CmResourceShareUndetermined;
|
|
//pCurrent->ShareDisposition = MapToNtDisposition(pIoData->IO_Data[i].IOR_RangeFlags, 0);
|
|
pCurrent->Spare1 = 0;
|
|
pCurrent->Spare2 = 0;
|
|
|
|
pCurrent->Flags = MapToNtPortFlags(pIoData->IO_Data[i].IOR_RangeFlags,
|
|
(DWORD)pIoData->IO_Data[i].IOR_Alias);
|
|
|
|
pCurrent->u.Port.Length = pIoData->IO_Data[i].IOR_nPorts;
|
|
|
|
pCurrent->u.Port.Alignment = MapToNtAlignment(pIoData->IO_Data[i].IOR_Align);
|
|
|
|
pCurrent->u.Port.MinimumAddress.HighPart = HIDWORD(pIoData->IO_Data[i].IOR_Min);
|
|
pCurrent->u.Port.MinimumAddress.LowPart = LODWORD(pIoData->IO_Data[i].IOR_Min);
|
|
|
|
pCurrent->u.Port.MaximumAddress.HighPart = HIDWORD(pIoData->IO_Data[i].IOR_Max);
|
|
pCurrent->u.Port.MaximumAddress.LowPart = LODWORD(pIoData->IO_Data[i].IOR_Max);
|
|
}
|
|
break;
|
|
}
|
|
|
|
|
|
case ResType_DMA: {
|
|
|
|
//-------------------------------------------------------
|
|
// DMA Resource Type
|
|
//-------------------------------------------------------
|
|
|
|
//
|
|
// Note: u.Dma.Port is not mapped
|
|
// u.Dma.Reserved is not mapped
|
|
//
|
|
|
|
PDMA_RESOURCE pDmaData = (PDMA_RESOURCE)ResourceData;
|
|
|
|
//
|
|
// validate resource data
|
|
//
|
|
if (ResourceLen < sizeof(DMA_RESOURCE)) {
|
|
Status = CR_FAILURE;
|
|
goto Clean0;
|
|
}
|
|
|
|
if (pDmaData->DMA_Header.DD_Type != DType_Range) {
|
|
Status = CR_INVALID_RES_DES;
|
|
goto Clean0;
|
|
}
|
|
|
|
*pulResCount = pDmaData->DMA_Header.DD_Count;
|
|
|
|
//
|
|
// copy DMA_RANGE info to IO_RESOURCE_DESCRIPTOR format
|
|
//
|
|
for (i = 0, pCurrent = pReqDes;
|
|
i < *pulResCount;
|
|
i++, pCurrent++) {
|
|
|
|
if (i == 0) {
|
|
pCurrent->Option = 0;
|
|
} else {
|
|
pCurrent->Option = IO_RESOURCE_ALTERNATIVE;
|
|
}
|
|
|
|
pCurrent->Type = CmResourceTypeDma;
|
|
pCurrent->ShareDisposition = CmResourceShareUndetermined;
|
|
//pCurrent->ShareDisposition = MapToNtDisposition(pDmaData->DMA_Data[i].DR_Flags, 0);
|
|
pCurrent->Spare1 = 0;
|
|
pCurrent->Spare2 = 0;
|
|
|
|
pCurrent->Flags = MapToNtDmaFlags(pDmaData->DMA_Data[i].DR_Flags);
|
|
|
|
pCurrent->u.Dma.MinimumChannel = pDmaData->DMA_Data[i].DR_Min;
|
|
pCurrent->u.Dma.MaximumChannel = pDmaData->DMA_Data[i].DR_Max;
|
|
}
|
|
break;
|
|
}
|
|
|
|
|
|
case ResType_IRQ: {
|
|
|
|
//-------------------------------------------------------
|
|
// IRQ Resource Type
|
|
//-------------------------------------------------------
|
|
|
|
if (ulFlags & CM_RESDES_WIDTH_64) {
|
|
//
|
|
// CM_RESDES_WIDTH_64
|
|
//
|
|
|
|
PIRQ_RESOURCE_64 pIrqData = (PIRQ_RESOURCE_64)ResourceData;
|
|
|
|
//
|
|
// validate resource data
|
|
//
|
|
if (ResourceLen < GetResDesSize(ResourceType, ulFlags)) {
|
|
Status = CR_FAILURE;
|
|
goto Clean0;
|
|
}
|
|
|
|
if (pIrqData->IRQ_Header.IRQD_Type != IRQType_Range) {
|
|
Status = CR_INVALID_RES_DES;
|
|
goto Clean0;
|
|
}
|
|
|
|
|
|
*pulResCount = pIrqData->IRQ_Header.IRQD_Count;
|
|
|
|
//
|
|
// copy IO_RANGE info to IO_RESOURCE_DESCRIPTOR format
|
|
//
|
|
for (i = 0, pCurrent = pReqDes;
|
|
i < *pulResCount;
|
|
i++, pCurrent++) {
|
|
|
|
if (i == 0) {
|
|
pCurrent->Option = 0;
|
|
} else {
|
|
pCurrent->Option = IO_RESOURCE_ALTERNATIVE;
|
|
}
|
|
|
|
pCurrent->Type = CmResourceTypeInterrupt;
|
|
pCurrent->Spare1 = 0;
|
|
pCurrent->Spare2 = 0;
|
|
|
|
pCurrent->ShareDisposition = MapToNtIrqShare(pIrqData->IRQ_Data[i].IRQR_Flags);
|
|
//pCurrent->ShareDisposition = MapToNtDisposition(pIrqData->IRQ_Data[i].IRQR_Flags, 1);
|
|
pCurrent->Flags = MapToNtIrqFlags(pIrqData->IRQ_Data[i].IRQR_Flags);
|
|
|
|
pCurrent->u.Interrupt.MinimumVector = pIrqData->IRQ_Data[i].IRQR_Min;
|
|
pCurrent->u.Interrupt.MaximumVector = pIrqData->IRQ_Data[i].IRQR_Max;
|
|
}
|
|
|
|
} else {
|
|
//
|
|
// CM_RESDES_WIDTH_32
|
|
//
|
|
|
|
PIRQ_RESOURCE_32 pIrqData = (PIRQ_RESOURCE_32)ResourceData;
|
|
|
|
//
|
|
// validate resource data
|
|
//
|
|
if (ResourceLen < GetResDesSize(ResourceType, ulFlags)) {
|
|
Status = CR_FAILURE;
|
|
goto Clean0;
|
|
}
|
|
|
|
if (pIrqData->IRQ_Header.IRQD_Type != IRQType_Range) {
|
|
Status = CR_INVALID_RES_DES;
|
|
goto Clean0;
|
|
}
|
|
|
|
|
|
*pulResCount = pIrqData->IRQ_Header.IRQD_Count;
|
|
|
|
//
|
|
// copy IO_RANGE info to IO_RESOURCE_DESCRIPTOR format
|
|
//
|
|
for (i = 0, pCurrent = pReqDes;
|
|
i < *pulResCount;
|
|
i++, pCurrent++) {
|
|
|
|
if (i == 0) {
|
|
pCurrent->Option = 0;
|
|
} else {
|
|
pCurrent->Option = IO_RESOURCE_ALTERNATIVE;
|
|
}
|
|
|
|
pCurrent->Type = CmResourceTypeInterrupt;
|
|
pCurrent->Spare1 = 0;
|
|
pCurrent->Spare2 = 0;
|
|
|
|
pCurrent->ShareDisposition = MapToNtIrqShare(pIrqData->IRQ_Data[i].IRQR_Flags);
|
|
//pCurrent->ShareDisposition = MapToNtDisposition(pIrqData->IRQ_Data[i].IRQR_Flags, 1);
|
|
pCurrent->Flags = MapToNtIrqFlags(pIrqData->IRQ_Data[i].IRQR_Flags);
|
|
|
|
pCurrent->u.Interrupt.MinimumVector = pIrqData->IRQ_Data[i].IRQR_Min;
|
|
pCurrent->u.Interrupt.MaximumVector = pIrqData->IRQ_Data[i].IRQR_Max;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
|
|
case ResType_DevicePrivate: {
|
|
|
|
//-------------------------------------------------------
|
|
// Device Private Resource Type
|
|
//-------------------------------------------------------
|
|
|
|
PDEVPRIVATE_RESOURCE pPrvData = (PDEVPRIVATE_RESOURCE)ResourceData;
|
|
|
|
//
|
|
// validate resource data
|
|
//
|
|
if (ResourceLen < sizeof(DEVPRIVATE_RESOURCE)) {
|
|
Status = CR_INVALID_RES_DES;
|
|
goto Clean0;
|
|
}
|
|
|
|
if (pPrvData->PRV_Header.PD_Type != PType_Range) {
|
|
Status = CR_INVALID_RES_DES;
|
|
goto Clean0;
|
|
}
|
|
|
|
*pulResCount = pPrvData->PRV_Header.PD_Count;
|
|
|
|
//
|
|
// copy DEVICEPRIVATE_RANGE info to IO_RESOURCE_DESCRIPTOR format
|
|
//
|
|
for (i = 0, pCurrent = pReqDes;
|
|
i < *pulResCount;
|
|
i++, pCurrent++) {
|
|
|
|
if (i == 0) {
|
|
pCurrent->Option = 0;
|
|
} else {
|
|
pCurrent->Option = IO_RESOURCE_ALTERNATIVE;
|
|
}
|
|
|
|
pCurrent->Type = CmResourceTypeDevicePrivate;
|
|
pCurrent->ShareDisposition = CmResourceShareUndetermined;
|
|
pCurrent->Spare1 = 0;
|
|
pCurrent->Spare2 = 0;
|
|
pCurrent->Flags = (USHORT)pPrvData->PRV_Header.PD_Flags;
|
|
|
|
pCurrent->u.DevicePrivate.Data[0] = pPrvData->PRV_Data[i].PR_Data1;
|
|
pCurrent->u.DevicePrivate.Data[1] = pPrvData->PRV_Data[i].PR_Data2;
|
|
pCurrent->u.DevicePrivate.Data[2] = pPrvData->PRV_Data[i].PR_Data3;
|
|
}
|
|
break;
|
|
}
|
|
|
|
|
|
case ResType_BusNumber: {
|
|
|
|
//-------------------------------------------------------
|
|
// Bus Number Resource Type
|
|
//-------------------------------------------------------
|
|
|
|
PBUSNUMBER_RESOURCE pBusData = (PBUSNUMBER_RESOURCE)ResourceData;
|
|
|
|
//
|
|
// validate resource data
|
|
//
|
|
if (ResourceLen < sizeof(BUSNUMBER_RESOURCE)) {
|
|
Status = CR_INVALID_RES_DES;
|
|
goto Clean0;
|
|
}
|
|
|
|
if (pBusData->BusNumber_Header.BUSD_Type != BusNumberType_Range) {
|
|
Status = CR_INVALID_RES_DES;
|
|
goto Clean0;
|
|
}
|
|
|
|
*pulResCount = pBusData->BusNumber_Header.BUSD_Count;
|
|
|
|
//
|
|
// copy BUSNUMBER_RANGE info to IO_RESOURCE_DESCRIPTOR format
|
|
//
|
|
for (i = 0, pCurrent = pReqDes;
|
|
i < *pulResCount;
|
|
i++, pCurrent++) {
|
|
|
|
if (i == 0) {
|
|
pCurrent->Option = 0;
|
|
} else {
|
|
pCurrent->Option = IO_RESOURCE_ALTERNATIVE;
|
|
}
|
|
|
|
pCurrent->Type = CmResourceTypeBusNumber;
|
|
pCurrent->ShareDisposition = CmResourceShareUndetermined;
|
|
pCurrent->Spare1 = 0;
|
|
pCurrent->Spare2 = 0;
|
|
pCurrent->Flags = (USHORT)pBusData->BusNumber_Data[i].BUSR_Flags;
|
|
|
|
pCurrent->u.BusNumber.Length = pBusData->BusNumber_Data[i].BUSR_nBusNumbers;
|
|
pCurrent->u.BusNumber.MinBusNumber = pBusData->BusNumber_Data[i].BUSR_Min;
|
|
pCurrent->u.BusNumber.MaxBusNumber = pBusData->BusNumber_Data[i].BUSR_Max;
|
|
pCurrent->u.BusNumber.Reserved = 0;
|
|
}
|
|
break;
|
|
}
|
|
|
|
|
|
case ResType_PcCardConfig: {
|
|
|
|
//-------------------------------------------------------
|
|
// PcCardConfig Resource Type
|
|
//-------------------------------------------------------
|
|
|
|
PPCCARD_RESOURCE pPcData = (PPCCARD_RESOURCE)ResourceData;
|
|
ULONG index;
|
|
ULONG flags;
|
|
ULONG waitstate[2];
|
|
|
|
//
|
|
// validate resource data
|
|
//
|
|
if (ResourceLen < sizeof(PCCARD_RESOURCE)) {
|
|
Status = CR_INVALID_RES_DES;
|
|
goto Clean0;
|
|
}
|
|
|
|
*pulResCount = 1;
|
|
|
|
//
|
|
// copy PCCARD_DES info to IO_RESOURCE_DESCRIPTOR format
|
|
//
|
|
pReqDes->Option = 0;
|
|
pReqDes->Type = CmResourceTypeDevicePrivate;
|
|
pReqDes->ShareDisposition = CmResourceShareUndetermined;
|
|
pReqDes->Spare1 = 0;
|
|
pReqDes->Spare2 = 0;
|
|
pReqDes->Flags = 0;
|
|
|
|
//
|
|
// The following macros use bit manipulation, initialize data
|
|
// fields first.
|
|
//
|
|
|
|
pReqDes->u.DevicePrivate.Data[0] = 0;
|
|
pReqDes->u.DevicePrivate.Data[1] = 0;
|
|
pReqDes->u.DevicePrivate.Data[2] = 0;
|
|
|
|
PCMRES_SET_DESCRIPTOR_TYPE(pReqDes, DPTYPE_PCMCIA_CONFIGURATION);
|
|
PCMRES_SET_CONFIG_INDEX(pReqDes, pPcData->PcCard_Header.PCD_ConfigIndex);
|
|
PCMRES_SET_MEMORY_CARDBASE(pReqDes, 0, pPcData->PcCard_Header.PCD_MemoryCardBase1);
|
|
PCMRES_SET_MEMORY_CARDBASE(pReqDes, 1, pPcData->PcCard_Header.PCD_MemoryCardBase2);
|
|
|
|
flags = pPcData->PcCard_Header.PCD_Flags;
|
|
|
|
if (flags & (fPCD_MEM_16 | fPCD_MEM1_16)) {
|
|
PCMRES_SET_MEMORY_FLAG(pReqDes, 0, PCMRESF_MEM_16BIT_ACCESS);
|
|
}
|
|
if (flags & (fPCD_MEM_16 | fPCD_MEM2_16)) {
|
|
PCMRES_SET_MEMORY_FLAG(pReqDes, 1, PCMRESF_MEM_16BIT_ACCESS);
|
|
}
|
|
|
|
if (flags & fPCD_MEM1_A) {
|
|
PCMRES_SET_MEMORY_FLAG(pReqDes, 0, PCMRESF_MEM_ATTRIBUTE);
|
|
}
|
|
if (flags & fPCD_MEM2_A) {
|
|
PCMRES_SET_MEMORY_FLAG(pReqDes, 1, PCMRESF_MEM_ATTRIBUTE);
|
|
}
|
|
|
|
if (flags & fPCD_ATTRIBUTES_PER_WINDOW) {
|
|
waitstate[0] = flags & mPCD_MEM1_WS;
|
|
waitstate[1] = flags & mPCD_MEM2_WS;
|
|
} else {
|
|
waitstate[0] = waitstate[1] = flags & mPCD_MEM_WS;
|
|
}
|
|
|
|
for (index = 0; index < 2; index++) {
|
|
switch (waitstate[index]) {
|
|
|
|
case fPCD_MEM_WS_ONE:
|
|
case fPCD_MEM1_WS_ONE:
|
|
case fPCD_MEM2_WS_ONE:
|
|
PCMRES_SET_MEMORY_WAITSTATES(pReqDes, index, PCMRESF_MEM_WAIT_1);
|
|
break;
|
|
|
|
case fPCD_MEM_WS_TWO:
|
|
case fPCD_MEM1_WS_TWO:
|
|
case fPCD_MEM2_WS_TWO:
|
|
PCMRES_SET_MEMORY_WAITSTATES(pReqDes, index, PCMRESF_MEM_WAIT_2);
|
|
break;
|
|
|
|
case fPCD_MEM_WS_THREE:
|
|
case fPCD_MEM1_WS_THREE:
|
|
case fPCD_MEM2_WS_THREE:
|
|
PCMRES_SET_MEMORY_WAITSTATES(pReqDes, index, PCMRESF_MEM_WAIT_3);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (flags & (fPCD_IO_16 | fPCD_IO1_16)) {
|
|
PCMRES_SET_IO_FLAG(pReqDes, 0, PCMRESF_IO_16BIT_ACCESS);
|
|
}
|
|
if (flags & (fPCD_IO_16 | fPCD_IO2_16)) {
|
|
PCMRES_SET_IO_FLAG(pReqDes, 1, PCMRESF_IO_16BIT_ACCESS);
|
|
}
|
|
if (flags & (fPCD_IO_ZW_8 | fPCD_IO1_ZW_8)) {
|
|
PCMRES_SET_IO_FLAG(pReqDes, 0, PCMRESF_IO_ZERO_WAIT_8);
|
|
}
|
|
if (flags & (fPCD_IO_ZW_8 | fPCD_IO2_ZW_8)) {
|
|
PCMRES_SET_IO_FLAG(pReqDes, 1, PCMRESF_IO_ZERO_WAIT_8);
|
|
}
|
|
if (flags & (fPCD_IO_SRC_16 | fPCD_IO1_SRC_16)) {
|
|
PCMRES_SET_IO_FLAG(pReqDes, 0, PCMRESF_IO_SOURCE_16);
|
|
}
|
|
if (flags & (fPCD_IO_SRC_16 | fPCD_IO2_SRC_16)) {
|
|
PCMRES_SET_IO_FLAG(pReqDes, 1, PCMRESF_IO_SOURCE_16);
|
|
}
|
|
if (flags & (fPCD_IO_WS_16 | fPCD_IO1_WS_16)) {
|
|
PCMRES_SET_IO_FLAG(pReqDes, 0, PCMRESF_IO_WAIT_16);
|
|
}
|
|
if (flags & (fPCD_IO_WS_16 | fPCD_IO2_WS_16)) {
|
|
PCMRES_SET_IO_FLAG(pReqDes, 1, PCMRESF_IO_WAIT_16);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case ResType_MfCardConfig: {
|
|
|
|
//-------------------------------------------------------
|
|
// PcCardConfig Resource Type
|
|
//-------------------------------------------------------
|
|
|
|
PMFCARD_RESOURCE pMfData = (PMFCARD_RESOURCE)ResourceData;
|
|
|
|
//
|
|
// validate resource data
|
|
//
|
|
if (ResourceLen < sizeof(MFCARD_RESOURCE)) {
|
|
Status = CR_INVALID_RES_DES;
|
|
goto Clean0;
|
|
}
|
|
|
|
*pulResCount = 1;
|
|
|
|
//
|
|
// copy PCCARD_DES info to IO_RESOURCE_DESCRIPTOR format
|
|
//
|
|
pReqDes->Option = 0;
|
|
pReqDes->Type = CmResourceTypeDevicePrivate;
|
|
pReqDes->ShareDisposition = CmResourceShareUndetermined;
|
|
pReqDes->Spare1 = 0;
|
|
pReqDes->Spare2 = 0;
|
|
pReqDes->Flags = 0;
|
|
|
|
//
|
|
// The following macros use bit manipulation, initialize data
|
|
// fields first.
|
|
//
|
|
|
|
pReqDes->u.DevicePrivate.Data[0] = 0;
|
|
pReqDes->u.DevicePrivate.Data[1] = 0;
|
|
pReqDes->u.DevicePrivate.Data[2] = 0;
|
|
|
|
PCMRES_SET_DESCRIPTOR_TYPE(pReqDes, DPTYPE_PCMCIA_MF_CONFIGURATION);
|
|
PCMRES_SET_CONFIG_OPTIONS(pReqDes, pMfData->MfCard_Header.PMF_ConfigOptions);
|
|
PCMRES_SET_PORT_RESOURCE_INDEX(pReqDes, pMfData->MfCard_Header.PMF_IoResourceIndex);
|
|
PCMRES_SET_CONFIG_REGISTER_BASE(pReqDes, pMfData->MfCard_Header.PMF_ConfigRegisterBase);
|
|
|
|
if ((pMfData->MfCard_Header.PMF_Flags & mPMF_AUDIO_ENABLE) == fPMF_AUDIO_ENABLE) {
|
|
PCMRES_SET_AUDIO_ENABLE(pReqDes);
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
Status = CR_INVALID_RESOURCEID;
|
|
break;
|
|
}
|
|
|
|
Clean0:
|
|
|
|
return Status;
|
|
|
|
} // ResDesToNtRequirements
|
|
|
|
|
|
|
|
CONFIGRET
|
|
NtResourceToResDes(
|
|
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pResDes,
|
|
IN OUT LPBYTE Buffer,
|
|
IN ULONG BufferLen,
|
|
IN LPBYTE pLastAddr,
|
|
IN ULONG ulFlags
|
|
)
|
|
{
|
|
CONFIGRET Status = CR_SUCCESS;
|
|
ULONG ulSize = 0;
|
|
|
|
UNREFERENCED_PARAMETER(pLastAddr);
|
|
|
|
//
|
|
// fill in resource type specific info
|
|
//
|
|
switch (pResDes->Type) {
|
|
|
|
case CmResourceTypeMemory: {
|
|
|
|
//-------------------------------------------------------
|
|
// Memory Resource Type
|
|
//-------------------------------------------------------
|
|
|
|
//
|
|
// NOTE: pMemData->MEM_Header.MD_Reserved is not mapped
|
|
// pMemData->MEM_Data.MR_Reserved is not mapped
|
|
//
|
|
|
|
PMEM_RESOURCE pMemData = (PMEM_RESOURCE)Buffer;
|
|
|
|
//
|
|
// verify passed in buffer size
|
|
//
|
|
if (BufferLen < sizeof(MEM_RESOURCE)) {
|
|
Status = CR_BUFFER_SMALL;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// copy CM_PARTIAL_RESOURCE_DESCRIPTOR info to MEM_DES format
|
|
//
|
|
pMemData->MEM_Header.MD_Count = 0;
|
|
pMemData->MEM_Header.MD_Type = MType_Range;
|
|
pMemData->MEM_Header.MD_Flags = MapFromNtMemoryFlags(pResDes->Flags);
|
|
//pMemData->MEM_Header.MD_Flags |= MapFromNtDisposition(pResDes->ShareDisposition, 0);
|
|
pMemData->MEM_Header.MD_Reserved = 0;
|
|
|
|
if (pResDes->u.Memory.Length != 0) {
|
|
|
|
pMemData->MEM_Header.MD_Alloc_Base = MAKEDWORDLONG(pResDes->u.Memory.Start.LowPart,
|
|
pResDes->u.Memory.Start.HighPart);
|
|
|
|
pMemData->MEM_Header.MD_Alloc_End = pMemData->MEM_Header.MD_Alloc_Base +
|
|
(DWORDLONG)pResDes->u.Memory.Length - 1;
|
|
} else {
|
|
|
|
pMemData->MEM_Header.MD_Alloc_Base = 1;
|
|
pMemData->MEM_Header.MD_Alloc_End = 0;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case CmResourceTypePort: {
|
|
|
|
//-------------------------------------------------------
|
|
// IO Port Resource Type
|
|
//
|
|
// NOTE: alias info lost during this conversion process
|
|
//-------------------------------------------------------
|
|
|
|
PIO_RESOURCE pIoData = (PIO_RESOURCE)Buffer;
|
|
|
|
//
|
|
// verify passed in buffer size
|
|
//
|
|
if (BufferLen < sizeof(IO_RESOURCE)) {
|
|
Status = CR_BUFFER_SMALL;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// copy CM_PARTIAL_RESOURCE_DESCRIPTOR info to IO_DES format
|
|
//
|
|
pIoData->IO_Header.IOD_Count = 0;
|
|
pIoData->IO_Header.IOD_Type = IOType_Range;
|
|
|
|
pIoData->IO_Header.IOD_DesFlags = MapFromNtPortFlags(pResDes->Flags);
|
|
//pIoData->IO_Header.IOD_DesFlags |= MapFromNtDisposition(pResDes->ShareDisposition, 0);
|
|
|
|
if (pResDes->u.Port.Length) {
|
|
|
|
pIoData->IO_Header.IOD_Alloc_Base = MAKEDWORDLONG(pResDes->u.Port.Start.LowPart,
|
|
pResDes->u.Port.Start.HighPart);
|
|
|
|
pIoData->IO_Header.IOD_Alloc_End = pIoData->IO_Header.IOD_Alloc_Base +
|
|
(DWORDLONG)pResDes->u.Port.Length - 1;
|
|
} else {
|
|
|
|
pIoData->IO_Header.IOD_Alloc_Base = 1;
|
|
pIoData->IO_Header.IOD_Alloc_End = 0;
|
|
}
|
|
break;
|
|
}
|
|
|
|
|
|
case CmResourceTypeDma: {
|
|
|
|
//-------------------------------------------------------
|
|
// DMA Resource Type
|
|
//-------------------------------------------------------
|
|
|
|
//
|
|
// Note: u.Dma.Port is not mapped
|
|
// u.Dma.Reserved is not mapped
|
|
//
|
|
|
|
PDMA_RESOURCE pDmaData = (PDMA_RESOURCE)Buffer;
|
|
|
|
//
|
|
// verify passed in buffer size
|
|
//
|
|
if (BufferLen < sizeof(DMA_RESOURCE)) {
|
|
Status = CR_BUFFER_SMALL;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// copy CM_PARTIAL_RESOURCE_DESCRIPTOR info to DMA_DES format
|
|
//
|
|
pDmaData->DMA_Header.DD_Count = 0;
|
|
pDmaData->DMA_Header.DD_Type = DType_Range;
|
|
pDmaData->DMA_Header.DD_Flags = MapFromNtDmaFlags(pResDes->Flags);
|
|
//pDmaData->DMA_Header.DD_Flags |= MapFromNtDisposition(pResDes->ShareDisposition, 0);
|
|
pDmaData->DMA_Header.DD_Alloc_Chan = pResDes->u.Dma.Channel;
|
|
|
|
break;
|
|
}
|
|
|
|
case CmResourceTypeInterrupt: {
|
|
|
|
//-------------------------------------------------------
|
|
// IRQ Resource Type
|
|
//-------------------------------------------------------
|
|
|
|
if (ulFlags & CM_RESDES_WIDTH_64) {
|
|
//
|
|
// CM_RESDES_WIDTH_64
|
|
//
|
|
|
|
PIRQ_RESOURCE_64 pIrqData = (PIRQ_RESOURCE_64)Buffer;
|
|
|
|
//
|
|
// verify passed in buffer size
|
|
//
|
|
if (BufferLen < GetResDesSize(ResType_IRQ, ulFlags)) {
|
|
Status = CR_BUFFER_SMALL;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// copy CM_PARTIAL_RESOURCE_DESCRIPTOR info to IRQ_DES format
|
|
//
|
|
pIrqData->IRQ_Header.IRQD_Count = 0;
|
|
pIrqData->IRQ_Header.IRQD_Type = IRQType_Range;
|
|
pIrqData->IRQ_Header.IRQD_Flags = MapFromNtIrqFlags(pResDes->Flags) |
|
|
MapFromNtIrqShare(pResDes->ShareDisposition);
|
|
//pIrqData->IRQ_Header.IRQD_Flags |= MapFromNtDisposition(pResDes->ShareDisposition, 1);
|
|
|
|
pIrqData->IRQ_Header.IRQD_Alloc_Num = pResDes->u.Interrupt.Level;
|
|
|
|
pIrqData->IRQ_Header.IRQD_Affinity = pResDes->u.Interrupt.Affinity;
|
|
} else {
|
|
//
|
|
// CM_RESDES_WIDTH_32
|
|
//
|
|
|
|
PIRQ_RESOURCE_32 pIrqData = (PIRQ_RESOURCE_32)Buffer;
|
|
|
|
//
|
|
// verify passed in buffer size
|
|
//
|
|
if (BufferLen < GetResDesSize(ResType_IRQ, ulFlags)) {
|
|
Status = CR_BUFFER_SMALL;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// copy CM_PARTIAL_RESOURCE_DESCRIPTOR info to IRQ_DES format
|
|
//
|
|
pIrqData->IRQ_Header.IRQD_Count = 0;
|
|
pIrqData->IRQ_Header.IRQD_Type = IRQType_Range;
|
|
pIrqData->IRQ_Header.IRQD_Flags = MapFromNtIrqFlags(pResDes->Flags) |
|
|
MapFromNtIrqShare(pResDes->ShareDisposition);
|
|
//pIrqData->IRQ_Header.IRQD_Flags |= MapFromNtDisposition(pResDes->ShareDisposition, 1);
|
|
|
|
pIrqData->IRQ_Header.IRQD_Alloc_Num = pResDes->u.Interrupt.Level;
|
|
|
|
#ifdef _WIN64
|
|
pIrqData->IRQ_Header.IRQD_Affinity = (ULONG)((pResDes->u.Interrupt.Affinity >> 32) |
|
|
pResDes->u.Interrupt.Affinity);
|
|
#else // !_WIN64
|
|
pIrqData->IRQ_Header.IRQD_Affinity = pResDes->u.Interrupt.Affinity;
|
|
#endif // !_WIN64
|
|
}
|
|
break;
|
|
}
|
|
|
|
case CmResourceTypeDevicePrivate: {
|
|
|
|
//-------------------------------------------------------
|
|
// Device Private Resource Type
|
|
//-------------------------------------------------------
|
|
|
|
PDEVPRIVATE_RESOURCE pPrvData = (PDEVPRIVATE_RESOURCE)Buffer;
|
|
|
|
//
|
|
// verify passed in buffer size
|
|
//
|
|
if (BufferLen < sizeof(DEVPRIVATE_RESOURCE)) {
|
|
Status = CR_BUFFER_SMALL;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// copy CM_PARTIAL_RESOURCE_DESCRIPTOR info to DEVICEPRIVATE_DES format
|
|
//
|
|
pPrvData->PRV_Header.PD_Count = 0;
|
|
pPrvData->PRV_Header.PD_Type = PType_Range;
|
|
|
|
pPrvData->PRV_Header.PD_Data1 = pResDes->u.DevicePrivate.Data[0];
|
|
pPrvData->PRV_Header.PD_Data2 = pResDes->u.DevicePrivate.Data[1];
|
|
pPrvData->PRV_Header.PD_Data3 = pResDes->u.DevicePrivate.Data[2];
|
|
|
|
pPrvData->PRV_Header.PD_Flags = pResDes->Flags;
|
|
break;
|
|
}
|
|
|
|
|
|
case CmResourceTypeBusNumber: {
|
|
|
|
//-------------------------------------------------------
|
|
// Bus Number Resource Type
|
|
//-------------------------------------------------------
|
|
|
|
PBUSNUMBER_RESOURCE pBusData = (PBUSNUMBER_RESOURCE)Buffer;
|
|
|
|
//
|
|
// verify passed in buffer size
|
|
//
|
|
if (BufferLen < sizeof(BUSNUMBER_RESOURCE)) {
|
|
Status = CR_BUFFER_SMALL;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// copy CM_PARTIAL_RESOURCE_DESCRIPTOR info to BUSNUMBER_DES format
|
|
//
|
|
pBusData->BusNumber_Header.BUSD_Count = 0;
|
|
pBusData->BusNumber_Header.BUSD_Type = BusNumberType_Range;
|
|
pBusData->BusNumber_Header.BUSD_Flags = pResDes->Flags;
|
|
pBusData->BusNumber_Header.BUSD_Alloc_Base = pResDes->u.BusNumber.Start;
|
|
pBusData->BusNumber_Header.BUSD_Alloc_End = pResDes->u.BusNumber.Start +
|
|
pResDes->u.BusNumber.Length - 1;
|
|
break;
|
|
}
|
|
|
|
case CmResourceTypePcCardConfig: {
|
|
|
|
//-------------------------------------------------------
|
|
// PcCardConfig Resource Type
|
|
//-------------------------------------------------------
|
|
|
|
PPCCARD_RESOURCE pPcData = (PPCCARD_RESOURCE)Buffer;
|
|
|
|
//
|
|
// verify passed in buffer size
|
|
//
|
|
if (BufferLen < sizeof(PCCARD_RESOURCE)) {
|
|
Status = CR_BUFFER_SMALL;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// copy CM_PARTIAL_RESOURCE_DESCRIPTOR info to PCCARD_DES format
|
|
//
|
|
pPcData->PcCard_Header.PCD_Reserved[0] = 0;
|
|
pPcData->PcCard_Header.PCD_Reserved[1] = 0;
|
|
pPcData->PcCard_Header.PCD_Reserved[2] = 0;
|
|
pPcData->PcCard_Header.PCD_ConfigIndex = PCMRES_GET_CONFIG_INDEX(pResDes);
|
|
pPcData->PcCard_Header.PCD_MemoryCardBase1 = PCMRES_GET_MEMORY_CARDBASE(pResDes, 0);
|
|
pPcData->PcCard_Header.PCD_MemoryCardBase2 = PCMRES_GET_MEMORY_CARDBASE(pResDes, 1);
|
|
|
|
if (PCMRES_GET_IO_FLAG(pResDes, 0, PCMRESF_IO_16BIT_ACCESS)) {
|
|
pPcData->PcCard_Header.PCD_Flags = fPCD_IO_16;
|
|
} else {
|
|
pPcData->PcCard_Header.PCD_Flags = fPCD_IO_8;
|
|
}
|
|
if (PCMRES_GET_MEMORY_FLAG(pResDes, 0, PCMRESF_MEM_16BIT_ACCESS)) {
|
|
pPcData->PcCard_Header.PCD_Flags |= fPCD_MEM_16;
|
|
} else {
|
|
pPcData->PcCard_Header.PCD_Flags |= fPCD_MEM_8;
|
|
}
|
|
break;
|
|
}
|
|
|
|
|
|
case CmResourceTypeDeviceSpecific: {
|
|
|
|
//-------------------------------------------------------
|
|
// Class Specific Resource Type
|
|
//-------------------------------------------------------
|
|
|
|
PCS_RESOURCE pCsData = (PCS_RESOURCE)Buffer;
|
|
LPBYTE ptr1 = NULL, ptr2 = NULL;
|
|
ULONG ulRequiredSize = sizeof(CS_RESOURCE);
|
|
|
|
//
|
|
// the Reserved fields should not exceed DataSize. if so, they
|
|
// may have been incorrectly initialized, so set them 0.
|
|
// we expect DataSize to be correct in all cases.
|
|
//
|
|
if (pResDes->u.DeviceSpecificData.Reserved1 > pResDes->u.DeviceSpecificData.DataSize) {
|
|
pResDes->u.DeviceSpecificData.Reserved1 = 0;
|
|
}
|
|
if (pResDes->u.DeviceSpecificData.Reserved2 > pResDes->u.DeviceSpecificData.DataSize) {
|
|
pResDes->u.DeviceSpecificData.Reserved2 = 0;
|
|
}
|
|
|
|
//
|
|
// verify passed in buffer size
|
|
//
|
|
if (pResDes->u.DeviceSpecificData.DataSize == 0) {
|
|
//
|
|
// there is no legacy data and no class-specific data
|
|
//
|
|
;
|
|
} else if (pResDes->u.DeviceSpecificData.Reserved2 == 0) {
|
|
//
|
|
// add space for legacy data
|
|
//
|
|
ulRequiredSize += pResDes->u.DeviceSpecificData.DataSize - 1;
|
|
} else {
|
|
//
|
|
// add space for legacy and signature data, as necessary
|
|
//
|
|
ulRequiredSize += pResDes->u.DeviceSpecificData.Reserved1 +
|
|
pResDes->u.DeviceSpecificData.Reserved2 - 1;
|
|
}
|
|
|
|
if (BufferLen < ulRequiredSize) {
|
|
Status = CR_BUFFER_SMALL;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// copy CM_PARTIAL_RESOURCE_DESCRIPTOR info to CS_DES format
|
|
//
|
|
pCsData->CS_Header.CSD_Flags = (DWORD)pResDes->Flags; // none defined
|
|
|
|
|
|
if (pResDes->u.DeviceSpecificData.DataSize == 0) {
|
|
//
|
|
// There is no legacy data and no class-specific data
|
|
//
|
|
pCsData->CS_Header.CSD_SignatureLength = 0;
|
|
pCsData->CS_Header.CSD_LegacyDataOffset = 0;
|
|
pCsData->CS_Header.CSD_LegacyDataSize = 0;
|
|
pCsData->CS_Header.CSD_Signature[0] = 0x0;
|
|
|
|
memset(&pCsData->CS_Header.CSD_ClassGuid, 0, sizeof(GUID));
|
|
}
|
|
|
|
else if (pResDes->u.DeviceSpecificData.Reserved2 == 0) {
|
|
//
|
|
// There is only legacy data
|
|
//
|
|
pCsData->CS_Header.CSD_SignatureLength = 0;
|
|
pCsData->CS_Header.CSD_LegacyDataOffset = 0;
|
|
pCsData->CS_Header.CSD_LegacyDataSize =
|
|
pResDes->u.DeviceSpecificData.DataSize;
|
|
pCsData->CS_Header.CSD_Signature[0] = 0x0;
|
|
|
|
memset(&pCsData->CS_Header.CSD_ClassGuid, 0, sizeof(GUID));
|
|
|
|
ptr1 = (LPBYTE)((LPBYTE)pResDes + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
|
|
|
|
memcpy(&pCsData->CS_Header.CSD_Signature, ptr1,
|
|
pResDes->u.DeviceSpecificData.DataSize);
|
|
}
|
|
|
|
else if (pResDes->u.DeviceSpecificData.Reserved1 == 0) {
|
|
//
|
|
// There is only class-specific data
|
|
//
|
|
pCsData->CS_Header.CSD_LegacyDataOffset = 0;
|
|
pCsData->CS_Header.CSD_LegacyDataSize = 0;
|
|
|
|
pCsData->CS_Header.CSD_SignatureLength =
|
|
pResDes->u.DeviceSpecificData.Reserved2;
|
|
|
|
ptr1 = (LPBYTE)((LPBYTE)pResDes + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
|
|
|
|
memcpy(pCsData->CS_Header.CSD_Signature, ptr1,
|
|
pResDes->u.DeviceSpecificData.Reserved2);
|
|
|
|
ptr1 += pResDes->u.DeviceSpecificData.Reserved2;
|
|
|
|
memcpy((LPBYTE)&pCsData->CS_Header.CSD_ClassGuid, ptr1, sizeof(GUID));
|
|
}
|
|
|
|
else {
|
|
//
|
|
// There is both legacy data and class-specific data
|
|
//
|
|
|
|
//
|
|
// copy legacy data
|
|
//
|
|
pCsData->CS_Header.CSD_LegacyDataOffset =
|
|
pResDes->u.DeviceSpecificData.Reserved2;
|
|
|
|
pCsData->CS_Header.CSD_LegacyDataSize =
|
|
pResDes->u.DeviceSpecificData.Reserved1;
|
|
|
|
ptr1 = pCsData->CS_Header.CSD_Signature +
|
|
pCsData->CS_Header.CSD_LegacyDataOffset;
|
|
|
|
ptr2 = (LPBYTE)((LPBYTE)pResDes + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
|
|
|
|
memcpy(ptr1, ptr2, pResDes->u.DeviceSpecificData.Reserved1);
|
|
|
|
//
|
|
// copy signature and class guid
|
|
//
|
|
pCsData->CS_Header.CSD_SignatureLength =
|
|
pResDes->u.DeviceSpecificData.Reserved2;
|
|
|
|
ptr2 += pResDes->u.DeviceSpecificData.Reserved1;
|
|
|
|
memcpy(pCsData->CS_Header.CSD_Signature, ptr2,
|
|
pResDes->u.DeviceSpecificData.Reserved2);
|
|
|
|
ptr2 += pResDes->u.DeviceSpecificData.Reserved2;
|
|
|
|
memcpy((LPBYTE)&pCsData->CS_Header.CSD_ClassGuid, ptr2, sizeof(GUID));
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
Clean0:
|
|
|
|
return Status;
|
|
|
|
} // NtResourceToResDes
|
|
|
|
|
|
|
|
CONFIGRET
|
|
NtRequirementsToResDes(
|
|
IN PIO_RESOURCE_DESCRIPTOR pReqDes,
|
|
IN OUT LPBYTE Buffer,
|
|
IN ULONG BufferLen,
|
|
IN LPBYTE pLastAddr,
|
|
IN ULONG ulFlags
|
|
)
|
|
{
|
|
CONFIGRET Status = CR_SUCCESS;
|
|
ULONG ulSize = 0, count = 0, i = 0, ReqPartialCount = 0;
|
|
PIO_RESOURCE_DESCRIPTOR pCurrent = NULL;
|
|
|
|
//
|
|
// fill in resource type specific info
|
|
//
|
|
switch (pReqDes->Type) {
|
|
|
|
case CmResourceTypeMemory: {
|
|
|
|
//-------------------------------------------------------
|
|
// Memory Resource Type
|
|
//-------------------------------------------------------
|
|
|
|
//
|
|
// NOTE: pMemData->MEM_Header.MD_Reserved is not mapped
|
|
// pMemData->MEM_Data.MR_Reserved is not mapped
|
|
//
|
|
|
|
PMEM_RESOURCE pMemData = (PMEM_RESOURCE)Buffer;
|
|
|
|
//
|
|
// verify passed in buffer size
|
|
//
|
|
ReqPartialCount = RANGE_COUNT(pReqDes, pLastAddr);
|
|
|
|
if (BufferLen < sizeof(MEM_RESOURCE) +
|
|
sizeof(MEM_RANGE) * (ReqPartialCount - 1)) {
|
|
|
|
Status = CR_BUFFER_SMALL;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// copy CM_PARTIAL_RESOURCE_DESCRIPTOR info to MEM_DES format
|
|
//
|
|
pMemData->MEM_Header.MD_Count = ReqPartialCount;
|
|
pMemData->MEM_Header.MD_Type = MType_Range;
|
|
pMemData->MEM_Header.MD_Flags = 0;
|
|
pMemData->MEM_Header.MD_Reserved = 0;
|
|
pMemData->MEM_Header.MD_Alloc_Base = 0;
|
|
pMemData->MEM_Header.MD_Alloc_End = 0;
|
|
|
|
//
|
|
// copy IO_RESOURCE_DESCRIPTOR info to MEM_RANGE format
|
|
//
|
|
for (count = 0, i = 0, pCurrent = pReqDes;
|
|
count < ReqPartialCount;
|
|
count++, pCurrent++) {
|
|
|
|
if (pCurrent->Type == CmResourceTypeMemory) {
|
|
pMemData->MEM_Data[i].MR_Align = MapFromNtAlignment(pCurrent->u.Memory.Alignment);
|
|
pMemData->MEM_Data[i].MR_nBytes = pCurrent->u.Memory.Length;
|
|
|
|
pMemData->MEM_Data[i].MR_Min = MAKEDWORDLONG(
|
|
pCurrent->u.Memory.MinimumAddress.LowPart,
|
|
pCurrent->u.Memory.MinimumAddress.HighPart);
|
|
|
|
pMemData->MEM_Data[i].MR_Max = MAKEDWORDLONG(
|
|
pCurrent->u.Memory.MaximumAddress.LowPart,
|
|
pCurrent->u.Memory.MaximumAddress.HighPart);
|
|
|
|
pMemData->MEM_Data[i].MR_Flags = MapFromNtMemoryFlags(pCurrent->Flags);
|
|
//pMemData->MEM_Data[i].MR_Flags |= MapFromNtDisposition(pCurrent->ShareDisposition, 0);
|
|
pMemData->MEM_Data[i].MR_Reserved = 0;
|
|
i++;
|
|
}
|
|
}
|
|
pMemData->MEM_Header.MD_Count = i;
|
|
break;
|
|
}
|
|
|
|
case CmResourceTypePort: {
|
|
|
|
//-------------------------------------------------------
|
|
// IO Port Resource Type
|
|
//-------------------------------------------------------
|
|
|
|
PIO_RESOURCE pIoData = (PIO_RESOURCE)Buffer;
|
|
|
|
//
|
|
// verify passed in buffer size
|
|
//
|
|
ReqPartialCount = RANGE_COUNT(pReqDes, pLastAddr);
|
|
|
|
if (BufferLen < sizeof(IO_RESOURCE) +
|
|
sizeof(IO_RANGE) * (ReqPartialCount - 1)) {
|
|
|
|
Status = CR_BUFFER_SMALL;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// copy CM_PARTIAL_RESOURCE_DESCRIPTOR info to IO_DES format
|
|
//
|
|
pIoData->IO_Header.IOD_Count = ReqPartialCount;
|
|
pIoData->IO_Header.IOD_Type = IOType_Range;
|
|
pIoData->IO_Header.IOD_Alloc_Base = 0;
|
|
pIoData->IO_Header.IOD_Alloc_End = 0;
|
|
pIoData->IO_Header.IOD_DesFlags = 0;
|
|
|
|
//
|
|
// copy IO_RESOURCE_DESCRIPTOR info to IO_RANGE format
|
|
//
|
|
for (count = 0, i = 0, pCurrent = pReqDes;
|
|
count < ReqPartialCount;
|
|
count++, pCurrent++) {
|
|
|
|
if (pCurrent->Type == CmResourceTypePort) {
|
|
pIoData->IO_Data[i].IOR_Align = MapFromNtAlignment(pCurrent->u.Port.Alignment);
|
|
pIoData->IO_Data[i].IOR_nPorts = pCurrent->u.Port.Length;
|
|
pIoData->IO_Data[i].IOR_Min = MAKEDWORDLONG(
|
|
pCurrent->u.Port.MinimumAddress.LowPart,
|
|
pCurrent->u.Port.MinimumAddress.HighPart);
|
|
pIoData->IO_Data[i].IOR_Max = MAKEDWORDLONG(
|
|
pCurrent->u.Port.MaximumAddress.LowPart,
|
|
pCurrent->u.Port.MaximumAddress.HighPart);
|
|
|
|
pIoData->IO_Data[i].IOR_RangeFlags = MapFromNtPortFlags(pCurrent->Flags);
|
|
//pIoData->IO_Data[i].IOR_RangeFlags |= MapFromNtDisposition(pCurrent->ShareDisposition, 0);
|
|
pIoData->IO_Data[i].IOR_Alias = MapAliasFromNtPortFlags(pCurrent->Flags);
|
|
i++;
|
|
}
|
|
}
|
|
pIoData->IO_Header.IOD_Count = i;
|
|
break;
|
|
}
|
|
|
|
case CmResourceTypeDma: {
|
|
|
|
//-------------------------------------------------------
|
|
// DMA Resource Type
|
|
//-------------------------------------------------------
|
|
|
|
//
|
|
// Note: u.Dma.Port is not mapped
|
|
// u.Dma.Reserved is not mapped
|
|
//
|
|
|
|
PDMA_RESOURCE pDmaData = (PDMA_RESOURCE)Buffer;
|
|
|
|
//
|
|
// verify passed in buffer size
|
|
//
|
|
ReqPartialCount = RANGE_COUNT(pReqDes, pLastAddr);
|
|
|
|
if (BufferLen < sizeof(DMA_RESOURCE) +
|
|
sizeof(DMA_RANGE) * (ReqPartialCount - 1)) {
|
|
|
|
Status = CR_BUFFER_SMALL;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// copy CM_PARTIAL_RESOURCE_DESCRIPTOR info to DMA_DES format
|
|
//
|
|
pDmaData->DMA_Header.DD_Count = ReqPartialCount;
|
|
pDmaData->DMA_Header.DD_Type = DType_Range;
|
|
pDmaData->DMA_Header.DD_Flags = 0;
|
|
pDmaData->DMA_Header.DD_Alloc_Chan = 0;
|
|
|
|
//
|
|
// copy DMA_RANGE info to IO_RESOURCE_DESCRIPTOR format
|
|
//
|
|
for (count = 0, i = 0, pCurrent = pReqDes;
|
|
count < ReqPartialCount;
|
|
count++, pCurrent++) {
|
|
|
|
if (pCurrent->Type == CmResourceTypeDma) {
|
|
pDmaData->DMA_Data[i].DR_Min = pCurrent->u.Dma.MinimumChannel;
|
|
pDmaData->DMA_Data[i].DR_Max = pCurrent->u.Dma.MaximumChannel;
|
|
pDmaData->DMA_Data[i].DR_Flags = MapFromNtDmaFlags(pCurrent->Flags);
|
|
//pDmaData->DMA_Data[i].DR_Flags |= MapFromNtDisposition(pCurrent->ShareDisposition, 0);
|
|
i++;
|
|
}
|
|
}
|
|
pDmaData->DMA_Header.DD_Count = i;
|
|
break;
|
|
}
|
|
|
|
case CmResourceTypeInterrupt: {
|
|
|
|
//-------------------------------------------------------
|
|
// IRQ Resource Type
|
|
//-------------------------------------------------------
|
|
|
|
if (ulFlags & CM_RESDES_WIDTH_64) {
|
|
//
|
|
// CM_RESDES_WIDTH_64
|
|
//
|
|
|
|
PIRQ_RESOURCE_64 pIrqData = (PIRQ_RESOURCE_64)Buffer;
|
|
|
|
//
|
|
// verify passed in buffer size
|
|
//
|
|
ReqPartialCount = RANGE_COUNT(pReqDes, pLastAddr);
|
|
|
|
if (BufferLen < sizeof(IRQ_RESOURCE_64) +
|
|
sizeof(IRQ_RANGE) * (ReqPartialCount - 1)) {
|
|
Status = CR_BUFFER_SMALL;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// copy CM_PARTIAL_RESOURCE_DESCRIPTOR info to IRQ_DES format
|
|
//
|
|
pIrqData->IRQ_Header.IRQD_Count = ReqPartialCount;
|
|
pIrqData->IRQ_Header.IRQD_Type = IRQType_Range;
|
|
pIrqData->IRQ_Header.IRQD_Flags = 0;
|
|
pIrqData->IRQ_Header.IRQD_Alloc_Num = 0;
|
|
pIrqData->IRQ_Header.IRQD_Affinity = 0;
|
|
|
|
//
|
|
// copy IO_RANGE info to IO_RESOURCE_DESCRIPTOR format
|
|
//
|
|
for (count = 0, i = 0, pCurrent = pReqDes;
|
|
count < ReqPartialCount;
|
|
count++, pCurrent++) {
|
|
|
|
if (pCurrent->Type == CmResourceTypeInterrupt) {
|
|
pIrqData->IRQ_Data[i].IRQR_Min = pCurrent->u.Interrupt.MinimumVector;
|
|
pIrqData->IRQ_Data[i].IRQR_Max = pCurrent->u.Interrupt.MaximumVector;
|
|
pIrqData->IRQ_Data[i].IRQR_Flags = MapFromNtIrqFlags(pCurrent->Flags) |
|
|
MapFromNtIrqShare(pCurrent->ShareDisposition);
|
|
//pIrqData->IRQ_Data[i].IRQR_Flags |= MapFromNtDisposition(pCurrent->ShareDisposition, 1);
|
|
i++;
|
|
}
|
|
}
|
|
pIrqData->IRQ_Header.IRQD_Count = i;
|
|
|
|
} else {
|
|
//
|
|
// CM_RESDES_WIDTH_32
|
|
//
|
|
|
|
PIRQ_RESOURCE_32 pIrqData = (PIRQ_RESOURCE_32)Buffer;
|
|
|
|
//
|
|
// verify passed in buffer size
|
|
//
|
|
ReqPartialCount = RANGE_COUNT(pReqDes, pLastAddr);
|
|
|
|
if (BufferLen < sizeof(IRQ_RESOURCE_32) +
|
|
sizeof(IRQ_RANGE) * (ReqPartialCount - 1)) {
|
|
Status = CR_BUFFER_SMALL;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// copy CM_PARTIAL_RESOURCE_DESCRIPTOR info to IRQ_DES format
|
|
//
|
|
pIrqData->IRQ_Header.IRQD_Count = ReqPartialCount;
|
|
pIrqData->IRQ_Header.IRQD_Type = IRQType_Range;
|
|
pIrqData->IRQ_Header.IRQD_Flags = 0;
|
|
pIrqData->IRQ_Header.IRQD_Alloc_Num = 0;
|
|
pIrqData->IRQ_Header.IRQD_Affinity = 0;
|
|
|
|
//
|
|
// copy IO_RANGE info to IO_RESOURCE_DESCRIPTOR format
|
|
//
|
|
for (count = 0, i = 0, pCurrent = pReqDes;
|
|
count < ReqPartialCount;
|
|
count++, pCurrent++) {
|
|
|
|
if (pCurrent->Type == CmResourceTypeInterrupt) {
|
|
pIrqData->IRQ_Data[i].IRQR_Min = pCurrent->u.Interrupt.MinimumVector;
|
|
pIrqData->IRQ_Data[i].IRQR_Max = pCurrent->u.Interrupt.MaximumVector;
|
|
pIrqData->IRQ_Data[i].IRQR_Flags = MapFromNtIrqFlags(pCurrent->Flags) |
|
|
MapFromNtIrqShare(pCurrent->ShareDisposition);
|
|
//pIrqData->IRQ_Data[i].IRQR_Flags |= MapFromNtDisposition(pCurrent->ShareDisposition, 1);
|
|
i++;
|
|
}
|
|
}
|
|
pIrqData->IRQ_Header.IRQD_Count = i;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case CmResourceTypeDevicePrivate: {
|
|
|
|
//-------------------------------------------------------
|
|
// Device Private Resource Type
|
|
//-------------------------------------------------------
|
|
|
|
PDEVPRIVATE_RESOURCE pPrvData = (PDEVPRIVATE_RESOURCE)Buffer;
|
|
|
|
//
|
|
// verify passed in buffer size
|
|
//
|
|
ReqPartialCount = RANGE_COUNT(pReqDes, pLastAddr);
|
|
|
|
if (BufferLen < sizeof(DEVPRIVATE_RESOURCE) +
|
|
sizeof(DEVPRIVATE_RANGE) * (ReqPartialCount - 1)) {
|
|
|
|
Status = CR_BUFFER_SMALL;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// copy CM_PARTIAL_RESOURCE_DESCRIPTOR info to MEM_DES format
|
|
//
|
|
pPrvData->PRV_Header.PD_Count = ReqPartialCount;
|
|
pPrvData->PRV_Header.PD_Type = PType_Range;
|
|
pPrvData->PRV_Header.PD_Data1 = 0;
|
|
pPrvData->PRV_Header.PD_Data2 = 0;
|
|
pPrvData->PRV_Header.PD_Data3 = 0;
|
|
pPrvData->PRV_Header.PD_Flags = 0;
|
|
|
|
//
|
|
// copy IO_RESOURCE_DESCRIPTOR info to MEM_RANGE format
|
|
//
|
|
for (i = 0, pCurrent = pReqDes;
|
|
i < ReqPartialCount;
|
|
i++, pCurrent++) {
|
|
|
|
pPrvData->PRV_Data[i].PR_Data1 = pCurrent->u.DevicePrivate.Data[0];
|
|
pPrvData->PRV_Data[i].PR_Data2 = pCurrent->u.DevicePrivate.Data[1];
|
|
pPrvData->PRV_Data[i].PR_Data3 = pCurrent->u.DevicePrivate.Data[2];
|
|
}
|
|
break;
|
|
}
|
|
|
|
|
|
case CmResourceTypeBusNumber: {
|
|
|
|
//-------------------------------------------------------
|
|
// Bus Number Resource Type
|
|
//-------------------------------------------------------
|
|
|
|
PBUSNUMBER_RESOURCE pBusData = (PBUSNUMBER_RESOURCE)Buffer;
|
|
|
|
//
|
|
// verify passed in buffer size
|
|
//
|
|
ReqPartialCount = RANGE_COUNT(pReqDes, pLastAddr);
|
|
|
|
if (BufferLen < sizeof(BUSNUMBER_RESOURCE) +
|
|
sizeof(BUSNUMBER_RANGE) * (ReqPartialCount - 1)) {
|
|
|
|
Status = CR_BUFFER_SMALL;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// copy CM_PARTIAL_RESOURCE_DESCRIPTOR info to BUSNUMBER_DES format
|
|
//
|
|
pBusData->BusNumber_Header.BUSD_Count = ReqPartialCount;
|
|
pBusData->BusNumber_Header.BUSD_Type = BusNumberType_Range;
|
|
pBusData->BusNumber_Header.BUSD_Flags = 0;
|
|
pBusData->BusNumber_Header.BUSD_Alloc_Base = 0;
|
|
pBusData->BusNumber_Header.BUSD_Alloc_End = 0;
|
|
|
|
//
|
|
// copy IO_RESOURCE_DESCRIPTOR info to MEM_RANGE format
|
|
//
|
|
for (i = 0, pCurrent = pReqDes;
|
|
i < ReqPartialCount;
|
|
i++, pCurrent++) {
|
|
|
|
pBusData->BusNumber_Data[i].BUSR_Min = pCurrent->u.BusNumber.MinBusNumber;
|
|
pBusData->BusNumber_Data[i].BUSR_Max = pCurrent->u.BusNumber.MaxBusNumber;
|
|
pBusData->BusNumber_Data[i].BUSR_nBusNumbers = pCurrent->u.BusNumber.Length;
|
|
pBusData->BusNumber_Data[i].BUSR_Flags = pCurrent->Flags;
|
|
}
|
|
break;
|
|
}
|
|
|
|
|
|
case CmResourceTypePcCardConfig: {
|
|
|
|
//-------------------------------------------------------
|
|
// PcCardConfig Resource Type
|
|
//-------------------------------------------------------
|
|
|
|
PPCCARD_RESOURCE pPcData = (PPCCARD_RESOURCE)Buffer;
|
|
ULONG index;
|
|
|
|
//
|
|
// verify passed in buffer size
|
|
//
|
|
ReqPartialCount = RANGE_COUNT(pReqDes, pLastAddr);
|
|
|
|
if (BufferLen < sizeof(PCCARD_RESOURCE)) {
|
|
Status = CR_BUFFER_SMALL;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// copy IO_RESOURCE_DESCRIPTOR info to PCCARD_DES format
|
|
//
|
|
pPcData->PcCard_Header.PCD_Reserved[0] = 0;
|
|
pPcData->PcCard_Header.PCD_Reserved[1] = 0;
|
|
pPcData->PcCard_Header.PCD_Reserved[2] = 0;
|
|
pPcData->PcCard_Header.PCD_ConfigIndex = PCMRES_GET_CONFIG_INDEX(pReqDes);
|
|
pPcData->PcCard_Header.PCD_MemoryCardBase1 = PCMRES_GET_MEMORY_CARDBASE(pReqDes, 0);
|
|
pPcData->PcCard_Header.PCD_MemoryCardBase2 = PCMRES_GET_MEMORY_CARDBASE(pReqDes, 1);
|
|
|
|
if (PCMRES_GET_IO_FLAG(pReqDes, 0, PCMRESF_IO_16BIT_ACCESS)) {
|
|
pPcData->PcCard_Header.PCD_Flags = fPCD_IO_16;
|
|
} else {
|
|
pPcData->PcCard_Header.PCD_Flags = fPCD_IO_8;
|
|
}
|
|
|
|
if (PCMRES_GET_MEMORY_FLAG(pReqDes, 0, PCMRESF_MEM_16BIT_ACCESS)) {
|
|
pPcData->PcCard_Header.PCD_Flags |= fPCD_MEM_16;
|
|
} else {
|
|
pPcData->PcCard_Header.PCD_Flags |= fPCD_MEM_8;
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
Clean0:
|
|
|
|
return Status;
|
|
|
|
} // NtRequirementsToResDes
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
// Routines to map flags between ConfigMgr and NT types
|
|
//-------------------------------------------------------------------
|
|
|
|
USHORT MapToNtMemoryFlags(IN DWORD CmMemoryFlags)
|
|
{
|
|
USHORT NtMemoryFlags = 0x0;
|
|
|
|
if (((CmMemoryFlags & mMD_MemoryType) == fMD_ROM) &&
|
|
((CmMemoryFlags & mMD_Readable) == fMD_ReadAllowed)) {
|
|
NtMemoryFlags |= CM_RESOURCE_MEMORY_READ_ONLY;
|
|
}
|
|
else if (((CmMemoryFlags & mMD_MemoryType) == fMD_RAM) &&
|
|
((CmMemoryFlags & mMD_Readable) == fMD_ReadDisallowed)) {
|
|
NtMemoryFlags |= CM_RESOURCE_MEMORY_WRITE_ONLY;
|
|
}
|
|
else {
|
|
NtMemoryFlags |= CM_RESOURCE_MEMORY_READ_WRITE;
|
|
}
|
|
|
|
if ((CmMemoryFlags & mMD_32_24) == fMD_24) {
|
|
NtMemoryFlags |= CM_RESOURCE_MEMORY_24;
|
|
}
|
|
|
|
if ((CmMemoryFlags & mMD_Prefetchable) == fMD_PrefetchAllowed) {
|
|
NtMemoryFlags |= CM_RESOURCE_MEMORY_PREFETCHABLE;
|
|
}
|
|
|
|
if ((CmMemoryFlags & mMD_CombinedWrite) == fMD_CombinedWriteAllowed) {
|
|
NtMemoryFlags |= CM_RESOURCE_MEMORY_COMBINEDWRITE;
|
|
}
|
|
|
|
if ((CmMemoryFlags & mMD_Cacheable) == fMD_Cacheable) {
|
|
NtMemoryFlags |= CM_RESOURCE_MEMORY_CACHEABLE;
|
|
}
|
|
|
|
return NtMemoryFlags;
|
|
}
|
|
|
|
|
|
|
|
DWORD MapFromNtMemoryFlags(IN USHORT NtMemoryFlags)
|
|
{
|
|
DWORD CmMemoryFlags = 0x0;
|
|
|
|
if (NtMemoryFlags & CM_RESOURCE_MEMORY_READ_ONLY) {
|
|
CmMemoryFlags |= (fMD_ReadAllowed | fMD_ROM);
|
|
}
|
|
else if (NtMemoryFlags & CM_RESOURCE_MEMORY_WRITE_ONLY) {
|
|
CmMemoryFlags |= (fMD_ReadDisallowed | fMD_RAM);
|
|
}
|
|
else {
|
|
CmMemoryFlags |= (fMD_ReadAllowed | fMD_RAM);
|
|
}
|
|
|
|
if (NtMemoryFlags & CM_RESOURCE_MEMORY_PREFETCHABLE) {
|
|
CmMemoryFlags |= fMD_PrefetchAllowed;
|
|
}
|
|
|
|
if (NtMemoryFlags & CM_RESOURCE_MEMORY_COMBINEDWRITE) {
|
|
CmMemoryFlags |= fMD_CombinedWriteAllowed;
|
|
}
|
|
|
|
if (NtMemoryFlags & CM_RESOURCE_MEMORY_CACHEABLE) {
|
|
CmMemoryFlags |= fMD_Cacheable;
|
|
}
|
|
|
|
if (!(NtMemoryFlags & CM_RESOURCE_MEMORY_24)) {
|
|
CmMemoryFlags |= fMD_32;
|
|
}
|
|
|
|
return CmMemoryFlags;
|
|
}
|
|
|
|
|
|
|
|
USHORT MapToNtPortFlags(IN DWORD CmPortFlags, IN DWORD CmAlias)
|
|
{
|
|
USHORT NtFlags = 0;
|
|
|
|
if ((CmPortFlags & fIOD_PortType) == fIOD_Memory) {
|
|
NtFlags |= CM_RESOURCE_PORT_MEMORY;
|
|
} else {
|
|
NtFlags |= CM_RESOURCE_PORT_IO;
|
|
}
|
|
|
|
//
|
|
// CmAlias uses the following rule:
|
|
//
|
|
// Positive Decode = 0xFF
|
|
// 10-bit decode = 0x0004 (2 ^ 2)
|
|
// 12-bit decode = 0x0010 (2 ^ 4)
|
|
// 16-bit decode = 0x0000 (2 ^ 8 = 0x0100, but since it's a byte, use 0)
|
|
//
|
|
// if CmAlias is zero, use flags to specify decode (new method)
|
|
//
|
|
|
|
if (CmAlias == 0) {
|
|
//
|
|
// use CM_RESOURCE_PORT_xxx related flags
|
|
//
|
|
// note that we need to mirror *ALL* flags from
|
|
// CM_RESOURCE_PORT_xxxx to fIOD_xxxx
|
|
// however bits need not be same
|
|
// not doing this will cause at least resource conflicts to fail
|
|
// see also MapFromNtPortFlags
|
|
//
|
|
if (CmPortFlags & fIOD_10_BIT_DECODE) {
|
|
NtFlags |= CM_RESOURCE_PORT_10_BIT_DECODE;
|
|
}
|
|
if (CmPortFlags & fIOD_12_BIT_DECODE) {
|
|
NtFlags |= CM_RESOURCE_PORT_12_BIT_DECODE;
|
|
}
|
|
if (CmPortFlags & fIOD_16_BIT_DECODE) {
|
|
NtFlags |= CM_RESOURCE_PORT_16_BIT_DECODE;
|
|
}
|
|
if (CmPortFlags & fIOD_POSITIVE_DECODE) {
|
|
NtFlags |= CM_RESOURCE_PORT_POSITIVE_DECODE;
|
|
}
|
|
}
|
|
else if (CmAlias == IO_ALIAS_POSITIVE_DECODE) {
|
|
NtFlags |= CM_RESOURCE_PORT_POSITIVE_DECODE;
|
|
} else if (CmAlias == IO_ALIAS_10_BIT_DECODE) {
|
|
NtFlags |= CM_RESOURCE_PORT_10_BIT_DECODE;
|
|
} else if (CmAlias == IO_ALIAS_12_BIT_DECODE) {
|
|
NtFlags |= CM_RESOURCE_PORT_12_BIT_DECODE;
|
|
} else if (CmAlias == IO_ALIAS_16_BIT_DECODE) {
|
|
NtFlags |= CM_RESOURCE_PORT_16_BIT_DECODE;
|
|
}
|
|
//
|
|
// these have no mirror in cmAlias, and can be combined
|
|
//
|
|
if (CmPortFlags & fIOD_PASSIVE_DECODE) {
|
|
NtFlags |= CM_RESOURCE_PORT_PASSIVE_DECODE;
|
|
}
|
|
if (CmPortFlags & fIOD_WINDOW_DECODE) {
|
|
NtFlags |= CM_RESOURCE_PORT_WINDOW_DECODE;
|
|
}
|
|
|
|
return NtFlags;
|
|
}
|
|
|
|
|
|
|
|
DWORD MapFromNtPortFlags(IN USHORT NtPortFlags)
|
|
{
|
|
DWORD Flags = 0;
|
|
|
|
if ((NtPortFlags & (CM_RESOURCE_PORT_MEMORY|CM_RESOURCE_PORT_IO)) == CM_RESOURCE_PORT_MEMORY) {
|
|
Flags |=fIOD_Memory;
|
|
} else {
|
|
Flags |=fIOD_IO;
|
|
}
|
|
|
|
//
|
|
// note that we need to mirror *ALL* flags from
|
|
// CM_RESOURCE_PORT_xxxx to fIOD_xxxx
|
|
// however bits need not be same
|
|
// not doing this will cause at least resource conflicts to fail
|
|
// see also MapToNtPortFlags
|
|
//
|
|
if (NtPortFlags & CM_RESOURCE_PORT_10_BIT_DECODE) {
|
|
Flags |= fIOD_10_BIT_DECODE;
|
|
}
|
|
if (NtPortFlags & CM_RESOURCE_PORT_12_BIT_DECODE) {
|
|
Flags |= fIOD_12_BIT_DECODE;
|
|
}
|
|
if (NtPortFlags & CM_RESOURCE_PORT_16_BIT_DECODE) {
|
|
Flags |= fIOD_16_BIT_DECODE;
|
|
}
|
|
if (NtPortFlags & CM_RESOURCE_PORT_POSITIVE_DECODE) {
|
|
Flags |= fIOD_POSITIVE_DECODE;
|
|
}
|
|
if (NtPortFlags & CM_RESOURCE_PORT_PASSIVE_DECODE) {
|
|
Flags |= fIOD_PASSIVE_DECODE;
|
|
}
|
|
if (NtPortFlags & CM_RESOURCE_PORT_WINDOW_DECODE) {
|
|
Flags |= fIOD_WINDOW_DECODE;
|
|
}
|
|
return Flags;
|
|
}
|
|
|
|
|
|
|
|
DWORD MapAliasFromNtPortFlags(IN USHORT NtPortFlags)
|
|
{
|
|
DWORD Alias = 0;
|
|
if (NtPortFlags & CM_RESOURCE_PORT_10_BIT_DECODE) {
|
|
Alias = IO_ALIAS_10_BIT_DECODE;
|
|
} else if (NtPortFlags & CM_RESOURCE_PORT_12_BIT_DECODE) {
|
|
Alias = IO_ALIAS_12_BIT_DECODE;
|
|
} else if (NtPortFlags & CM_RESOURCE_PORT_16_BIT_DECODE) {
|
|
Alias = IO_ALIAS_16_BIT_DECODE;
|
|
} else if (NtPortFlags & CM_RESOURCE_PORT_POSITIVE_DECODE) {
|
|
Alias = IO_ALIAS_POSITIVE_DECODE;
|
|
}
|
|
return Alias;
|
|
}
|
|
|
|
|
|
|
|
ULONG MapToNtAlignment(IN DWORDLONG CmPortAlign)
|
|
{
|
|
return (ULONG)(~CmPortAlign + 1);
|
|
}
|
|
|
|
|
|
|
|
DWORDLONG MapFromNtAlignment(IN ULONG NtPortAlign)
|
|
{
|
|
return (DWORDLONG)(~((DWORDLONG)NtPortAlign - 1));
|
|
}
|
|
|
|
|
|
|
|
USHORT MapToNtDmaFlags(IN DWORD CmDmaFlags)
|
|
{
|
|
USHORT NtDmaFlags;
|
|
|
|
if ((CmDmaFlags & mDD_Width) == fDD_DWORD) {
|
|
NtDmaFlags = CM_RESOURCE_DMA_32;
|
|
} else if ((CmDmaFlags & mDD_Width) == fDD_WORD) {
|
|
NtDmaFlags = CM_RESOURCE_DMA_16;
|
|
} else if ((CmDmaFlags & mDD_Width) == fDD_BYTE_AND_WORD) {
|
|
NtDmaFlags = CM_RESOURCE_DMA_8_AND_16;
|
|
} else {
|
|
NtDmaFlags = CM_RESOURCE_DMA_8; //default
|
|
}
|
|
|
|
if ((CmDmaFlags & mDD_BusMaster) == fDD_BusMaster) {
|
|
NtDmaFlags |= CM_RESOURCE_DMA_BUS_MASTER;
|
|
}
|
|
|
|
if ((CmDmaFlags & mDD_Type) == fDD_TypeA) {
|
|
NtDmaFlags |= CM_RESOURCE_DMA_TYPE_A;
|
|
} else if ((CmDmaFlags & mDD_Type) == fDD_TypeB) {
|
|
NtDmaFlags |= CM_RESOURCE_DMA_TYPE_B;
|
|
} else if ((CmDmaFlags & mDD_Type) == fDD_TypeF) {
|
|
NtDmaFlags |= CM_RESOURCE_DMA_TYPE_F;
|
|
}
|
|
|
|
return NtDmaFlags;
|
|
}
|
|
|
|
|
|
|
|
DWORD MapFromNtDmaFlags(IN USHORT NtDmaFlags)
|
|
{
|
|
DWORD CmDmaFlags;
|
|
|
|
if (NtDmaFlags & CM_RESOURCE_DMA_32) {
|
|
CmDmaFlags = fDD_DWORD;
|
|
} else if (NtDmaFlags & CM_RESOURCE_DMA_8_AND_16) {
|
|
CmDmaFlags = fDD_BYTE_AND_WORD;
|
|
} else if (NtDmaFlags & CM_RESOURCE_DMA_16) {
|
|
CmDmaFlags = fDD_WORD;
|
|
} else {
|
|
CmDmaFlags = fDD_BYTE;
|
|
}
|
|
|
|
if (NtDmaFlags & CM_RESOURCE_DMA_BUS_MASTER) {
|
|
CmDmaFlags |= fDD_BusMaster;
|
|
}
|
|
|
|
if (NtDmaFlags & CM_RESOURCE_DMA_TYPE_A) {
|
|
CmDmaFlags |= fDD_TypeA;
|
|
} else if (NtDmaFlags & CM_RESOURCE_DMA_TYPE_B) {
|
|
CmDmaFlags |= fDD_TypeB;
|
|
} else if (NtDmaFlags & CM_RESOURCE_DMA_TYPE_F) {
|
|
CmDmaFlags |= fDD_TypeF;
|
|
}
|
|
|
|
return CmDmaFlags;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
USHORT MapToNtIrqFlags(IN DWORD CmIrqFlags)
|
|
{
|
|
if ((CmIrqFlags & mIRQD_Edge_Level) == fIRQD_Level) {
|
|
return CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
|
|
} else {
|
|
return CM_RESOURCE_INTERRUPT_LATCHED;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
DWORD MapFromNtIrqFlags(IN USHORT NtIrqFlags)
|
|
{
|
|
if (NtIrqFlags == CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE) {
|
|
return fIRQD_Level;
|
|
} else {
|
|
return fIRQD_Edge;
|
|
}
|
|
}
|
|
|
|
#if 0
|
|
UCHAR MapToNtDisposition(IN DWORD CmFlags, IN BOOL bIrq)
|
|
{
|
|
UCHAR disposition;
|
|
DWORD flag = CmFlags & mD_ShareDisposition;
|
|
|
|
if (flag == fD_ShareDeviceExclusive) {
|
|
disposition = CmResourceShareDeviceExclusive;
|
|
} else if (flag == fD_ShareDriverExclusive) {
|
|
disposition = CmResourceShareDriverExclusive;
|
|
} else if (flag == fD_ShareShared) {
|
|
disposition = CmResourceShareShared;
|
|
} else if (flag == fD_ShareUndetermined) {
|
|
//
|
|
// if undetermined, also check for the old irq specific
|
|
// share flags
|
|
//
|
|
if ((CmFlags & mIRQD_Share) == fIRQD_Share) {
|
|
disposition = CmResourceShareShared;
|
|
} else {
|
|
disposition = CmResourceShareUndetermined;
|
|
}
|
|
}
|
|
|
|
return disposition;
|
|
}
|
|
|
|
|
|
DWORD MapFromNtDisposition(IN UCHAR NtDisposition, IN BOOL bIrq)
|
|
{
|
|
DWORD flag = 0;
|
|
|
|
if (NtDisposition == CmResourceShareUndetermined) {
|
|
flag = fD_ShareUndetermined;
|
|
} else if (NtDisposition == CmResourceShareDeviceExclusive) {
|
|
flag = fD_ShareDeviceExclusive;
|
|
} else if (NtDisposition == CmResourceShareDriverExclusive) {
|
|
flag = fD_ShareDriverExclusive;
|
|
} else if (NtDisposition == CmResourceShareShared) {
|
|
flag = fD_ShareShared;
|
|
}
|
|
|
|
if (bIrq) {
|
|
//
|
|
// also set the irq specific shared/exclusive bit, this is for
|
|
// backwards compatibility, new apps should look at the new bits.
|
|
//
|
|
if (flag == fD_ShareShared) {
|
|
flag |= fIRQD_Share;
|
|
} else {
|
|
flag |= fIRQD_Exclusive;
|
|
}
|
|
}
|
|
|
|
return flag;
|
|
}
|
|
#endif
|
|
|
|
|
|
UCHAR MapToNtIrqShare(IN DWORD CmIrqFlags)
|
|
{
|
|
if ((CmIrqFlags & mIRQD_Share) == fIRQD_Exclusive) {
|
|
return CmResourceShareDeviceExclusive;
|
|
} else {
|
|
return CmResourceShareShared;
|
|
}
|
|
}
|
|
|
|
DWORD MapFromNtIrqShare(IN UCHAR NtIrqShare)
|
|
{
|
|
if (NtIrqShare == CmResourceShareDeviceExclusive) {
|
|
return fIRQD_Exclusive;
|
|
}
|
|
else if (NtIrqShare == CmResourceShareDriverExclusive) {
|
|
return fIRQD_Exclusive;
|
|
}
|
|
else return fIRQD_Share;
|
|
}
|
|
|
|
|
|
|
|
#define CM_RESOURCE_BUSNUMBER_SUBALLOCATE_FIRST_VALUE 0x0001
|
|
|
|
#define mBUSD_SubAllocFirst (0x1) // Bitmask, whether SubAlloc first value allowed
|
|
#define fBUSD_SubAllocFirst_Allowed (0x0) // Suballoc from first value
|
|
#define fBUSD_SubAllocFirst_Disallowed (0x1) // Don't suballoc from first value
|