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.

763 lines
19 KiB

  1. /*++
  2. Copyright (c) 1997-1999 Microsoft Corporation
  3. Module Name:
  4. alloc.c
  5. Abstract:
  6. WMI data structure allocation routines
  7. Author:
  8. 16-Jan-1997 AlanWar
  9. Revision History:
  10. --*/
  11. #include "wmikmp.h"
  12. // HEY: This is duplicated from wmium.h.
  13. //
  14. // This guid is for notifications of changes to registration
  15. // {B48D49A1-E777-11d0-A50C-00A0C9062910}
  16. GUID GUID_REGISTRATION_CHANGE_NOTIFICATION = {0xb48d49a1, 0xe777, 0x11d0, 0xa5, 0xc, 0x0, 0xa0, 0xc9, 0x6, 0x29, 0x10};
  17. //
  18. // This guid id for notifications of new mof resources being added
  19. // {B48D49A2-E777-11d0-A50C-00A0C9062910}
  20. GUID GUID_MOF_RESOURCE_ADDED_NOTIFICATION = {0xb48d49a2, 0xe777, 0x11d0, 0xa5, 0xc, 0x0, 0xa0, 0xc9, 0x6, 0x29, 0x10};
  21. //
  22. // This guid id for notifications of new mof resources being added
  23. // {B48D49A3-E777-11d0-A50C-00A0C9062910}
  24. GUID GUID_MOF_RESOURCE_REMOVED_NOTIFICATION = {0xb48d49a3, 0xe777, 0x11d0, 0xa5, 0xc, 0x0, 0xa0, 0xc9, 0x6, 0x29, 0x10};
  25. //
  26. // This defines the number of DataSources allocated in each DataSource chunk
  27. #if DBG
  28. #define DSCHUNKSIZE 4
  29. #else
  30. #define DSCHUNKSIZE 64
  31. #endif
  32. void WmipDSCleanup(
  33. PCHUNKINFO ChunkInfo,
  34. PENTRYHEADER Entry
  35. );
  36. CHUNKINFO WmipDSChunkInfo =
  37. {
  38. { NULL, NULL },
  39. sizeof(DATASOURCE),
  40. DSCHUNKSIZE,
  41. WmipDSCleanup,
  42. FLAG_ENTRY_REMOVE_LIST,
  43. DS_SIGNATURE
  44. };
  45. LIST_ENTRY WmipDSHead; // Head of registerd data source list
  46. PLIST_ENTRY WmipDSHeadPtr;
  47. //
  48. // This defines the number of GuidEntrys allocated in each GuidEntry chunk
  49. #if DBG
  50. #define GECHUNKSIZE 4
  51. #else
  52. #define GECHUNKSIZE 512
  53. #endif
  54. void WmipGECleanup(
  55. PCHUNKINFO ChunkInfo,
  56. PENTRYHEADER Entry
  57. );
  58. CHUNKINFO WmipGEChunkInfo =
  59. {
  60. { NULL, NULL },
  61. sizeof(GUIDENTRY),
  62. GECHUNKSIZE,
  63. WmipGECleanup,
  64. FLAG_ENTRY_REMOVE_LIST,
  65. GE_SIGNATURE
  66. };
  67. LIST_ENTRY WmipGEHead; // Head of registerd guid list
  68. PLIST_ENTRY WmipGEHeadPtr;
  69. //
  70. // This defines the number of InstanceSets allocated in each InstanceSet chunk
  71. #if DBG
  72. #define ISCHUNKSIZE 4
  73. #else
  74. #define ISCHUNKSIZE 2048
  75. #endif
  76. void WmipISCleanup(
  77. PCHUNKINFO ChunkInfo,
  78. PENTRYHEADER Entry
  79. );
  80. CHUNKINFO WmipISChunkInfo =
  81. {
  82. { NULL, NULL },
  83. sizeof(INSTANCESET),
  84. ISCHUNKSIZE,
  85. WmipISCleanup,
  86. 0,
  87. IS_SIGNATURE
  88. };
  89. #if DBG
  90. #define MRCHUNKSIZE 2
  91. #else
  92. #define MRCHUNKSIZE 16
  93. #endif
  94. void WmipMRCleanup(
  95. PCHUNKINFO ChunkInfo,
  96. PENTRYHEADER Entry
  97. );
  98. CHUNKINFO WmipMRChunkInfo =
  99. {
  100. { NULL, NULL },
  101. sizeof(MOFRESOURCE),
  102. MRCHUNKSIZE,
  103. WmipMRCleanup,
  104. FLAG_ENTRY_REMOVE_LIST,
  105. MR_SIGNATURE
  106. };
  107. LIST_ENTRY WmipMRHead; // Head of Mof Resource list
  108. PLIST_ENTRY WmipMRHeadPtr;
  109. #ifdef ALLOC_PRAGMA
  110. #pragma alloc_text (PAGE, WmipDSCleanup)
  111. #pragma alloc_text (PAGE, WmipAllocDataSource)
  112. #pragma alloc_text (PAGE, WmipGECleanup)
  113. #pragma alloc_text (PAGE, WmipAllocGuidEntryX)
  114. #pragma alloc_text (PAGE, WmipISCleanup)
  115. #pragma alloc_text (PAGE, WmipMRCleanup)
  116. #pragma alloc_text (PAGE, WmipFindGEByGuid)
  117. #pragma alloc_text (PAGE, WmipFindDSByProviderId)
  118. #pragma alloc_text (PAGE, WmipFindISByGuid)
  119. #pragma alloc_text (PAGE, WmipFindMRByNames)
  120. #pragma alloc_text (PAGE, WmipFindISinGEbyName)
  121. #pragma alloc_text (PAGE, WmipRealloc)
  122. #pragma alloc_text (PAGE, WmipIsNumber)
  123. #endif
  124. PBDATASOURCE WmipAllocDataSource(
  125. void
  126. )
  127. /*++
  128. Routine Description:
  129. Allocates a Data Source structure
  130. Arguments:
  131. Return Value:
  132. pointer to data source structure or NULL if one cannot be allocated
  133. --*/
  134. {
  135. PBDATASOURCE DataSource;
  136. DataSource = (PBDATASOURCE)WmipAllocEntry(&WmipDSChunkInfo);
  137. if (DataSource != NULL)
  138. {
  139. InitializeListHead(&DataSource->ISHead);
  140. DataSource->MofResourceCount = AVGMOFRESOURCECOUNT;
  141. DataSource->MofResources = DataSource->StaticMofResources;
  142. memset(DataSource->MofResources,
  143. 0,
  144. AVGMOFRESOURCECOUNT * sizeof(PMOFRESOURCE));
  145. }
  146. return(DataSource);
  147. }
  148. void WmipDSCleanup(
  149. PCHUNKINFO ChunkInfo,
  150. PENTRYHEADER Entry
  151. )
  152. /*++
  153. Routine Description:
  154. Cleans up data source structure and any other structures or handles
  155. associated with it.
  156. Arguments:
  157. Data source structure to free
  158. Return Value:
  159. --*/
  160. {
  161. PBDATASOURCE DataSource = (PBDATASOURCE)Entry;
  162. PBINSTANCESET InstanceSet;
  163. PLIST_ENTRY InstanceSetList;
  164. ULONG i;
  165. UNREFERENCED_PARAMETER (ChunkInfo);
  166. WmipAssert(DataSource != NULL);
  167. WmipAssert(DataSource->Flags & FLAG_ENTRY_INVALID);
  168. WmipEnterSMCritSection();
  169. InstanceSetList = DataSource->ISHead.Flink;
  170. while (InstanceSetList != &DataSource->ISHead)
  171. {
  172. InstanceSet = CONTAINING_RECORD(InstanceSetList,
  173. INSTANCESET,
  174. DSISList);
  175. if (InstanceSet->GuidISList.Flink != NULL)
  176. {
  177. RemoveEntryList(&InstanceSet->GuidISList);
  178. InstanceSet->DataSource = NULL;
  179. InstanceSet->GuidEntry->ISCount--;
  180. }
  181. if ((InstanceSet->GuidEntry != NULL) &&
  182. (! (InstanceSet->Flags & IS_NEWLY_REGISTERED)))
  183. {
  184. if (IsEqualGUID(&InstanceSet->GuidEntry->Guid,
  185. &WmipBinaryMofGuid))
  186. {
  187. WmipLeaveSMCritSection();
  188. WmipGenerateBinaryMofNotification(InstanceSet,
  189. &GUID_MOF_RESOURCE_REMOVED_NOTIFICATION);
  190. WmipEnterSMCritSection();
  191. }
  192. WmipUnreferenceGE(InstanceSet->GuidEntry);
  193. }
  194. InstanceSet->GuidEntry = NULL;
  195. InstanceSetList = InstanceSetList->Flink;
  196. WmipUnreferenceIS(InstanceSet);
  197. }
  198. WmipLeaveSMCritSection();
  199. for (i = 0; i < DataSource->MofResourceCount; i++)
  200. {
  201. if (DataSource->MofResources[i] != NULL)
  202. {
  203. WmipUnreferenceMR(DataSource->MofResources[i]);
  204. }
  205. }
  206. if (DataSource->MofResources != DataSource->StaticMofResources)
  207. {
  208. WmipFree(DataSource->MofResources);
  209. DataSource->MofResources = NULL;
  210. }
  211. if (DataSource->RegistryPath != NULL)
  212. {
  213. WmipFree(DataSource->RegistryPath);
  214. DataSource->RegistryPath = NULL;
  215. }
  216. }
  217. void WmipGECleanup(
  218. PCHUNKINFO ChunkInfo,
  219. PENTRYHEADER Entry
  220. )
  221. /*++
  222. Routine Description:
  223. Cleans up guid entry structure and any other structures or handles
  224. associated with it.
  225. Arguments:
  226. GuidEntry structure to free
  227. Return Value:
  228. --*/
  229. {
  230. PBGUIDENTRY GuidEntry = (PBGUIDENTRY)Entry;
  231. UNREFERENCED_PARAMETER (ChunkInfo);
  232. WmipAssert(GuidEntry != NULL);
  233. WmipAssert(GuidEntry->Flags & FLAG_ENTRY_INVALID);
  234. GuidEntry->Guid.Data4[7] ^= 0xff;
  235. if (GuidEntry->CollectInProgress != NULL)
  236. {
  237. ExFreePool(GuidEntry->CollectInProgress);
  238. GuidEntry->CollectInProgress = NULL;
  239. }
  240. }
  241. PBGUIDENTRY WmipAllocGuidEntryX(
  242. ULONG LINE,
  243. PCHAR FILE
  244. )
  245. {
  246. PBGUIDENTRY GuidEntry;
  247. PKEVENT Event;
  248. #if ! DBG
  249. UNREFERENCED_PARAMETER(LINE);
  250. UNREFERENCED_PARAMETER(FILE);
  251. #endif
  252. GuidEntry = NULL;
  253. Event = ExAllocatePoolWithTag(NonPagedPool,
  254. sizeof(KEVENT),
  255. WMIPOOLTAG);
  256. if (Event != NULL)
  257. {
  258. GuidEntry = (PBGUIDENTRY)WmipAllocEntry(&WmipGEChunkInfo);
  259. if (GuidEntry != NULL)
  260. {
  261. WmipDebugPrintEx((DPFLTR_WMICORE_ID, DPFLTR_INFO_LEVEL, "WMI: %p.%p Create GE %p (%x) at %s %d\n", PsGetCurrentProcessId(), PsGetCurrentThreadId(), GuidEntry, GuidEntry->RefCount, FILE, LINE));
  262. InitializeListHead(&GuidEntry->ISHead);
  263. InitializeListHead(&GuidEntry->ObjectHead);
  264. GuidEntry->CollectInProgress = Event;
  265. } else {
  266. ExFreePool(Event);
  267. }
  268. }
  269. return(GuidEntry);
  270. }
  271. void WmipISCleanup(
  272. PCHUNKINFO ChunkInfo,
  273. PENTRYHEADER Entry
  274. )
  275. {
  276. PBINSTANCESET InstanceSet = (PBINSTANCESET)Entry;
  277. UNREFERENCED_PARAMETER (ChunkInfo);
  278. WmipAssert(InstanceSet != NULL);
  279. WmipAssert(InstanceSet->Flags & FLAG_ENTRY_INVALID);
  280. if (InstanceSet->IsBaseName != NULL)
  281. {
  282. WmipFree(InstanceSet->IsBaseName);
  283. InstanceSet->IsBaseName = NULL;
  284. }
  285. }
  286. void WmipMRCleanup(
  287. IN PCHUNKINFO ChunkInfo,
  288. IN PENTRYHEADER Entry
  289. )
  290. {
  291. PMOFRESOURCE MofResource = (PMOFRESOURCE)Entry;
  292. PAGED_CODE();
  293. UNREFERENCED_PARAMETER (ChunkInfo);
  294. if ((MofResource->RegistryPath != NULL) &&
  295. (MofResource->MofResourceName != NULL) &&
  296. ((MofResource->Flags & MR_FLAG_USER_MODE) != MR_FLAG_USER_MODE))
  297. {
  298. WmipGenerateMofResourceNotification(MofResource->RegistryPath,
  299. MofResource->MofResourceName,
  300. &GUID_MOF_RESOURCE_REMOVED_NOTIFICATION,
  301. MofResource->Flags & MR_FLAG_USER_MODE ?
  302. MOFEVENT_ACTION_IMAGE_PATH :
  303. MOFEVENT_ACTION_REGISTRY_PATH);
  304. }
  305. if (MofResource->RegistryPath != NULL)
  306. {
  307. WmipFree(MofResource->RegistryPath);
  308. MofResource->RegistryPath = NULL;
  309. }
  310. if (MofResource->MofResourceName != NULL)
  311. {
  312. WmipFree(MofResource->MofResourceName);
  313. MofResource->MofResourceName = NULL;
  314. }
  315. }
  316. PBGUIDENTRY WmipFindGEByGuid(
  317. LPGUID Guid,
  318. BOOLEAN MakeTopOfList
  319. )
  320. /*++
  321. Routine Description:
  322. Searches guid list for first occurence of guid. Guid's refcount is
  323. incremented if found.
  324. Arguments:
  325. Guid is pointer to guid that is to be found
  326. MakeTopOfList is TRUE then if NE is found it is placed at the top of the
  327. NE list
  328. Return Value:
  329. pointer to guid entry pointer or NULL if not found
  330. --*/
  331. {
  332. PLIST_ENTRY GuidEntryList;
  333. PBGUIDENTRY GuidEntry;
  334. WmipEnterSMCritSection();
  335. GuidEntryList = WmipGEHeadPtr->Flink;
  336. while (GuidEntryList != WmipGEHeadPtr)
  337. {
  338. GuidEntry = CONTAINING_RECORD(GuidEntryList,
  339. GUIDENTRY,
  340. MainGEList);
  341. if (IsEqualGUID(Guid, &GuidEntry->Guid))
  342. {
  343. WmipReferenceGE(GuidEntry);
  344. if (MakeTopOfList)
  345. {
  346. RemoveEntryList(GuidEntryList);
  347. InsertHeadList(WmipGEHeadPtr, GuidEntryList);
  348. }
  349. WmipLeaveSMCritSection();
  350. WmipAssert(GuidEntry->Signature == GE_SIGNATURE);
  351. return(GuidEntry);
  352. }
  353. GuidEntryList = GuidEntryList->Flink;
  354. }
  355. WmipLeaveSMCritSection();
  356. return(NULL);
  357. }
  358. PBDATASOURCE WmipFindDSByProviderId(
  359. ULONG_PTR ProviderId
  360. )
  361. /*++
  362. Routine Description:
  363. This routine finds a DataSource on the provider id passed. DataSource's
  364. ref count is incremented if found
  365. Arguments:
  366. ProviderId is the data source provider id
  367. Return Value:
  368. DataSource pointer or NULL if no data source was found
  369. --*/
  370. {
  371. PLIST_ENTRY DataSourceList;
  372. PBDATASOURCE DataSource;
  373. WmipEnterSMCritSection();
  374. DataSourceList = WmipDSHeadPtr->Flink;
  375. while (DataSourceList != WmipDSHeadPtr)
  376. {
  377. DataSource = CONTAINING_RECORD(DataSourceList,
  378. DATASOURCE,
  379. MainDSList);
  380. if (DataSource->ProviderId == ProviderId)
  381. {
  382. WmipReferenceDS(DataSource);
  383. WmipLeaveSMCritSection();
  384. WmipAssert(DataSource->Signature == DS_SIGNATURE);
  385. return(DataSource);
  386. }
  387. DataSourceList = DataSourceList->Flink;
  388. }
  389. WmipLeaveSMCritSection();
  390. return(NULL);
  391. }
  392. PBINSTANCESET WmipFindISByGuid(
  393. PBDATASOURCE DataSource,
  394. GUID UNALIGNED *Guid
  395. )
  396. /*++
  397. Routine Description:
  398. This routine will find an instance set within a data source list for a
  399. specific guid. Note that any instance sets that have been replaceed
  400. (have IS_REPLACED_BY_REFERENCE) are ignored and not returned. The
  401. InstanceSet that is found has its reference count increased.
  402. Arguments:
  403. DataSource is the data source whose instance set list is searched
  404. Guid is a pointer to a guid which defines which instance set list to find
  405. Return Value:
  406. InstanceSet pointer or NULL if not found
  407. --*/
  408. {
  409. PBINSTANCESET InstanceSet;
  410. PLIST_ENTRY InstanceSetList;
  411. WmipEnterSMCritSection();
  412. InstanceSetList = DataSource->ISHead.Flink;
  413. while (InstanceSetList != &DataSource->ISHead)
  414. {
  415. InstanceSet = CONTAINING_RECORD(InstanceSetList,
  416. INSTANCESET,
  417. DSISList);
  418. if (IsEqualGUID(&InstanceSet->GuidEntry->Guid, Guid))
  419. {
  420. WmipReferenceIS(InstanceSet);
  421. WmipLeaveSMCritSection();
  422. WmipAssert(InstanceSet->Signature == IS_SIGNATURE);
  423. return(InstanceSet);
  424. }
  425. InstanceSetList = InstanceSetList->Flink;
  426. }
  427. WmipLeaveSMCritSection();
  428. return(NULL);
  429. }
  430. PMOFRESOURCE WmipFindMRByNames(
  431. LPCWSTR ImagePath,
  432. LPCWSTR MofResourceName
  433. )
  434. /*++
  435. Routine Description:
  436. Searches mof resource list for a MR that has the same image path and
  437. resource name. If ine is found a reference count is added to it.
  438. Arguments:
  439. ImagePath points at a string that has the full path to the image
  440. file that contains the MOF resource
  441. MofResourceName points at a string that has the name of the MOF
  442. resource
  443. Return Value:
  444. pointer to mof resource or NULL if not found
  445. --*/
  446. {
  447. PLIST_ENTRY MofResourceList;
  448. PMOFRESOURCE MofResource;
  449. WmipEnterSMCritSection();
  450. MofResourceList = WmipMRHeadPtr->Flink;
  451. while (MofResourceList != WmipMRHeadPtr)
  452. {
  453. MofResource = CONTAINING_RECORD(MofResourceList,
  454. MOFRESOURCE,
  455. MainMRList);
  456. if ((wcscmp(MofResource->RegistryPath, ImagePath) == 0) &&
  457. (wcscmp(MofResource->MofResourceName, MofResourceName) == 0))
  458. {
  459. WmipReferenceMR(MofResource);
  460. WmipLeaveSMCritSection();
  461. WmipAssert(MofResource->Signature == MR_SIGNATURE);
  462. return(MofResource);
  463. }
  464. MofResourceList = MofResourceList->Flink;
  465. }
  466. WmipLeaveSMCritSection();
  467. return(NULL);
  468. }
  469. BOOLEAN WmipIsNumber(
  470. LPCWSTR String
  471. )
  472. {
  473. while (*String != UNICODE_NULL)
  474. {
  475. if ((*String < L'0') || (*String > L'9'))
  476. {
  477. return(FALSE);
  478. }
  479. String++;
  480. }
  481. return(TRUE);
  482. }
  483. PBINSTANCESET WmipFindISinGEbyName(
  484. PBGUIDENTRY GuidEntry,
  485. PWCHAR InstanceName,
  486. PULONG InstanceIndex
  487. )
  488. /*++
  489. Routine Description:
  490. This routine finds the instance set containing the instance name passed
  491. within the GuidEntry passed. If found it will also return the index of
  492. the instance name within the instance set. The instance set found has its
  493. ref count incremented.
  494. Arguments:
  495. GuidEntry contains the instance sets to look through
  496. InstanceName is the instance name to look for
  497. *InstanceIndex return instance index within set
  498. Return Value:
  499. Instance set containing instance name or NULL of instance name not found
  500. --*/
  501. {
  502. PBINSTANCESET InstanceSet;
  503. PLIST_ENTRY InstanceSetList;
  504. SIZE_T BaseNameLen;
  505. PWCHAR InstanceNamePtr;
  506. ULONG InstanceNameIndex;
  507. ULONG InstanceSetFirstIndex, InstanceSetLastIndex;
  508. ULONG i;
  509. WmipEnterSMCritSection();
  510. InstanceSetList = GuidEntry->ISHead.Flink;
  511. while (InstanceSetList != &GuidEntry->ISHead)
  512. {
  513. InstanceSet = CONTAINING_RECORD(InstanceSetList,
  514. INSTANCESET,
  515. GuidISList);
  516. if (InstanceSet->Flags & IS_INSTANCE_BASENAME)
  517. {
  518. BaseNameLen = wcslen(InstanceSet->IsBaseName->BaseName);
  519. if (wcsncmp(InstanceName,
  520. InstanceSet->IsBaseName->BaseName,
  521. BaseNameLen) == 0)
  522. {
  523. InstanceNamePtr = InstanceName + BaseNameLen;
  524. InstanceNameIndex = _wtoi(InstanceNamePtr);
  525. InstanceSetFirstIndex = InstanceSet->IsBaseName->BaseIndex;
  526. InstanceSetLastIndex = InstanceSetFirstIndex + InstanceSet->Count;
  527. if (( (InstanceNameIndex >= InstanceSetFirstIndex) &&
  528. (InstanceNameIndex < InstanceSetLastIndex)) &&
  529. ((InstanceNameIndex != 0) || WmipIsNumber(InstanceNamePtr)))
  530. {
  531. InstanceSet = CONTAINING_RECORD(InstanceSetList,
  532. INSTANCESET,
  533. GuidISList);
  534. *InstanceIndex = InstanceNameIndex - InstanceSetFirstIndex;
  535. WmipReferenceIS(InstanceSet);
  536. WmipAssert(InstanceSet->Signature == IS_SIGNATURE);
  537. WmipLeaveSMCritSection();
  538. return(InstanceSet);
  539. }
  540. }
  541. } else if (InstanceSet->Flags & IS_INSTANCE_STATICNAMES) {
  542. for (i = 0; i < InstanceSet->Count; i++)
  543. {
  544. if (wcscmp(InstanceName,
  545. InstanceSet->IsStaticNames->StaticNamePtr[i]) == 0)
  546. {
  547. InstanceSet = CONTAINING_RECORD(InstanceSetList,
  548. INSTANCESET,
  549. GuidISList);
  550. *InstanceIndex = i;
  551. WmipReferenceIS(InstanceSet);
  552. WmipAssert(InstanceSet->Signature == IS_SIGNATURE);
  553. WmipLeaveSMCritSection();
  554. return(InstanceSet);
  555. }
  556. }
  557. }
  558. InstanceSetList = InstanceSetList->Flink;
  559. }
  560. WmipLeaveSMCritSection();
  561. return(NULL);
  562. }
  563. BOOLEAN WmipRealloc(
  564. PVOID *Buffer,
  565. ULONG CurrentSize,
  566. ULONG NewSize,
  567. BOOLEAN FreeOriginalBuffer
  568. )
  569. /*++
  570. Routine Description:
  571. Reallocate a buffer to a larger size while preserving data
  572. Arguments:
  573. Buffer on entry has the buffer to be reallocated, on exit has the new
  574. buffer
  575. CurrentSize is the current size of the buffer
  576. NewSize has the new size desired
  577. Return Value:
  578. TRUE if realloc was successful
  579. --*/
  580. {
  581. PVOID NewBuffer;
  582. WmipAssert(NewSize > CurrentSize);
  583. NewBuffer = WmipAlloc(NewSize);
  584. if (NewBuffer != NULL)
  585. {
  586. memset(NewBuffer, 0, NewSize);
  587. memcpy(NewBuffer, *Buffer, CurrentSize);
  588. if (FreeOriginalBuffer)
  589. {
  590. WmipFree(*Buffer);
  591. }
  592. *Buffer = NewBuffer;
  593. return(TRUE);
  594. }
  595. return(FALSE);
  596. }