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.

972 lines
26 KiB

  1. /*++
  2. Copyright (c) 1995-2001 Microsoft Corporation
  3. Module Name:
  4. conflist.c
  5. Abstract:
  6. This module contains the API routines that manage conflict list reporting
  7. CM_Query_Resource_Conflict_List
  8. CM_Free_Resource_Conflict_Handle
  9. CM_Get_Resource_Conflict_Count
  10. CM_Get_Resource_Conflict_Details
  11. Author:
  12. Jamie Hunter (jamiehun) 4-14-1998
  13. Environment:
  14. User mode only.
  15. Revision History:
  16. April-14-1998 jamiehun
  17. Addition of NT extended resource-conflict functions
  18. --*/
  19. //
  20. // includes
  21. //
  22. #include "precomp.h"
  23. #include "cfgi.h"
  24. #include "setupapi.h"
  25. #include "spapip.h"
  26. typedef struct _CONFLICT_LIST_HEADER {
  27. HMACHINE Machine; // indicates relevent machine
  28. PPLUGPLAY_CONTROL_CONFLICT_LIST ConflictInfo; // data obtained via UMPNPMGR
  29. ULONG Signature; // marks this structure as a handle
  30. } CONFLICT_LIST_HEADER, *PCONFLICT_LIST_HEADER;
  31. //
  32. // Private prototypes
  33. //
  34. BOOL
  35. ValidateConfListHandle(
  36. PCONFLICT_LIST_HEADER pConfList
  37. );
  38. VOID
  39. FreeConfListHandle(
  40. PCONFLICT_LIST_HEADER pConfList
  41. );
  42. //
  43. // private prototypes from resdes.c
  44. //
  45. CONFIGRET
  46. CreateResDesHandle(
  47. PRES_DES prdResDes,
  48. DEVINST dnDevInst,
  49. ULONG ulLogType,
  50. ULONG ulLogTag,
  51. ULONG ulResType,
  52. ULONG ulResTag
  53. );
  54. BOOL
  55. ValidateResDesHandle(
  56. PPrivate_Res_Des_Handle pResDes
  57. );
  58. CONFIGRET
  59. Get32bitResDesFrom64bitResDes(
  60. IN RESOURCEID ResourceID,
  61. IN PCVOID ResData64,
  62. IN ULONG ResLen64,
  63. OUT PVOID * ResData32,
  64. OUT ULONG * ResLen32
  65. );
  66. //
  67. // private prototypes from logconf.c
  68. //
  69. CONFIGRET
  70. CreateLogConfHandle(
  71. PLOG_CONF plcLogConf,
  72. DEVINST dnDevInst,
  73. ULONG ulLogType,
  74. ULONG ulLogTag
  75. );
  76. BOOL
  77. ValidateLogConfHandle(
  78. PPrivate_Log_Conf_Handle pLogConf
  79. );
  80. //
  81. // API functions
  82. //
  83. CMAPI
  84. CONFIGRET
  85. WINAPI
  86. CM_Query_Resource_Conflict_List(
  87. OUT PCONFLICT_LIST pclConflictList,
  88. IN DEVINST dnDevInst,
  89. IN RESOURCEID ResourceID,
  90. IN PCVOID ResourceData,
  91. IN ULONG ResourceLen,
  92. IN ULONG ulFlags,
  93. IN HMACHINE hMachine
  94. )
  95. /*++
  96. Routine Description:
  97. Retrieves conflict list
  98. returns a handle for list
  99. Arguments:
  100. pclConflictList - holds returned conflict list handle
  101. dnDevInst Device we want to allocate a resource for
  102. ResourceID Type of resource, ResType_xxxx
  103. ResourceData Resource specific data
  104. ResourceLen length of ResourceData
  105. ulFlags Width of certain variable-size resource
  106. descriptor structure fields, where applicable.
  107. Currently, the following flags are defined:
  108. CM_RESDES_WIDTH_32 or
  109. CM_RESDES_WIDTH_64
  110. If no flags are specified, the width of the variable-sized
  111. resource data supplied is assumed to be that native to the
  112. platform of the caller.
  113. hMachine - optional machine to query
  114. Return Value:
  115. CM status value
  116. --*/
  117. {
  118. CONFIGRET Status = CR_SUCCESS;
  119. WCHAR DeviceID[MAX_DEVICE_ID_LEN];
  120. PVOID hStringTable = NULL;
  121. handle_t hBinding = NULL;
  122. PPLUGPLAY_CONTROL_CONFLICT_LIST pConfList1 = NULL;
  123. PPLUGPLAY_CONTROL_CONFLICT_LIST pConfList2 = NULL;
  124. PCONFLICT_LIST_HEADER pConfListHeader = NULL;
  125. ULONG ConfListSize1;
  126. ULONG ConfListSize2;
  127. ULONG ulLen = MAX_DEVICE_ID_LEN;
  128. BOOL Success;
  129. PVOID ResourceData32 = NULL;
  130. ULONG ResourceLen32 = 0;
  131. try {
  132. //
  133. // validate parameters
  134. //
  135. if (dnDevInst == 0) {
  136. Status = CR_INVALID_DEVINST;
  137. goto Clean0;
  138. }
  139. if (INVALID_FLAGS(ulFlags, CM_RESDES_WIDTH_BITS)) {
  140. Status = CR_INVALID_FLAG;
  141. goto Clean0;
  142. }
  143. if ((ulFlags & CM_RESDES_WIDTH_32) && (ulFlags & CM_RESDES_WIDTH_64)) {
  144. Status = CR_INVALID_FLAG;
  145. goto Clean0;
  146. }
  147. #ifdef _WIN64
  148. if ((ulFlags & CM_RESDES_WIDTH_BITS) == CM_RESDES_WIDTH_DEFAULT) {
  149. ulFlags |= CM_RESDES_WIDTH_64;
  150. }
  151. #endif // _WIN64
  152. if (ulFlags & CM_RESDES_WIDTH_32) {
  153. ulFlags &= ~CM_RESDES_WIDTH_BITS;
  154. }
  155. if (pclConflictList == NULL) {
  156. Status = CR_INVALID_POINTER;
  157. goto Clean0;
  158. }
  159. if (ResourceData == NULL || ResourceLen == 0) {
  160. Status = CR_INVALID_POINTER;
  161. goto Clean0;
  162. }
  163. #if 0
  164. if (ResourceID > ResType_MAX) { // ClassSpecific not allowed
  165. Status = CR_INVALID_RESOURCEID;
  166. goto Clean0;
  167. }
  168. #endif
  169. if (ResourceID == ResType_All) {
  170. Status = CR_INVALID_RESOURCEID; // can't specify All on a detect
  171. goto Clean0;
  172. }
  173. //
  174. // Initialize parameters
  175. //
  176. *pclConflictList = 0;
  177. //
  178. // setup rpc binding handle and string table handle
  179. //
  180. if (!PnPGetGlobalHandles(hMachine, &hStringTable, &hBinding)) {
  181. Status = CR_FAILURE;
  182. goto Clean0;
  183. }
  184. //
  185. // Make sure the server can support the client's 64-bit resdes request.
  186. // Only server versions 0x0501 and greater support CM_RESDES_WIDTH_64.
  187. //
  188. if (ulFlags & CM_RESDES_WIDTH_64) {
  189. if (!CM_Is_Version_Available_Ex((WORD)0x0501,
  190. hMachine)) {
  191. //
  192. // Server can only support 32-bit resdes. Have the client
  193. // convert the caller's 64-bit resdes to a 32-bit resdes for the
  194. // server.
  195. //
  196. ulFlags &= ~CM_RESDES_WIDTH_BITS;
  197. Status = Get32bitResDesFrom64bitResDes(ResourceID,ResourceData,ResourceLen,&ResourceData32,&ResourceLen32);
  198. if(Status != CR_SUCCESS) {
  199. goto Clean0;
  200. }
  201. if(ResourceData32) {
  202. ResourceData = ResourceData32;
  203. ResourceLen = ResourceLen32;
  204. }
  205. }
  206. }
  207. //
  208. // retreive device instance string that corresponds to dnDevInst
  209. //
  210. Success = pSetupStringTableStringFromIdEx(hStringTable, dnDevInst,DeviceID,&ulLen);
  211. if (Success == FALSE || INVALID_DEVINST(DeviceID)) {
  212. Status = CR_INVALID_DEVINST;
  213. goto Clean0;
  214. }
  215. pConfListHeader = (PCONFLICT_LIST_HEADER)pSetupMalloc(sizeof(CONFLICT_LIST_HEADER));
  216. if (pConfListHeader == NULL) {
  217. Status = CR_OUT_OF_MEMORY;
  218. goto Clean0;
  219. }
  220. //
  221. // estimate size required to hold one conflict
  222. //
  223. ConfListSize1 = sizeof(PLUGPLAY_CONTROL_CONFLICT_LIST)+ // header + one entry
  224. sizeof(PLUGPLAY_CONTROL_CONFLICT_STRINGS)+ // strings marker
  225. (sizeof(WCHAR)*MAX_DEVICE_ID_LEN); // enough space for one string
  226. pConfList1 = (PPLUGPLAY_CONTROL_CONFLICT_LIST)pSetupMalloc(ConfListSize1);
  227. if (pConfList1 == NULL) {
  228. Status = CR_OUT_OF_MEMORY;
  229. goto Clean0;
  230. }
  231. //
  232. // first try
  233. //
  234. RpcTryExcept {
  235. //
  236. // call rpc service entry point
  237. //
  238. Status = PNP_QueryResConfList(
  239. hBinding, // rpc binding handle
  240. DeviceID, // device id string
  241. ResourceID, // resource type
  242. (LPBYTE)ResourceData, // actual res des data
  243. ResourceLen, // size in bytes of ResourceData
  244. (LPBYTE)pConfList1, // buffer
  245. ConfListSize1, // size of buffer
  246. ulFlags); // currently zero
  247. }
  248. RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
  249. KdPrintEx((DPFLTR_PNPMGR_ID,
  250. DBGF_ERRORS,
  251. "PNP_QueryResConfList (first pass) caused an exception (%d)\n",
  252. RpcExceptionCode()));
  253. Status = MapRpcExceptionToCR(RpcExceptionCode());
  254. }
  255. RpcEndExcept
  256. if (Status != CR_SUCCESS) {
  257. goto Clean0; // quit for any error
  258. }
  259. if (pConfList1->ConflictsCounted > pConfList1->ConflictsListed) {
  260. //
  261. // need more space, multiple conflict
  262. //
  263. ConfListSize2 = pConfList1->RequiredBufferSize;
  264. pConfList2 = (PPLUGPLAY_CONTROL_CONFLICT_LIST)pSetupMalloc(ConfListSize2);
  265. if (pConfList2 != NULL) {
  266. //
  267. // Try to use this instead
  268. //
  269. RpcTryExcept {
  270. //
  271. // call rpc service entry point
  272. //
  273. Status = PNP_QueryResConfList(
  274. hBinding, // rpc binding handle
  275. DeviceID, // device id string
  276. ResourceID, // resource type
  277. (LPBYTE)ResourceData, // actual res des data
  278. ResourceLen, // size in bytes of ResourceData
  279. (LPBYTE)pConfList2, // buffer
  280. ConfListSize2, // size of buffer
  281. ulFlags); // currently zero
  282. }
  283. RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
  284. KdPrintEx((DPFLTR_PNPMGR_ID,
  285. DBGF_ERRORS,
  286. "PNP_QueryResConfList (second pass) caused an exception (%d)\n",
  287. RpcExceptionCode()));
  288. Status = MapRpcExceptionToCR(RpcExceptionCode());
  289. }
  290. RpcEndExcept
  291. if (Status != CR_SUCCESS) {
  292. //
  293. // if we got error second time, but first time success
  294. // use what we got on first attempt
  295. // (I can't see this happening, but Murphey says it can)
  296. //
  297. pSetupFree(pConfList2);
  298. Status = CR_SUCCESS;
  299. } else {
  300. //
  301. // use second attempt
  302. //
  303. pSetupFree(pConfList1);
  304. pConfList1 = pConfList2;
  305. ConfListSize1 = ConfListSize2;
  306. }
  307. //
  308. // either way, we've deleted a buffer
  309. //
  310. pConfList2 = NULL;
  311. }
  312. }
  313. if(ConfListSize1 > pConfList1->RequiredBufferSize) {
  314. //
  315. // we can release some of the buffer we requested
  316. //
  317. ConfListSize2 = pConfList1->RequiredBufferSize;
  318. pConfList2 = (PPLUGPLAY_CONTROL_CONFLICT_LIST)pSetupRealloc(pConfList1,ConfListSize2);
  319. if(pConfList2) {
  320. //
  321. // success, we managed to save space
  322. //
  323. pConfList1 = pConfList2;
  324. ConfListSize1 = ConfListSize2;
  325. pConfList2 = NULL;
  326. }
  327. }
  328. //
  329. // if we get here, we have a successfully valid handle
  330. //
  331. pConfListHeader->Signature = CM_PRIVATE_CONFLIST_SIGNATURE;
  332. pConfListHeader->Machine = hMachine;
  333. pConfListHeader->ConflictInfo = pConfList1;
  334. *pclConflictList = (ULONG_PTR)pConfListHeader;
  335. pConfList1 = NULL;
  336. pConfListHeader = NULL;
  337. Clean0:
  338. NOTHING;
  339. } except(EXCEPTION_EXECUTE_HANDLER) {
  340. Status = CR_FAILURE;
  341. }
  342. //
  343. // cleanup
  344. //
  345. if (pConfListHeader != NULL) {
  346. pSetupFree(pConfListHeader);
  347. }
  348. if (pConfList1 != NULL) {
  349. pSetupFree(pConfList1);
  350. }
  351. if (pConfList2 != NULL) {
  352. pSetupFree(pConfList2);
  353. }
  354. if (ResourceData32) {
  355. pSetupFree(ResourceData32);
  356. }
  357. return Status;
  358. } // CM_Query_Resource_Conflict_List
  359. CMAPI
  360. CONFIGRET
  361. WINAPI
  362. CM_Free_Resource_Conflict_Handle(
  363. IN CONFLICT_LIST clConflictList
  364. )
  365. /*++
  366. Routine Description:
  367. Free's a conflict-list handle
  368. Arguments:
  369. clConflictList - handle of conflict list to free
  370. Return Value:
  371. CM status value
  372. --*/
  373. {
  374. CONFIGRET Status = CR_SUCCESS;
  375. PCONFLICT_LIST_HEADER pConfList = NULL;
  376. try {
  377. //
  378. // Validate parameters
  379. //
  380. pConfList = (PCONFLICT_LIST_HEADER)clConflictList;
  381. if (!ValidateConfListHandle(pConfList)) {
  382. Status = CR_INVALID_CONFLICT_LIST;
  383. goto Clean0;
  384. }
  385. FreeConfListHandle(pConfList);
  386. Clean0:
  387. NOTHING;
  388. } except(EXCEPTION_EXECUTE_HANDLER) {
  389. Status = CR_FAILURE;
  390. }
  391. return Status;
  392. }
  393. CMAPI
  394. CONFIGRET
  395. WINAPI
  396. CM_Get_Resource_Conflict_Count(
  397. IN CONFLICT_LIST clConflictList,
  398. OUT PULONG pulCount
  399. )
  400. /*++
  401. Routine Description:
  402. Retrieves number of conflicts from list
  403. Arguments:
  404. clConflictList - handle of conflict list
  405. pulCount - filled with number of conflicts (0 if no conflicts)
  406. Return Value:
  407. CM status value
  408. --*/
  409. {
  410. CONFIGRET Status = CR_SUCCESS;
  411. PCONFLICT_LIST_HEADER pConfList;
  412. try {
  413. //
  414. // Validate parameters
  415. //
  416. pConfList = (PCONFLICT_LIST_HEADER)clConflictList;
  417. if (!ValidateConfListHandle(pConfList)) {
  418. Status = CR_INVALID_CONFLICT_LIST;
  419. goto Clean0;
  420. }
  421. if (pulCount == NULL) {
  422. Status = CR_INVALID_POINTER;
  423. goto Clean0;
  424. }
  425. //
  426. // return count parameter
  427. // that can be used to iterate conflicts
  428. //
  429. *pulCount = pConfList->ConflictInfo->ConflictsListed;
  430. Clean0:
  431. NOTHING;
  432. } except(EXCEPTION_EXECUTE_HANDLER) {
  433. Status = CR_FAILURE;
  434. }
  435. return Status;
  436. } // CM_Free_Resource_Conflict_Handle
  437. CMAPI
  438. CONFIGRET
  439. WINAPI
  440. CM_Get_Resource_Conflict_DetailsW(
  441. IN CONFLICT_LIST clConflictList,
  442. IN ULONG ulIndex,
  443. IN OUT PCONFLICT_DETAILS_W pConflictDetails
  444. )
  445. /*++
  446. Routine Description:
  447. Retrieves conflict details
  448. for a specific conflict
  449. Arguments:
  450. clConflictList - handle of conflict list
  451. ulIndex - index of conflict to query, 0 to count-1
  452. where count is obtained from CM_Get_Resource_Conflict_Count
  453. pConflictDetails - structure to be filled with conflict details
  454. must have CD_ulSize & CD_ulFlags initialized before calling function
  455. eg: pConflictDetails->CD_ulSize = sizeof(CONFLICT_DETAILS)
  456. pConflictDetails->CD_ulFlags = CM_CDMASK_ALL
  457. Return Value:
  458. CM status value
  459. --*/
  460. {
  461. CONFIGRET Status = CR_SUCCESS;
  462. PCONFLICT_LIST_HEADER pConfList;
  463. PPLUGPLAY_CONTROL_CONFLICT_ENTRY pConfEntry;
  464. PWCHAR pString;
  465. ULONG ulFlags;
  466. PPLUGPLAY_CONTROL_CONFLICT_STRINGS ConfStrings;
  467. PVOID hStringTable = NULL;
  468. handle_t hBinding = NULL;
  469. HMACHINE hMachine = NULL;
  470. DEVINST dnDevInst;
  471. ULONG ulSize;
  472. try {
  473. //
  474. // Validate parameters
  475. //
  476. pConfList = (PCONFLICT_LIST_HEADER)clConflictList;
  477. if (!ValidateConfListHandle(pConfList)) {
  478. Status = CR_INVALID_CONFLICT_LIST;
  479. goto Clean0;
  480. }
  481. if (pConflictDetails == NULL) {
  482. Status = CR_INVALID_POINTER;
  483. goto Clean0;
  484. }
  485. if(pConflictDetails->CD_ulSize != sizeof(CONFLICT_DETAILS_W)) {
  486. //
  487. // currently only one structure size supported
  488. //
  489. Status = CR_INVALID_STRUCTURE_SIZE;
  490. goto Clean0;
  491. }
  492. if (INVALID_FLAGS(pConflictDetails->CD_ulMask, CM_CDMASK_VALID)) {
  493. //
  494. // CM_CDMASK_VALID describes the bits that are supported
  495. //
  496. Status = CR_INVALID_FLAG;
  497. goto Clean0;
  498. }
  499. if (pConflictDetails->CD_ulMask == 0) {
  500. //
  501. // must want something
  502. //
  503. Status = CR_INVALID_FLAG;
  504. goto Clean0;
  505. }
  506. if(ulIndex >= pConfList->ConflictInfo->ConflictsListed) {
  507. //
  508. // validate index
  509. //
  510. Status = CR_INVALID_INDEX;
  511. goto Clean0;
  512. }
  513. hMachine = (HMACHINE)(pConfList->Machine);
  514. if (!PnPGetGlobalHandles(hMachine, &hStringTable, &hBinding)) {
  515. //
  516. // handles
  517. //
  518. Status = CR_FAILURE;
  519. goto Clean0;
  520. }
  521. ConfStrings = (PPLUGPLAY_CONTROL_CONFLICT_STRINGS)&(pConfList->ConflictInfo->ConflictEntry[pConfList->ConflictInfo->ConflictsListed]);
  522. pConfEntry = pConfList->ConflictInfo->ConflictEntry + ulIndex;
  523. pString = ConfStrings->DeviceInstanceStrings + pConfEntry->DeviceInstance; // the string for this entry
  524. //
  525. // init requested parameters
  526. //
  527. ulFlags = pConflictDetails->CD_ulMask;
  528. pConflictDetails->CD_ulMask = 0;
  529. if (IS_FLAG_SET(ulFlags , CM_CDMASK_DEVINST)) {
  530. pConflictDetails->CD_dnDevInst = 0;
  531. }
  532. if (IS_FLAG_SET(ulFlags , CM_CDMASK_RESDES)) {
  533. pConflictDetails->CD_rdResDes = 0;
  534. }
  535. if (IS_FLAG_SET(ulFlags , CM_CDMASK_FLAGS)) {
  536. pConflictDetails->CD_ulFlags = 0;
  537. }
  538. if (IS_FLAG_SET(ulFlags , CM_CDMASK_DESCRIPTION)) {
  539. pConflictDetails->CD_szDescription[0] = 0;
  540. }
  541. //
  542. // fill in requested parameters
  543. //
  544. if (IS_FLAG_SET(ulFlags , CM_CDMASK_DEVINST)) {
  545. if (pString[0] == 0 || IS_FLAG_SET(pConfEntry->DeviceFlags,PNP_CE_LEGACY_DRIVER)) {
  546. //
  547. // not a valid dev-instance
  548. //
  549. dnDevInst = -1;
  550. } else {
  551. //
  552. // lookup DeviceID
  553. //
  554. ASSERT(pString && *pString && IsLegalDeviceId(pString));
  555. dnDevInst = (DEVINST)pSetupStringTableAddString(hStringTable,
  556. pString,
  557. STRTAB_CASE_SENSITIVE);
  558. if (dnDevInst == (DEVINST)(-1)) {
  559. Status = CR_OUT_OF_MEMORY; // probably out of memory
  560. goto Clean0;
  561. }
  562. }
  563. pConflictDetails->CD_dnDevInst = dnDevInst;
  564. pConflictDetails->CD_ulMask |= CM_CDMASK_DEVINST;
  565. }
  566. if (IS_FLAG_SET(ulFlags , CM_CDMASK_RESDES)) {
  567. //
  568. // not implemented yet
  569. //
  570. pConflictDetails->CD_rdResDes = 0;
  571. }
  572. if (IS_FLAG_SET(ulFlags , CM_CDMASK_FLAGS)) {
  573. //
  574. // convert flags
  575. //
  576. pConflictDetails->CD_ulFlags = 0;
  577. if(IS_FLAG_SET(pConfEntry->DeviceFlags,PNP_CE_LEGACY_DRIVER)) {
  578. //
  579. // description describes a driver, not a device
  580. //
  581. pConflictDetails->CD_ulFlags |= CM_CDFLAGS_DRIVER;
  582. }
  583. if(IS_FLAG_SET(pConfEntry->DeviceFlags,PNP_CE_ROOT_OWNED)) {
  584. //
  585. // resource is owned by root device
  586. //
  587. pConflictDetails->CD_ulFlags |= CM_CDFLAGS_ROOT_OWNED;
  588. }
  589. if(IS_FLAG_SET(pConfEntry->DeviceFlags,PNP_CE_TRANSLATE_FAILED) || IS_FLAG_SET(pConfEntry->DeviceFlags,PNP_CE_ROOT_OWNED)) {
  590. //
  591. // resource cannot be allocated, but no descriptive text
  592. //
  593. pConflictDetails->CD_ulFlags |= CM_CDFLAGS_RESERVED;
  594. }
  595. }
  596. if (IS_FLAG_SET(ulFlags , CM_CDMASK_DESCRIPTION)) {
  597. if (pString[0] == 0 || IS_FLAG_SET(pConfEntry->DeviceFlags,PNP_CE_LEGACY_DRIVER)) {
  598. //
  599. // copy string directly, specifies legacy driver (or nothing for unavailable)
  600. //
  601. lstrcpynW(pConflictDetails->CD_szDescription,pString,MAX_PATH);
  602. } else {
  603. //
  604. // copy a descriptive name for P&P device
  605. //
  606. ASSERT(pString && *pString && IsLegalDeviceId(pString));
  607. dnDevInst = (DEVINST)pSetupStringTableAddString(hStringTable,
  608. pString,
  609. STRTAB_CASE_SENSITIVE);
  610. if (dnDevInst == (DEVINST)(-1)) {
  611. Status = CR_OUT_OF_MEMORY; // probably out of memory
  612. goto Clean0;
  613. }
  614. ulSize = sizeof(pConflictDetails->CD_szDescription);
  615. if (CM_Get_DevNode_Registry_Property_ExW(dnDevInst,
  616. CM_DRP_FRIENDLYNAME,
  617. NULL, (LPBYTE)(pConflictDetails->CD_szDescription),
  618. &ulSize, 0,hMachine) != CR_SUCCESS) {
  619. ulSize = sizeof(pConflictDetails->CD_szDescription);
  620. if (CM_Get_DevNode_Registry_Property_ExW(dnDevInst,
  621. CM_DRP_DEVICEDESC,
  622. NULL, (LPBYTE)(pConflictDetails->CD_szDescription),
  623. &ulSize, 0,hMachine) != CR_SUCCESS) {
  624. //
  625. // unknown
  626. //
  627. pConflictDetails->CD_szDescription[0] = 0;
  628. }
  629. }
  630. }
  631. pConflictDetails->CD_ulMask |= CM_CDMASK_DESCRIPTION;
  632. }
  633. Clean0:
  634. NOTHING;
  635. } except(EXCEPTION_EXECUTE_HANDLER) {
  636. Status = CR_FAILURE;
  637. }
  638. return Status;
  639. } // CM_Get_Resource_Conflict_DetailsW
  640. BOOL
  641. ValidateConfListHandle(
  642. PCONFLICT_LIST_HEADER pConfList
  643. )
  644. /*++
  645. Routine Description:
  646. Validates a conflict-list handle
  647. pConfList must not be null, and must
  648. contain a valid signature
  649. Arguments:
  650. pConfList - handle to conflict list
  651. Return Value:
  652. TRUE if valid, FALSE if not valid
  653. --*/
  654. {
  655. //
  656. // validate parameters
  657. //
  658. if (pConfList == NULL) {
  659. return FALSE;
  660. }
  661. //
  662. // check for the private conflict list signature
  663. //
  664. if (pConfList->Signature != CM_PRIVATE_CONFLIST_SIGNATURE) {
  665. return FALSE;
  666. }
  667. return TRUE;
  668. } // ValidateConfListHandle
  669. VOID
  670. FreeConfListHandle(
  671. PCONFLICT_LIST_HEADER pConfList
  672. )
  673. /*++
  674. Routine Description:
  675. Releases memory allocated for Conflict List
  676. Makes sure Signature is invalid
  677. Arguments:
  678. pConfList - valid handle to conflict list
  679. Return Value:
  680. none
  681. --*/
  682. {
  683. if(pConfList != NULL) {
  684. pConfList->Signature = 0;
  685. if(pConfList->ConflictInfo) {
  686. pSetupFree(pConfList->ConflictInfo);
  687. }
  688. pSetupFree(pConfList);
  689. }
  690. return;
  691. } // FreeConfListHandle
  692. //-------------------------------------------------------------------
  693. // ANSI STUBS
  694. //-------------------------------------------------------------------
  695. CMAPI
  696. CONFIGRET
  697. WINAPI
  698. CM_Get_Resource_Conflict_DetailsA(
  699. IN CONFLICT_LIST clConflictList,
  700. IN ULONG ulIndex,
  701. IN OUT PCONFLICT_DETAILS_A pConflictDetails
  702. )
  703. /*++
  704. Routine Description:
  705. Ansi version of CM_Get_Resource_Conflict_DetailsW
  706. --*/
  707. {
  708. CONFLICT_DETAILS_W detailsW;
  709. CONFIGRET Status = CR_SUCCESS;
  710. ULONG ulAnsiLength;
  711. try {
  712. //
  713. // Validate parameters we need for Ansi part
  714. // further validation occurs in Wide-char part
  715. //
  716. if (pConflictDetails == NULL) {
  717. Status = CR_INVALID_POINTER;
  718. goto Clean0;
  719. }
  720. if(pConflictDetails->CD_ulSize != sizeof(CONFLICT_DETAILS_A)) {
  721. //
  722. // currently only one structure size supported
  723. //
  724. Status = CR_INVALID_STRUCTURE_SIZE;
  725. goto Clean0;
  726. }
  727. if (INVALID_FLAGS(pConflictDetails->CD_ulMask, CM_CDMASK_VALID)) {
  728. //
  729. // CM_CDMASK_VALID describes the bits that are supported
  730. //
  731. Status = CR_INVALID_FLAG;
  732. goto Clean0;
  733. }
  734. if (pConflictDetails->CD_ulMask == 0) {
  735. //
  736. // must want something
  737. //
  738. Status = CR_INVALID_FLAG;
  739. goto Clean0;
  740. }
  741. ZeroMemory(&detailsW,sizeof(detailsW));
  742. detailsW.CD_ulSize = sizeof(detailsW);
  743. detailsW.CD_ulMask = pConflictDetails->CD_ulMask;
  744. Status = CM_Get_Resource_Conflict_DetailsW(clConflictList,ulIndex,&detailsW);
  745. if (Status != CR_SUCCESS) {
  746. goto Clean0;
  747. }
  748. //
  749. // copy details
  750. //
  751. pConflictDetails->CD_ulMask = detailsW.CD_ulMask;
  752. if (IS_FLAG_SET(detailsW.CD_ulMask , CM_CDMASK_DEVINST)) {
  753. pConflictDetails->CD_dnDevInst = detailsW.CD_dnDevInst;
  754. }
  755. if (IS_FLAG_SET(detailsW.CD_ulMask , CM_CDMASK_RESDES)) {
  756. pConflictDetails->CD_rdResDes = detailsW.CD_rdResDes;
  757. }
  758. if (IS_FLAG_SET(detailsW.CD_ulMask , CM_CDMASK_FLAGS)) {
  759. pConflictDetails->CD_ulFlags = detailsW.CD_ulFlags;
  760. }
  761. if (IS_FLAG_SET(detailsW.CD_ulMask , CM_CDMASK_DESCRIPTION)) {
  762. pConflictDetails->CD_szDescription[0] = 0;
  763. //
  764. // need to convery from UNICODE to ANSI
  765. //
  766. ulAnsiLength = MAX_PATH;
  767. Status = PnPUnicodeToMultiByte(detailsW.CD_szDescription,
  768. MAX_PATH*sizeof(WCHAR),
  769. pConflictDetails->CD_szDescription,
  770. &ulAnsiLength);
  771. if (Status != CR_SUCCESS) {
  772. //
  773. // error occurred
  774. //
  775. Status = CR_FAILURE;
  776. }
  777. }
  778. Clean0:
  779. NOTHING;
  780. } except(EXCEPTION_EXECUTE_HANDLER) {
  781. Status = CR_FAILURE;
  782. }
  783. return Status;
  784. } // CM_Get_Resource_Conflict_DetailsA