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.

703 lines
17 KiB

  1. /*****************************************************************************
  2. * resource.cpp - resource list object implementation
  3. *****************************************************************************
  4. * Copyright (c) 1997-2000 Microsoft Corporation. All rights reserved.
  5. */
  6. #include "private.h"
  7. /*****************************************************************************
  8. * Factory.
  9. */
  10. #pragma code_seg("PAGE")
  11. /*****************************************************************************
  12. * CreateResourceList()
  13. *****************************************************************************
  14. * Creates a resource list object.
  15. */
  16. NTSTATUS
  17. CreateResourceList
  18. (
  19. OUT PUNKNOWN * Unknown,
  20. IN REFCLSID,
  21. IN PUNKNOWN UnknownOuter OPTIONAL,
  22. IN POOL_TYPE PoolType
  23. )
  24. {
  25. PAGED_CODE();
  26. ASSERT(Unknown);
  27. _DbgPrintF(DEBUGLVL_LIFETIME,("Creating RESOURCELIST"));
  28. STD_CREATE_BODY
  29. (
  30. CResourceList,
  31. Unknown,
  32. UnknownOuter,
  33. PoolType
  34. );
  35. }
  36. /*****************************************************************************
  37. * PcNewResourceList()
  38. *****************************************************************************
  39. * Creates and initializes a resource list.
  40. * Creates an empty resource list if both of the PCM_RESOURCE_LIST parameters
  41. * are NULL.
  42. */
  43. PORTCLASSAPI
  44. NTSTATUS
  45. NTAPI
  46. PcNewResourceList
  47. (
  48. OUT PRESOURCELIST * OutResourceList,
  49. IN PUNKNOWN OuterUnknown OPTIONAL,
  50. IN POOL_TYPE PoolType,
  51. IN PCM_RESOURCE_LIST TranslatedResources,
  52. IN PCM_RESOURCE_LIST UntranslatedResources
  53. )
  54. {
  55. PAGED_CODE();
  56. ASSERT(OutResourceList);
  57. //
  58. // Validate Parameters.
  59. //
  60. if (NULL == OutResourceList)
  61. {
  62. _DbgPrintF(DEBUGLVL_TERSE, ("PcNewResourceList : Invalid Parameter"));
  63. return STATUS_INVALID_PARAMETER;
  64. }
  65. PUNKNOWN unknown;
  66. NTSTATUS ntStatus =
  67. CreateResourceList
  68. (
  69. &unknown,
  70. GUID_NULL,
  71. OuterUnknown,
  72. PoolType
  73. );
  74. if (NT_SUCCESS(ntStatus))
  75. {
  76. PRESOURCELISTINIT resourceList;
  77. ntStatus =
  78. unknown->QueryInterface
  79. (
  80. IID_IResourceList,
  81. (PVOID *) &resourceList
  82. );
  83. if (NT_SUCCESS(ntStatus))
  84. {
  85. ntStatus =
  86. resourceList->Init
  87. (
  88. TranslatedResources,
  89. UntranslatedResources,
  90. PoolType
  91. );
  92. if (NT_SUCCESS(ntStatus))
  93. {
  94. *OutResourceList = resourceList;
  95. }
  96. else
  97. {
  98. resourceList->Release();
  99. }
  100. }
  101. unknown->Release();
  102. }
  103. return ntStatus;
  104. }
  105. /*****************************************************************************
  106. * PcNewResourceSublist()
  107. *****************************************************************************
  108. * Creates and initializes an empty resource list derived from another
  109. * resource list.
  110. */
  111. PORTCLASSAPI
  112. NTSTATUS
  113. NTAPI
  114. PcNewResourceSublist
  115. (
  116. OUT PRESOURCELIST * OutResourceList,
  117. IN PUNKNOWN OuterUnknown OPTIONAL,
  118. IN POOL_TYPE PoolType,
  119. IN PRESOURCELIST ParentList,
  120. IN ULONG MaximumEntries
  121. )
  122. {
  123. PAGED_CODE();
  124. ASSERT(OutResourceList);
  125. ASSERT(ParentList);
  126. ASSERT(MaximumEntries);
  127. //
  128. // Validate Parameters.
  129. //
  130. if (NULL == OutResourceList ||
  131. NULL == ParentList ||
  132. 0 == MaximumEntries)
  133. {
  134. _DbgPrintF(DEBUGLVL_TERSE, ("PcNewResourceSubList : Invalid Parameter"));
  135. return STATUS_INVALID_PARAMETER;
  136. }
  137. PUNKNOWN unknown;
  138. NTSTATUS ntStatus =
  139. CreateResourceList
  140. (
  141. &unknown,
  142. GUID_NULL,
  143. OuterUnknown,
  144. PoolType
  145. );
  146. if (NT_SUCCESS(ntStatus))
  147. {
  148. PRESOURCELISTINIT resourceList;
  149. ntStatus =
  150. unknown->QueryInterface
  151. (
  152. IID_IResourceList,
  153. (PVOID *) &resourceList
  154. );
  155. if (NT_SUCCESS(ntStatus))
  156. {
  157. ntStatus =
  158. resourceList->InitFromParent
  159. (
  160. ParentList,
  161. MaximumEntries,
  162. PoolType
  163. );
  164. if (NT_SUCCESS(ntStatus))
  165. {
  166. *OutResourceList = resourceList;
  167. }
  168. else
  169. {
  170. resourceList->Release();
  171. }
  172. }
  173. unknown->Release();
  174. }
  175. return ntStatus;
  176. }
  177. /*****************************************************************************
  178. * Member functions.
  179. */
  180. /*****************************************************************************
  181. * CResourceList::~CResourceList()
  182. *****************************************************************************
  183. * Destructor.
  184. */
  185. CResourceList::
  186. ~CResourceList
  187. ( void
  188. )
  189. {
  190. PAGED_CODE();
  191. _DbgPrintF(DEBUGLVL_LIFETIME,("Destroying RESOURCELIST (0x%08x)",this));
  192. if (Translated)
  193. {
  194. ExFreePool(Translated);
  195. }
  196. if (Untranslated)
  197. {
  198. ExFreePool(Untranslated);
  199. }
  200. }
  201. /*****************************************************************************
  202. * CResourceList::NonDelegatingQueryInterface()
  203. *****************************************************************************
  204. * Obtains an interface.
  205. */
  206. STDMETHODIMP_(NTSTATUS)
  207. CResourceList::
  208. NonDelegatingQueryInterface
  209. (
  210. REFIID Interface,
  211. PVOID * Object
  212. )
  213. {
  214. PAGED_CODE();
  215. ASSERT(Object);
  216. if (IsEqualGUIDAligned(Interface,IID_IUnknown))
  217. {
  218. *Object = PVOID(PUNKNOWN(this));
  219. }
  220. else
  221. if (IsEqualGUIDAligned(Interface,IID_IResourceList))
  222. {
  223. *Object = PVOID(PRESOURCELISTINIT(this));
  224. }
  225. else
  226. {
  227. *Object = NULL;
  228. }
  229. if (*Object)
  230. {
  231. PUNKNOWN(*Object)->AddRef();
  232. return STATUS_SUCCESS;
  233. }
  234. return STATUS_INVALID_PARAMETER;
  235. }
  236. /*****************************************************************************
  237. * CResourceList::Init()
  238. *****************************************************************************
  239. * Initializes the object.
  240. */
  241. STDMETHODIMP_(NTSTATUS)
  242. CResourceList::
  243. Init
  244. (
  245. IN PCM_RESOURCE_LIST TranslatedResources,
  246. IN PCM_RESOURCE_LIST UntranslatedResources,
  247. IN POOL_TYPE PoolType
  248. )
  249. {
  250. PAGED_CODE();
  251. _DbgPrintF(DEBUGLVL_LIFETIME,("Initializing RESOURCELIST (0x%08x)",this));
  252. // check NULL resource lists.
  253. if (!TranslatedResources && !UntranslatedResources)
  254. {
  255. EntriesAllocated = EntriesInUse = 0;
  256. Translated = Untranslated = NULL;
  257. return STATUS_SUCCESS;
  258. }
  259. // this check fails if _one_ of the resource lists is NULL, which should
  260. // never happen.
  261. ASSERT (TranslatedResources);
  262. ASSERT (UntranslatedResources);
  263. if (!TranslatedResources || !UntranslatedResources)
  264. {
  265. return STATUS_INVALID_PARAMETER;
  266. }
  267. EntriesAllocated =
  268. EntriesInUse =
  269. UntranslatedResources->List[0].PartialResourceList.Count;
  270. ULONG listSize =
  271. ( sizeof(CM_RESOURCE_LIST)
  272. + ( (EntriesInUse - 1)
  273. * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)
  274. )
  275. );
  276. NTSTATUS ntStatus = STATUS_SUCCESS;
  277. Translated = PCM_RESOURCE_LIST(ExAllocatePoolWithTag(PoolType,listSize,'lRcP'));
  278. if (Translated)
  279. {
  280. Untranslated =
  281. PCM_RESOURCE_LIST(ExAllocatePoolWithTag(PoolType,listSize,'lRcP'));
  282. if (Untranslated)
  283. {
  284. RtlCopyMemory(Untranslated,UntranslatedResources,listSize);
  285. RtlCopyMemory(Translated,TranslatedResources,listSize);
  286. }
  287. else
  288. {
  289. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  290. ExFreePool(Translated);
  291. Translated = NULL;
  292. }
  293. }
  294. else
  295. {
  296. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  297. }
  298. return ntStatus;
  299. }
  300. /*****************************************************************************
  301. * CResourceList::InitFromParent()
  302. *****************************************************************************
  303. * Initializes the object from a parent object.
  304. */
  305. STDMETHODIMP_(NTSTATUS)
  306. CResourceList::
  307. InitFromParent
  308. (
  309. IN PRESOURCELIST ParentList,
  310. IN ULONG MaximumEntries,
  311. IN POOL_TYPE PoolType
  312. )
  313. {
  314. PAGED_CODE();
  315. ASSERT(ParentList);
  316. ASSERT(MaximumEntries);
  317. ULONG listSize =
  318. ( sizeof(CM_RESOURCE_LIST)
  319. + ( ( MaximumEntries
  320. - 1
  321. )
  322. * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)
  323. )
  324. );
  325. NTSTATUS ntStatus = STATUS_SUCCESS;
  326. Translated = PCM_RESOURCE_LIST(ExAllocatePoolWithTag(PoolType,listSize,'lRcP'));
  327. if (Translated)
  328. {
  329. Untranslated = PCM_RESOURCE_LIST(ExAllocatePoolWithTag(PoolType,listSize,'lRcP'));
  330. if (Untranslated)
  331. {
  332. RtlZeroMemory(Translated,listSize);
  333. RtlZeroMemory(Untranslated,listSize);
  334. // Copy headers from the parent.
  335. RtlCopyMemory
  336. (
  337. Translated,
  338. ParentList->TranslatedList(),
  339. ( sizeof(CM_RESOURCE_LIST)
  340. - sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)
  341. )
  342. );
  343. RtlCopyMemory
  344. (
  345. Untranslated,
  346. ParentList->UntranslatedList(),
  347. ( sizeof(CM_RESOURCE_LIST)
  348. - sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)
  349. )
  350. );
  351. EntriesAllocated = MaximumEntries;
  352. EntriesInUse = 0;
  353. Translated->List[0].PartialResourceList.Count = EntriesInUse;
  354. Untranslated->List[0].PartialResourceList.Count = EntriesInUse;
  355. }
  356. else
  357. {
  358. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  359. ExFreePool(Translated);
  360. Translated = NULL;
  361. }
  362. }
  363. else
  364. {
  365. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  366. }
  367. return ntStatus;
  368. }
  369. /*****************************************************************************
  370. * CResourceList::NumberOfEntries()
  371. *****************************************************************************
  372. * Determine the number of entries in the list.
  373. */
  374. STDMETHODIMP_(ULONG)
  375. CResourceList::
  376. NumberOfEntries
  377. ( void
  378. )
  379. {
  380. PAGED_CODE();
  381. return EntriesInUse;
  382. }
  383. /*****************************************************************************
  384. * CResourceList::NumberOfEntriesOfType()
  385. *****************************************************************************
  386. * Determines the number of entries of a given type in the list.
  387. */
  388. STDMETHODIMP_(ULONG)
  389. CResourceList::
  390. NumberOfEntriesOfType
  391. (
  392. IN CM_RESOURCE_TYPE Type
  393. )
  394. {
  395. PAGED_CODE();
  396. if (!Untranslated) {
  397. return 0;
  398. }
  399. PCM_PARTIAL_RESOURCE_DESCRIPTOR descriptor =
  400. Untranslated->List[0].PartialResourceList.PartialDescriptors;
  401. ULONG entriesOfType = 0;
  402. for
  403. ( ULONG count = EntriesInUse;
  404. count--;
  405. descriptor++
  406. )
  407. {
  408. if (descriptor->Type == Type)
  409. {
  410. entriesOfType++;
  411. }
  412. }
  413. return entriesOfType;
  414. }
  415. /*****************************************************************************
  416. * CResourceList::FindTranslatedEntry()
  417. *****************************************************************************
  418. * Finds a translated entry.
  419. */
  420. STDMETHODIMP_(PCM_PARTIAL_RESOURCE_DESCRIPTOR)
  421. CResourceList::
  422. FindTranslatedEntry
  423. (
  424. IN CM_RESOURCE_TYPE Type,
  425. IN ULONG Index
  426. )
  427. {
  428. PAGED_CODE();
  429. if (!Translated) {
  430. return 0;
  431. }
  432. PCM_PARTIAL_RESOURCE_DESCRIPTOR descriptor =
  433. Translated->List[0].PartialResourceList.PartialDescriptors;
  434. ULONG count = EntriesInUse;
  435. if (count)
  436. {
  437. while (descriptor)
  438. {
  439. if (count-- == 0)
  440. {
  441. descriptor = NULL;
  442. }
  443. else
  444. {
  445. if (descriptor->Type == Type)
  446. {
  447. if (Index-- == 0)
  448. {
  449. break;
  450. }
  451. }
  452. descriptor++;
  453. }
  454. }
  455. }
  456. return descriptor;
  457. }
  458. /*****************************************************************************
  459. * CResourceList::FindUntranslatedEntry()
  460. *****************************************************************************
  461. * Finds an untranslated entry.
  462. */
  463. STDMETHODIMP_(PCM_PARTIAL_RESOURCE_DESCRIPTOR)
  464. CResourceList::
  465. FindUntranslatedEntry
  466. (
  467. IN CM_RESOURCE_TYPE Type,
  468. IN ULONG Index
  469. )
  470. {
  471. PAGED_CODE();
  472. if (!Untranslated) {
  473. return 0;
  474. }
  475. PCM_PARTIAL_RESOURCE_DESCRIPTOR descriptor =
  476. Untranslated->List[0].PartialResourceList.PartialDescriptors;
  477. ULONG count = EntriesInUse;
  478. if (count)
  479. {
  480. while (descriptor)
  481. {
  482. if (count-- == 0)
  483. {
  484. descriptor = NULL;
  485. }
  486. else
  487. {
  488. if (descriptor->Type == Type)
  489. {
  490. if (Index-- == 0)
  491. {
  492. break;
  493. }
  494. }
  495. descriptor++;
  496. }
  497. }
  498. }
  499. return descriptor;
  500. }
  501. /*****************************************************************************
  502. * CResourceList::AddEntry()
  503. *****************************************************************************
  504. * Adds an entry.
  505. */
  506. STDMETHODIMP_(NTSTATUS)
  507. CResourceList::
  508. AddEntry
  509. (
  510. IN PCM_PARTIAL_RESOURCE_DESCRIPTOR TranslatedDescr,
  511. IN PCM_PARTIAL_RESOURCE_DESCRIPTOR UntranslatedDescr
  512. )
  513. {
  514. PAGED_CODE();
  515. ASSERT(TranslatedDescr);
  516. ASSERT(UntranslatedDescr);
  517. NTSTATUS ntStatus = STATUS_SUCCESS;
  518. // when there is no resource list stored in this object, both EntriesInUse
  519. // and EntriesAllocated are 0.
  520. if (EntriesInUse < EntriesAllocated)
  521. {
  522. Translated->
  523. List[0].PartialResourceList.PartialDescriptors[EntriesInUse] =
  524. *TranslatedDescr;
  525. Untranslated->
  526. List[0].PartialResourceList.PartialDescriptors[EntriesInUse] =
  527. *UntranslatedDescr;
  528. EntriesInUse++;
  529. // update counts
  530. Translated->
  531. List[0].PartialResourceList.Count = EntriesInUse;
  532. Untranslated->
  533. List[0].PartialResourceList.Count = EntriesInUse;
  534. }
  535. else
  536. {
  537. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  538. }
  539. return ntStatus;
  540. }
  541. /*****************************************************************************
  542. * CResourceList::AddEntryFromParent()
  543. *****************************************************************************
  544. * Adds an entry from a parent.
  545. */
  546. STDMETHODIMP_(NTSTATUS)
  547. CResourceList::
  548. AddEntryFromParent
  549. (
  550. IN PRESOURCELIST Parent,
  551. IN CM_RESOURCE_TYPE Type,
  552. IN ULONG Index
  553. )
  554. {
  555. PAGED_CODE();
  556. ASSERT(Parent);
  557. PCM_PARTIAL_RESOURCE_DESCRIPTOR translated =
  558. Parent->FindTranslatedEntry(Type,Index);
  559. PCM_PARTIAL_RESOURCE_DESCRIPTOR untranslated =
  560. Parent->FindUntranslatedEntry(Type,Index);
  561. NTSTATUS ntStatus;
  562. if (translated && untranslated)
  563. {
  564. ntStatus = AddEntry(translated,untranslated);
  565. }
  566. else
  567. {
  568. ntStatus = STATUS_INVALID_PARAMETER;
  569. }
  570. return ntStatus;
  571. }
  572. /*****************************************************************************
  573. * CResourceList::TranslatedList()
  574. *****************************************************************************
  575. * Gets the list of translated resources.
  576. */
  577. STDMETHODIMP_(PCM_RESOURCE_LIST)
  578. CResourceList::
  579. TranslatedList
  580. ( void
  581. )
  582. {
  583. PAGED_CODE();
  584. return Translated; // Attention: This could be NULL.
  585. }
  586. /*****************************************************************************
  587. * CResourceList::UntranslatedList()
  588. *****************************************************************************
  589. * Gets the list of untranslated resources.
  590. */
  591. STDMETHODIMP_(PCM_RESOURCE_LIST)
  592. CResourceList::
  593. UntranslatedList
  594. ( void
  595. )
  596. {
  597. PAGED_CODE();
  598. return Untranslated; // Attention: This could be NULL.
  599. }
  600. #pragma code_seg()