Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

4959 lines
158 KiB

  1. /*++
  2. Copyright (c) 1995-2001 Microsoft Corporation
  3. Module Name:
  4. rresdes.c
  5. Abstract:
  6. This module contains the server-side resource description APIs.
  7. PNP_AddResDes
  8. PNP_FreeResDes
  9. PNP_GetNextResDes
  10. PNP_GetResDesData
  11. PNP_GetResDesDataSize
  12. PNP_ModifyResDes
  13. PNP_DetectResourceConflict
  14. Author:
  15. Paula Tomlinson (paulat) 9-27-1995
  16. Environment:
  17. User-mode only.
  18. Revision History:
  19. 27-Sept-1995 paulat
  20. Creation and initial implementation.
  21. --*/
  22. //
  23. // includes
  24. //
  25. #include "precomp.h"
  26. #include "umpnpi.h"
  27. //
  28. // private prototypes
  29. //
  30. BOOL
  31. FindLogConf(
  32. IN LPBYTE pList,
  33. OUT LPBYTE *ppLogConf,
  34. IN ULONG RegDataType,
  35. IN ULONG ulTag
  36. );
  37. BOOL
  38. FindResDes(
  39. IN LPBYTE pList,
  40. IN ULONG RegDataType,
  41. IN ULONG ulLogConfTag,
  42. IN ULONG ulResTag,
  43. IN RESOURCEID ResType,
  44. OUT LPBYTE *ppRD,
  45. OUT LPBYTE *ppLogConf,
  46. OUT PULONG pulSubIndex OPTIONAL
  47. );
  48. PIO_RESOURCE_DESCRIPTOR
  49. AdvanceRequirementsDescriptorPtr(
  50. IN PIO_RESOURCE_DESCRIPTOR pReqDesStart,
  51. IN ULONG ulIncrement,
  52. IN ULONG ulRemainingRanges,
  53. OUT PULONG pulRangeCount
  54. );
  55. ULONG
  56. RANGE_COUNT(
  57. IN PIO_RESOURCE_DESCRIPTOR pReqDes,
  58. IN LPBYTE pLastReqAddr
  59. );
  60. ULONG
  61. GetResDesSize(
  62. IN ULONG ResourceID,
  63. IN ULONG ulFlags
  64. );
  65. ULONG
  66. GetReqDesSize(
  67. IN ULONG ResourceID,
  68. IN PIO_RESOURCE_DESCRIPTOR pReqDes,
  69. IN LPBYTE pLastReqAddr,
  70. IN ULONG ulFlags
  71. );
  72. CONFIGRET
  73. ResDesToNtResource(
  74. IN PCVOID ResourceData,
  75. IN RESOURCEID ResourceID,
  76. IN ULONG ResourceLen,
  77. IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pResDes,
  78. IN ULONG ulTag,
  79. IN ULONG ulFlags
  80. );
  81. CONFIGRET
  82. ResDesToNtRequirements(
  83. IN PCVOID ResourceData,
  84. IN RESOURCEID ResourceType,
  85. IN ULONG ResourceLen,
  86. IN PIO_RESOURCE_DESCRIPTOR pReqDes,
  87. IN OUT PULONG pulResCount,
  88. IN ULONG ulTag,
  89. IN ULONG ulFlags
  90. );
  91. CONFIGRET
  92. NtResourceToResDes(
  93. IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pResDes,
  94. IN OUT LPBYTE Buffer,
  95. IN ULONG BufferLen,
  96. IN LPBYTE pLastAddr,
  97. IN ULONG ulFlags
  98. );
  99. CONFIGRET
  100. NtRequirementsToResDes(
  101. IN PIO_RESOURCE_DESCRIPTOR pReqDes,
  102. IN OUT LPBYTE Buffer,
  103. IN ULONG BufferLen,
  104. IN LPBYTE pLastAddr,
  105. IN ULONG ulFlags
  106. );
  107. UCHAR
  108. NT_RES_TYPE(
  109. IN RESOURCEID ResourceID
  110. );
  111. ULONG
  112. CM_RES_TYPE(
  113. IN UCHAR ResourceType
  114. );
  115. USHORT MapToNtMemoryFlags(IN DWORD);
  116. DWORD MapFromNtMemoryFlags(IN USHORT);
  117. USHORT MapToNtPortFlags(IN DWORD, IN DWORD);
  118. DWORD MapFromNtPortFlags(IN USHORT);
  119. DWORD MapAliasFromNtPortFlags(IN USHORT);
  120. ULONG MapToNtAlignment(IN DWORDLONG);
  121. DWORDLONG MapFromNtAlignment(IN ULONG);
  122. USHORT MapToNtDmaFlags(IN DWORD);
  123. DWORD MapFromNtDmaFlags(IN USHORT);
  124. USHORT MapToNtIrqFlags(IN DWORD);
  125. DWORD MapFromNtIrqFlags(IN USHORT);
  126. UCHAR MapToNtIrqShare(IN DWORD);
  127. DWORD MapFromNtIrqShare(IN UCHAR);
  128. //
  129. // prototypes from rlogconf.c
  130. //
  131. CONFIGRET
  132. GetLogConfData(
  133. IN HKEY hKey,
  134. IN ULONG ulLogConfType,
  135. OUT PULONG pulRegDataType,
  136. OUT LPWSTR pszValueName,
  137. OUT LPBYTE *ppBuffer,
  138. OUT PULONG pulBufferSize
  139. );
  140. PCM_FULL_RESOURCE_DESCRIPTOR
  141. AdvanceResourcePtr(
  142. IN PCM_FULL_RESOURCE_DESCRIPTOR pRes
  143. );
  144. PIO_RESOURCE_LIST
  145. AdvanceRequirementsPtr(
  146. IN PIO_RESOURCE_LIST pReq
  147. );
  148. //
  149. // global data
  150. //
  151. #define HIDWORD(x) ((DWORD)(((DWORDLONG)(x) >> 32) & 0xFFFFFFFF))
  152. #define LODWORD(x) ((DWORD)(x))
  153. #define MAKEDWORDLONG(x,y) ((DWORDLONG)(((DWORD)(x)) | ((DWORDLONG)((DWORD)(y))) << 32))
  154. CONFIGRET
  155. PNP_AddResDes(
  156. IN handle_t hBinding,
  157. IN LPWSTR pDeviceID,
  158. IN ULONG LogConfTag,
  159. IN ULONG LogConfType,
  160. IN RESOURCEID ResourceID,
  161. OUT PULONG pResourceTag,
  162. IN LPBYTE ResourceData,
  163. IN ULONG ResourceLen,
  164. IN ULONG ulFlags
  165. )
  166. /*++
  167. Routine Description:
  168. This the server-side of an RPC remote call. This routine adds
  169. a res des to the specified log conf.
  170. Arguments:
  171. hBinding RPC binding handle.
  172. pDeviceID Null-terminated device instance id string.
  173. LogConfTag Specifies the log conf within a given type.
  174. LogConfType Specifies the log conf type.
  175. ResourceID Specifies the resource type.
  176. ResourceTag Returns with resource within a given type.
  177. ResourceData Resource data (of ResourceID type) to add to log conf.
  178. ResourceLen Size of ResourceData in bytes.
  179. ulFlags Specifies the width of certain variable-size resource
  180. descriptor structure fields, where applicable.
  181. Currently, the following flags are defined:
  182. CM_RESDES_WIDTH_32 or
  183. CM_RESDES_WIDTH_64
  184. If no flags are specified, the width of the variable-sized
  185. resource data supplied is assumed to be that native to the
  186. platform of the caller.
  187. Return Value:
  188. If the specified device instance is valid, it returns CR_SUCCESS,
  189. otherwise it returns CR_ error code.
  190. --*/
  191. {
  192. CONFIGRET Status = CR_SUCCESS;
  193. HKEY hKey = NULL;
  194. WCHAR szValueName[64];
  195. ULONG RegDataType = 0, ulListSize = 0, i = 0, ulSize = 0, ulOffset = 0,
  196. ulAddListSize = 0;
  197. LPBYTE pList = NULL, pLogConf = NULL, pTemp = NULL;
  198. //
  199. // Always add the res des to the end, except in the case where a
  200. // class-specific res des has already been added. The class-specific
  201. // res des always MUST be last so add any new (non-class specific)
  202. // res des just before the class specific. Note that there can be
  203. // only one class-specific res des.
  204. //
  205. try {
  206. //
  207. // verify client access
  208. //
  209. if (!VerifyClientAccess(hBinding, &gLuidLoadDriverPrivilege)) {
  210. Status = CR_ACCESS_DENIED;
  211. goto Clean0;
  212. }
  213. //
  214. // validate/initialize output parameters
  215. //
  216. if (!ARGUMENT_PRESENT(pResourceTag)) {
  217. Status = CR_INVALID_POINTER;
  218. goto Clean0;
  219. } else {
  220. *pResourceTag = 0;
  221. }
  222. //
  223. // validate parameters
  224. //
  225. if (INVALID_FLAGS(ulFlags, CM_RESDES_WIDTH_BITS)) {
  226. Status = CR_INVALID_FLAG;
  227. goto Clean0;
  228. }
  229. //
  230. // validate res des size
  231. //
  232. if (ResourceLen < GetResDesSize(ResourceID, ulFlags)) {
  233. Status = CR_INVALID_DATA;
  234. goto Clean0;
  235. }
  236. //
  237. // make sure original caller didn't specify root devnode
  238. //
  239. if (!IsLegalDeviceId(pDeviceID) || IsRootDeviceID(pDeviceID)) {
  240. Status = CR_INVALID_LOG_CONF;
  241. goto Clean0;
  242. }
  243. //
  244. // open a key to the device's LogConf subkey
  245. //
  246. Status = OpenLogConfKey(pDeviceID, LogConfType, &hKey);
  247. if (Status != CR_SUCCESS) {
  248. goto Clean0;
  249. }
  250. //
  251. // Retrieve log conf data from the registry
  252. //
  253. Status = GetLogConfData(hKey, LogConfType,
  254. &RegDataType, szValueName,
  255. &pList, &ulListSize);
  256. if (Status != CR_SUCCESS) {
  257. goto Clean0;
  258. }
  259. //
  260. // Seek to the log conf that matches the log conf tag
  261. //
  262. if (!FindLogConf(pList, &pLogConf, RegDataType, LogConfTag)) {
  263. Status = CR_INVALID_LOG_CONF;
  264. goto Clean0;
  265. }
  266. //-------------------------------------------------------------
  267. // Specified log conf type contains Resource Data only
  268. //-------------------------------------------------------------
  269. if (RegDataType == REG_RESOURCE_LIST) {
  270. PCM_RESOURCE_LIST pResList = (PCM_RESOURCE_LIST)pList;
  271. PCM_FULL_RESOURCE_DESCRIPTOR pRes = (PCM_FULL_RESOURCE_DESCRIPTOR)pLogConf;
  272. PCM_PARTIAL_RESOURCE_DESCRIPTOR pResDes = NULL;
  273. //
  274. // determine size required to hold the new res des
  275. //
  276. ulAddListSize = sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
  277. if (ResourceID == ResType_ClassSpecific) {
  278. PCS_RESOURCE pCsRes = (PCS_RESOURCE)ResourceData;
  279. //
  280. // first make sure there isn't already a cs (only one per lc)
  281. //
  282. if (pRes->PartialResourceList.Count != 0 &&
  283. pRes->PartialResourceList.PartialDescriptors[pRes->PartialResourceList.Count-1].Type
  284. == CmResourceTypeDeviceSpecific) {
  285. Status = CR_INVALID_RES_DES;
  286. goto Clean0;
  287. }
  288. //
  289. // account for any extra class specific data in res list
  290. //
  291. ulAddListSize += sizeof(GUID) +
  292. pCsRes->CS_Header.CSD_SignatureLength +
  293. pCsRes->CS_Header.CSD_LegacyDataSize;
  294. }
  295. //
  296. // reallocate the resource buffers to hold the new res des
  297. //
  298. ulOffset = (DWORD)((ULONG_PTR)pRes - (ULONG_PTR)pResList); // for restoring later
  299. pResList = HeapReAlloc(ghPnPHeap, 0, pResList, ulListSize + ulAddListSize);
  300. if (pResList == NULL) {
  301. Status = CR_OUT_OF_MEMORY;
  302. goto Clean0;
  303. }
  304. pList = (LPBYTE)pResList;
  305. pRes = (PCM_FULL_RESOURCE_DESCRIPTOR)((LPBYTE)pResList + ulOffset);
  306. //
  307. // Find location for new res des (make a hole if necessary)
  308. //
  309. // If the following conditions are true, then can just append the
  310. // new data to the end of the rsource list:
  311. // - The selected LogConf is the last LogConf, and
  312. // - No ClassSpecific resource has been added yet (or no resource period)
  313. //
  314. i = pRes->PartialResourceList.Count;
  315. if ((LogConfTag == pResList->Count - 1) &&
  316. (i == 0 ||
  317. pRes->PartialResourceList.PartialDescriptors[i-1].Type !=
  318. CmResourceTypeDeviceSpecific)) {
  319. *pResourceTag = i;
  320. pResDes = &pRes->PartialResourceList.PartialDescriptors[i];
  321. } else {
  322. //
  323. // Need to make a hole for the new data before copying it.
  324. // Find the spot to add the new res des data at - either as the
  325. // last res des for this log conf or just before the class
  326. // specific res des if it exists.
  327. //
  328. if (i == 0) {
  329. *pResourceTag = 0;
  330. pResDes = &pRes->PartialResourceList.PartialDescriptors[0];
  331. } else if (pRes->PartialResourceList.PartialDescriptors[i-1].Type ==
  332. CmResourceTypeDeviceSpecific) {
  333. *pResourceTag = i-1;
  334. pResDes = &pRes->PartialResourceList.PartialDescriptors[i-1];
  335. } else {
  336. *pResourceTag = i;
  337. pResDes = &pRes->PartialResourceList.PartialDescriptors[i];
  338. }
  339. //
  340. // Move any data after this point down a notch to make room for
  341. // the new res des
  342. //
  343. ulSize = ulListSize - (DWORD)((ULONG_PTR)pResDes - (ULONG_PTR)pResList);
  344. pTemp = HeapAlloc(ghPnPHeap, 0, ulSize);
  345. if (pTemp == NULL) {
  346. Status = CR_OUT_OF_MEMORY;
  347. goto Clean0;
  348. }
  349. memcpy(pTemp, pResDes, ulSize);
  350. memcpy((LPBYTE)((LPBYTE)pResDes + ulAddListSize), pTemp, ulSize);
  351. }
  352. if (ResourceID == ResType_ClassSpecific) {
  353. *pResourceTag = RESDES_CS_TAG;
  354. }
  355. //
  356. // Add res des to the log conf
  357. //
  358. Status = ResDesToNtResource(ResourceData, ResourceID, ResourceLen,
  359. pResDes, *pResourceTag, ulFlags);
  360. //
  361. // update the lc and res header
  362. //
  363. pRes->PartialResourceList.Count += 1; // added a single res des (_DES)
  364. }
  365. //-------------------------------------------------------------
  366. // Specified log conf type contains requirements data only
  367. //-------------------------------------------------------------
  368. else if (RegDataType == REG_RESOURCE_REQUIREMENTS_LIST) {
  369. PIO_RESOURCE_REQUIREMENTS_LIST pReqList = (PIO_RESOURCE_REQUIREMENTS_LIST)pList;
  370. PIO_RESOURCE_LIST pReq = (PIO_RESOURCE_LIST)pLogConf;
  371. PIO_RESOURCE_DESCRIPTOR pReqDes = NULL;
  372. PGENERIC_RESOURCE pGenRes = (PGENERIC_RESOURCE)ResourceData;
  373. //
  374. // validate res des type - ClassSpecific not allowed in
  375. // requirements list (only resource list)
  376. //
  377. if (ResourceID == ResType_ClassSpecific ||
  378. pGenRes->GENERIC_Header.GENERIC_Count == 0) {
  379. Status = CR_INVALID_RES_DES;
  380. goto Clean0;
  381. }
  382. //
  383. // determine size required to hold the new res des
  384. //
  385. ulAddListSize = pGenRes->GENERIC_Header.GENERIC_Count *
  386. sizeof(IO_RESOURCE_DESCRIPTOR);
  387. //
  388. // reallocate the resource buffers to hold the new res des
  389. //
  390. ulOffset = (DWORD)((ULONG_PTR)pReq - (ULONG_PTR)pReqList); // for restoring later
  391. pReqList = HeapReAlloc(ghPnPHeap, 0, pReqList, ulListSize + ulAddListSize);
  392. if (pReqList == NULL) {
  393. Status = CR_OUT_OF_MEMORY;
  394. goto Clean0;
  395. }
  396. pList = (LPBYTE)pReqList;
  397. pReq = (PIO_RESOURCE_LIST)((LPBYTE)pReqList + ulOffset);
  398. //
  399. // Find location for new res des - the new res des always ends
  400. // up being added as the last res des for this log conf.
  401. //
  402. *pResourceTag = pReq->Count;
  403. pReqDes = &pReq->Descriptors[*pResourceTag];
  404. //
  405. // If the selected LogConf is the last LogConf then can just
  406. // append the new res des data to the end of the requirements
  407. // list. Otherwise, need to make a whole for the new data
  408. // before copying it.
  409. //
  410. if (LogConfTag != pReqList->AlternativeLists - 1) {
  411. ulSize = ulListSize - (DWORD)((ULONG_PTR)pReqDes - (ULONG_PTR)pReqList);
  412. pTemp = HeapAlloc(ghPnPHeap, 0, ulSize);
  413. if (pTemp == NULL) {
  414. Status = CR_OUT_OF_MEMORY;
  415. goto Clean0;
  416. }
  417. memcpy(pTemp, pReqDes, ulSize);
  418. memcpy((LPBYTE)((LPBYTE)pReqDes + ulAddListSize), pTemp, ulSize);
  419. }
  420. //
  421. // Add res des to the log conf.
  422. //
  423. Status = ResDesToNtRequirements(ResourceData, ResourceID, ResourceLen,
  424. pReqDes, &i, *pResourceTag, ulFlags);
  425. //
  426. // update the lc and res header
  427. //
  428. pReq->Count += i; // _RANGES added
  429. pReqList->ListSize = ulListSize + ulAddListSize;
  430. }
  431. //
  432. // Write out the new/updated log conf list to the registry
  433. //
  434. if (RegSetValueEx(hKey, szValueName, 0, RegDataType,
  435. pList, ulListSize + ulAddListSize)
  436. != ERROR_SUCCESS) {
  437. Status = CR_REGISTRY_ERROR;
  438. goto Clean0;
  439. }
  440. Clean0:
  441. NOTHING;
  442. } except(EXCEPTION_EXECUTE_HANDLER) {
  443. Status = CR_FAILURE;
  444. }
  445. if (pList != NULL) {
  446. HeapFree(ghPnPHeap, 0, pList);
  447. }
  448. if (pTemp != NULL) {
  449. HeapFree(ghPnPHeap, 0, pTemp);
  450. }
  451. if (hKey != NULL) {
  452. RegCloseKey(hKey);
  453. }
  454. return Status;
  455. } // PNP_AddResDes
  456. CONFIGRET
  457. PNP_FreeResDes(
  458. IN handle_t hBinding,
  459. IN LPWSTR pDeviceID,
  460. IN ULONG LogConfTag,
  461. IN ULONG LogConfType,
  462. IN RESOURCEID ResourceID,
  463. IN ULONG ResourceTag,
  464. OUT PULONG pulPreviousResType,
  465. OUT PULONG pulPreviousResTag,
  466. IN ULONG ulFlags
  467. )
  468. /*++
  469. Routine Description:
  470. This the server-side of an RPC remote call. This routine frees
  471. a res des to the specified log conf.
  472. Arguments:
  473. hBinding RPC binding handle.
  474. pDeviceID Null-terminated device instance id string.
  475. LogConfTag Specifies the log conf within a given type.
  476. LogConfType Specifies the log conf type.
  477. ResourceID Specifies the resource type.
  478. ResourceTag Specifies the resource within a given type.
  479. pulPreviousResType Receives the previous resource type.
  480. pulPreviousResTag Receives the previous resource within a given type.
  481. ulFlags Not used, must be zero.
  482. Return Value:
  483. If the specified device instance is valid, it returns CR_SUCCESS,
  484. otherwise it returns CR_ error code.
  485. --*/
  486. {
  487. CONFIGRET Status = CR_SUCCESS;
  488. HKEY hKey = NULL;
  489. WCHAR szValueName[64];
  490. ULONG RegDataType=0, RdCount=0, ulCount=0, ulListSize=0, ulSize=0;
  491. LPBYTE pList=NULL, pLogConf=NULL, pRD=NULL, pTemp=NULL, pNext=NULL;
  492. try {
  493. //
  494. // verify client access
  495. //
  496. if (!VerifyClientAccess(hBinding, &gLuidLoadDriverPrivilege)) {
  497. Status = CR_ACCESS_DENIED;
  498. goto Clean0;
  499. }
  500. //
  501. // validate parameters
  502. //
  503. if (INVALID_FLAGS(ulFlags, 0)) {
  504. Status = CR_INVALID_FLAG;
  505. goto Clean0;
  506. }
  507. //
  508. // make sure original caller didn't specify root devnode
  509. //
  510. if (!IsLegalDeviceId(pDeviceID) || IsRootDeviceID(pDeviceID)) {
  511. Status = CR_INVALID_LOG_CONF;
  512. goto Clean0;
  513. }
  514. //
  515. // open a key to the device's LogConf subkey
  516. //
  517. Status = OpenLogConfKey(pDeviceID, LogConfType, &hKey);
  518. if (Status != CR_SUCCESS) {
  519. goto Clean0;
  520. }
  521. //
  522. // Retrieve log conf data from the registry
  523. //
  524. Status = GetLogConfData(hKey, LogConfType,
  525. &RegDataType, szValueName,
  526. &pList, &ulListSize);
  527. if (Status != CR_SUCCESS) {
  528. Status = CR_INVALID_RES_DES; // log conf doesn't exist
  529. goto Clean0;
  530. }
  531. //
  532. // seek to the res des that matches the resource tag.
  533. //
  534. if (!FindResDes(pList, RegDataType, LogConfTag,
  535. ResourceTag, ResourceID, &pRD, &pLogConf, &ulCount)) {
  536. Status = CR_INVALID_RES_DES;
  537. goto Clean0;
  538. }
  539. //-------------------------------------------------------------
  540. // Specified log conf type contains Resource Data only
  541. //-------------------------------------------------------------
  542. if (RegDataType == REG_RESOURCE_LIST) {
  543. PCM_RESOURCE_LIST pResList = (PCM_RESOURCE_LIST)pList;
  544. PCM_FULL_RESOURCE_DESCRIPTOR pRes = (PCM_FULL_RESOURCE_DESCRIPTOR)pLogConf;
  545. PCM_PARTIAL_RESOURCE_DESCRIPTOR pResDes = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)pRD;
  546. //
  547. // If this is the last log conf and last res des, then don't
  548. // need to do anything except truncate it by writing less data
  549. // back into the registry.
  550. //
  551. if ((LogConfTag == pResList->Count - 1) &&
  552. ((ResourceTag == pRes->PartialResourceList.Count - 1) ||
  553. (ResourceTag == RESDES_CS_TAG))) {
  554. pRes->PartialResourceList.Count -= 1;
  555. ulListSize = (DWORD)((ULONG_PTR)(pResDes) - (ULONG_PTR)(pResList));
  556. } else {
  557. //
  558. // If the res des is not at the end of the structure, then
  559. // migrate the remainder of the structure up to keep the
  560. // struct contiguous when removing a res des.
  561. //
  562. // pResDes points to the beginning of the res des to remove,
  563. // pNext points to the byte just after the res des to remove
  564. //
  565. pNext = (LPBYTE)((LPBYTE)pResDes + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
  566. if (pResDes->Type == CmResourceTypeDeviceSpecific) {
  567. pNext += pResDes->u.DeviceSpecificData.DataSize;
  568. }
  569. ulSize = ulListSize - (DWORD)((ULONG_PTR)pNext - (ULONG_PTR)pResList);
  570. ulListSize -= (DWORD)((ULONG_PTR)pNext - (ULONG_PTR)pResDes); // new lc list size
  571. pTemp = HeapAlloc(ghPnPHeap, 0, ulSize);
  572. if (pTemp == NULL) {
  573. Status = CR_OUT_OF_MEMORY;
  574. goto Clean0;
  575. }
  576. memcpy(pTemp, pNext, ulSize);
  577. memcpy((LPBYTE)pResDes, pTemp, ulSize);
  578. pRes->PartialResourceList.Count -= 1;
  579. }
  580. //
  581. // if no more res des's in this log conf, then return that
  582. // status (the client side will return a handle to the lc)
  583. //
  584. if (pRes->PartialResourceList.Count == 0) {
  585. Status = CR_NO_MORE_RES_DES;
  586. } else {
  587. //
  588. // return the previous res des type and tag
  589. //
  590. *pulPreviousResType =
  591. CM_RES_TYPE(pRes->PartialResourceList.PartialDescriptors[ResourceTag-1].Type);
  592. if (*pulPreviousResType == ResType_ClassSpecific) {
  593. *pulPreviousResTag = RESDES_CS_TAG; // special tag for cs
  594. } else {
  595. *pulPreviousResTag = ResourceTag - 1;
  596. }
  597. }
  598. }
  599. //-------------------------------------------------------------
  600. // Specified log conf type contains requirements data only
  601. //-------------------------------------------------------------
  602. else if (RegDataType == REG_RESOURCE_REQUIREMENTS_LIST) {
  603. PIO_RESOURCE_REQUIREMENTS_LIST pReqList = (PIO_RESOURCE_REQUIREMENTS_LIST)pList;
  604. PIO_RESOURCE_LIST pReq = (PIO_RESOURCE_LIST)pLogConf;
  605. PIO_RESOURCE_DESCRIPTOR pReqDes = (PIO_RESOURCE_DESCRIPTOR)pRD;
  606. //
  607. // If this is the last log conf and last res des, then don't
  608. // need to do anything except truncate it by writing less data
  609. // back into the registry.
  610. //
  611. RdCount = RANGE_COUNT(pReqDes, (LPBYTE)pReqList + ulListSize - 1);
  612. if ((LogConfTag == pReqList->AlternativeLists - 1) &&
  613. (RdCount + ulCount == pReq->Count - 1)) {
  614. ulListSize = (DWORD)((ULONG_PTR)(pReqDes) - (ULONG_PTR)pReqList);
  615. } else {
  616. //
  617. // If the res des is not at the end of the structure, then
  618. // migrate the remainder of the structure up to keep the
  619. // struct contiguous when removing a res des.
  620. //
  621. // pReqDes points to the beginning of the res des(s) to remove,
  622. // pNext points to the byte just after the res des(s) to remove
  623. //
  624. pNext = (LPBYTE)((LPBYTE)pReqDes +
  625. RdCount * sizeof(IO_RESOURCE_DESCRIPTOR));
  626. ulSize = ulListSize - (DWORD)((ULONG_PTR)pNext - (ULONG_PTR)pReqList);
  627. ulListSize -= (DWORD)((ULONG_PTR)pNext - (ULONG_PTR)pReqDes); // new lc list size
  628. pTemp = HeapAlloc(ghPnPHeap, 0, ulSize);
  629. if (pTemp == NULL) {
  630. Status = CR_OUT_OF_MEMORY;
  631. goto Clean0;
  632. }
  633. memcpy(pTemp, pNext, ulSize);
  634. memcpy((LPBYTE)pReqDes, pTemp, ulSize);
  635. }
  636. pReqList->ListSize = ulListSize;
  637. pReq->Count -= RdCount;
  638. //
  639. // if no more res des's in this log conf, then return that status
  640. // (the client side will return a handle to the log conf)
  641. //
  642. if (pReq->Count == 0) {
  643. Status = CR_NO_MORE_RES_DES;
  644. } else {
  645. //
  646. // return the previous res des type and tag
  647. //
  648. pReqDes = AdvanceRequirementsDescriptorPtr(&pReq->Descriptors[0],
  649. ResourceTag-1, pReq->Count, NULL);
  650. //
  651. // Double check whether this is the first ConfigData res des,
  652. // skip it if so.
  653. //
  654. if (pReqDes == NULL || pReqDes->Type == CmResourceTypeConfigData) {
  655. Status = CR_NO_MORE_RES_DES;
  656. } else {
  657. *pulPreviousResType = CM_RES_TYPE(pReqDes->Type);
  658. *pulPreviousResTag = ResourceTag - 1;
  659. }
  660. }
  661. }
  662. //
  663. // Write out the updated log conf list to the registry
  664. //
  665. if (RegSetValueEx(hKey, szValueName, 0, RegDataType,
  666. pList, ulListSize) != ERROR_SUCCESS) {
  667. Status = CR_REGISTRY_ERROR;
  668. goto Clean0;
  669. }
  670. Clean0:
  671. NOTHING;
  672. } except(EXCEPTION_EXECUTE_HANDLER) {
  673. Status = CR_INVALID_RES_DES; // mostly likely reason we got here
  674. }
  675. if (pList != NULL) {
  676. HeapFree(ghPnPHeap, 0, pList);
  677. }
  678. if (pTemp != NULL) {
  679. HeapFree(ghPnPHeap, 0, pTemp);
  680. }
  681. if (hKey != NULL) {
  682. RegCloseKey(hKey);
  683. }
  684. return Status;
  685. } // PNP_FreeResDes
  686. CONFIGRET
  687. PNP_GetNextResDes(
  688. IN handle_t hBinding,
  689. IN LPWSTR pDeviceID,
  690. IN ULONG LogConfTag,
  691. IN ULONG LogConfType,
  692. IN RESOURCEID ResourceID,
  693. IN ULONG ResourceTag,
  694. OUT PULONG pulNextResDesTag,
  695. OUT PULONG pulNextResDesType,
  696. IN ULONG ulFlags
  697. )
  698. /*++
  699. Routine Description:
  700. This the server-side of an RPC remote call. This routine gets the
  701. next res des in the specified log conf.
  702. Arguments:
  703. hBinding RPC binding handle, not used.
  704. pDeviceID Null-terminated device instance id string.
  705. LogConfTag Specifies the log conf within a given type.
  706. LogConfType Specifies the log conf type.
  707. ResourceID Specifies the resource type.
  708. ResourceTag Specifies current resource descriptor (if any).
  709. pulNextResDesTag Receives the next resource type.
  710. pulNextResDesType Receives the next resource within a given type.
  711. ulFlags Not used, must be zero.
  712. Return Value:
  713. If the specified device instance is valid, it returns CR_SUCCESS,
  714. otherwise it returns CR_ error code.
  715. --*/
  716. {
  717. CONFIGRET Status = CR_SUCCESS;
  718. HKEY hKey = NULL;
  719. WCHAR szValueName[64];
  720. ULONG RegDataType = 0, ulListSize = 0, i = 0, ulCount = 0;
  721. LPBYTE pList = NULL, pLogConf = NULL;
  722. UNREFERENCED_PARAMETER(hBinding);
  723. try {
  724. //
  725. // validate/initialize output parameters
  726. //
  727. if (!ARGUMENT_PRESENT(pulNextResDesTag)) {
  728. Status = CR_INVALID_POINTER;
  729. goto Clean0;
  730. } else {
  731. *pulNextResDesTag = 0;
  732. }
  733. //
  734. // validate parameters
  735. //
  736. if (INVALID_FLAGS(ulFlags, 0)) {
  737. Status = CR_INVALID_FLAG;
  738. goto Clean0;
  739. }
  740. //
  741. // make sure original caller didn't specify root devnode
  742. //
  743. if (!IsLegalDeviceId(pDeviceID) || IsRootDeviceID(pDeviceID)) {
  744. Status = CR_INVALID_LOG_CONF;
  745. goto Clean0;
  746. }
  747. //
  748. // open a key to the device's LogConf subkey
  749. //
  750. Status = OpenLogConfKey(pDeviceID, LogConfType, &hKey);
  751. if (Status != CR_SUCCESS) {
  752. goto Clean0;
  753. }
  754. //
  755. // Retrieve log conf data from the registry
  756. //
  757. Status = GetLogConfData(hKey, LogConfType,
  758. &RegDataType, szValueName,
  759. &pList, &ulListSize);
  760. if (Status != CR_SUCCESS) {
  761. Status = CR_INVALID_RES_DES; // log conf doesn't exist
  762. goto Clean0;
  763. }
  764. //
  765. // Seek to the log conf that matches the log conf tag
  766. //
  767. if (!FindLogConf(pList, &pLogConf, RegDataType, LogConfTag)) {
  768. Status = CR_INVALID_LOG_CONF;
  769. goto Clean0;
  770. }
  771. //
  772. // find the next res des. A resource tag of max indicates that we want
  773. // a find first operation.
  774. //
  775. if (ResourceTag == MAX_RESDES_TAG) {
  776. //
  777. // This is essentially a Get-First operation
  778. //
  779. *pulNextResDesTag = 0;
  780. } else if (ResourceTag == RESDES_CS_TAG) {
  781. //
  782. // By definition, if the resource type is classspecific, it's last,
  783. // so there aren't any more after this.
  784. //
  785. Status = CR_NO_MORE_RES_DES;
  786. goto Clean0;
  787. } else {
  788. *pulNextResDesTag = ResourceTag + 1; // we want the "next" res des
  789. }
  790. //-------------------------------------------------------------
  791. // Specified log conf type contains Resource Data only
  792. //-------------------------------------------------------------
  793. if (RegDataType == REG_RESOURCE_LIST) {
  794. PCM_RESOURCE_LIST pResList = (PCM_RESOURCE_LIST)pList;
  795. PCM_FULL_RESOURCE_DESCRIPTOR pRes = (PCM_FULL_RESOURCE_DESCRIPTOR)pLogConf;
  796. ULONG ulTmpResDesTag, ulTmpLogConfTag;
  797. ulTmpResDesTag = *pulNextResDesTag;
  798. ulTmpLogConfTag = LogConfTag;
  799. for ( ; ; ) {
  800. while (ulTmpResDesTag >= pRes->PartialResourceList.Count) {
  801. ulTmpResDesTag -= pRes->PartialResourceList.Count;
  802. ulTmpLogConfTag++;
  803. //
  804. // Seek to the log conf that matches the log conf tag
  805. //
  806. if (!FindLogConf(pList, &pLogConf, RegDataType, ulTmpLogConfTag)) {
  807. Status = CR_NO_MORE_RES_DES; // there is no "next"
  808. goto Clean0;
  809. }
  810. pRes = (PCM_FULL_RESOURCE_DESCRIPTOR)pLogConf;
  811. }
  812. //
  813. // Not done yet, if a specific resource type was specified, then
  814. // we may need to keep looking.
  815. //
  816. if (ResourceID != ResType_All) {
  817. UCHAR NtResType = NT_RES_TYPE(ResourceID);
  818. if (pRes->PartialResourceList.PartialDescriptors[ulTmpResDesTag].Type
  819. != NtResType) {
  820. (*pulNextResDesTag)++;
  821. ulTmpResDesTag++;
  822. continue;
  823. }
  824. }
  825. break;
  826. }
  827. //
  828. // Return the type and tag of the "next" res des
  829. //
  830. *pulNextResDesType = CM_RES_TYPE(pRes->PartialResourceList.
  831. PartialDescriptors[ulTmpResDesTag].Type);
  832. if (*pulNextResDesType == ResType_ClassSpecific) {
  833. *pulNextResDesTag = RESDES_CS_TAG; // special tag for cs
  834. }
  835. }
  836. //-------------------------------------------------------------
  837. // Specified log conf type contains requirements data only
  838. //-------------------------------------------------------------
  839. else if (RegDataType == REG_RESOURCE_REQUIREMENTS_LIST) {
  840. PIO_RESOURCE_REQUIREMENTS_LIST pReqList = (PIO_RESOURCE_REQUIREMENTS_LIST)pList;
  841. PIO_RESOURCE_LIST pReq = (PIO_RESOURCE_LIST)pLogConf;
  842. PIO_RESOURCE_DESCRIPTOR pReqDes;
  843. //
  844. // Point pResDes at the first possible "next" res des
  845. //
  846. if (*pulNextResDesTag == 0) {
  847. if (pReq->Count == 0) {
  848. Status = CR_NO_MORE_RES_DES; // there is no "next"
  849. goto Clean0;
  850. }
  851. if (pReq->Descriptors[0].Type == CmResourceTypeConfigData) {
  852. //
  853. // This one doesn't count, it's privately created and maintained,
  854. // skip to the next rd
  855. //
  856. *pulNextResDesTag = 1;
  857. }
  858. }
  859. if (*pulNextResDesTag > 0) {
  860. pReqDes = AdvanceRequirementsDescriptorPtr(&pReq->Descriptors[0], *pulNextResDesTag, pReq->Count, &ulCount); // current
  861. if (pReqDes == NULL) {
  862. Status = CR_NO_MORE_RES_DES; // there is no "next"
  863. goto Clean0;
  864. }
  865. } else {
  866. ulCount = 0;
  867. pReqDes = &pReq->Descriptors[0];
  868. }
  869. //
  870. // Not done yet, if a specific resource type was specified, then
  871. // we may need to keep looking.
  872. //
  873. if (ResourceID != ResType_All) {
  874. UCHAR NtResType = NT_RES_TYPE(ResourceID);
  875. while (pReqDes->Type != NtResType) {
  876. if (ulCount >= pReq->Count) {
  877. Status = CR_NO_MORE_RES_DES;
  878. goto Clean0;
  879. }
  880. pReqDes = AdvanceRequirementsDescriptorPtr(pReqDes, 1, pReq->Count - ulCount, &i);
  881. if (pReqDes == NULL) {
  882. Status = CR_NO_MORE_RES_DES;
  883. goto Clean0;
  884. }
  885. ulCount += i;
  886. *pulNextResDesTag += 1;
  887. }
  888. }
  889. *pulNextResDesType = CM_RES_TYPE(pReqDes->Type);
  890. }
  891. Clean0:
  892. NOTHING;
  893. } except(EXCEPTION_EXECUTE_HANDLER) {
  894. Status = CR_FAILURE;
  895. }
  896. if (pList != NULL) {
  897. HeapFree(ghPnPHeap, 0, pList);
  898. }
  899. if (hKey != NULL) {
  900. RegCloseKey(hKey);
  901. }
  902. return Status;
  903. } // PNP_GetNextResDes
  904. CONFIGRET
  905. PNP_GetResDesData(
  906. IN handle_t hBinding,
  907. IN LPWSTR pDeviceID,
  908. IN ULONG LogConfTag,
  909. IN ULONG LogConfType,
  910. IN RESOURCEID ResourceID,
  911. IN ULONG ResourceTag,
  912. OUT LPBYTE Buffer,
  913. IN ULONG BufferLen,
  914. IN ULONG ulFlags
  915. )
  916. /*++
  917. Routine Description:
  918. This the server-side of an RPC remote call. This routine retrieves
  919. the data for the specified res des.
  920. Arguments:
  921. hBinding RPC binding handle, not used.
  922. pDeviceID Null-terminated device instance id string.
  923. LogConfTag Specifies the log conf within a given type.
  924. LogConfType Specifies the log conf type.
  925. ResourceID Specifies the resource type.
  926. ResourceTag Returns with resource within a given type.
  927. Buffer Returns resource data (of ResourceID type) from log conf.
  928. BufferLen Size of Buffer in bytes.
  929. ulFlags Specifies the width of certain variable-size resource
  930. descriptor structure fields, where applicable.
  931. Currently, the following flags are defined:
  932. CM_RESDES_WIDTH_32 or
  933. CM_RESDES_WIDTH_64
  934. If no flags are specified, the width of the variable-sized
  935. resource data expected is assumed to be that native to the
  936. platform of the caller.
  937. Return Value:
  938. If the specified device instance is valid, it returns CR_SUCCESS,
  939. otherwise it returns CR_ error code.
  940. --*/
  941. {
  942. CONFIGRET Status = CR_SUCCESS;
  943. HKEY hKey = NULL;
  944. WCHAR szValueName[64];
  945. ULONG RegDataType = 0, ulListSize = 0, ulCount = 0;
  946. LPBYTE pList = NULL, pLogConf = NULL, pRD = NULL;
  947. UNREFERENCED_PARAMETER(hBinding);
  948. try {
  949. //
  950. // validate parameters
  951. //
  952. if (INVALID_FLAGS(ulFlags, CM_RESDES_WIDTH_BITS)) {
  953. Status = CR_INVALID_FLAG;
  954. goto Clean0;
  955. }
  956. //
  957. // make sure original caller didn't specify root devnode
  958. //
  959. if (!IsLegalDeviceId(pDeviceID) || IsRootDeviceID(pDeviceID)) {
  960. Status = CR_INVALID_LOG_CONF;
  961. goto Clean0;
  962. }
  963. //
  964. // open a key to the device's LogConf subkey
  965. //
  966. Status = OpenLogConfKey(pDeviceID, LogConfType, &hKey);
  967. if (Status != CR_SUCCESS) {
  968. goto Clean0;
  969. }
  970. //
  971. // Retrieve log conf data from the registry
  972. //
  973. Status = GetLogConfData(hKey, LogConfType,
  974. &RegDataType, szValueName,
  975. &pList, &ulListSize);
  976. if (Status != CR_SUCCESS) {
  977. Status = CR_INVALID_RES_DES; // log conf doesn't exist
  978. goto Clean0;
  979. }
  980. //
  981. // seek to the res des that matches the resource tag.
  982. //
  983. if (!FindResDes(pList, RegDataType, LogConfTag,
  984. ResourceTag, ResourceID, &pRD, &pLogConf, &ulCount)) {
  985. Status = CR_INVALID_RES_DES;
  986. goto Clean0;
  987. }
  988. //-------------------------------------------------------------
  989. // Specified log conf type contains Resource Data only
  990. //-------------------------------------------------------------
  991. if (RegDataType == REG_RESOURCE_LIST) {
  992. PCM_RESOURCE_LIST pResList = (PCM_RESOURCE_LIST)pList;
  993. PCM_PARTIAL_RESOURCE_DESCRIPTOR pResDes = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)pRD;
  994. //
  995. // map the NT-style info into ConfigMgr-style structures
  996. //
  997. Status = NtResourceToResDes(pResDes, Buffer, BufferLen,
  998. (LPBYTE)pResList + ulListSize - 1, ulFlags);
  999. }
  1000. //-------------------------------------------------------------
  1001. // Specified log conf type contains requirements data only
  1002. //-------------------------------------------------------------
  1003. else if (RegDataType == REG_RESOURCE_REQUIREMENTS_LIST) {
  1004. PIO_RESOURCE_REQUIREMENTS_LIST pReqList = (PIO_RESOURCE_REQUIREMENTS_LIST)pList;
  1005. PIO_RESOURCE_DESCRIPTOR pReqDes = (PIO_RESOURCE_DESCRIPTOR)pRD;
  1006. //
  1007. // map the NT-style info into ConfigMgr-style structures
  1008. //
  1009. Status = NtRequirementsToResDes(pReqDes, Buffer, BufferLen,
  1010. (LPBYTE)pReqList + ulListSize - 1, ulFlags);
  1011. }
  1012. Clean0:
  1013. NOTHING;
  1014. } except(EXCEPTION_EXECUTE_HANDLER) {
  1015. Status = CR_FAILURE;
  1016. }
  1017. if (hKey != NULL) {
  1018. RegCloseKey(hKey);
  1019. }
  1020. if (pList != NULL) {
  1021. HeapFree(ghPnPHeap, 0, pList);
  1022. }
  1023. return Status;
  1024. } // PNP_GetResDesData
  1025. CONFIGRET
  1026. PNP_GetResDesDataSize(
  1027. IN handle_t hBinding,
  1028. IN LPWSTR pDeviceID,
  1029. IN ULONG LogConfTag,
  1030. IN ULONG LogConfType,
  1031. IN RESOURCEID ResourceID,
  1032. IN ULONG ResourceTag,
  1033. OUT PULONG pulSize,
  1034. IN ULONG ulFlags
  1035. )
  1036. /*++
  1037. Routine Description:
  1038. This the server-side of an RPC remote call. This routine retrieves
  1039. the data size for the specified res des.
  1040. Arguments:
  1041. hBinding RPC binding handle, not used.
  1042. pDeviceID Null-terminated device instance id string.
  1043. LogConfTag Specifies the log conf within a given type.
  1044. LogConfType Specifies the log conf type.
  1045. ResourceID Specifies the resource type.
  1046. ResourceTag Returns with resource within a given type.
  1047. pulSize Returns size of buffer in bytes required to hold the
  1048. resource data (of ResourceID type) from log conf.
  1049. ulFlags Specifies the width of certain variable-size resource
  1050. descriptor structure fields, where applicable.
  1051. Currently, the following flags are defined:
  1052. CM_RESDES_WIDTH_32 or
  1053. CM_RESDES_WIDTH_64
  1054. If no flags are specified, the width of the variable-sized
  1055. resource data expected is assumed to be that native to the
  1056. platform of the caller.
  1057. Return Value:
  1058. If the specified device instance is valid, it returns CR_SUCCESS,
  1059. otherwise it returns CR_ error code.
  1060. --*/
  1061. {
  1062. CONFIGRET Status = CR_SUCCESS;
  1063. HKEY hKey = NULL;
  1064. WCHAR szValueName[64];
  1065. ULONG RegDataType = 0, ulListSize = 0, ulCount = 0;
  1066. LPBYTE pList = NULL, pLogConf = NULL, pRD = NULL;
  1067. UNREFERENCED_PARAMETER(hBinding);
  1068. try {
  1069. //
  1070. // validate/initialize output parameters
  1071. //
  1072. if (!ARGUMENT_PRESENT(pulSize)) {
  1073. Status = CR_INVALID_POINTER;
  1074. goto Clean0;
  1075. } else {
  1076. *pulSize = 0;
  1077. }
  1078. //
  1079. // validate parameters
  1080. //
  1081. if (INVALID_FLAGS(ulFlags, CM_RESDES_WIDTH_BITS)) {
  1082. Status = CR_INVALID_FLAG;
  1083. goto Clean0;
  1084. }
  1085. //
  1086. // make sure original caller didn't specify root devnode
  1087. //
  1088. if (!IsLegalDeviceId(pDeviceID) || IsRootDeviceID(pDeviceID)) {
  1089. Status = CR_INVALID_LOG_CONF;
  1090. goto Clean0;
  1091. }
  1092. //
  1093. // open a key to the device's LogConf subkey
  1094. //
  1095. Status = OpenLogConfKey(pDeviceID, LogConfType, &hKey);
  1096. if (Status != CR_SUCCESS) {
  1097. goto Clean0;
  1098. }
  1099. //
  1100. // Retrieve log conf data from the registry
  1101. //
  1102. Status = GetLogConfData(hKey, LogConfType,
  1103. &RegDataType, szValueName,
  1104. &pList, &ulListSize);
  1105. if (Status != CR_SUCCESS) {
  1106. Status = CR_INVALID_RES_DES; // log conf doesn't exist
  1107. goto Clean0;
  1108. }
  1109. //
  1110. // seek to the res des that matches the resource tag.
  1111. //
  1112. if (!FindResDes(pList, RegDataType, LogConfTag,
  1113. ResourceTag, ResourceID, &pRD, &pLogConf, &ulCount)) {
  1114. Status = CR_INVALID_RES_DES;
  1115. goto Clean0;
  1116. }
  1117. //-------------------------------------------------------------
  1118. // Specified log conf type contains Resource Data only
  1119. //-------------------------------------------------------------
  1120. if (RegDataType == REG_RESOURCE_LIST) {
  1121. PCM_PARTIAL_RESOURCE_DESCRIPTOR pResDes = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)pRD;
  1122. //
  1123. // calculate data size required (in terms of ConfigMgr structures)
  1124. //
  1125. *pulSize = GetResDesSize(ResourceID, ulFlags);
  1126. if (ResourceID == ResType_ClassSpecific) {
  1127. //
  1128. // the Reserved fields should not exceed DataSize. if so, they
  1129. // may have been incorrectly initialized, so set them 0.
  1130. // we expect DataSize to be correct in all cases.
  1131. //
  1132. if (pResDes->u.DeviceSpecificData.Reserved1 > pResDes->u.DeviceSpecificData.DataSize) {
  1133. pResDes->u.DeviceSpecificData.Reserved1 = 0;
  1134. }
  1135. if (pResDes->u.DeviceSpecificData.Reserved2 > pResDes->u.DeviceSpecificData.DataSize) {
  1136. pResDes->u.DeviceSpecificData.Reserved2 = 0;
  1137. }
  1138. //
  1139. // add space for legacy and signature data but not the
  1140. // GUID - it's already included in the CM structures
  1141. //
  1142. if (pResDes->u.DeviceSpecificData.DataSize == 0) {
  1143. //
  1144. // no legacy data or class-specific data
  1145. //
  1146. ;
  1147. } else if (pResDes->u.DeviceSpecificData.Reserved2 == 0) {
  1148. //
  1149. // add space for legacy data
  1150. //
  1151. *pulSize += pResDes->u.DeviceSpecificData.DataSize - 1;
  1152. } else {
  1153. //
  1154. // add space for class-specific data and/or legacy data
  1155. //
  1156. *pulSize += pResDes->u.DeviceSpecificData.Reserved1 +
  1157. pResDes->u.DeviceSpecificData.Reserved2 - 1;
  1158. }
  1159. }
  1160. }
  1161. //-------------------------------------------------------------
  1162. // Specified log conf type contains requirements data only
  1163. //-------------------------------------------------------------
  1164. else if (RegDataType == REG_RESOURCE_REQUIREMENTS_LIST) {
  1165. PIO_RESOURCE_DESCRIPTOR pReqDes = (PIO_RESOURCE_DESCRIPTOR)pRD;
  1166. LPBYTE pLastReqAddr = (LPBYTE)pList + ulListSize - 1;
  1167. //
  1168. // calculate data size required (in terms of ConfigMgr structures)
  1169. //
  1170. *pulSize = GetReqDesSize(ResourceID, pReqDes, pLastReqAddr, ulFlags);
  1171. }
  1172. Clean0:
  1173. NOTHING;
  1174. } except(EXCEPTION_EXECUTE_HANDLER) {
  1175. Status = CR_FAILURE;
  1176. }
  1177. if (hKey != NULL) {
  1178. RegCloseKey(hKey);
  1179. }
  1180. if (pList != NULL) {
  1181. HeapFree(ghPnPHeap, 0, pList);
  1182. }
  1183. return Status;
  1184. } // PNP_GetResDesDataSize
  1185. CONFIGRET
  1186. PNP_ModifyResDes(
  1187. IN handle_t hBinding,
  1188. IN LPWSTR pDeviceID,
  1189. IN ULONG LogConfTag,
  1190. IN ULONG LogConfType,
  1191. IN RESOURCEID CurrentResourceID,
  1192. IN RESOURCEID NewResourceID,
  1193. IN ULONG ResourceTag,
  1194. IN LPBYTE ResourceData,
  1195. IN ULONG ResourceLen,
  1196. IN ULONG ulFlags
  1197. )
  1198. /*++
  1199. Routine Description:
  1200. This the server-side of an RPC remote call. This routine modifies
  1201. the specified res des.
  1202. Arguments:
  1203. hBinding RPC binding handle.
  1204. pDeviceID Null-terminated device instance id string.
  1205. LogConfTag Specifies the log conf within a given type.
  1206. LogConfType Specifies the log conf type.
  1207. ResourceID Specifies the resource type.
  1208. ResourceIndex Returns with resource within a given type.
  1209. ResourceData New resource data (of ResourceID type).
  1210. ResourceLen Size of ResourceData in bytes.
  1211. ulFlags Specifies the width of certain variable-size resource
  1212. descriptor structure fields, where applicable.
  1213. Currently, the following flags are defined:
  1214. CM_RESDES_WIDTH_32 or
  1215. CM_RESDES_WIDTH_64
  1216. If no flags are specified, the width of the variable-sized
  1217. resource data supplied is assumed to be that native to the
  1218. platform of the caller.
  1219. Return Value:
  1220. If the specified device instance is valid, it returns CR_SUCCESS,
  1221. otherwise it returns CR_ error code.
  1222. --*/
  1223. {
  1224. CONFIGRET Status = CR_SUCCESS;
  1225. HKEY hKey = NULL;
  1226. WCHAR szValueName[64];
  1227. ULONG ulListSize = 0, ulOldSize = 0, ulNewSize = 0, ulSize = 0,
  1228. ulOldCount = 0, ulNewCount = 0, RegDataType = 0, ulCount = 0;
  1229. LONG AddSize = 0;
  1230. LPBYTE pList = NULL, pRD = NULL, pLogConf = NULL,
  1231. pTemp = NULL, pNext = NULL;
  1232. try {
  1233. //
  1234. // verify client access
  1235. //
  1236. if (!VerifyClientAccess(hBinding, &gLuidLoadDriverPrivilege)) {
  1237. Status = CR_ACCESS_DENIED;
  1238. goto Clean0;
  1239. }
  1240. //
  1241. // validate parameters
  1242. //
  1243. if (INVALID_FLAGS(ulFlags, CM_RESDES_WIDTH_BITS)) {
  1244. Status = CR_INVALID_FLAG;
  1245. goto Clean0;
  1246. }
  1247. //
  1248. // validate res des size
  1249. //
  1250. if (ResourceLen < GetResDesSize(NewResourceID, ulFlags)) {
  1251. Status = CR_INVALID_DATA;
  1252. goto Clean0;
  1253. }
  1254. //
  1255. // make sure original caller didn't specify root devnode
  1256. //
  1257. if (!IsLegalDeviceId(pDeviceID) || IsRootDeviceID(pDeviceID)) {
  1258. Status = CR_INVALID_LOG_CONF;
  1259. goto Clean0;
  1260. }
  1261. //
  1262. // open a key to the device's LogConf subkey
  1263. //
  1264. Status = OpenLogConfKey(pDeviceID, LogConfType, &hKey);
  1265. if (Status != CR_SUCCESS) {
  1266. goto Clean0;
  1267. }
  1268. //
  1269. // Retrieve log conf data from the registry
  1270. //
  1271. Status = GetLogConfData(hKey, LogConfType,
  1272. &RegDataType, szValueName,
  1273. &pList, &ulListSize);
  1274. if (Status != CR_SUCCESS) {
  1275. Status = CR_INVALID_RES_DES; // log conf doesn't exist
  1276. goto Clean0;
  1277. }
  1278. //
  1279. // seek to the res des that matches the resource tag.
  1280. //
  1281. if (!FindResDes(pList, RegDataType, LogConfTag,
  1282. ResourceTag, CurrentResourceID, &pRD, &pLogConf, &ulCount)) {
  1283. Status = CR_INVALID_RES_DES;
  1284. goto Clean0;
  1285. }
  1286. //-------------------------------------------------------------
  1287. // Specified log conf type contains Resource Data only
  1288. //-------------------------------------------------------------
  1289. if (RegDataType == REG_RESOURCE_LIST) {
  1290. PCM_RESOURCE_LIST pResList = (PCM_RESOURCE_LIST)pList;
  1291. PCM_FULL_RESOURCE_DESCRIPTOR pRes = (PCM_FULL_RESOURCE_DESCRIPTOR)pLogConf;
  1292. PCM_PARTIAL_RESOURCE_DESCRIPTOR pResDes = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)pRD;
  1293. //
  1294. // If new res des type is ClassSpecific, then it must be the last
  1295. // res des that is attempting to be modified (only last res des can
  1296. // be class specific).
  1297. //
  1298. if (NewResourceID == ResType_ClassSpecific &&
  1299. ResourceTag != RESDES_CS_TAG) {
  1300. Status = CR_INVALID_RES_DES;
  1301. goto Clean0;
  1302. }
  1303. //
  1304. // calculate the current size and the new size of the res des data
  1305. //
  1306. ulNewSize = ulOldSize = sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
  1307. if (CurrentResourceID == ResType_ClassSpecific) {
  1308. ulOldSize += pResDes->u.DeviceSpecificData.DataSize;
  1309. }
  1310. if (NewResourceID == ResType_ClassSpecific) {
  1311. PCS_RESOURCE pCsRes = (PCS_RESOURCE)ResourceData;
  1312. ulNewSize += sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) +
  1313. sizeof(GUID) +
  1314. pCsRes->CS_Header.CSD_SignatureLength +
  1315. pCsRes->CS_Header.CSD_LegacyDataSize;
  1316. }
  1317. //
  1318. // How much does data need to grow/shrink to accomodate the change?
  1319. //
  1320. AddSize = ulNewSize - ulOldSize;
  1321. //
  1322. // reallocate the buffers and shrink/expand the contents as
  1323. // necessary
  1324. //
  1325. if (AddSize != 0) {
  1326. if (AddSize > 0) {
  1327. //
  1328. // only bother reallocating if the buffer size is growing
  1329. //
  1330. ULONG ulOffset = (ULONG)((ULONG_PTR)pResDes - (ULONG_PTR)pResList);
  1331. pResList = HeapReAlloc(ghPnPHeap, 0, pResList, ulListSize + AddSize);
  1332. if (pResList == NULL) {
  1333. Status = CR_OUT_OF_MEMORY;
  1334. goto Clean0;
  1335. }
  1336. pList = (LPBYTE)pResList;
  1337. pResDes = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)((LPBYTE)pResList + ulOffset);
  1338. }
  1339. //
  1340. // if not the last lc and rd, then need to move the following data
  1341. // either up or down to account for changed res des data size
  1342. //
  1343. if ((LogConfTag != pResList->Count - 1) ||
  1344. ((ResourceTag != pRes->PartialResourceList.Count - 1) &&
  1345. ResourceTag != RESDES_CS_TAG)) {
  1346. pNext = (LPBYTE)((LPBYTE)pResDes + ulOldSize);
  1347. ulSize = ulListSize - (DWORD)((ULONG_PTR)pNext - (ULONG_PTR)pResList);
  1348. pTemp = HeapAlloc(ghPnPHeap, 0, ulSize);
  1349. if (pTemp == NULL) {
  1350. Status = CR_OUT_OF_MEMORY;
  1351. goto Clean0;
  1352. }
  1353. memcpy(pTemp, pNext, ulSize);
  1354. memcpy((LPBYTE)((LPBYTE)pResDes + ulNewSize), pTemp, ulSize);
  1355. }
  1356. }
  1357. //
  1358. // write out modified data
  1359. //
  1360. Status = ResDesToNtResource(ResourceData, NewResourceID, ResourceLen,
  1361. pResDes, ResourceTag, ulFlags);
  1362. }
  1363. //-------------------------------------------------------------
  1364. // Specified log conf type contains requirements data only
  1365. //-------------------------------------------------------------
  1366. else if (RegDataType == REG_RESOURCE_REQUIREMENTS_LIST) {
  1367. PIO_RESOURCE_REQUIREMENTS_LIST pReqList = (PIO_RESOURCE_REQUIREMENTS_LIST)pList;
  1368. PIO_RESOURCE_LIST pReq = (PIO_RESOURCE_LIST)pLogConf;
  1369. PIO_RESOURCE_DESCRIPTOR pReqDes = (PIO_RESOURCE_DESCRIPTOR)pRD;
  1370. LPBYTE pLastReqAddr = (LPBYTE)pReqList + ulListSize - 1;
  1371. PGENERIC_RESOURCE pGenRes = (PGENERIC_RESOURCE)ResourceData;
  1372. //
  1373. // Can't add class specific resdes to this type of log conf
  1374. //
  1375. if (NewResourceID == ResType_ClassSpecific) {
  1376. Status = CR_INVALID_RES_DES;
  1377. goto Clean0;
  1378. }
  1379. //
  1380. // calculate the current size and the new size of the res des data
  1381. //
  1382. ulOldCount = RANGE_COUNT(pReqDes, pLastReqAddr);
  1383. ulOldSize = sizeof(IO_RESOURCE_DESCRIPTOR) * ulOldCount;
  1384. ulNewSize = sizeof(IO_RESOURCE_DESCRIPTOR) *
  1385. pGenRes->GENERIC_Header.GENERIC_Count;
  1386. //
  1387. // How much does data need to grow/shrink to accomodate the change?
  1388. //
  1389. AddSize = ulNewSize - ulOldSize;
  1390. //
  1391. // reallocate the buffers and shrink/expand the contents as
  1392. // necessary
  1393. //
  1394. if (AddSize != 0) {
  1395. if (AddSize > 0) {
  1396. //
  1397. // only bother reallocating if the buffer size is growing
  1398. //
  1399. ULONG ulOffset = (ULONG)((ULONG_PTR)pReqDes - (ULONG_PTR)pReqList);
  1400. pReqList = HeapReAlloc(ghPnPHeap, 0, pReqList, ulListSize + AddSize);
  1401. if (pReqList == NULL) {
  1402. Status = CR_OUT_OF_MEMORY;
  1403. goto Clean0;
  1404. }
  1405. pList = (LPBYTE)pReqList;
  1406. pReqDes = (PIO_RESOURCE_DESCRIPTOR)((LPBYTE)pReqList + ulOffset);
  1407. }
  1408. //
  1409. // set to last index for this res des (whole)
  1410. //
  1411. ulCount += RANGE_COUNT(pReqDes, (LPBYTE)((ULONG_PTR)pList + ulListSize));
  1412. //
  1413. // if not the last lc and rd, then need to move the following data
  1414. // either up or down to account for changed res des data size
  1415. //
  1416. if (LogConfTag != pReqList->AlternativeLists - 1 ||
  1417. ulCount != pReq->Count - 1) {
  1418. pNext = (LPBYTE)((LPBYTE)pReqDes + ulOldSize);
  1419. ulSize = ulListSize - (DWORD)((ULONG_PTR)pNext - (ULONG_PTR)pReqList);
  1420. pTemp = HeapAlloc(ghPnPHeap, 0, ulSize);
  1421. if (pTemp == NULL) {
  1422. Status = CR_OUT_OF_MEMORY;
  1423. goto Clean0;
  1424. }
  1425. memcpy(pTemp, pNext, ulSize);
  1426. memcpy((LPBYTE)((LPBYTE)pReqDes + ulNewSize), pTemp, ulSize);
  1427. }
  1428. }
  1429. //
  1430. // write out modified data
  1431. //
  1432. Status = ResDesToNtRequirements(ResourceData, NewResourceID, ResourceLen,
  1433. pReqDes, &ulNewCount, ResourceTag, ulFlags);
  1434. if (Status == CR_SUCCESS) {
  1435. //
  1436. // update the requirements header (changes will be zero if CS)
  1437. //
  1438. pReq->Count += ulNewCount - ulOldCount;
  1439. pReqList->ListSize = ulListSize + AddSize;
  1440. }
  1441. }
  1442. if (Status == CR_SUCCESS) {
  1443. //
  1444. // Write out the new/updated log conf list to the registry
  1445. //
  1446. if (RegSetValueEx(hKey, szValueName, 0, RegDataType, pList,
  1447. ulListSize + AddSize) != ERROR_SUCCESS) {
  1448. Status = CR_REGISTRY_ERROR;
  1449. goto Clean0;
  1450. }
  1451. }
  1452. Clean0:
  1453. NOTHING;
  1454. } except(EXCEPTION_EXECUTE_HANDLER) {
  1455. Status = CR_FAILURE;
  1456. }
  1457. if (hKey != NULL) {
  1458. RegCloseKey(hKey);
  1459. }
  1460. if (pList != NULL) {
  1461. HeapFree(ghPnPHeap, 0, pList);
  1462. }
  1463. if (pTemp != NULL) {
  1464. HeapFree(ghPnPHeap, 0, pTemp);
  1465. }
  1466. return Status;
  1467. } // PNP_ModifyResDes
  1468. CONFIGRET
  1469. PNP_DetectResourceConflict(
  1470. IN handle_t hBinding,
  1471. IN LPWSTR pDeviceID,
  1472. IN RESOURCEID ResourceID,
  1473. IN LPBYTE ResourceData,
  1474. IN ULONG ResourceLen,
  1475. OUT PBOOL pbConflictDetected,
  1476. IN ULONG ulFlags
  1477. )
  1478. /*++
  1479. Routine Description:
  1480. This the server-side of an RPC remote call. This routine detects
  1481. conflicts with the specified res des.
  1482. Arguments:
  1483. hBinding RPC binding handle, not used.
  1484. pDeviceID Null-terminated device instance id string.
  1485. ResourceID Specifies the resource type.
  1486. ResourceData Specifies resource data (of ResourceID type).
  1487. ResourceLen Size of ResourceData in bytes.
  1488. pbConflictDetected Returns whether a conflict was detected.
  1489. ulFlags Not used, must be zero.
  1490. Return Value:
  1491. ** PRESENTLY, ALWAYS RETURNS CR_CALL_NOT_IMPLEMENTED **
  1492. Note:
  1493. This routine is currently not implemented. It initializes
  1494. pbConflictDetected to FALSE, and returns CR_CALL_NOT_IMPLEMENTED.
  1495. --*/
  1496. {
  1497. UNREFERENCED_PARAMETER(hBinding);
  1498. UNREFERENCED_PARAMETER(pDeviceID);
  1499. UNREFERENCED_PARAMETER(ResourceID);
  1500. UNREFERENCED_PARAMETER(ResourceData);
  1501. UNREFERENCED_PARAMETER(ResourceLen);
  1502. UNREFERENCED_PARAMETER(ulFlags);
  1503. try {
  1504. //
  1505. // initialize output parameters
  1506. //
  1507. if (ARGUMENT_PRESENT(pbConflictDetected)) {
  1508. *pbConflictDetected = FALSE;
  1509. }
  1510. } except(EXCEPTION_EXECUTE_HANDLER) {
  1511. NOTHING;
  1512. }
  1513. return CR_CALL_NOT_IMPLEMENTED;
  1514. } // PNP_DetectResourceConflict
  1515. //------------------------------------------------------------------------
  1516. // Private Utility Functions
  1517. //------------------------------------------------------------------------
  1518. BOOL
  1519. FindLogConf(
  1520. IN LPBYTE pList,
  1521. OUT LPBYTE *ppLogConf,
  1522. IN ULONG RegDataType,
  1523. IN ULONG ulTag
  1524. )
  1525. {
  1526. ULONG Index = 0;
  1527. //
  1528. // Input data is a Resource List
  1529. //
  1530. if (RegDataType == REG_RESOURCE_LIST) {
  1531. PCM_RESOURCE_LIST pResList = (PCM_RESOURCE_LIST)pList;
  1532. PCM_FULL_RESOURCE_DESCRIPTOR pRes = NULL;
  1533. if (ulTag >= pResList->Count) {
  1534. return FALSE;
  1535. }
  1536. pRes = (PCM_FULL_RESOURCE_DESCRIPTOR)(&pResList->List[0]); // first lc
  1537. for (Index = 0; Index < ulTag; Index++) {
  1538. pRes = AdvanceResourcePtr(pRes); // next lc
  1539. }
  1540. *ppLogConf = (LPBYTE)pRes;
  1541. }
  1542. //
  1543. // Input data is a Requirments List
  1544. //
  1545. else if (RegDataType == REG_RESOURCE_REQUIREMENTS_LIST) {
  1546. PIO_RESOURCE_REQUIREMENTS_LIST pReqList = (PIO_RESOURCE_REQUIREMENTS_LIST)pList;
  1547. PIO_RESOURCE_LIST pReq = NULL;
  1548. if (ulTag >= pReqList->AlternativeLists) {
  1549. return FALSE;
  1550. }
  1551. pReq = (PIO_RESOURCE_LIST)(&pReqList->List[0]); // first lc
  1552. for (Index = 0; Index < ulTag; Index++) {
  1553. pReq = AdvanceRequirementsPtr(pReq); // next lc
  1554. }
  1555. *ppLogConf = (LPBYTE)pReq;
  1556. } else {
  1557. return FALSE;
  1558. }
  1559. return TRUE;
  1560. } // FindLogConf
  1561. BOOL
  1562. FindResDes(
  1563. IN LPBYTE pList,
  1564. IN ULONG RegDataType,
  1565. IN ULONG ulLogConfTag,
  1566. IN ULONG ulResTag,
  1567. IN RESOURCEID ResType,
  1568. OUT LPBYTE *ppRD,
  1569. OUT LPBYTE *ppLogConf,
  1570. OUT PULONG pulSubIndex OPTIONAL
  1571. )
  1572. {
  1573. ULONG ulIndex;
  1574. //
  1575. // Input data is a Resource List
  1576. //
  1577. if (RegDataType == REG_RESOURCE_LIST) {
  1578. PCM_RESOURCE_LIST pResList = (PCM_RESOURCE_LIST)pList;
  1579. PCM_FULL_RESOURCE_DESCRIPTOR pRes = NULL;
  1580. PCM_PARTIAL_RESOURCE_DESCRIPTOR pResDes = NULL;
  1581. ULONG ulSubIndex;
  1582. ULONG ulResTagOffset;
  1583. if (ulLogConfTag != 0) {
  1584. return FALSE;
  1585. }
  1586. if (pResList->Count == 0) {
  1587. return FALSE;
  1588. }
  1589. //
  1590. // The tag is just the res des index with the exception of a
  1591. // DeviceSpecificData type which has a unique tag. This is
  1592. // necessary because new res des's will always get placed at
  1593. // the end unless there's already a device specific res des,
  1594. // in which case new res des get added just before it.
  1595. //
  1596. if (ulResTag == RESDES_CS_TAG) {
  1597. //
  1598. // If there is a devicespecific res des, it will be the last.
  1599. //
  1600. pRes = (PCM_FULL_RESOURCE_DESCRIPTOR)&pResList->List[0]; // first lc
  1601. ulSubIndex = 0;
  1602. for (ulIndex = 0; ulIndex < (pResList->Count - 1); ulIndex++) {
  1603. ulSubIndex += pRes->PartialResourceList.Count;
  1604. pRes = AdvanceResourcePtr(pRes); // next lc
  1605. }
  1606. ulResTagOffset = pRes->PartialResourceList.Count - 1;
  1607. pResDes = &pRes->PartialResourceList.PartialDescriptors[ulResTagOffset];
  1608. if (pResDes->Type != CmResourceTypeDeviceSpecific) {
  1609. return FALSE;
  1610. }
  1611. if (pulSubIndex) {
  1612. *pulSubIndex = ulSubIndex + ulResTagOffset; // for res list, subindex = index
  1613. }
  1614. } else {
  1615. pRes = (PCM_FULL_RESOURCE_DESCRIPTOR)&pResList->List[0]; // first lc
  1616. ulResTagOffset = ulResTag;
  1617. for (ulIndex = 0; ulIndex < pResList->Count; ulIndex++) {
  1618. if (ulResTagOffset >= pRes->PartialResourceList.Count) {
  1619. ulResTagOffset -= pRes->PartialResourceList.Count;
  1620. pRes = AdvanceResourcePtr(pRes); // next lc
  1621. } else {
  1622. break;
  1623. }
  1624. }
  1625. if (ulResTagOffset >= pRes->PartialResourceList.Count) {
  1626. return FALSE;
  1627. }
  1628. if (pulSubIndex) {
  1629. *pulSubIndex = ulResTag; // for res list, subindex = index = tag
  1630. }
  1631. pResDes = &pRes->PartialResourceList.PartialDescriptors[ulResTagOffset];
  1632. }
  1633. //
  1634. // Validate against res des type
  1635. //
  1636. if (pResDes->Type != NT_RES_TYPE(ResType)) {
  1637. return FALSE;
  1638. }
  1639. *ppLogConf = (LPBYTE)pRes;
  1640. *ppRD = (LPBYTE)pResDes;
  1641. }
  1642. //
  1643. // Input data is a Requirments List
  1644. //
  1645. else if (RegDataType == REG_RESOURCE_REQUIREMENTS_LIST) {
  1646. LPBYTE pLogConf = NULL;
  1647. PIO_RESOURCE_LIST pReq = NULL;
  1648. PIO_RESOURCE_DESCRIPTOR pReqDes = NULL;
  1649. ULONG Index, i = 0, Count = 0;
  1650. if (!FindLogConf(pList, &pLogConf, RegDataType, ulLogConfTag)) {
  1651. return FALSE;
  1652. }
  1653. pReq = (PIO_RESOURCE_LIST)pLogConf;
  1654. if (pReq == NULL || pReq->Count == 0 || ulResTag >= pReq->Count) {
  1655. return FALSE;
  1656. }
  1657. //
  1658. // Find the res des that matches the specified tag. In this case the
  1659. // tag is the index based on res des groupings.
  1660. //
  1661. pReqDes = AdvanceRequirementsDescriptorPtr(&pReq->Descriptors[0], ulResTag, pReq->Count, &Count);
  1662. if (pReqDes == NULL) {
  1663. return FALSE;
  1664. }
  1665. if (pulSubIndex) {
  1666. *pulSubIndex = Count;
  1667. }
  1668. //
  1669. // Validate against res des type
  1670. //
  1671. if (pReqDes->Type != NT_RES_TYPE(ResType)) {
  1672. return FALSE;
  1673. }
  1674. *ppLogConf = (LPBYTE)pReq;
  1675. *ppRD = (LPBYTE)pReqDes;
  1676. }
  1677. return TRUE;
  1678. } // FindResDes
  1679. PIO_RESOURCE_DESCRIPTOR
  1680. AdvanceRequirementsDescriptorPtr(
  1681. IN PIO_RESOURCE_DESCRIPTOR pReqDesStart,
  1682. IN ULONG ulIncrement,
  1683. IN ULONG ulRemainingRanges,
  1684. OUT PULONG pulRangeCount
  1685. )
  1686. {
  1687. PIO_RESOURCE_DESCRIPTOR pReqDes = NULL;
  1688. ULONG i = 0, Count = 0;
  1689. //
  1690. // Advance requirements descriptor pointer by number passed
  1691. // in ulIncrement parameter. Return the actual index to the
  1692. // first range in this descriptor list and range count if
  1693. // desired. This routine assumes there is at least one more
  1694. // requirements descriptor in the list.
  1695. //
  1696. if (pReqDesStart == NULL) {
  1697. return NULL;
  1698. }
  1699. try {
  1700. pReqDes = pReqDesStart;
  1701. for (i = 0; i < ulIncrement; i++) {
  1702. //
  1703. // skip to next "whole" res des
  1704. //
  1705. if (Count < ulRemainingRanges &&
  1706. (pReqDes->Option == 0 ||
  1707. pReqDes->Option == IO_RESOURCE_PREFERRED ||
  1708. pReqDes->Option == IO_RESOURCE_DEFAULT)) {
  1709. //
  1710. // This is a valid Option, there may be one or more alternate
  1711. // descriptor in the set associated with this descriptor,
  1712. // treat the set as "one" descriptor. (loop through the
  1713. // descriptors until I find another non-alternative descriptor)
  1714. //
  1715. pReqDes++; // next range
  1716. Count++;
  1717. while (Count < ulRemainingRanges &&
  1718. (pReqDes->Option == IO_RESOURCE_ALTERNATIVE ||
  1719. pReqDes->Option == IO_RESOURCE_ALTERNATIVE + IO_RESOURCE_PREFERRED ||
  1720. pReqDes->Option == IO_RESOURCE_ALTERNATIVE + IO_RESOURCE_DEFAULT)) {
  1721. pReqDes++; // next range
  1722. Count++;
  1723. }
  1724. if (Count >= ulRemainingRanges) {
  1725. pReqDes = NULL;
  1726. Count = 0;
  1727. break;
  1728. }
  1729. } else {
  1730. //
  1731. // invalid Option value
  1732. //
  1733. pReqDes = NULL;
  1734. Count = 0;
  1735. break;
  1736. }
  1737. }
  1738. } except(EXCEPTION_EXECUTE_HANDLER) {
  1739. pReqDes = NULL;
  1740. Count = 0;
  1741. }
  1742. if (pulRangeCount) {
  1743. *pulRangeCount = Count;
  1744. }
  1745. return pReqDes;
  1746. } // AdvanceRequirementsDescriptorPtr
  1747. ULONG
  1748. RANGE_COUNT(
  1749. IN PIO_RESOURCE_DESCRIPTOR pReqDes,
  1750. IN LPBYTE pLastReqAddr
  1751. )
  1752. {
  1753. ULONG ulRangeCount = 0;
  1754. try {
  1755. if (pReqDes == NULL) {
  1756. goto Clean0;
  1757. }
  1758. ulRangeCount++;
  1759. if (pReqDes->Option == 0 ||
  1760. pReqDes->Option == IO_RESOURCE_PREFERRED ||
  1761. pReqDes->Option == IO_RESOURCE_DEFAULT) {
  1762. PIO_RESOURCE_DESCRIPTOR p = pReqDes;
  1763. p++;
  1764. while (((LPBYTE)p < pLastReqAddr) &&
  1765. (p->Option == IO_RESOURCE_ALTERNATIVE ||
  1766. p->Option == IO_RESOURCE_ALTERNATIVE + IO_RESOURCE_PREFERRED ||
  1767. p->Option == IO_RESOURCE_ALTERNATIVE + IO_RESOURCE_DEFAULT)) {
  1768. ulRangeCount++;
  1769. p++; // skip to next res des
  1770. }
  1771. }
  1772. Clean0:
  1773. NOTHING;
  1774. } except(EXCEPTION_EXECUTE_HANDLER) {
  1775. ulRangeCount = 0;
  1776. }
  1777. return ulRangeCount;
  1778. } // RANGE_COUNT
  1779. ULONG
  1780. GetResDesSize(
  1781. IN ULONG ResourceID,
  1782. IN ULONG ulFlags
  1783. )
  1784. {
  1785. switch (ResourceID) {
  1786. case ResType_Mem:
  1787. return sizeof(MEM_RESOURCE);
  1788. case ResType_IO:
  1789. return sizeof(IO_RESOURCE);
  1790. case ResType_DMA:
  1791. return sizeof(DMA_RESOURCE);
  1792. case ResType_IRQ:
  1793. if (ulFlags & CM_RESDES_WIDTH_64) {
  1794. return sizeof(IRQ_RESOURCE_64);
  1795. } else {
  1796. return sizeof(IRQ_RESOURCE_32);
  1797. }
  1798. case ResType_ClassSpecific:
  1799. return sizeof(CS_RESOURCE);
  1800. case ResType_DevicePrivate:
  1801. return sizeof(DEVPRIVATE_RESOURCE);
  1802. case ResType_BusNumber:
  1803. return sizeof(BUSNUMBER_RESOURCE);
  1804. case ResType_PcCardConfig:
  1805. return sizeof(PCCARD_RESOURCE);
  1806. case ResType_MfCardConfig:
  1807. return sizeof(MFCARD_RESOURCE);
  1808. default:
  1809. return 0;
  1810. }
  1811. } // GetResDesSize
  1812. ULONG
  1813. GetReqDesSize(
  1814. IN ULONG ResourceID,
  1815. IN PIO_RESOURCE_DESCRIPTOR pReqDes,
  1816. IN LPBYTE pLastReqAddr,
  1817. IN ULONG ulFlags
  1818. )
  1819. {
  1820. ULONG ulSize = 0;
  1821. switch (ResourceID) {
  1822. case ResType_Mem:
  1823. ulSize = sizeof(MEM_RESOURCE);
  1824. ulSize += (RANGE_COUNT(pReqDes, pLastReqAddr) - 1) * sizeof(MEM_RANGE);
  1825. break;
  1826. case ResType_IO:
  1827. ulSize = sizeof(IO_RESOURCE);
  1828. ulSize += (RANGE_COUNT(pReqDes, pLastReqAddr) - 1) * sizeof(IO_RANGE);
  1829. break;
  1830. case ResType_DMA:
  1831. ulSize = sizeof(DMA_RESOURCE);
  1832. ulSize += (RANGE_COUNT(pReqDes, pLastReqAddr) - 1) * sizeof(DMA_RANGE);
  1833. break;
  1834. case ResType_IRQ:
  1835. if (ulFlags & CM_RESDES_WIDTH_64) {
  1836. ulSize = sizeof(IRQ_RESOURCE_64);
  1837. } else {
  1838. ulSize = sizeof(IRQ_RESOURCE_32);
  1839. }
  1840. ulSize += (RANGE_COUNT(pReqDes, pLastReqAddr) - 1) * sizeof(IRQ_RANGE);
  1841. break;
  1842. case ResType_DevicePrivate:
  1843. ulSize = sizeof(DEVPRIVATE_RESOURCE);
  1844. ulSize += (RANGE_COUNT(pReqDes, pLastReqAddr) - 1) * sizeof(DEVPRIVATE_RANGE);
  1845. break;
  1846. case ResType_BusNumber:
  1847. ulSize = sizeof(BUSNUMBER_RESOURCE);
  1848. ulSize += (RANGE_COUNT(pReqDes, pLastReqAddr) - 1) * sizeof(BUSNUMBER_RANGE);
  1849. break;
  1850. case ResType_PcCardConfig:
  1851. //
  1852. // Non-arbitrated types don't have a range side in the user-mode structs
  1853. //
  1854. ulSize = sizeof(PCCARD_RESOURCE);
  1855. break;
  1856. case ResType_MfCardConfig:
  1857. //
  1858. // Non-arbitrated types don't have a range side in the user-mode structs
  1859. //
  1860. ulSize = sizeof(MFCARD_RESOURCE);
  1861. break;
  1862. default:
  1863. break;
  1864. }
  1865. return ulSize;
  1866. } // GetReqDesSize
  1867. UCHAR
  1868. NT_RES_TYPE(
  1869. IN RESOURCEID ResourceID
  1870. )
  1871. {
  1872. ULONG resid = 0;
  1873. if ((ResourceID < 0x06)) {
  1874. //
  1875. // First handle the divergent cases that can only be mapped
  1876. // on a case by case basis. These are the values from zero
  1877. // through five plus the special class specific case.
  1878. //
  1879. switch(ResourceID) {
  1880. case ResType_None:
  1881. return CmResourceTypeNull;
  1882. break;
  1883. case ResType_Mem:
  1884. return CmResourceTypeMemory;
  1885. case ResType_IO:
  1886. return CmResourceTypePort;
  1887. case ResType_DMA:
  1888. return CmResourceTypeDma;
  1889. case ResType_IRQ:
  1890. return CmResourceTypeInterrupt;
  1891. case ResType_DoNotUse:
  1892. return (UCHAR)-1;
  1893. DEFAULT_UNREACHABLE;
  1894. }
  1895. } else if (ResourceID == ResType_ClassSpecific) {
  1896. //
  1897. // ResType_ClassSpecific is another special case.
  1898. //
  1899. return CmResourceTypeDeviceSpecific;
  1900. } else {
  1901. //
  1902. // For all other cases, rules apply as to how to map a kernel-mode
  1903. // resource type id to a user-mode resource type id.
  1904. //
  1905. if (ResourceID >= 0x8080) {
  1906. //
  1907. // Anything larger this can't be mapped to the kernel-mode USHORT
  1908. // values so it's invalid.
  1909. //
  1910. return (UCHAR)-1;
  1911. } else if (!(ResourceID & ResType_Ignored_Bit)) {
  1912. //
  1913. // Values in the range [0x6,0x8000] use the same values
  1914. // for ConfigMgr as for kernel-mode.
  1915. //
  1916. return (UCHAR)ResourceID;
  1917. } else if (ResourceID & ResType_Ignored_Bit) {
  1918. //
  1919. // For the non arbitrated types (0x8000 bit set), do special
  1920. // mapping to get the kernel-mode resource id type.
  1921. //
  1922. resid = ResourceID;
  1923. resid &= ~(ResType_Ignored_Bit); // clear um non-arbitrated bit
  1924. resid |= CmResourceTypeNonArbitrated; // set km non-arbitrated bit
  1925. return (UCHAR)resid;
  1926. } else {
  1927. return (CHAR)-1;
  1928. }
  1929. }
  1930. } // NT_RES_TYPE
  1931. ULONG
  1932. CM_RES_TYPE(
  1933. IN UCHAR ResourceType
  1934. )
  1935. {
  1936. ULONG resid = 0;
  1937. if ((ResourceType < 0x06)) {
  1938. //
  1939. // First handle the divergent cases that can only be mapped
  1940. // on a case by case basis. These are the values from zero
  1941. // through five plus the special class specific case.
  1942. //
  1943. switch(ResourceType) {
  1944. case CmResourceTypeNull:
  1945. return ResType_None;
  1946. case CmResourceTypePort:
  1947. return ResType_IO;
  1948. case CmResourceTypeInterrupt:
  1949. return ResType_IRQ;
  1950. case CmResourceTypeMemory:
  1951. return ResType_Mem;
  1952. case CmResourceTypeDma:
  1953. return ResType_DMA;
  1954. case CmResourceTypeDeviceSpecific:
  1955. return ResType_ClassSpecific;
  1956. DEFAULT_UNREACHABLE;
  1957. }
  1958. } else {
  1959. //
  1960. // For all other cases, rules apply as to how to map a kernel-mode
  1961. // resource type id to a user-mode resource type id.
  1962. //
  1963. if (!(ResourceType & CmResourceTypeNonArbitrated)) {
  1964. //
  1965. // Values in the range [0x6,0x80] use the same values
  1966. // for ConfigMgr as for kernel-mode.
  1967. //
  1968. return (ULONG)ResourceType;
  1969. } else if (ResourceType & CmResourceTypeNonArbitrated) {
  1970. //
  1971. // For the non arbitrated types (0x80 bit set), do special
  1972. // mapping to get the user-mode resource id type.
  1973. //
  1974. resid = (ULONG)ResourceType;
  1975. resid &= ~(CmResourceTypeNonArbitrated); // clear km non-arbitrated bit
  1976. resid |= ResType_Ignored_Bit; // set um non-arbitrated bit
  1977. return resid;
  1978. } else {
  1979. return (ULONG)-1;
  1980. }
  1981. }
  1982. } // NT_RES_TYPE
  1983. CONFIGRET
  1984. ResDesToNtResource(
  1985. IN PCVOID ResourceData,
  1986. IN RESOURCEID ResourceType,
  1987. IN ULONG ResourceLen,
  1988. IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pResDes,
  1989. IN ULONG ulTag,
  1990. IN ULONG ulFlags
  1991. )
  1992. {
  1993. CONFIGRET Status = CR_SUCCESS;
  1994. UNREFERENCED_PARAMETER(ulTag);
  1995. //
  1996. // fill in resource type specific info
  1997. //
  1998. switch (ResourceType) {
  1999. case ResType_Mem: {
  2000. //-------------------------------------------------------
  2001. // Memory Resource Type
  2002. //-------------------------------------------------------
  2003. //
  2004. // NOTE: pMemData->MEM_Header.MD_Reserved is not mapped
  2005. // pMemData->MEM_Data.MR_Reserved is not mapped
  2006. //
  2007. PMEM_RESOURCE pMemData = (PMEM_RESOURCE)ResourceData;
  2008. //
  2009. // validate resource data
  2010. //
  2011. if (ResourceLen < sizeof(MEM_RESOURCE)) {
  2012. Status = CR_INVALID_RES_DES;
  2013. goto Clean0;
  2014. }
  2015. if (pMemData->MEM_Header.MD_Type != MType_Range) {
  2016. Status = CR_INVALID_RES_DES;
  2017. goto Clean0;
  2018. }
  2019. //
  2020. // copy MEM_DES info to CM_PARTIAL_RESOURCE_DESCRIPTOR format
  2021. //
  2022. pResDes->Type = CmResourceTypeMemory;
  2023. pResDes->ShareDisposition = CmResourceShareUndetermined;
  2024. //pResDes->ShareDisposition = MapToNtDisposition(pMemData->MEM_Header.MD_Flags, 0);
  2025. pResDes->Flags = MapToNtMemoryFlags(pMemData->MEM_Header.MD_Flags);
  2026. pResDes->u.Memory.Start.HighPart = HIDWORD(pMemData->MEM_Header.MD_Alloc_Base);
  2027. pResDes->u.Memory.Start.LowPart = LODWORD(pMemData->MEM_Header.MD_Alloc_Base);
  2028. pResDes->u.Memory.Length = (DWORD)(pMemData->MEM_Header.MD_Alloc_End -
  2029. pMemData->MEM_Header.MD_Alloc_Base + 1);
  2030. break;
  2031. }
  2032. case ResType_IO: {
  2033. //-------------------------------------------------------
  2034. // IO Port Resource Type
  2035. //
  2036. // NOTE: alias info lost during this conversion process
  2037. //-------------------------------------------------------
  2038. PIO_RESOURCE pIoData = (PIO_RESOURCE)ResourceData;
  2039. //
  2040. // validate resource data
  2041. //
  2042. if (ResourceLen < sizeof(IO_RESOURCE)) {
  2043. Status = CR_FAILURE;
  2044. goto Clean0;
  2045. }
  2046. if (pIoData->IO_Header.IOD_Type != IOType_Range) {
  2047. Status = CR_INVALID_RES_DES;
  2048. goto Clean0;
  2049. }
  2050. //
  2051. // copy IO_DES info to CM_PARTIAL_RESOURCE_DESCRIPTOR format
  2052. //
  2053. pResDes->Type = CmResourceTypePort;
  2054. pResDes->ShareDisposition = CmResourceShareUndetermined;
  2055. //pResDes->ShareDisposition = MapToNtDisposition(pIoData->IO_Header.IOD_DesFlags, 0);
  2056. pResDes->Flags = MapToNtPortFlags(pIoData->IO_Header.IOD_DesFlags, 0);
  2057. pResDes->u.Port.Start.HighPart = HIDWORD(pIoData->IO_Header.IOD_Alloc_Base);
  2058. pResDes->u.Port.Start.LowPart = LODWORD(pIoData->IO_Header.IOD_Alloc_Base);
  2059. pResDes->u.Port.Length = (DWORD)(pIoData->IO_Header.IOD_Alloc_End -
  2060. pIoData->IO_Header.IOD_Alloc_Base + 1);
  2061. break;
  2062. }
  2063. case ResType_DMA: {
  2064. //-------------------------------------------------------
  2065. // DMA Resource Type
  2066. //-------------------------------------------------------
  2067. //
  2068. // Note: u.Dma.Port is not mapped
  2069. // u.Dma.Reserved is not mapped
  2070. //
  2071. PDMA_RESOURCE pDmaData = (PDMA_RESOURCE)ResourceData;
  2072. //
  2073. // validate resource data
  2074. //
  2075. if (ResourceLen < sizeof(DMA_RESOURCE)) {
  2076. Status = CR_FAILURE;
  2077. goto Clean0;
  2078. }
  2079. if (pDmaData->DMA_Header.DD_Type != DType_Range) {
  2080. Status = CR_INVALID_RES_DES;
  2081. goto Clean0;
  2082. }
  2083. //
  2084. // copy DMA_DES info to CM_PARTIAL_RESOURCE_DESCRIPTOR format
  2085. //
  2086. pResDes->Type = CmResourceTypeDma;
  2087. pResDes->ShareDisposition = CmResourceShareUndetermined;
  2088. //pResDes->ShareDisposition = MapToNtDisposition(pDmaData->DMA_Header.DD_Flags, 0);
  2089. pResDes->Flags = MapToNtDmaFlags(pDmaData->DMA_Header.DD_Flags);
  2090. pResDes->u.Dma.Channel = pDmaData->DMA_Header.DD_Alloc_Chan;
  2091. pResDes->u.Dma.Port = 0;
  2092. pResDes->u.Dma.Reserved1 = 0;
  2093. break;
  2094. }
  2095. case ResType_IRQ: {
  2096. //-------------------------------------------------------
  2097. // IRQ Resource Type
  2098. //-------------------------------------------------------
  2099. if (ulFlags & CM_RESDES_WIDTH_64) {
  2100. //
  2101. // CM_RESDES_WIDTH_64
  2102. //
  2103. PIRQ_RESOURCE_64 pIrqData = (PIRQ_RESOURCE_64)ResourceData;
  2104. //
  2105. // validate resource data
  2106. //
  2107. if (ResourceLen < GetResDesSize(ResourceType, ulFlags)) {
  2108. Status = CR_FAILURE;
  2109. goto Clean0;
  2110. }
  2111. if (pIrqData->IRQ_Header.IRQD_Type != IRQType_Range) {
  2112. Status = CR_INVALID_RES_DES;
  2113. goto Clean0;
  2114. }
  2115. //
  2116. // copy IRQ_DES info to CM_PARTIAL_RESOURCE_DESCRIPTOR format
  2117. //
  2118. pResDes->Type = CmResourceTypeInterrupt;
  2119. pResDes->ShareDisposition = MapToNtIrqShare(pIrqData->IRQ_Header.IRQD_Flags);
  2120. //pResDes->ShareDisposition = MapToNtDisposition(pIrqData->IRQ_Header.IRQD_Flags, 1);
  2121. pResDes->Flags = MapToNtIrqFlags(pIrqData->IRQ_Header.IRQD_Flags);
  2122. pResDes->u.Interrupt.Level = pIrqData->IRQ_Header.IRQD_Alloc_Num;
  2123. pResDes->u.Interrupt.Vector = pIrqData->IRQ_Header.IRQD_Alloc_Num;
  2124. #ifdef _WIN64
  2125. pResDes->u.Interrupt.Affinity = pIrqData->IRQ_Header.IRQD_Affinity;
  2126. #else // !_WIN64
  2127. pResDes->u.Interrupt.Affinity = (ULONG)pIrqData->IRQ_Header.IRQD_Affinity;
  2128. #endif // !_WIN64
  2129. } else {
  2130. //
  2131. // CM_RESDES_WIDTH_32
  2132. //
  2133. PIRQ_RESOURCE_32 pIrqData = (PIRQ_RESOURCE_32)ResourceData;
  2134. //
  2135. // validate resource data
  2136. //
  2137. if (ResourceLen < GetResDesSize(ResourceType, ulFlags)) {
  2138. Status = CR_FAILURE;
  2139. goto Clean0;
  2140. }
  2141. if (pIrqData->IRQ_Header.IRQD_Type != IRQType_Range) {
  2142. Status = CR_INVALID_RES_DES;
  2143. goto Clean0;
  2144. }
  2145. //
  2146. // copy IRQ_DES info to CM_PARTIAL_RESOURCE_DESCRIPTOR format
  2147. //
  2148. pResDes->Type = CmResourceTypeInterrupt;
  2149. pResDes->ShareDisposition = MapToNtIrqShare(pIrqData->IRQ_Header.IRQD_Flags);
  2150. //pResDes->ShareDisposition = MapToNtDisposition(pIrqData->IRQ_Header.IRQD_Flags, 1);
  2151. pResDes->Flags = MapToNtIrqFlags(pIrqData->IRQ_Header.IRQD_Flags);
  2152. pResDes->u.Interrupt.Level = pIrqData->IRQ_Header.IRQD_Alloc_Num;
  2153. pResDes->u.Interrupt.Vector = pIrqData->IRQ_Header.IRQD_Alloc_Num;
  2154. pResDes->u.Interrupt.Affinity = pIrqData->IRQ_Header.IRQD_Affinity;
  2155. }
  2156. break;
  2157. }
  2158. case ResType_DevicePrivate: {
  2159. //-------------------------------------------------------
  2160. // Device Private Resource Type
  2161. //-------------------------------------------------------
  2162. PDEVPRIVATE_RESOURCE pPrvData = (PDEVPRIVATE_RESOURCE)ResourceData;
  2163. //
  2164. // validate resource data
  2165. //
  2166. if (ResourceLen < sizeof(DEVPRIVATE_RESOURCE)) {
  2167. Status = CR_INVALID_RES_DES;
  2168. goto Clean0;
  2169. }
  2170. if (pPrvData->PRV_Header.PD_Type != PType_Range) {
  2171. Status = CR_INVALID_RES_DES;
  2172. goto Clean0;
  2173. }
  2174. //
  2175. // copy DEVICEPRIVATE_DES info to CM_PARTIAL_RESOURCE_DESCRIPTOR format
  2176. //
  2177. pResDes->Type = CmResourceTypeDevicePrivate;
  2178. pResDes->ShareDisposition = CmResourceShareUndetermined;
  2179. pResDes->Flags = (USHORT)pPrvData->PRV_Header.PD_Flags;
  2180. pResDes->u.DevicePrivate.Data[0] = pPrvData->PRV_Header.PD_Data1;
  2181. pResDes->u.DevicePrivate.Data[1] = pPrvData->PRV_Header.PD_Data2;
  2182. pResDes->u.DevicePrivate.Data[2] = pPrvData->PRV_Header.PD_Data3;
  2183. break;
  2184. }
  2185. case ResType_BusNumber: {
  2186. //-------------------------------------------------------
  2187. // Bus Number Resource Type
  2188. //-------------------------------------------------------
  2189. PBUSNUMBER_RESOURCE pBusData = (PBUSNUMBER_RESOURCE)ResourceData;
  2190. //
  2191. // validate resource data
  2192. //
  2193. if (ResourceLen < sizeof(BUSNUMBER_RESOURCE)) {
  2194. Status = CR_INVALID_RES_DES;
  2195. goto Clean0;
  2196. }
  2197. if (pBusData->BusNumber_Header.BUSD_Type != BusNumberType_Range) {
  2198. Status = CR_INVALID_RES_DES;
  2199. goto Clean0;
  2200. }
  2201. //
  2202. // copy BUSNUMBER_DES info to CM_PARTIAL_RESOURCE_DESCRIPTOR format
  2203. //
  2204. pResDes->Type = CmResourceTypeBusNumber;
  2205. pResDes->ShareDisposition = CmResourceShareUndetermined;
  2206. pResDes->Flags = (USHORT)pBusData->BusNumber_Header.BUSD_Flags;
  2207. pResDes->u.BusNumber.Start = pBusData->BusNumber_Header.BUSD_Alloc_Base;
  2208. pResDes->u.BusNumber.Length = pBusData->BusNumber_Header.BUSD_Alloc_End;
  2209. pResDes->u.BusNumber.Reserved = 0;
  2210. break;
  2211. }
  2212. case ResType_PcCardConfig: {
  2213. //-------------------------------------------------------
  2214. // PcCarConfig Resource Type
  2215. //-------------------------------------------------------
  2216. PPCCARD_RESOURCE pPcData = (PPCCARD_RESOURCE)ResourceData;
  2217. ULONG index;
  2218. ULONG flags;
  2219. ULONG waitstate[2];
  2220. //
  2221. // validate resource data
  2222. //
  2223. if (ResourceLen < sizeof(PCCARD_RESOURCE)) {
  2224. Status = CR_INVALID_RES_DES;
  2225. goto Clean0;
  2226. }
  2227. //
  2228. // The following macros use bit manipulation, initialize data
  2229. // fields first.
  2230. //
  2231. pResDes->u.DevicePrivate.Data[0] = 0;
  2232. pResDes->u.DevicePrivate.Data[1] = 0;
  2233. pResDes->u.DevicePrivate.Data[2] = 0;
  2234. //
  2235. // copy PCCARD_DES info to CM_PARTIAL_RESOURCE_DESCRIPTOR format
  2236. //
  2237. PCMRES_SET_DESCRIPTOR_TYPE(pResDes, DPTYPE_PCMCIA_CONFIGURATION);
  2238. PCMRES_SET_CONFIG_INDEX(pResDes, pPcData->PcCard_Header.PCD_ConfigIndex);
  2239. PCMRES_SET_MEMORY_CARDBASE(pResDes, 0, pPcData->PcCard_Header.PCD_MemoryCardBase1);
  2240. PCMRES_SET_MEMORY_CARDBASE(pResDes, 1, pPcData->PcCard_Header.PCD_MemoryCardBase2);
  2241. flags = pPcData->PcCard_Header.PCD_Flags;
  2242. if (flags & (fPCD_MEM_16 | fPCD_MEM1_16)) {
  2243. PCMRES_SET_MEMORY_FLAG(pResDes, 0, PCMRESF_MEM_16BIT_ACCESS);
  2244. }
  2245. if (flags & (fPCD_MEM_16 | fPCD_MEM2_16)) {
  2246. PCMRES_SET_MEMORY_FLAG(pResDes, 1, PCMRESF_MEM_16BIT_ACCESS);
  2247. }
  2248. if (flags & fPCD_MEM1_A) {
  2249. PCMRES_SET_MEMORY_FLAG(pResDes, 0, PCMRESF_MEM_ATTRIBUTE);
  2250. }
  2251. if (flags & fPCD_MEM2_A) {
  2252. PCMRES_SET_MEMORY_FLAG(pResDes, 1, PCMRESF_MEM_ATTRIBUTE);
  2253. }
  2254. if (flags & fPCD_ATTRIBUTES_PER_WINDOW) {
  2255. waitstate[0] = flags & mPCD_MEM1_WS;
  2256. waitstate[1] = flags & mPCD_MEM2_WS;
  2257. } else {
  2258. waitstate[0] = waitstate[1] = flags & mPCD_MEM_WS;
  2259. }
  2260. for (index = 0; index < 2; index++) {
  2261. switch (waitstate[index]) {
  2262. case fPCD_MEM_WS_ONE:
  2263. case fPCD_MEM1_WS_ONE:
  2264. case fPCD_MEM2_WS_ONE:
  2265. PCMRES_SET_MEMORY_WAITSTATES(pResDes, index, PCMRESF_MEM_WAIT_1);
  2266. break;
  2267. case fPCD_MEM_WS_TWO:
  2268. case fPCD_MEM1_WS_TWO:
  2269. case fPCD_MEM2_WS_TWO:
  2270. PCMRES_SET_MEMORY_WAITSTATES(pResDes, index, PCMRESF_MEM_WAIT_2);
  2271. break;
  2272. case fPCD_MEM_WS_THREE:
  2273. case fPCD_MEM1_WS_THREE:
  2274. case fPCD_MEM2_WS_THREE:
  2275. PCMRES_SET_MEMORY_WAITSTATES(pResDes, index, PCMRESF_MEM_WAIT_3);
  2276. break;
  2277. }
  2278. }
  2279. if (flags & (fPCD_IO_16 | fPCD_IO1_16)) {
  2280. PCMRES_SET_IO_FLAG(pResDes, 0, PCMRESF_IO_16BIT_ACCESS);
  2281. }
  2282. if (flags & (fPCD_IO_16 | fPCD_IO2_16)) {
  2283. PCMRES_SET_IO_FLAG(pResDes, 1, PCMRESF_IO_16BIT_ACCESS);
  2284. }
  2285. if (flags & (fPCD_IO_ZW_8 | fPCD_IO1_ZW_8)) {
  2286. PCMRES_SET_IO_FLAG(pResDes, 0, PCMRESF_IO_ZERO_WAIT_8);
  2287. }
  2288. if (flags & (fPCD_IO_ZW_8 | fPCD_IO2_ZW_8)) {
  2289. PCMRES_SET_IO_FLAG(pResDes, 1, PCMRESF_IO_ZERO_WAIT_8);
  2290. }
  2291. if (flags & (fPCD_IO_SRC_16 | fPCD_IO1_SRC_16)) {
  2292. PCMRES_SET_IO_FLAG(pResDes, 0, PCMRESF_IO_SOURCE_16);
  2293. }
  2294. if (flags & (fPCD_IO_SRC_16 | fPCD_IO2_SRC_16)) {
  2295. PCMRES_SET_IO_FLAG(pResDes, 1, PCMRESF_IO_SOURCE_16);
  2296. }
  2297. if (flags & (fPCD_IO_WS_16 | fPCD_IO1_WS_16)) {
  2298. PCMRES_SET_IO_FLAG(pResDes, 0, PCMRESF_IO_WAIT_16);
  2299. }
  2300. if (flags & (fPCD_IO_WS_16 | fPCD_IO2_WS_16)) {
  2301. PCMRES_SET_IO_FLAG(pResDes, 1, PCMRESF_IO_WAIT_16);
  2302. }
  2303. break;
  2304. }
  2305. case ResType_MfCardConfig: {
  2306. //-------------------------------------------------------
  2307. // MfCardConfig Resource Type
  2308. //-------------------------------------------------------
  2309. PMFCARD_RESOURCE pMfData = (PMFCARD_RESOURCE)ResourceData;
  2310. //
  2311. // validate resource data
  2312. //
  2313. if (ResourceLen < sizeof(MFCARD_RESOURCE)) {
  2314. Status = CR_INVALID_RES_DES;
  2315. goto Clean0;
  2316. }
  2317. //
  2318. // The following macros use bit manipulation, initialize data
  2319. // fields first.
  2320. //
  2321. pResDes->u.DevicePrivate.Data[0] = 0;
  2322. pResDes->u.DevicePrivate.Data[1] = 0;
  2323. pResDes->u.DevicePrivate.Data[2] = 0;
  2324. //
  2325. // copy MFCARD_DES info to CM_PARTIAL_RESOURCE_DESCRIPTOR format
  2326. //
  2327. PCMRES_SET_DESCRIPTOR_TYPE(pResDes, DPTYPE_PCMCIA_MF_CONFIGURATION);
  2328. PCMRES_SET_CONFIG_OPTIONS(pResDes, pMfData->MfCard_Header.PMF_ConfigOptions);
  2329. PCMRES_SET_PORT_RESOURCE_INDEX(pResDes, pMfData->MfCard_Header.PMF_IoResourceIndex);
  2330. PCMRES_SET_CONFIG_REGISTER_BASE(pResDes, pMfData->MfCard_Header.PMF_ConfigRegisterBase);
  2331. if ((pMfData->MfCard_Header.PMF_Flags & mPMF_AUDIO_ENABLE) == fPMF_AUDIO_ENABLE) {
  2332. PCMRES_SET_AUDIO_ENABLE(pResDes);
  2333. }
  2334. break;
  2335. }
  2336. case ResType_ClassSpecific: {
  2337. //-------------------------------------------------------
  2338. // Class Specific Resource Type
  2339. //-------------------------------------------------------
  2340. PCS_RESOURCE pCsData = (PCS_RESOURCE)ResourceData;
  2341. LPBYTE ptr = NULL;
  2342. //
  2343. // validate resource data
  2344. //
  2345. if (ResourceLen < sizeof(CS_RESOURCE)) {
  2346. Status = CR_FAILURE;
  2347. goto Clean0;
  2348. }
  2349. //
  2350. // copy CS_DES info to CM_PARTIAL_RESOURCE_DESCRIPTOR format
  2351. //
  2352. pResDes->Type = CmResourceTypeDeviceSpecific;
  2353. pResDes->ShareDisposition = CmResourceShareUndetermined;
  2354. pResDes->Flags = (USHORT)pCsData->CS_Header.CSD_Flags; // none defined
  2355. pResDes->u.DeviceSpecificData.DataSize = pCsData->CS_Header.CSD_LegacyDataSize +
  2356. sizeof(GUID) +
  2357. pCsData->CS_Header.CSD_SignatureLength;
  2358. pResDes->u.DeviceSpecificData.Reserved1 = pCsData->CS_Header.CSD_LegacyDataSize;
  2359. pResDes->u.DeviceSpecificData.Reserved2 = pCsData->CS_Header.CSD_SignatureLength;
  2360. //
  2361. // copy the legacy and class-specific signature data
  2362. //
  2363. ptr = (LPBYTE)((LPBYTE)pResDes + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
  2364. memcpy(ptr,
  2365. pCsData->CS_Header.CSD_Signature + pCsData->CS_Header.CSD_LegacyDataOffset,
  2366. pCsData->CS_Header.CSD_LegacyDataSize); // copy legacy data first...
  2367. ptr += pCsData->CS_Header.CSD_LegacyDataSize;
  2368. memcpy(ptr,
  2369. pCsData->CS_Header.CSD_Signature,
  2370. pCsData->CS_Header.CSD_SignatureLength); // then copy signature...
  2371. ptr += pCsData->CS_Header.CSD_SignatureLength;
  2372. memcpy(ptr,
  2373. &pCsData->CS_Header.CSD_ClassGuid,
  2374. sizeof(GUID)); // then copy GUID
  2375. break;
  2376. }
  2377. default:
  2378. Status = CR_INVALID_RESOURCEID;
  2379. break;
  2380. }
  2381. Clean0:
  2382. return Status;
  2383. } // ResDesToNtResource
  2384. CONFIGRET
  2385. ResDesToNtRequirements(
  2386. IN PCVOID ResourceData,
  2387. IN RESOURCEID ResourceType,
  2388. IN ULONG ResourceLen,
  2389. IN PIO_RESOURCE_DESCRIPTOR pReqDes,
  2390. IN OUT PULONG pulResCount,
  2391. IN ULONG ulTag,
  2392. IN ULONG ulFlags
  2393. )
  2394. {
  2395. CONFIGRET Status = CR_SUCCESS;
  2396. ULONG i = 0;
  2397. PIO_RESOURCE_DESCRIPTOR pCurrent = NULL;
  2398. UNREFERENCED_PARAMETER(ulTag);
  2399. //
  2400. // fill in resource type specific info
  2401. //
  2402. switch (ResourceType) {
  2403. case ResType_Mem: {
  2404. //-------------------------------------------------------
  2405. // Memory Resource Type
  2406. //-------------------------------------------------------
  2407. //
  2408. // NOTE: pMemData->MEM_Header.MD_Reserved is not mapped
  2409. // pMemData->MEM_Data.MR_Reserved is not mapped
  2410. //
  2411. PMEM_RESOURCE pMemData = (PMEM_RESOURCE)ResourceData;
  2412. //
  2413. // validate resource data
  2414. //
  2415. if (ResourceLen < sizeof(MEM_RESOURCE)) {
  2416. Status = CR_INVALID_RES_DES;
  2417. goto Clean0;
  2418. }
  2419. if (pMemData->MEM_Header.MD_Type != MType_Range) {
  2420. Status = CR_INVALID_RES_DES;
  2421. goto Clean0;
  2422. }
  2423. *pulResCount = pMemData->MEM_Header.MD_Count;
  2424. //
  2425. // copy MEM_RANGE info to IO_RESOURCE_DESCRIPTOR format
  2426. //
  2427. for (i = 0, pCurrent = pReqDes;
  2428. i < *pulResCount;
  2429. i++, pCurrent++) {
  2430. if (i == 0) {
  2431. pCurrent->Option = 0;
  2432. } else {
  2433. pCurrent->Option = IO_RESOURCE_ALTERNATIVE;
  2434. }
  2435. pCurrent->Type = CmResourceTypeMemory;
  2436. pCurrent->ShareDisposition = CmResourceShareUndetermined;
  2437. //pCurrent->ShareDisposition = MapToNtDisposition(pMemData->MEM_Data[i].MR_Flags, 0);
  2438. pCurrent->Spare1 = 0;
  2439. pCurrent->Spare2 = 0;
  2440. pCurrent->Flags = MapToNtMemoryFlags(pMemData->MEM_Data[i].MR_Flags);
  2441. pCurrent->u.Memory.Length = pMemData->MEM_Data[i].MR_nBytes;
  2442. pCurrent->u.Memory.Alignment = MapToNtAlignment(pMemData->MEM_Data[i].MR_Align);
  2443. pCurrent->u.Memory.MinimumAddress.HighPart = HIDWORD(pMemData->MEM_Data[i].MR_Min);
  2444. pCurrent->u.Memory.MinimumAddress.LowPart = LODWORD(pMemData->MEM_Data[i].MR_Min);
  2445. pCurrent->u.Memory.MaximumAddress.HighPart = HIDWORD(pMemData->MEM_Data[i].MR_Max);
  2446. pCurrent->u.Memory.MaximumAddress.LowPart = LODWORD(pMemData->MEM_Data[i].MR_Max);
  2447. }
  2448. break;
  2449. }
  2450. case ResType_IO: {
  2451. //-------------------------------------------------------
  2452. // IO Port Resource Type
  2453. //-------------------------------------------------------
  2454. PIO_RESOURCE pIoData = (PIO_RESOURCE)ResourceData;
  2455. //
  2456. // validate resource data
  2457. //
  2458. if (ResourceLen < sizeof(IO_RESOURCE)) {
  2459. Status = CR_FAILURE;
  2460. goto Clean0;
  2461. }
  2462. if (pIoData->IO_Header.IOD_Type != IOType_Range) {
  2463. Status = CR_INVALID_RES_DES;
  2464. goto Clean0;
  2465. }
  2466. *pulResCount = pIoData->IO_Header.IOD_Count;
  2467. //
  2468. // copy IO_RANGE info to IO_RESOURCE_DESCRIPTOR format
  2469. //
  2470. for (i = 0, pCurrent = pReqDes;
  2471. i < *pulResCount;
  2472. i++, pCurrent++) {
  2473. if (i == 0) {
  2474. pCurrent->Option = 0;
  2475. } else {
  2476. pCurrent->Option = IO_RESOURCE_ALTERNATIVE;
  2477. }
  2478. pCurrent->Type = CmResourceTypePort;
  2479. pCurrent->ShareDisposition = CmResourceShareUndetermined;
  2480. //pCurrent->ShareDisposition = MapToNtDisposition(pIoData->IO_Data[i].IOR_RangeFlags, 0);
  2481. pCurrent->Spare1 = 0;
  2482. pCurrent->Spare2 = 0;
  2483. pCurrent->Flags = MapToNtPortFlags(pIoData->IO_Data[i].IOR_RangeFlags,
  2484. (DWORD)pIoData->IO_Data[i].IOR_Alias);
  2485. pCurrent->u.Port.Length = pIoData->IO_Data[i].IOR_nPorts;
  2486. pCurrent->u.Port.Alignment = MapToNtAlignment(pIoData->IO_Data[i].IOR_Align);
  2487. pCurrent->u.Port.MinimumAddress.HighPart = HIDWORD(pIoData->IO_Data[i].IOR_Min);
  2488. pCurrent->u.Port.MinimumAddress.LowPart = LODWORD(pIoData->IO_Data[i].IOR_Min);
  2489. pCurrent->u.Port.MaximumAddress.HighPart = HIDWORD(pIoData->IO_Data[i].IOR_Max);
  2490. pCurrent->u.Port.MaximumAddress.LowPart = LODWORD(pIoData->IO_Data[i].IOR_Max);
  2491. }
  2492. break;
  2493. }
  2494. case ResType_DMA: {
  2495. //-------------------------------------------------------
  2496. // DMA Resource Type
  2497. //-------------------------------------------------------
  2498. //
  2499. // Note: u.Dma.Port is not mapped
  2500. // u.Dma.Reserved is not mapped
  2501. //
  2502. PDMA_RESOURCE pDmaData = (PDMA_RESOURCE)ResourceData;
  2503. //
  2504. // validate resource data
  2505. //
  2506. if (ResourceLen < sizeof(DMA_RESOURCE)) {
  2507. Status = CR_FAILURE;
  2508. goto Clean0;
  2509. }
  2510. if (pDmaData->DMA_Header.DD_Type != DType_Range) {
  2511. Status = CR_INVALID_RES_DES;
  2512. goto Clean0;
  2513. }
  2514. *pulResCount = pDmaData->DMA_Header.DD_Count;
  2515. //
  2516. // copy DMA_RANGE info to IO_RESOURCE_DESCRIPTOR format
  2517. //
  2518. for (i = 0, pCurrent = pReqDes;
  2519. i < *pulResCount;
  2520. i++, pCurrent++) {
  2521. if (i == 0) {
  2522. pCurrent->Option = 0;
  2523. } else {
  2524. pCurrent->Option = IO_RESOURCE_ALTERNATIVE;
  2525. }
  2526. pCurrent->Type = CmResourceTypeDma;
  2527. pCurrent->ShareDisposition = CmResourceShareUndetermined;
  2528. //pCurrent->ShareDisposition = MapToNtDisposition(pDmaData->DMA_Data[i].DR_Flags, 0);
  2529. pCurrent->Spare1 = 0;
  2530. pCurrent->Spare2 = 0;
  2531. pCurrent->Flags = MapToNtDmaFlags(pDmaData->DMA_Data[i].DR_Flags);
  2532. pCurrent->u.Dma.MinimumChannel = pDmaData->DMA_Data[i].DR_Min;
  2533. pCurrent->u.Dma.MaximumChannel = pDmaData->DMA_Data[i].DR_Max;
  2534. }
  2535. break;
  2536. }
  2537. case ResType_IRQ: {
  2538. //-------------------------------------------------------
  2539. // IRQ Resource Type
  2540. //-------------------------------------------------------
  2541. if (ulFlags & CM_RESDES_WIDTH_64) {
  2542. //
  2543. // CM_RESDES_WIDTH_64
  2544. //
  2545. PIRQ_RESOURCE_64 pIrqData = (PIRQ_RESOURCE_64)ResourceData;
  2546. //
  2547. // validate resource data
  2548. //
  2549. if (ResourceLen < GetResDesSize(ResourceType, ulFlags)) {
  2550. Status = CR_FAILURE;
  2551. goto Clean0;
  2552. }
  2553. if (pIrqData->IRQ_Header.IRQD_Type != IRQType_Range) {
  2554. Status = CR_INVALID_RES_DES;
  2555. goto Clean0;
  2556. }
  2557. *pulResCount = pIrqData->IRQ_Header.IRQD_Count;
  2558. //
  2559. // copy IO_RANGE info to IO_RESOURCE_DESCRIPTOR format
  2560. //
  2561. for (i = 0, pCurrent = pReqDes;
  2562. i < *pulResCount;
  2563. i++, pCurrent++) {
  2564. if (i == 0) {
  2565. pCurrent->Option = 0;
  2566. } else {
  2567. pCurrent->Option = IO_RESOURCE_ALTERNATIVE;
  2568. }
  2569. pCurrent->Type = CmResourceTypeInterrupt;
  2570. pCurrent->Spare1 = 0;
  2571. pCurrent->Spare2 = 0;
  2572. pCurrent->ShareDisposition = MapToNtIrqShare(pIrqData->IRQ_Data[i].IRQR_Flags);
  2573. //pCurrent->ShareDisposition = MapToNtDisposition(pIrqData->IRQ_Data[i].IRQR_Flags, 1);
  2574. pCurrent->Flags = MapToNtIrqFlags(pIrqData->IRQ_Data[i].IRQR_Flags);
  2575. pCurrent->u.Interrupt.MinimumVector = pIrqData->IRQ_Data[i].IRQR_Min;
  2576. pCurrent->u.Interrupt.MaximumVector = pIrqData->IRQ_Data[i].IRQR_Max;
  2577. }
  2578. } else {
  2579. //
  2580. // CM_RESDES_WIDTH_32
  2581. //
  2582. PIRQ_RESOURCE_32 pIrqData = (PIRQ_RESOURCE_32)ResourceData;
  2583. //
  2584. // validate resource data
  2585. //
  2586. if (ResourceLen < GetResDesSize(ResourceType, ulFlags)) {
  2587. Status = CR_FAILURE;
  2588. goto Clean0;
  2589. }
  2590. if (pIrqData->IRQ_Header.IRQD_Type != IRQType_Range) {
  2591. Status = CR_INVALID_RES_DES;
  2592. goto Clean0;
  2593. }
  2594. *pulResCount = pIrqData->IRQ_Header.IRQD_Count;
  2595. //
  2596. // copy IO_RANGE info to IO_RESOURCE_DESCRIPTOR format
  2597. //
  2598. for (i = 0, pCurrent = pReqDes;
  2599. i < *pulResCount;
  2600. i++, pCurrent++) {
  2601. if (i == 0) {
  2602. pCurrent->Option = 0;
  2603. } else {
  2604. pCurrent->Option = IO_RESOURCE_ALTERNATIVE;
  2605. }
  2606. pCurrent->Type = CmResourceTypeInterrupt;
  2607. pCurrent->Spare1 = 0;
  2608. pCurrent->Spare2 = 0;
  2609. pCurrent->ShareDisposition = MapToNtIrqShare(pIrqData->IRQ_Data[i].IRQR_Flags);
  2610. //pCurrent->ShareDisposition = MapToNtDisposition(pIrqData->IRQ_Data[i].IRQR_Flags, 1);
  2611. pCurrent->Flags = MapToNtIrqFlags(pIrqData->IRQ_Data[i].IRQR_Flags);
  2612. pCurrent->u.Interrupt.MinimumVector = pIrqData->IRQ_Data[i].IRQR_Min;
  2613. pCurrent->u.Interrupt.MaximumVector = pIrqData->IRQ_Data[i].IRQR_Max;
  2614. }
  2615. }
  2616. break;
  2617. }
  2618. case ResType_DevicePrivate: {
  2619. //-------------------------------------------------------
  2620. // Device Private Resource Type
  2621. //-------------------------------------------------------
  2622. PDEVPRIVATE_RESOURCE pPrvData = (PDEVPRIVATE_RESOURCE)ResourceData;
  2623. //
  2624. // validate resource data
  2625. //
  2626. if (ResourceLen < sizeof(DEVPRIVATE_RESOURCE)) {
  2627. Status = CR_INVALID_RES_DES;
  2628. goto Clean0;
  2629. }
  2630. if (pPrvData->PRV_Header.PD_Type != PType_Range) {
  2631. Status = CR_INVALID_RES_DES;
  2632. goto Clean0;
  2633. }
  2634. *pulResCount = pPrvData->PRV_Header.PD_Count;
  2635. //
  2636. // copy DEVICEPRIVATE_RANGE info to IO_RESOURCE_DESCRIPTOR format
  2637. //
  2638. for (i = 0, pCurrent = pReqDes;
  2639. i < *pulResCount;
  2640. i++, pCurrent++) {
  2641. if (i == 0) {
  2642. pCurrent->Option = 0;
  2643. } else {
  2644. pCurrent->Option = IO_RESOURCE_ALTERNATIVE;
  2645. }
  2646. pCurrent->Type = CmResourceTypeDevicePrivate;
  2647. pCurrent->ShareDisposition = CmResourceShareUndetermined;
  2648. pCurrent->Spare1 = 0;
  2649. pCurrent->Spare2 = 0;
  2650. pCurrent->Flags = (USHORT)pPrvData->PRV_Header.PD_Flags;
  2651. pCurrent->u.DevicePrivate.Data[0] = pPrvData->PRV_Data[i].PR_Data1;
  2652. pCurrent->u.DevicePrivate.Data[1] = pPrvData->PRV_Data[i].PR_Data2;
  2653. pCurrent->u.DevicePrivate.Data[2] = pPrvData->PRV_Data[i].PR_Data3;
  2654. }
  2655. break;
  2656. }
  2657. case ResType_BusNumber: {
  2658. //-------------------------------------------------------
  2659. // Bus Number Resource Type
  2660. //-------------------------------------------------------
  2661. PBUSNUMBER_RESOURCE pBusData = (PBUSNUMBER_RESOURCE)ResourceData;
  2662. //
  2663. // validate resource data
  2664. //
  2665. if (ResourceLen < sizeof(BUSNUMBER_RESOURCE)) {
  2666. Status = CR_INVALID_RES_DES;
  2667. goto Clean0;
  2668. }
  2669. if (pBusData->BusNumber_Header.BUSD_Type != BusNumberType_Range) {
  2670. Status = CR_INVALID_RES_DES;
  2671. goto Clean0;
  2672. }
  2673. *pulResCount = pBusData->BusNumber_Header.BUSD_Count;
  2674. //
  2675. // copy BUSNUMBER_RANGE info to IO_RESOURCE_DESCRIPTOR format
  2676. //
  2677. for (i = 0, pCurrent = pReqDes;
  2678. i < *pulResCount;
  2679. i++, pCurrent++) {
  2680. if (i == 0) {
  2681. pCurrent->Option = 0;
  2682. } else {
  2683. pCurrent->Option = IO_RESOURCE_ALTERNATIVE;
  2684. }
  2685. pCurrent->Type = CmResourceTypeBusNumber;
  2686. pCurrent->ShareDisposition = CmResourceShareUndetermined;
  2687. pCurrent->Spare1 = 0;
  2688. pCurrent->Spare2 = 0;
  2689. pCurrent->Flags = (USHORT)pBusData->BusNumber_Data[i].BUSR_Flags;
  2690. pCurrent->u.BusNumber.Length = pBusData->BusNumber_Data[i].BUSR_nBusNumbers;
  2691. pCurrent->u.BusNumber.MinBusNumber = pBusData->BusNumber_Data[i].BUSR_Min;
  2692. pCurrent->u.BusNumber.MaxBusNumber = pBusData->BusNumber_Data[i].BUSR_Max;
  2693. pCurrent->u.BusNumber.Reserved = 0;
  2694. }
  2695. break;
  2696. }
  2697. case ResType_PcCardConfig: {
  2698. //-------------------------------------------------------
  2699. // PcCardConfig Resource Type
  2700. //-------------------------------------------------------
  2701. PPCCARD_RESOURCE pPcData = (PPCCARD_RESOURCE)ResourceData;
  2702. ULONG index;
  2703. ULONG flags;
  2704. ULONG waitstate[2];
  2705. //
  2706. // validate resource data
  2707. //
  2708. if (ResourceLen < sizeof(PCCARD_RESOURCE)) {
  2709. Status = CR_INVALID_RES_DES;
  2710. goto Clean0;
  2711. }
  2712. *pulResCount = 1;
  2713. //
  2714. // copy PCCARD_DES info to IO_RESOURCE_DESCRIPTOR format
  2715. //
  2716. pReqDes->Option = 0;
  2717. pReqDes->Type = CmResourceTypeDevicePrivate;
  2718. pReqDes->ShareDisposition = CmResourceShareUndetermined;
  2719. pReqDes->Spare1 = 0;
  2720. pReqDes->Spare2 = 0;
  2721. pReqDes->Flags = 0;
  2722. //
  2723. // The following macros use bit manipulation, initialize data
  2724. // fields first.
  2725. //
  2726. pReqDes->u.DevicePrivate.Data[0] = 0;
  2727. pReqDes->u.DevicePrivate.Data[1] = 0;
  2728. pReqDes->u.DevicePrivate.Data[2] = 0;
  2729. PCMRES_SET_DESCRIPTOR_TYPE(pReqDes, DPTYPE_PCMCIA_CONFIGURATION);
  2730. PCMRES_SET_CONFIG_INDEX(pReqDes, pPcData->PcCard_Header.PCD_ConfigIndex);
  2731. PCMRES_SET_MEMORY_CARDBASE(pReqDes, 0, pPcData->PcCard_Header.PCD_MemoryCardBase1);
  2732. PCMRES_SET_MEMORY_CARDBASE(pReqDes, 1, pPcData->PcCard_Header.PCD_MemoryCardBase2);
  2733. flags = pPcData->PcCard_Header.PCD_Flags;
  2734. if (flags & (fPCD_MEM_16 | fPCD_MEM1_16)) {
  2735. PCMRES_SET_MEMORY_FLAG(pReqDes, 0, PCMRESF_MEM_16BIT_ACCESS);
  2736. }
  2737. if (flags & (fPCD_MEM_16 | fPCD_MEM2_16)) {
  2738. PCMRES_SET_MEMORY_FLAG(pReqDes, 1, PCMRESF_MEM_16BIT_ACCESS);
  2739. }
  2740. if (flags & fPCD_MEM1_A) {
  2741. PCMRES_SET_MEMORY_FLAG(pReqDes, 0, PCMRESF_MEM_ATTRIBUTE);
  2742. }
  2743. if (flags & fPCD_MEM2_A) {
  2744. PCMRES_SET_MEMORY_FLAG(pReqDes, 1, PCMRESF_MEM_ATTRIBUTE);
  2745. }
  2746. if (flags & fPCD_ATTRIBUTES_PER_WINDOW) {
  2747. waitstate[0] = flags & mPCD_MEM1_WS;
  2748. waitstate[1] = flags & mPCD_MEM2_WS;
  2749. } else {
  2750. waitstate[0] = waitstate[1] = flags & mPCD_MEM_WS;
  2751. }
  2752. for (index = 0; index < 2; index++) {
  2753. switch (waitstate[index]) {
  2754. case fPCD_MEM_WS_ONE:
  2755. case fPCD_MEM1_WS_ONE:
  2756. case fPCD_MEM2_WS_ONE:
  2757. PCMRES_SET_MEMORY_WAITSTATES(pReqDes, index, PCMRESF_MEM_WAIT_1);
  2758. break;
  2759. case fPCD_MEM_WS_TWO:
  2760. case fPCD_MEM1_WS_TWO:
  2761. case fPCD_MEM2_WS_TWO:
  2762. PCMRES_SET_MEMORY_WAITSTATES(pReqDes, index, PCMRESF_MEM_WAIT_2);
  2763. break;
  2764. case fPCD_MEM_WS_THREE:
  2765. case fPCD_MEM1_WS_THREE:
  2766. case fPCD_MEM2_WS_THREE:
  2767. PCMRES_SET_MEMORY_WAITSTATES(pReqDes, index, PCMRESF_MEM_WAIT_3);
  2768. break;
  2769. }
  2770. }
  2771. if (flags & (fPCD_IO_16 | fPCD_IO1_16)) {
  2772. PCMRES_SET_IO_FLAG(pReqDes, 0, PCMRESF_IO_16BIT_ACCESS);
  2773. }
  2774. if (flags & (fPCD_IO_16 | fPCD_IO2_16)) {
  2775. PCMRES_SET_IO_FLAG(pReqDes, 1, PCMRESF_IO_16BIT_ACCESS);
  2776. }
  2777. if (flags & (fPCD_IO_ZW_8 | fPCD_IO1_ZW_8)) {
  2778. PCMRES_SET_IO_FLAG(pReqDes, 0, PCMRESF_IO_ZERO_WAIT_8);
  2779. }
  2780. if (flags & (fPCD_IO_ZW_8 | fPCD_IO2_ZW_8)) {
  2781. PCMRES_SET_IO_FLAG(pReqDes, 1, PCMRESF_IO_ZERO_WAIT_8);
  2782. }
  2783. if (flags & (fPCD_IO_SRC_16 | fPCD_IO1_SRC_16)) {
  2784. PCMRES_SET_IO_FLAG(pReqDes, 0, PCMRESF_IO_SOURCE_16);
  2785. }
  2786. if (flags & (fPCD_IO_SRC_16 | fPCD_IO2_SRC_16)) {
  2787. PCMRES_SET_IO_FLAG(pReqDes, 1, PCMRESF_IO_SOURCE_16);
  2788. }
  2789. if (flags & (fPCD_IO_WS_16 | fPCD_IO1_WS_16)) {
  2790. PCMRES_SET_IO_FLAG(pReqDes, 0, PCMRESF_IO_WAIT_16);
  2791. }
  2792. if (flags & (fPCD_IO_WS_16 | fPCD_IO2_WS_16)) {
  2793. PCMRES_SET_IO_FLAG(pReqDes, 1, PCMRESF_IO_WAIT_16);
  2794. }
  2795. break;
  2796. }
  2797. case ResType_MfCardConfig: {
  2798. //-------------------------------------------------------
  2799. // PcCardConfig Resource Type
  2800. //-------------------------------------------------------
  2801. PMFCARD_RESOURCE pMfData = (PMFCARD_RESOURCE)ResourceData;
  2802. //
  2803. // validate resource data
  2804. //
  2805. if (ResourceLen < sizeof(MFCARD_RESOURCE)) {
  2806. Status = CR_INVALID_RES_DES;
  2807. goto Clean0;
  2808. }
  2809. *pulResCount = 1;
  2810. //
  2811. // copy PCCARD_DES info to IO_RESOURCE_DESCRIPTOR format
  2812. //
  2813. pReqDes->Option = 0;
  2814. pReqDes->Type = CmResourceTypeDevicePrivate;
  2815. pReqDes->ShareDisposition = CmResourceShareUndetermined;
  2816. pReqDes->Spare1 = 0;
  2817. pReqDes->Spare2 = 0;
  2818. pReqDes->Flags = 0;
  2819. //
  2820. // The following macros use bit manipulation, initialize data
  2821. // fields first.
  2822. //
  2823. pReqDes->u.DevicePrivate.Data[0] = 0;
  2824. pReqDes->u.DevicePrivate.Data[1] = 0;
  2825. pReqDes->u.DevicePrivate.Data[2] = 0;
  2826. PCMRES_SET_DESCRIPTOR_TYPE(pReqDes, DPTYPE_PCMCIA_MF_CONFIGURATION);
  2827. PCMRES_SET_CONFIG_OPTIONS(pReqDes, pMfData->MfCard_Header.PMF_ConfigOptions);
  2828. PCMRES_SET_PORT_RESOURCE_INDEX(pReqDes, pMfData->MfCard_Header.PMF_IoResourceIndex);
  2829. PCMRES_SET_CONFIG_REGISTER_BASE(pReqDes, pMfData->MfCard_Header.PMF_ConfigRegisterBase);
  2830. if ((pMfData->MfCard_Header.PMF_Flags & mPMF_AUDIO_ENABLE) == fPMF_AUDIO_ENABLE) {
  2831. PCMRES_SET_AUDIO_ENABLE(pReqDes);
  2832. }
  2833. break;
  2834. }
  2835. default:
  2836. Status = CR_INVALID_RESOURCEID;
  2837. break;
  2838. }
  2839. Clean0:
  2840. return Status;
  2841. } // ResDesToNtRequirements
  2842. CONFIGRET
  2843. NtResourceToResDes(
  2844. IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pResDes,
  2845. IN OUT LPBYTE Buffer,
  2846. IN ULONG BufferLen,
  2847. IN LPBYTE pLastAddr,
  2848. IN ULONG ulFlags
  2849. )
  2850. {
  2851. CONFIGRET Status = CR_SUCCESS;
  2852. ULONG ulSize = 0;
  2853. UNREFERENCED_PARAMETER(pLastAddr);
  2854. //
  2855. // fill in resource type specific info
  2856. //
  2857. switch (pResDes->Type) {
  2858. case CmResourceTypeMemory: {
  2859. //-------------------------------------------------------
  2860. // Memory Resource Type
  2861. //-------------------------------------------------------
  2862. //
  2863. // NOTE: pMemData->MEM_Header.MD_Reserved is not mapped
  2864. // pMemData->MEM_Data.MR_Reserved is not mapped
  2865. //
  2866. PMEM_RESOURCE pMemData = (PMEM_RESOURCE)Buffer;
  2867. //
  2868. // verify passed in buffer size
  2869. //
  2870. if (BufferLen < sizeof(MEM_RESOURCE)) {
  2871. Status = CR_BUFFER_SMALL;
  2872. goto Clean0;
  2873. }
  2874. //
  2875. // copy CM_PARTIAL_RESOURCE_DESCRIPTOR info to MEM_DES format
  2876. //
  2877. pMemData->MEM_Header.MD_Count = 0;
  2878. pMemData->MEM_Header.MD_Type = MType_Range;
  2879. pMemData->MEM_Header.MD_Flags = MapFromNtMemoryFlags(pResDes->Flags);
  2880. //pMemData->MEM_Header.MD_Flags |= MapFromNtDisposition(pResDes->ShareDisposition, 0);
  2881. pMemData->MEM_Header.MD_Reserved = 0;
  2882. if (pResDes->u.Memory.Length != 0) {
  2883. pMemData->MEM_Header.MD_Alloc_Base = MAKEDWORDLONG(pResDes->u.Memory.Start.LowPart,
  2884. pResDes->u.Memory.Start.HighPart);
  2885. pMemData->MEM_Header.MD_Alloc_End = pMemData->MEM_Header.MD_Alloc_Base +
  2886. (DWORDLONG)pResDes->u.Memory.Length - 1;
  2887. } else {
  2888. pMemData->MEM_Header.MD_Alloc_Base = 1;
  2889. pMemData->MEM_Header.MD_Alloc_End = 0;
  2890. }
  2891. break;
  2892. }
  2893. case CmResourceTypePort: {
  2894. //-------------------------------------------------------
  2895. // IO Port Resource Type
  2896. //
  2897. // NOTE: alias info lost during this conversion process
  2898. //-------------------------------------------------------
  2899. PIO_RESOURCE pIoData = (PIO_RESOURCE)Buffer;
  2900. //
  2901. // verify passed in buffer size
  2902. //
  2903. if (BufferLen < sizeof(IO_RESOURCE)) {
  2904. Status = CR_BUFFER_SMALL;
  2905. goto Clean0;
  2906. }
  2907. //
  2908. // copy CM_PARTIAL_RESOURCE_DESCRIPTOR info to IO_DES format
  2909. //
  2910. pIoData->IO_Header.IOD_Count = 0;
  2911. pIoData->IO_Header.IOD_Type = IOType_Range;
  2912. pIoData->IO_Header.IOD_DesFlags = MapFromNtPortFlags(pResDes->Flags);
  2913. //pIoData->IO_Header.IOD_DesFlags |= MapFromNtDisposition(pResDes->ShareDisposition, 0);
  2914. if (pResDes->u.Port.Length) {
  2915. pIoData->IO_Header.IOD_Alloc_Base = MAKEDWORDLONG(pResDes->u.Port.Start.LowPart,
  2916. pResDes->u.Port.Start.HighPart);
  2917. pIoData->IO_Header.IOD_Alloc_End = pIoData->IO_Header.IOD_Alloc_Base +
  2918. (DWORDLONG)pResDes->u.Port.Length - 1;
  2919. } else {
  2920. pIoData->IO_Header.IOD_Alloc_Base = 1;
  2921. pIoData->IO_Header.IOD_Alloc_End = 0;
  2922. }
  2923. break;
  2924. }
  2925. case CmResourceTypeDma: {
  2926. //-------------------------------------------------------
  2927. // DMA Resource Type
  2928. //-------------------------------------------------------
  2929. //
  2930. // Note: u.Dma.Port is not mapped
  2931. // u.Dma.Reserved is not mapped
  2932. //
  2933. PDMA_RESOURCE pDmaData = (PDMA_RESOURCE)Buffer;
  2934. //
  2935. // verify passed in buffer size
  2936. //
  2937. if (BufferLen < sizeof(DMA_RESOURCE)) {
  2938. Status = CR_BUFFER_SMALL;
  2939. goto Clean0;
  2940. }
  2941. //
  2942. // copy CM_PARTIAL_RESOURCE_DESCRIPTOR info to DMA_DES format
  2943. //
  2944. pDmaData->DMA_Header.DD_Count = 0;
  2945. pDmaData->DMA_Header.DD_Type = DType_Range;
  2946. pDmaData->DMA_Header.DD_Flags = MapFromNtDmaFlags(pResDes->Flags);
  2947. //pDmaData->DMA_Header.DD_Flags |= MapFromNtDisposition(pResDes->ShareDisposition, 0);
  2948. pDmaData->DMA_Header.DD_Alloc_Chan = pResDes->u.Dma.Channel;
  2949. break;
  2950. }
  2951. case CmResourceTypeInterrupt: {
  2952. //-------------------------------------------------------
  2953. // IRQ Resource Type
  2954. //-------------------------------------------------------
  2955. if (ulFlags & CM_RESDES_WIDTH_64) {
  2956. //
  2957. // CM_RESDES_WIDTH_64
  2958. //
  2959. PIRQ_RESOURCE_64 pIrqData = (PIRQ_RESOURCE_64)Buffer;
  2960. //
  2961. // verify passed in buffer size
  2962. //
  2963. if (BufferLen < GetResDesSize(ResType_IRQ, ulFlags)) {
  2964. Status = CR_BUFFER_SMALL;
  2965. goto Clean0;
  2966. }
  2967. //
  2968. // copy CM_PARTIAL_RESOURCE_DESCRIPTOR info to IRQ_DES format
  2969. //
  2970. pIrqData->IRQ_Header.IRQD_Count = 0;
  2971. pIrqData->IRQ_Header.IRQD_Type = IRQType_Range;
  2972. pIrqData->IRQ_Header.IRQD_Flags = MapFromNtIrqFlags(pResDes->Flags) |
  2973. MapFromNtIrqShare(pResDes->ShareDisposition);
  2974. //pIrqData->IRQ_Header.IRQD_Flags |= MapFromNtDisposition(pResDes->ShareDisposition, 1);
  2975. pIrqData->IRQ_Header.IRQD_Alloc_Num = pResDes->u.Interrupt.Level;
  2976. pIrqData->IRQ_Header.IRQD_Affinity = pResDes->u.Interrupt.Affinity;
  2977. } else {
  2978. //
  2979. // CM_RESDES_WIDTH_32
  2980. //
  2981. PIRQ_RESOURCE_32 pIrqData = (PIRQ_RESOURCE_32)Buffer;
  2982. //
  2983. // verify passed in buffer size
  2984. //
  2985. if (BufferLen < GetResDesSize(ResType_IRQ, ulFlags)) {
  2986. Status = CR_BUFFER_SMALL;
  2987. goto Clean0;
  2988. }
  2989. //
  2990. // copy CM_PARTIAL_RESOURCE_DESCRIPTOR info to IRQ_DES format
  2991. //
  2992. pIrqData->IRQ_Header.IRQD_Count = 0;
  2993. pIrqData->IRQ_Header.IRQD_Type = IRQType_Range;
  2994. pIrqData->IRQ_Header.IRQD_Flags = MapFromNtIrqFlags(pResDes->Flags) |
  2995. MapFromNtIrqShare(pResDes->ShareDisposition);
  2996. //pIrqData->IRQ_Header.IRQD_Flags |= MapFromNtDisposition(pResDes->ShareDisposition, 1);
  2997. pIrqData->IRQ_Header.IRQD_Alloc_Num = pResDes->u.Interrupt.Level;
  2998. #ifdef _WIN64
  2999. pIrqData->IRQ_Header.IRQD_Affinity = (ULONG)((pResDes->u.Interrupt.Affinity >> 32) |
  3000. pResDes->u.Interrupt.Affinity);
  3001. #else // !_WIN64
  3002. pIrqData->IRQ_Header.IRQD_Affinity = pResDes->u.Interrupt.Affinity;
  3003. #endif // !_WIN64
  3004. }
  3005. break;
  3006. }
  3007. case CmResourceTypeDevicePrivate: {
  3008. //-------------------------------------------------------
  3009. // Device Private Resource Type
  3010. //-------------------------------------------------------
  3011. PDEVPRIVATE_RESOURCE pPrvData = (PDEVPRIVATE_RESOURCE)Buffer;
  3012. //
  3013. // verify passed in buffer size
  3014. //
  3015. if (BufferLen < sizeof(DEVPRIVATE_RESOURCE)) {
  3016. Status = CR_BUFFER_SMALL;
  3017. goto Clean0;
  3018. }
  3019. //
  3020. // copy CM_PARTIAL_RESOURCE_DESCRIPTOR info to DEVICEPRIVATE_DES format
  3021. //
  3022. pPrvData->PRV_Header.PD_Count = 0;
  3023. pPrvData->PRV_Header.PD_Type = PType_Range;
  3024. pPrvData->PRV_Header.PD_Data1 = pResDes->u.DevicePrivate.Data[0];
  3025. pPrvData->PRV_Header.PD_Data2 = pResDes->u.DevicePrivate.Data[1];
  3026. pPrvData->PRV_Header.PD_Data3 = pResDes->u.DevicePrivate.Data[2];
  3027. pPrvData->PRV_Header.PD_Flags = pResDes->Flags;
  3028. break;
  3029. }
  3030. case CmResourceTypeBusNumber: {
  3031. //-------------------------------------------------------
  3032. // Bus Number Resource Type
  3033. //-------------------------------------------------------
  3034. PBUSNUMBER_RESOURCE pBusData = (PBUSNUMBER_RESOURCE)Buffer;
  3035. //
  3036. // verify passed in buffer size
  3037. //
  3038. if (BufferLen < sizeof(BUSNUMBER_RESOURCE)) {
  3039. Status = CR_BUFFER_SMALL;
  3040. goto Clean0;
  3041. }
  3042. //
  3043. // copy CM_PARTIAL_RESOURCE_DESCRIPTOR info to BUSNUMBER_DES format
  3044. //
  3045. pBusData->BusNumber_Header.BUSD_Count = 0;
  3046. pBusData->BusNumber_Header.BUSD_Type = BusNumberType_Range;
  3047. pBusData->BusNumber_Header.BUSD_Flags = pResDes->Flags;
  3048. pBusData->BusNumber_Header.BUSD_Alloc_Base = pResDes->u.BusNumber.Start;
  3049. pBusData->BusNumber_Header.BUSD_Alloc_End = pResDes->u.BusNumber.Start +
  3050. pResDes->u.BusNumber.Length - 1;
  3051. break;
  3052. }
  3053. case CmResourceTypePcCardConfig: {
  3054. //-------------------------------------------------------
  3055. // PcCardConfig Resource Type
  3056. //-------------------------------------------------------
  3057. PPCCARD_RESOURCE pPcData = (PPCCARD_RESOURCE)Buffer;
  3058. //
  3059. // verify passed in buffer size
  3060. //
  3061. if (BufferLen < sizeof(PCCARD_RESOURCE)) {
  3062. Status = CR_BUFFER_SMALL;
  3063. goto Clean0;
  3064. }
  3065. //
  3066. // copy CM_PARTIAL_RESOURCE_DESCRIPTOR info to PCCARD_DES format
  3067. //
  3068. pPcData->PcCard_Header.PCD_Reserved[0] = 0;
  3069. pPcData->PcCard_Header.PCD_Reserved[1] = 0;
  3070. pPcData->PcCard_Header.PCD_Reserved[2] = 0;
  3071. pPcData->PcCard_Header.PCD_ConfigIndex = PCMRES_GET_CONFIG_INDEX(pResDes);
  3072. pPcData->PcCard_Header.PCD_MemoryCardBase1 = PCMRES_GET_MEMORY_CARDBASE(pResDes, 0);
  3073. pPcData->PcCard_Header.PCD_MemoryCardBase2 = PCMRES_GET_MEMORY_CARDBASE(pResDes, 1);
  3074. if (PCMRES_GET_IO_FLAG(pResDes, 0, PCMRESF_IO_16BIT_ACCESS)) {
  3075. pPcData->PcCard_Header.PCD_Flags = fPCD_IO_16;
  3076. } else {
  3077. pPcData->PcCard_Header.PCD_Flags = fPCD_IO_8;
  3078. }
  3079. if (PCMRES_GET_MEMORY_FLAG(pResDes, 0, PCMRESF_MEM_16BIT_ACCESS)) {
  3080. pPcData->PcCard_Header.PCD_Flags |= fPCD_MEM_16;
  3081. } else {
  3082. pPcData->PcCard_Header.PCD_Flags |= fPCD_MEM_8;
  3083. }
  3084. break;
  3085. }
  3086. case CmResourceTypeDeviceSpecific: {
  3087. //-------------------------------------------------------
  3088. // Class Specific Resource Type
  3089. //-------------------------------------------------------
  3090. PCS_RESOURCE pCsData = (PCS_RESOURCE)Buffer;
  3091. LPBYTE ptr1 = NULL, ptr2 = NULL;
  3092. ULONG ulRequiredSize = sizeof(CS_RESOURCE);
  3093. //
  3094. // the Reserved fields should not exceed DataSize. if so, they
  3095. // may have been incorrectly initialized, so set them 0.
  3096. // we expect DataSize to be correct in all cases.
  3097. //
  3098. if (pResDes->u.DeviceSpecificData.Reserved1 > pResDes->u.DeviceSpecificData.DataSize) {
  3099. pResDes->u.DeviceSpecificData.Reserved1 = 0;
  3100. }
  3101. if (pResDes->u.DeviceSpecificData.Reserved2 > pResDes->u.DeviceSpecificData.DataSize) {
  3102. pResDes->u.DeviceSpecificData.Reserved2 = 0;
  3103. }
  3104. //
  3105. // verify passed in buffer size
  3106. //
  3107. if (pResDes->u.DeviceSpecificData.DataSize == 0) {
  3108. //
  3109. // there is no legacy data and no class-specific data
  3110. //
  3111. ;
  3112. } else if (pResDes->u.DeviceSpecificData.Reserved2 == 0) {
  3113. //
  3114. // add space for legacy data
  3115. //
  3116. ulRequiredSize += pResDes->u.DeviceSpecificData.DataSize - 1;
  3117. } else {
  3118. //
  3119. // add space for legacy and signature data, as necessary
  3120. //
  3121. ulRequiredSize += pResDes->u.DeviceSpecificData.Reserved1 +
  3122. pResDes->u.DeviceSpecificData.Reserved2 - 1;
  3123. }
  3124. if (BufferLen < ulRequiredSize) {
  3125. Status = CR_BUFFER_SMALL;
  3126. goto Clean0;
  3127. }
  3128. //
  3129. // copy CM_PARTIAL_RESOURCE_DESCRIPTOR info to CS_DES format
  3130. //
  3131. pCsData->CS_Header.CSD_Flags = (DWORD)pResDes->Flags; // none defined
  3132. if (pResDes->u.DeviceSpecificData.DataSize == 0) {
  3133. //
  3134. // There is no legacy data and no class-specific data
  3135. //
  3136. pCsData->CS_Header.CSD_SignatureLength = 0;
  3137. pCsData->CS_Header.CSD_LegacyDataOffset = 0;
  3138. pCsData->CS_Header.CSD_LegacyDataSize = 0;
  3139. pCsData->CS_Header.CSD_Signature[0] = 0x0;
  3140. memset(&pCsData->CS_Header.CSD_ClassGuid, 0, sizeof(GUID));
  3141. }
  3142. else if (pResDes->u.DeviceSpecificData.Reserved2 == 0) {
  3143. //
  3144. // There is only legacy data
  3145. //
  3146. pCsData->CS_Header.CSD_SignatureLength = 0;
  3147. pCsData->CS_Header.CSD_LegacyDataOffset = 0;
  3148. pCsData->CS_Header.CSD_LegacyDataSize =
  3149. pResDes->u.DeviceSpecificData.DataSize;
  3150. pCsData->CS_Header.CSD_Signature[0] = 0x0;
  3151. memset(&pCsData->CS_Header.CSD_ClassGuid, 0, sizeof(GUID));
  3152. ptr1 = (LPBYTE)((LPBYTE)pResDes + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
  3153. memcpy(&pCsData->CS_Header.CSD_Signature, ptr1,
  3154. pResDes->u.DeviceSpecificData.DataSize);
  3155. }
  3156. else if (pResDes->u.DeviceSpecificData.Reserved1 == 0) {
  3157. //
  3158. // There is only class-specific data
  3159. //
  3160. pCsData->CS_Header.CSD_LegacyDataOffset = 0;
  3161. pCsData->CS_Header.CSD_LegacyDataSize = 0;
  3162. pCsData->CS_Header.CSD_SignatureLength =
  3163. pResDes->u.DeviceSpecificData.Reserved2;
  3164. ptr1 = (LPBYTE)((LPBYTE)pResDes + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
  3165. memcpy(pCsData->CS_Header.CSD_Signature, ptr1,
  3166. pResDes->u.DeviceSpecificData.Reserved2);
  3167. ptr1 += pResDes->u.DeviceSpecificData.Reserved2;
  3168. memcpy((LPBYTE)&pCsData->CS_Header.CSD_ClassGuid, ptr1, sizeof(GUID));
  3169. }
  3170. else {
  3171. //
  3172. // There is both legacy data and class-specific data
  3173. //
  3174. //
  3175. // copy legacy data
  3176. //
  3177. pCsData->CS_Header.CSD_LegacyDataOffset =
  3178. pResDes->u.DeviceSpecificData.Reserved2;
  3179. pCsData->CS_Header.CSD_LegacyDataSize =
  3180. pResDes->u.DeviceSpecificData.Reserved1;
  3181. ptr1 = pCsData->CS_Header.CSD_Signature +
  3182. pCsData->CS_Header.CSD_LegacyDataOffset;
  3183. ptr2 = (LPBYTE)((LPBYTE)pResDes + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
  3184. memcpy(ptr1, ptr2, pResDes->u.DeviceSpecificData.Reserved1);
  3185. //
  3186. // copy signature and class guid
  3187. //
  3188. pCsData->CS_Header.CSD_SignatureLength =
  3189. pResDes->u.DeviceSpecificData.Reserved2;
  3190. ptr2 += pResDes->u.DeviceSpecificData.Reserved1;
  3191. memcpy(pCsData->CS_Header.CSD_Signature, ptr2,
  3192. pResDes->u.DeviceSpecificData.Reserved2);
  3193. ptr2 += pResDes->u.DeviceSpecificData.Reserved2;
  3194. memcpy((LPBYTE)&pCsData->CS_Header.CSD_ClassGuid, ptr2, sizeof(GUID));
  3195. }
  3196. break;
  3197. }
  3198. default:
  3199. break;
  3200. }
  3201. Clean0:
  3202. return Status;
  3203. } // NtResourceToResDes
  3204. CONFIGRET
  3205. NtRequirementsToResDes(
  3206. IN PIO_RESOURCE_DESCRIPTOR pReqDes,
  3207. IN OUT LPBYTE Buffer,
  3208. IN ULONG BufferLen,
  3209. IN LPBYTE pLastAddr,
  3210. IN ULONG ulFlags
  3211. )
  3212. {
  3213. CONFIGRET Status = CR_SUCCESS;
  3214. ULONG ulSize = 0, count = 0, i = 0, ReqPartialCount = 0;
  3215. PIO_RESOURCE_DESCRIPTOR pCurrent = NULL;
  3216. //
  3217. // fill in resource type specific info
  3218. //
  3219. switch (pReqDes->Type) {
  3220. case CmResourceTypeMemory: {
  3221. //-------------------------------------------------------
  3222. // Memory Resource Type
  3223. //-------------------------------------------------------
  3224. //
  3225. // NOTE: pMemData->MEM_Header.MD_Reserved is not mapped
  3226. // pMemData->MEM_Data.MR_Reserved is not mapped
  3227. //
  3228. PMEM_RESOURCE pMemData = (PMEM_RESOURCE)Buffer;
  3229. //
  3230. // verify passed in buffer size
  3231. //
  3232. ReqPartialCount = RANGE_COUNT(pReqDes, pLastAddr);
  3233. if (BufferLen < sizeof(MEM_RESOURCE) +
  3234. sizeof(MEM_RANGE) * (ReqPartialCount - 1)) {
  3235. Status = CR_BUFFER_SMALL;
  3236. goto Clean0;
  3237. }
  3238. //
  3239. // copy CM_PARTIAL_RESOURCE_DESCRIPTOR info to MEM_DES format
  3240. //
  3241. pMemData->MEM_Header.MD_Count = ReqPartialCount;
  3242. pMemData->MEM_Header.MD_Type = MType_Range;
  3243. pMemData->MEM_Header.MD_Flags = 0;
  3244. pMemData->MEM_Header.MD_Reserved = 0;
  3245. pMemData->MEM_Header.MD_Alloc_Base = 0;
  3246. pMemData->MEM_Header.MD_Alloc_End = 0;
  3247. //
  3248. // copy IO_RESOURCE_DESCRIPTOR info to MEM_RANGE format
  3249. //
  3250. for (count = 0, i = 0, pCurrent = pReqDes;
  3251. count < ReqPartialCount;
  3252. count++, pCurrent++) {
  3253. if (pCurrent->Type == CmResourceTypeMemory) {
  3254. pMemData->MEM_Data[i].MR_Align = MapFromNtAlignment(pCurrent->u.Memory.Alignment);
  3255. pMemData->MEM_Data[i].MR_nBytes = pCurrent->u.Memory.Length;
  3256. pMemData->MEM_Data[i].MR_Min = MAKEDWORDLONG(
  3257. pCurrent->u.Memory.MinimumAddress.LowPart,
  3258. pCurrent->u.Memory.MinimumAddress.HighPart);
  3259. pMemData->MEM_Data[i].MR_Max = MAKEDWORDLONG(
  3260. pCurrent->u.Memory.MaximumAddress.LowPart,
  3261. pCurrent->u.Memory.MaximumAddress.HighPart);
  3262. pMemData->MEM_Data[i].MR_Flags = MapFromNtMemoryFlags(pCurrent->Flags);
  3263. //pMemData->MEM_Data[i].MR_Flags |= MapFromNtDisposition(pCurrent->ShareDisposition, 0);
  3264. pMemData->MEM_Data[i].MR_Reserved = 0;
  3265. i++;
  3266. }
  3267. }
  3268. pMemData->MEM_Header.MD_Count = i;
  3269. break;
  3270. }
  3271. case CmResourceTypePort: {
  3272. //-------------------------------------------------------
  3273. // IO Port Resource Type
  3274. //-------------------------------------------------------
  3275. PIO_RESOURCE pIoData = (PIO_RESOURCE)Buffer;
  3276. //
  3277. // verify passed in buffer size
  3278. //
  3279. ReqPartialCount = RANGE_COUNT(pReqDes, pLastAddr);
  3280. if (BufferLen < sizeof(IO_RESOURCE) +
  3281. sizeof(IO_RANGE) * (ReqPartialCount - 1)) {
  3282. Status = CR_BUFFER_SMALL;
  3283. goto Clean0;
  3284. }
  3285. //
  3286. // copy CM_PARTIAL_RESOURCE_DESCRIPTOR info to IO_DES format
  3287. //
  3288. pIoData->IO_Header.IOD_Count = ReqPartialCount;
  3289. pIoData->IO_Header.IOD_Type = IOType_Range;
  3290. pIoData->IO_Header.IOD_Alloc_Base = 0;
  3291. pIoData->IO_Header.IOD_Alloc_End = 0;
  3292. pIoData->IO_Header.IOD_DesFlags = 0;
  3293. //
  3294. // copy IO_RESOURCE_DESCRIPTOR info to IO_RANGE format
  3295. //
  3296. for (count = 0, i = 0, pCurrent = pReqDes;
  3297. count < ReqPartialCount;
  3298. count++, pCurrent++) {
  3299. if (pCurrent->Type == CmResourceTypePort) {
  3300. pIoData->IO_Data[i].IOR_Align = MapFromNtAlignment(pCurrent->u.Port.Alignment);
  3301. pIoData->IO_Data[i].IOR_nPorts = pCurrent->u.Port.Length;
  3302. pIoData->IO_Data[i].IOR_Min = MAKEDWORDLONG(
  3303. pCurrent->u.Port.MinimumAddress.LowPart,
  3304. pCurrent->u.Port.MinimumAddress.HighPart);
  3305. pIoData->IO_Data[i].IOR_Max = MAKEDWORDLONG(
  3306. pCurrent->u.Port.MaximumAddress.LowPart,
  3307. pCurrent->u.Port.MaximumAddress.HighPart);
  3308. pIoData->IO_Data[i].IOR_RangeFlags = MapFromNtPortFlags(pCurrent->Flags);
  3309. //pIoData->IO_Data[i].IOR_RangeFlags |= MapFromNtDisposition(pCurrent->ShareDisposition, 0);
  3310. pIoData->IO_Data[i].IOR_Alias = MapAliasFromNtPortFlags(pCurrent->Flags);
  3311. i++;
  3312. }
  3313. }
  3314. pIoData->IO_Header.IOD_Count = i;
  3315. break;
  3316. }
  3317. case CmResourceTypeDma: {
  3318. //-------------------------------------------------------
  3319. // DMA Resource Type
  3320. //-------------------------------------------------------
  3321. //
  3322. // Note: u.Dma.Port is not mapped
  3323. // u.Dma.Reserved is not mapped
  3324. //
  3325. PDMA_RESOURCE pDmaData = (PDMA_RESOURCE)Buffer;
  3326. //
  3327. // verify passed in buffer size
  3328. //
  3329. ReqPartialCount = RANGE_COUNT(pReqDes, pLastAddr);
  3330. if (BufferLen < sizeof(DMA_RESOURCE) +
  3331. sizeof(DMA_RANGE) * (ReqPartialCount - 1)) {
  3332. Status = CR_BUFFER_SMALL;
  3333. goto Clean0;
  3334. }
  3335. //
  3336. // copy CM_PARTIAL_RESOURCE_DESCRIPTOR info to DMA_DES format
  3337. //
  3338. pDmaData->DMA_Header.DD_Count = ReqPartialCount;
  3339. pDmaData->DMA_Header.DD_Type = DType_Range;
  3340. pDmaData->DMA_Header.DD_Flags = 0;
  3341. pDmaData->DMA_Header.DD_Alloc_Chan = 0;
  3342. //
  3343. // copy DMA_RANGE info to IO_RESOURCE_DESCRIPTOR format
  3344. //
  3345. for (count = 0, i = 0, pCurrent = pReqDes;
  3346. count < ReqPartialCount;
  3347. count++, pCurrent++) {
  3348. if (pCurrent->Type == CmResourceTypeDma) {
  3349. pDmaData->DMA_Data[i].DR_Min = pCurrent->u.Dma.MinimumChannel;
  3350. pDmaData->DMA_Data[i].DR_Max = pCurrent->u.Dma.MaximumChannel;
  3351. pDmaData->DMA_Data[i].DR_Flags = MapFromNtDmaFlags(pCurrent->Flags);
  3352. //pDmaData->DMA_Data[i].DR_Flags |= MapFromNtDisposition(pCurrent->ShareDisposition, 0);
  3353. i++;
  3354. }
  3355. }
  3356. pDmaData->DMA_Header.DD_Count = i;
  3357. break;
  3358. }
  3359. case CmResourceTypeInterrupt: {
  3360. //-------------------------------------------------------
  3361. // IRQ Resource Type
  3362. //-------------------------------------------------------
  3363. if (ulFlags & CM_RESDES_WIDTH_64) {
  3364. //
  3365. // CM_RESDES_WIDTH_64
  3366. //
  3367. PIRQ_RESOURCE_64 pIrqData = (PIRQ_RESOURCE_64)Buffer;
  3368. //
  3369. // verify passed in buffer size
  3370. //
  3371. ReqPartialCount = RANGE_COUNT(pReqDes, pLastAddr);
  3372. if (BufferLen < sizeof(IRQ_RESOURCE_64) +
  3373. sizeof(IRQ_RANGE) * (ReqPartialCount - 1)) {
  3374. Status = CR_BUFFER_SMALL;
  3375. goto Clean0;
  3376. }
  3377. //
  3378. // copy CM_PARTIAL_RESOURCE_DESCRIPTOR info to IRQ_DES format
  3379. //
  3380. pIrqData->IRQ_Header.IRQD_Count = ReqPartialCount;
  3381. pIrqData->IRQ_Header.IRQD_Type = IRQType_Range;
  3382. pIrqData->IRQ_Header.IRQD_Flags = 0;
  3383. pIrqData->IRQ_Header.IRQD_Alloc_Num = 0;
  3384. pIrqData->IRQ_Header.IRQD_Affinity = 0;
  3385. //
  3386. // copy IO_RANGE info to IO_RESOURCE_DESCRIPTOR format
  3387. //
  3388. for (count = 0, i = 0, pCurrent = pReqDes;
  3389. count < ReqPartialCount;
  3390. count++, pCurrent++) {
  3391. if (pCurrent->Type == CmResourceTypeInterrupt) {
  3392. pIrqData->IRQ_Data[i].IRQR_Min = pCurrent->u.Interrupt.MinimumVector;
  3393. pIrqData->IRQ_Data[i].IRQR_Max = pCurrent->u.Interrupt.MaximumVector;
  3394. pIrqData->IRQ_Data[i].IRQR_Flags = MapFromNtIrqFlags(pCurrent->Flags) |
  3395. MapFromNtIrqShare(pCurrent->ShareDisposition);
  3396. //pIrqData->IRQ_Data[i].IRQR_Flags |= MapFromNtDisposition(pCurrent->ShareDisposition, 1);
  3397. i++;
  3398. }
  3399. }
  3400. pIrqData->IRQ_Header.IRQD_Count = i;
  3401. } else {
  3402. //
  3403. // CM_RESDES_WIDTH_32
  3404. //
  3405. PIRQ_RESOURCE_32 pIrqData = (PIRQ_RESOURCE_32)Buffer;
  3406. //
  3407. // verify passed in buffer size
  3408. //
  3409. ReqPartialCount = RANGE_COUNT(pReqDes, pLastAddr);
  3410. if (BufferLen < sizeof(IRQ_RESOURCE_32) +
  3411. sizeof(IRQ_RANGE) * (ReqPartialCount - 1)) {
  3412. Status = CR_BUFFER_SMALL;
  3413. goto Clean0;
  3414. }
  3415. //
  3416. // copy CM_PARTIAL_RESOURCE_DESCRIPTOR info to IRQ_DES format
  3417. //
  3418. pIrqData->IRQ_Header.IRQD_Count = ReqPartialCount;
  3419. pIrqData->IRQ_Header.IRQD_Type = IRQType_Range;
  3420. pIrqData->IRQ_Header.IRQD_Flags = 0;
  3421. pIrqData->IRQ_Header.IRQD_Alloc_Num = 0;
  3422. pIrqData->IRQ_Header.IRQD_Affinity = 0;
  3423. //
  3424. // copy IO_RANGE info to IO_RESOURCE_DESCRIPTOR format
  3425. //
  3426. for (count = 0, i = 0, pCurrent = pReqDes;
  3427. count < ReqPartialCount;
  3428. count++, pCurrent++) {
  3429. if (pCurrent->Type == CmResourceTypeInterrupt) {
  3430. pIrqData->IRQ_Data[i].IRQR_Min = pCurrent->u.Interrupt.MinimumVector;
  3431. pIrqData->IRQ_Data[i].IRQR_Max = pCurrent->u.Interrupt.MaximumVector;
  3432. pIrqData->IRQ_Data[i].IRQR_Flags = MapFromNtIrqFlags(pCurrent->Flags) |
  3433. MapFromNtIrqShare(pCurrent->ShareDisposition);
  3434. //pIrqData->IRQ_Data[i].IRQR_Flags |= MapFromNtDisposition(pCurrent->ShareDisposition, 1);
  3435. i++;
  3436. }
  3437. }
  3438. pIrqData->IRQ_Header.IRQD_Count = i;
  3439. }
  3440. break;
  3441. }
  3442. case CmResourceTypeDevicePrivate: {
  3443. //-------------------------------------------------------
  3444. // Device Private Resource Type
  3445. //-------------------------------------------------------
  3446. PDEVPRIVATE_RESOURCE pPrvData = (PDEVPRIVATE_RESOURCE)Buffer;
  3447. //
  3448. // verify passed in buffer size
  3449. //
  3450. ReqPartialCount = RANGE_COUNT(pReqDes, pLastAddr);
  3451. if (BufferLen < sizeof(DEVPRIVATE_RESOURCE) +
  3452. sizeof(DEVPRIVATE_RANGE) * (ReqPartialCount - 1)) {
  3453. Status = CR_BUFFER_SMALL;
  3454. goto Clean0;
  3455. }
  3456. //
  3457. // copy CM_PARTIAL_RESOURCE_DESCRIPTOR info to MEM_DES format
  3458. //
  3459. pPrvData->PRV_Header.PD_Count = ReqPartialCount;
  3460. pPrvData->PRV_Header.PD_Type = PType_Range;
  3461. pPrvData->PRV_Header.PD_Data1 = 0;
  3462. pPrvData->PRV_Header.PD_Data2 = 0;
  3463. pPrvData->PRV_Header.PD_Data3 = 0;
  3464. pPrvData->PRV_Header.PD_Flags = 0;
  3465. //
  3466. // copy IO_RESOURCE_DESCRIPTOR info to MEM_RANGE format
  3467. //
  3468. for (i = 0, pCurrent = pReqDes;
  3469. i < ReqPartialCount;
  3470. i++, pCurrent++) {
  3471. pPrvData->PRV_Data[i].PR_Data1 = pCurrent->u.DevicePrivate.Data[0];
  3472. pPrvData->PRV_Data[i].PR_Data2 = pCurrent->u.DevicePrivate.Data[1];
  3473. pPrvData->PRV_Data[i].PR_Data3 = pCurrent->u.DevicePrivate.Data[2];
  3474. }
  3475. break;
  3476. }
  3477. case CmResourceTypeBusNumber: {
  3478. //-------------------------------------------------------
  3479. // Bus Number Resource Type
  3480. //-------------------------------------------------------
  3481. PBUSNUMBER_RESOURCE pBusData = (PBUSNUMBER_RESOURCE)Buffer;
  3482. //
  3483. // verify passed in buffer size
  3484. //
  3485. ReqPartialCount = RANGE_COUNT(pReqDes, pLastAddr);
  3486. if (BufferLen < sizeof(BUSNUMBER_RESOURCE) +
  3487. sizeof(BUSNUMBER_RANGE) * (ReqPartialCount - 1)) {
  3488. Status = CR_BUFFER_SMALL;
  3489. goto Clean0;
  3490. }
  3491. //
  3492. // copy CM_PARTIAL_RESOURCE_DESCRIPTOR info to BUSNUMBER_DES format
  3493. //
  3494. pBusData->BusNumber_Header.BUSD_Count = ReqPartialCount;
  3495. pBusData->BusNumber_Header.BUSD_Type = BusNumberType_Range;
  3496. pBusData->BusNumber_Header.BUSD_Flags = 0;
  3497. pBusData->BusNumber_Header.BUSD_Alloc_Base = 0;
  3498. pBusData->BusNumber_Header.BUSD_Alloc_End = 0;
  3499. //
  3500. // copy IO_RESOURCE_DESCRIPTOR info to MEM_RANGE format
  3501. //
  3502. for (i = 0, pCurrent = pReqDes;
  3503. i < ReqPartialCount;
  3504. i++, pCurrent++) {
  3505. pBusData->BusNumber_Data[i].BUSR_Min = pCurrent->u.BusNumber.MinBusNumber;
  3506. pBusData->BusNumber_Data[i].BUSR_Max = pCurrent->u.BusNumber.MaxBusNumber;
  3507. pBusData->BusNumber_Data[i].BUSR_nBusNumbers = pCurrent->u.BusNumber.Length;
  3508. pBusData->BusNumber_Data[i].BUSR_Flags = pCurrent->Flags;
  3509. }
  3510. break;
  3511. }
  3512. case CmResourceTypePcCardConfig: {
  3513. //-------------------------------------------------------
  3514. // PcCardConfig Resource Type
  3515. //-------------------------------------------------------
  3516. PPCCARD_RESOURCE pPcData = (PPCCARD_RESOURCE)Buffer;
  3517. ULONG index;
  3518. //
  3519. // verify passed in buffer size
  3520. //
  3521. ReqPartialCount = RANGE_COUNT(pReqDes, pLastAddr);
  3522. if (BufferLen < sizeof(PCCARD_RESOURCE)) {
  3523. Status = CR_BUFFER_SMALL;
  3524. goto Clean0;
  3525. }
  3526. //
  3527. // copy IO_RESOURCE_DESCRIPTOR info to PCCARD_DES format
  3528. //
  3529. pPcData->PcCard_Header.PCD_Reserved[0] = 0;
  3530. pPcData->PcCard_Header.PCD_Reserved[1] = 0;
  3531. pPcData->PcCard_Header.PCD_Reserved[2] = 0;
  3532. pPcData->PcCard_Header.PCD_ConfigIndex = PCMRES_GET_CONFIG_INDEX(pReqDes);
  3533. pPcData->PcCard_Header.PCD_MemoryCardBase1 = PCMRES_GET_MEMORY_CARDBASE(pReqDes, 0);
  3534. pPcData->PcCard_Header.PCD_MemoryCardBase2 = PCMRES_GET_MEMORY_CARDBASE(pReqDes, 1);
  3535. if (PCMRES_GET_IO_FLAG(pReqDes, 0, PCMRESF_IO_16BIT_ACCESS)) {
  3536. pPcData->PcCard_Header.PCD_Flags = fPCD_IO_16;
  3537. } else {
  3538. pPcData->PcCard_Header.PCD_Flags = fPCD_IO_8;
  3539. }
  3540. if (PCMRES_GET_MEMORY_FLAG(pReqDes, 0, PCMRESF_MEM_16BIT_ACCESS)) {
  3541. pPcData->PcCard_Header.PCD_Flags |= fPCD_MEM_16;
  3542. } else {
  3543. pPcData->PcCard_Header.PCD_Flags |= fPCD_MEM_8;
  3544. }
  3545. break;
  3546. }
  3547. default:
  3548. break;
  3549. }
  3550. Clean0:
  3551. return Status;
  3552. } // NtRequirementsToResDes
  3553. //-------------------------------------------------------------------
  3554. // Routines to map flags between ConfigMgr and NT types
  3555. //-------------------------------------------------------------------
  3556. USHORT MapToNtMemoryFlags(IN DWORD CmMemoryFlags)
  3557. {
  3558. USHORT NtMemoryFlags = 0x0;
  3559. if (((CmMemoryFlags & mMD_MemoryType) == fMD_ROM) &&
  3560. ((CmMemoryFlags & mMD_Readable) == fMD_ReadAllowed)) {
  3561. NtMemoryFlags |= CM_RESOURCE_MEMORY_READ_ONLY;
  3562. }
  3563. else if (((CmMemoryFlags & mMD_MemoryType) == fMD_RAM) &&
  3564. ((CmMemoryFlags & mMD_Readable) == fMD_ReadDisallowed)) {
  3565. NtMemoryFlags |= CM_RESOURCE_MEMORY_WRITE_ONLY;
  3566. }
  3567. else {
  3568. NtMemoryFlags |= CM_RESOURCE_MEMORY_READ_WRITE;
  3569. }
  3570. if ((CmMemoryFlags & mMD_32_24) == fMD_24) {
  3571. NtMemoryFlags |= CM_RESOURCE_MEMORY_24;
  3572. }
  3573. if ((CmMemoryFlags & mMD_Prefetchable) == fMD_PrefetchAllowed) {
  3574. NtMemoryFlags |= CM_RESOURCE_MEMORY_PREFETCHABLE;
  3575. }
  3576. if ((CmMemoryFlags & mMD_CombinedWrite) == fMD_CombinedWriteAllowed) {
  3577. NtMemoryFlags |= CM_RESOURCE_MEMORY_COMBINEDWRITE;
  3578. }
  3579. if ((CmMemoryFlags & mMD_Cacheable) == fMD_Cacheable) {
  3580. NtMemoryFlags |= CM_RESOURCE_MEMORY_CACHEABLE;
  3581. }
  3582. return NtMemoryFlags;
  3583. }
  3584. DWORD MapFromNtMemoryFlags(IN USHORT NtMemoryFlags)
  3585. {
  3586. DWORD CmMemoryFlags = 0x0;
  3587. if (NtMemoryFlags & CM_RESOURCE_MEMORY_READ_ONLY) {
  3588. CmMemoryFlags |= (fMD_ReadAllowed | fMD_ROM);
  3589. }
  3590. else if (NtMemoryFlags & CM_RESOURCE_MEMORY_WRITE_ONLY) {
  3591. CmMemoryFlags |= (fMD_ReadDisallowed | fMD_RAM);
  3592. }
  3593. else {
  3594. CmMemoryFlags |= (fMD_ReadAllowed | fMD_RAM);
  3595. }
  3596. if (NtMemoryFlags & CM_RESOURCE_MEMORY_PREFETCHABLE) {
  3597. CmMemoryFlags |= fMD_PrefetchAllowed;
  3598. }
  3599. if (NtMemoryFlags & CM_RESOURCE_MEMORY_COMBINEDWRITE) {
  3600. CmMemoryFlags |= fMD_CombinedWriteAllowed;
  3601. }
  3602. if (NtMemoryFlags & CM_RESOURCE_MEMORY_CACHEABLE) {
  3603. CmMemoryFlags |= fMD_Cacheable;
  3604. }
  3605. if (!(NtMemoryFlags & CM_RESOURCE_MEMORY_24)) {
  3606. CmMemoryFlags |= fMD_32;
  3607. }
  3608. return CmMemoryFlags;
  3609. }
  3610. USHORT MapToNtPortFlags(IN DWORD CmPortFlags, IN DWORD CmAlias)
  3611. {
  3612. USHORT NtFlags = 0;
  3613. if ((CmPortFlags & fIOD_PortType) == fIOD_Memory) {
  3614. NtFlags |= CM_RESOURCE_PORT_MEMORY;
  3615. } else {
  3616. NtFlags |= CM_RESOURCE_PORT_IO;
  3617. }
  3618. //
  3619. // CmAlias uses the following rule:
  3620. //
  3621. // Positive Decode = 0xFF
  3622. // 10-bit decode = 0x0004 (2 ^ 2)
  3623. // 12-bit decode = 0x0010 (2 ^ 4)
  3624. // 16-bit decode = 0x0000 (2 ^ 8 = 0x0100, but since it's a byte, use 0)
  3625. //
  3626. // if CmAlias is zero, use flags to specify decode (new method)
  3627. //
  3628. if (CmAlias == 0) {
  3629. //
  3630. // use CM_RESOURCE_PORT_xxx related flags
  3631. //
  3632. // note that we need to mirror *ALL* flags from
  3633. // CM_RESOURCE_PORT_xxxx to fIOD_xxxx
  3634. // however bits need not be same
  3635. // not doing this will cause at least resource conflicts to fail
  3636. // see also MapFromNtPortFlags
  3637. //
  3638. if (CmPortFlags & fIOD_10_BIT_DECODE) {
  3639. NtFlags |= CM_RESOURCE_PORT_10_BIT_DECODE;
  3640. }
  3641. if (CmPortFlags & fIOD_12_BIT_DECODE) {
  3642. NtFlags |= CM_RESOURCE_PORT_12_BIT_DECODE;
  3643. }
  3644. if (CmPortFlags & fIOD_16_BIT_DECODE) {
  3645. NtFlags |= CM_RESOURCE_PORT_16_BIT_DECODE;
  3646. }
  3647. if (CmPortFlags & fIOD_POSITIVE_DECODE) {
  3648. NtFlags |= CM_RESOURCE_PORT_POSITIVE_DECODE;
  3649. }
  3650. }
  3651. else if (CmAlias == IO_ALIAS_POSITIVE_DECODE) {
  3652. NtFlags |= CM_RESOURCE_PORT_POSITIVE_DECODE;
  3653. } else if (CmAlias == IO_ALIAS_10_BIT_DECODE) {
  3654. NtFlags |= CM_RESOURCE_PORT_10_BIT_DECODE;
  3655. } else if (CmAlias == IO_ALIAS_12_BIT_DECODE) {
  3656. NtFlags |= CM_RESOURCE_PORT_12_BIT_DECODE;
  3657. } else if (CmAlias == IO_ALIAS_16_BIT_DECODE) {
  3658. NtFlags |= CM_RESOURCE_PORT_16_BIT_DECODE;
  3659. }
  3660. //
  3661. // these have no mirror in cmAlias, and can be combined
  3662. //
  3663. if (CmPortFlags & fIOD_PASSIVE_DECODE) {
  3664. NtFlags |= CM_RESOURCE_PORT_PASSIVE_DECODE;
  3665. }
  3666. if (CmPortFlags & fIOD_WINDOW_DECODE) {
  3667. NtFlags |= CM_RESOURCE_PORT_WINDOW_DECODE;
  3668. }
  3669. return NtFlags;
  3670. }
  3671. DWORD MapFromNtPortFlags(IN USHORT NtPortFlags)
  3672. {
  3673. DWORD Flags = 0;
  3674. if ((NtPortFlags & (CM_RESOURCE_PORT_MEMORY|CM_RESOURCE_PORT_IO)) == CM_RESOURCE_PORT_MEMORY) {
  3675. Flags |=fIOD_Memory;
  3676. } else {
  3677. Flags |=fIOD_IO;
  3678. }
  3679. //
  3680. // note that we need to mirror *ALL* flags from
  3681. // CM_RESOURCE_PORT_xxxx to fIOD_xxxx
  3682. // however bits need not be same
  3683. // not doing this will cause at least resource conflicts to fail
  3684. // see also MapToNtPortFlags
  3685. //
  3686. if (NtPortFlags & CM_RESOURCE_PORT_10_BIT_DECODE) {
  3687. Flags |= fIOD_10_BIT_DECODE;
  3688. }
  3689. if (NtPortFlags & CM_RESOURCE_PORT_12_BIT_DECODE) {
  3690. Flags |= fIOD_12_BIT_DECODE;
  3691. }
  3692. if (NtPortFlags & CM_RESOURCE_PORT_16_BIT_DECODE) {
  3693. Flags |= fIOD_16_BIT_DECODE;
  3694. }
  3695. if (NtPortFlags & CM_RESOURCE_PORT_POSITIVE_DECODE) {
  3696. Flags |= fIOD_POSITIVE_DECODE;
  3697. }
  3698. if (NtPortFlags & CM_RESOURCE_PORT_PASSIVE_DECODE) {
  3699. Flags |= fIOD_PASSIVE_DECODE;
  3700. }
  3701. if (NtPortFlags & CM_RESOURCE_PORT_WINDOW_DECODE) {
  3702. Flags |= fIOD_WINDOW_DECODE;
  3703. }
  3704. return Flags;
  3705. }
  3706. DWORD MapAliasFromNtPortFlags(IN USHORT NtPortFlags)
  3707. {
  3708. DWORD Alias = 0;
  3709. if (NtPortFlags & CM_RESOURCE_PORT_10_BIT_DECODE) {
  3710. Alias = IO_ALIAS_10_BIT_DECODE;
  3711. } else if (NtPortFlags & CM_RESOURCE_PORT_12_BIT_DECODE) {
  3712. Alias = IO_ALIAS_12_BIT_DECODE;
  3713. } else if (NtPortFlags & CM_RESOURCE_PORT_16_BIT_DECODE) {
  3714. Alias = IO_ALIAS_16_BIT_DECODE;
  3715. } else if (NtPortFlags & CM_RESOURCE_PORT_POSITIVE_DECODE) {
  3716. Alias = IO_ALIAS_POSITIVE_DECODE;
  3717. }
  3718. return Alias;
  3719. }
  3720. ULONG MapToNtAlignment(IN DWORDLONG CmPortAlign)
  3721. {
  3722. return (ULONG)(~CmPortAlign + 1);
  3723. }
  3724. DWORDLONG MapFromNtAlignment(IN ULONG NtPortAlign)
  3725. {
  3726. return (DWORDLONG)(~((DWORDLONG)NtPortAlign - 1));
  3727. }
  3728. USHORT MapToNtDmaFlags(IN DWORD CmDmaFlags)
  3729. {
  3730. USHORT NtDmaFlags;
  3731. if ((CmDmaFlags & mDD_Width) == fDD_DWORD) {
  3732. NtDmaFlags = CM_RESOURCE_DMA_32;
  3733. } else if ((CmDmaFlags & mDD_Width) == fDD_WORD) {
  3734. NtDmaFlags = CM_RESOURCE_DMA_16;
  3735. } else if ((CmDmaFlags & mDD_Width) == fDD_BYTE_AND_WORD) {
  3736. NtDmaFlags = CM_RESOURCE_DMA_8_AND_16;
  3737. } else {
  3738. NtDmaFlags = CM_RESOURCE_DMA_8; //default
  3739. }
  3740. if ((CmDmaFlags & mDD_BusMaster) == fDD_BusMaster) {
  3741. NtDmaFlags |= CM_RESOURCE_DMA_BUS_MASTER;
  3742. }
  3743. if ((CmDmaFlags & mDD_Type) == fDD_TypeA) {
  3744. NtDmaFlags |= CM_RESOURCE_DMA_TYPE_A;
  3745. } else if ((CmDmaFlags & mDD_Type) == fDD_TypeB) {
  3746. NtDmaFlags |= CM_RESOURCE_DMA_TYPE_B;
  3747. } else if ((CmDmaFlags & mDD_Type) == fDD_TypeF) {
  3748. NtDmaFlags |= CM_RESOURCE_DMA_TYPE_F;
  3749. }
  3750. return NtDmaFlags;
  3751. }
  3752. DWORD MapFromNtDmaFlags(IN USHORT NtDmaFlags)
  3753. {
  3754. DWORD CmDmaFlags;
  3755. if (NtDmaFlags & CM_RESOURCE_DMA_32) {
  3756. CmDmaFlags = fDD_DWORD;
  3757. } else if (NtDmaFlags & CM_RESOURCE_DMA_8_AND_16) {
  3758. CmDmaFlags = fDD_BYTE_AND_WORD;
  3759. } else if (NtDmaFlags & CM_RESOURCE_DMA_16) {
  3760. CmDmaFlags = fDD_WORD;
  3761. } else {
  3762. CmDmaFlags = fDD_BYTE;
  3763. }
  3764. if (NtDmaFlags & CM_RESOURCE_DMA_BUS_MASTER) {
  3765. CmDmaFlags |= fDD_BusMaster;
  3766. }
  3767. if (NtDmaFlags & CM_RESOURCE_DMA_TYPE_A) {
  3768. CmDmaFlags |= fDD_TypeA;
  3769. } else if (NtDmaFlags & CM_RESOURCE_DMA_TYPE_B) {
  3770. CmDmaFlags |= fDD_TypeB;
  3771. } else if (NtDmaFlags & CM_RESOURCE_DMA_TYPE_F) {
  3772. CmDmaFlags |= fDD_TypeF;
  3773. }
  3774. return CmDmaFlags;
  3775. }
  3776. USHORT MapToNtIrqFlags(IN DWORD CmIrqFlags)
  3777. {
  3778. if ((CmIrqFlags & mIRQD_Edge_Level) == fIRQD_Level) {
  3779. return CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
  3780. } else {
  3781. return CM_RESOURCE_INTERRUPT_LATCHED;
  3782. }
  3783. }
  3784. DWORD MapFromNtIrqFlags(IN USHORT NtIrqFlags)
  3785. {
  3786. if (NtIrqFlags == CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE) {
  3787. return fIRQD_Level;
  3788. } else {
  3789. return fIRQD_Edge;
  3790. }
  3791. }
  3792. #if 0
  3793. UCHAR MapToNtDisposition(IN DWORD CmFlags, IN BOOL bIrq)
  3794. {
  3795. UCHAR disposition;
  3796. DWORD flag = CmFlags & mD_ShareDisposition;
  3797. if (flag == fD_ShareDeviceExclusive) {
  3798. disposition = CmResourceShareDeviceExclusive;
  3799. } else if (flag == fD_ShareDriverExclusive) {
  3800. disposition = CmResourceShareDriverExclusive;
  3801. } else if (flag == fD_ShareShared) {
  3802. disposition = CmResourceShareShared;
  3803. } else if (flag == fD_ShareUndetermined) {
  3804. //
  3805. // if undetermined, also check for the old irq specific
  3806. // share flags
  3807. //
  3808. if ((CmFlags & mIRQD_Share) == fIRQD_Share) {
  3809. disposition = CmResourceShareShared;
  3810. } else {
  3811. disposition = CmResourceShareUndetermined;
  3812. }
  3813. }
  3814. return disposition;
  3815. }
  3816. DWORD MapFromNtDisposition(IN UCHAR NtDisposition, IN BOOL bIrq)
  3817. {
  3818. DWORD flag = 0;
  3819. if (NtDisposition == CmResourceShareUndetermined) {
  3820. flag = fD_ShareUndetermined;
  3821. } else if (NtDisposition == CmResourceShareDeviceExclusive) {
  3822. flag = fD_ShareDeviceExclusive;
  3823. } else if (NtDisposition == CmResourceShareDriverExclusive) {
  3824. flag = fD_ShareDriverExclusive;
  3825. } else if (NtDisposition == CmResourceShareShared) {
  3826. flag = fD_ShareShared;
  3827. }
  3828. if (bIrq) {
  3829. //
  3830. // also set the irq specific shared/exclusive bit, this is for
  3831. // backwards compatibility, new apps should look at the new bits.
  3832. //
  3833. if (flag == fD_ShareShared) {
  3834. flag |= fIRQD_Share;
  3835. } else {
  3836. flag |= fIRQD_Exclusive;
  3837. }
  3838. }
  3839. return flag;
  3840. }
  3841. #endif
  3842. UCHAR MapToNtIrqShare(IN DWORD CmIrqFlags)
  3843. {
  3844. if ((CmIrqFlags & mIRQD_Share) == fIRQD_Exclusive) {
  3845. return CmResourceShareDeviceExclusive;
  3846. } else {
  3847. return CmResourceShareShared;
  3848. }
  3849. }
  3850. DWORD MapFromNtIrqShare(IN UCHAR NtIrqShare)
  3851. {
  3852. if (NtIrqShare == CmResourceShareDeviceExclusive) {
  3853. return fIRQD_Exclusive;
  3854. }
  3855. else if (NtIrqShare == CmResourceShareDriverExclusive) {
  3856. return fIRQD_Exclusive;
  3857. }
  3858. else return fIRQD_Share;
  3859. }
  3860. #define CM_RESOURCE_BUSNUMBER_SUBALLOCATE_FIRST_VALUE 0x0001
  3861. #define mBUSD_SubAllocFirst (0x1) // Bitmask, whether SubAlloc first value allowed
  3862. #define fBUSD_SubAllocFirst_Allowed (0x0) // Suballoc from first value
  3863. #define fBUSD_SubAllocFirst_Disallowed (0x1) // Don't suballoc from first value