Leaked source code of windows server 2003
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.

1011 lines
28 KiB

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