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.

2500 lines
79 KiB

  1. /*++
  2. Copyright (c) 1997-1999 Microsoft Corporation
  3. Module Name:
  4. ds.c
  5. Abstract:
  6. WMI data provider registration code
  7. Author:
  8. AlanWar
  9. Environment:
  10. Kernel Mode
  11. Revision History:
  12. --*/
  13. #include "wmikmp.h"
  14. #include <strsafe.h>
  15. void WmipEnableCollectionForNewGuid(
  16. LPGUID Guid,
  17. PBINSTANCESET InstanceSet
  18. );
  19. void WmipDisableCollectionForRemovedGuid(
  20. LPGUID Guid,
  21. PBINSTANCESET InstanceSet
  22. );
  23. ULONG WmipDetermineInstanceBaseIndex(
  24. LPGUID Guid,
  25. PWCHAR BaseName,
  26. ULONG InstanceCount
  27. );
  28. ULONG WmipMangleInstanceName(
  29. LPGUID Guid,
  30. PWCHAR Name,
  31. ULONG MaxMangledNameLen,
  32. PWCHAR MangledName
  33. );
  34. NTSTATUS WmipBuildInstanceSet(
  35. PWMIREGGUID RegGuid,
  36. PWMIREGINFOW WmiRegInfo,
  37. ULONG BufferSize,
  38. PBINSTANCESET InstanceSet,
  39. ULONG ProviderId,
  40. LPCTSTR MofImagePath
  41. );
  42. NTSTATUS WmipLinkDataSourceToList(
  43. PBDATASOURCE DataSource,
  44. BOOLEAN AddDSToList
  45. );
  46. void WmipSendGuidUpdateNotifications(
  47. NOTIFICATIONTYPES NotificationType,
  48. ULONG GuidCount,
  49. PTRCACHE *GuidList
  50. );
  51. void WmipGenerateBinaryMofNotification(
  52. PBINSTANCESET BinaryMofInstanceSet,
  53. LPCGUID Guid
  54. );
  55. void WmipGenerateRegistrationNotification(
  56. PBDATASOURCE DataSource,
  57. ULONG NotificationCode
  58. );
  59. NTSTATUS WmipAddMofResource(
  60. PBDATASOURCE DataSource,
  61. LPWSTR ImagePath,
  62. BOOLEAN IsImagePath,
  63. LPWSTR MofResourceName,
  64. PBOOLEAN NewMofResource
  65. );
  66. PBINSTANCESET WmipFindISInDSByGuid(
  67. PBDATASOURCE DataSource,
  68. LPGUID Guid
  69. );
  70. ULONG WmipUpdateAddGuid(
  71. PBDATASOURCE DataSource,
  72. PWMIREGGUID RegGuid,
  73. PWMIREGINFO WmiRegInfo,
  74. ULONG BufferSize,
  75. PBINSTANCESET *AddModInstanceSet
  76. );
  77. PWCHAR GuidToString(
  78. PWCHAR s,
  79. ULONG SizeInBytes,
  80. LPGUID piid
  81. );
  82. BOOLEAN WmipUpdateRemoveGuid(
  83. PBDATASOURCE DataSource,
  84. PWMIREGGUID RegGuid,
  85. PBINSTANCESET *AddModInstanceSet
  86. );
  87. BOOLEAN WmipIsEqualInstanceSets(
  88. PBINSTANCESET InstanceSet1,
  89. PBINSTANCESET InstanceSet2
  90. );
  91. ULONG WmipUpdateModifyGuid(
  92. PBDATASOURCE DataSource,
  93. PWMIREGGUID RegGuid,
  94. PWMIREGINFO WmiRegInfo,
  95. ULONG BufferSize,
  96. PBINSTANCESET *AddModInstanceSet
  97. );
  98. void WmipCachePtrs(
  99. LPGUID Ptr1,
  100. PBINSTANCESET Ptr2,
  101. ULONG *PtrCount,
  102. ULONG *PtrMax,
  103. PTRCACHE **PtrArray
  104. );
  105. NTSTATUS WmipUpdateDataSource(
  106. PREGENTRY RegEntry,
  107. PWMIREGINFOW WmiRegInfo,
  108. ULONG RetSize
  109. );
  110. void WmipRemoveDataSourceByDS(
  111. PBDATASOURCE DataSource
  112. );
  113. NTSTATUS WmipRemoveDataSource(
  114. PREGENTRY RegEntry
  115. );
  116. NTSTATUS WmipInitializeDataStructs(
  117. void
  118. );
  119. NTSTATUS WmipEnumerateMofResources(
  120. PWMIMOFLIST MofList,
  121. ULONG BufferSize,
  122. ULONG *RetSize
  123. );
  124. #ifdef ALLOC_PRAGMA
  125. #pragma alloc_text(INIT,WmipInitializeDataStructs)
  126. #pragma alloc_text(PAGE,WmipEnableCollectionForNewGuid)
  127. #pragma alloc_text(PAGE,WmipDisableCollectionForRemovedGuid)
  128. #pragma alloc_text(PAGE,WmipDetermineInstanceBaseIndex)
  129. #pragma alloc_text(PAGE,WmipMangleInstanceName)
  130. #pragma alloc_text(PAGE,WmipBuildInstanceSet)
  131. #pragma alloc_text(PAGE,WmipLinkDataSourceToList)
  132. #pragma alloc_text(PAGE,WmipSendGuidUpdateNotifications)
  133. #pragma alloc_text(PAGE,WmipGenerateBinaryMofNotification)
  134. #pragma alloc_text(PAGE,WmipGenerateMofResourceNotification)
  135. #pragma alloc_text(PAGE,WmipGenerateRegistrationNotification)
  136. #pragma alloc_text(PAGE,WmipAddMofResource)
  137. #pragma alloc_text(PAGE,WmipAddDataSource)
  138. #pragma alloc_text(PAGE,WmipFindISInDSByGuid)
  139. #pragma alloc_text(PAGE,WmipUpdateAddGuid)
  140. #pragma alloc_text(PAGE,WmipUpdateRemoveGuid)
  141. #pragma alloc_text(PAGE,WmipIsEqualInstanceSets)
  142. #pragma alloc_text(PAGE,WmipUpdateModifyGuid)
  143. #pragma alloc_text(PAGE,WmipCachePtrs)
  144. #pragma alloc_text(PAGE,WmipUpdateDataSource)
  145. #pragma alloc_text(PAGE,WmipRemoveDataSourceByDS)
  146. #pragma alloc_text(PAGE,WmipRemoveDataSource)
  147. #pragma alloc_text(PAGE,WmipEnumerateMofResources)
  148. #if DBG
  149. #pragma alloc_text(PAGE,GuidToString)
  150. #endif
  151. #endif
  152. #ifdef ALLOC_DATA_PRAGMA
  153. #pragma const_seg("PAGECONST")
  154. #endif
  155. const GUID WmipBinaryMofGuid = BINARY_MOF_GUID;
  156. // {4EE0B301-94BC-11d0-A4EC-00A0C9062910}
  157. const GUID RegChangeNotificationGuid =
  158. { 0x4ee0b301, 0x94bc, 0x11d0, { 0xa4, 0xec, 0x0, 0xa0, 0xc9, 0x6, 0x29, 0x10 } };
  159. void WmipEnableCollectionForNewGuid(
  160. LPGUID Guid,
  161. PBINSTANCESET InstanceSet
  162. )
  163. {
  164. WNODE_HEADER Wnode;
  165. PBGUIDENTRY GuidEntry;
  166. ULONG Status;
  167. BOOLEAN IsTraceLog;
  168. PAGED_CODE();
  169. GuidEntry = WmipFindGEByGuid(Guid, FALSE);
  170. if (GuidEntry != NULL)
  171. {
  172. memset(&Wnode, 0, sizeof(WNODE_HEADER));
  173. memcpy(&Wnode.Guid, Guid, sizeof(GUID));
  174. Wnode.BufferSize = sizeof(WNODE_HEADER);
  175. WmipEnterSMCritSection();
  176. if ((GuidEntry->EventRefCount > 0) &&
  177. ((InstanceSet->Flags & IS_ENABLE_EVENT) == 0))
  178. {
  179. //
  180. // Events were previously enabled for this guid, but not for this
  181. // instance set so call data source for instance set to enable
  182. // the events. First set the in progress flag and InstanceSet
  183. // set flag to denote that events have been enabled for the
  184. // instance set.
  185. InstanceSet->Flags |= IS_ENABLE_EVENT;
  186. //
  187. // If it is Tracelog, NewGuid notifications are piggybacked with
  188. // Registration call return.
  189. //
  190. IsTraceLog = ((InstanceSet->Flags & IS_TRACED) == IS_TRACED) ? TRUE : FALSE;
  191. if (IsTraceLog)
  192. {
  193. if (!(InstanceSet->DataSource->Flags & DS_KERNEL_MODE) )
  194. {
  195. if (GuidEntry != NULL)
  196. {
  197. WmipUnreferenceGE(GuidEntry);
  198. }
  199. WmipLeaveSMCritSection();
  200. return;
  201. }
  202. //
  203. // For the Kernel Mode Trace Providers pass on the context
  204. //
  205. Wnode.HistoricalContext = GuidEntry->LoggerContext;
  206. }
  207. GuidEntry->Flags |= GE_FLAG_NOTIFICATION_IN_PROGRESS;
  208. WmipLeaveSMCritSection();
  209. WmipDeliverWnodeToDS(IRP_MN_ENABLE_EVENTS,
  210. InstanceSet->DataSource,
  211. &Wnode,
  212. Wnode.BufferSize);
  213. WmipEnterSMCritSection();
  214. //
  215. // Now we need to check if events were disabled while the enable
  216. // request was in progress. If so go do the work to actually
  217. // disable them.
  218. if (GuidEntry->EventRefCount == 0)
  219. {
  220. Status = WmipDoDisableRequest(GuidEntry,
  221. TRUE,
  222. IsTraceLog,
  223. GuidEntry->LoggerContext,
  224. GE_FLAG_NOTIFICATION_IN_PROGRESS);
  225. } else {
  226. GuidEntry->Flags &= ~GE_FLAG_NOTIFICATION_IN_PROGRESS;
  227. }
  228. }
  229. //
  230. // Now check to see if collection needs to be enabled for this guid
  231. //
  232. if ((GuidEntry->CollectRefCount > 0) &&
  233. ((InstanceSet->Flags & IS_ENABLE_COLLECTION) == 0) &&
  234. (InstanceSet->Flags & IS_EXPENSIVE) )
  235. {
  236. //
  237. // Collection was previously enabled for this guid, but not
  238. // for this instance set so call data source for instance set
  239. // to enable collection. First set the in progress flag and
  240. // InstanceSet set flag to denote that collection has been enabled
  241. // for the instance set.
  242. //
  243. GuidEntry->Flags |= GE_FLAG_COLLECTION_IN_PROGRESS;
  244. InstanceSet->Flags |= IS_ENABLE_COLLECTION;
  245. WmipLeaveSMCritSection();
  246. WmipDeliverWnodeToDS(IRP_MN_ENABLE_COLLECTION,
  247. InstanceSet->DataSource,
  248. &Wnode,
  249. Wnode.BufferSize);
  250. WmipEnterSMCritSection();
  251. //
  252. // Now we need to check if events were disabled while the enable
  253. // request was in progress. If so go do the work to actually
  254. // disable them.
  255. //
  256. if (GuidEntry->CollectRefCount == 0)
  257. {
  258. Status = WmipDoDisableRequest(GuidEntry,
  259. FALSE,
  260. FALSE,
  261. 0,
  262. GE_FLAG_COLLECTION_IN_PROGRESS);
  263. } else {
  264. GuidEntry->Flags &= ~GE_FLAG_COLLECTION_IN_PROGRESS;
  265. //
  266. // If there are any other threads that were waiting
  267. // until all of the enable/disable work completed, we
  268. // close the event handle to release them from their wait.
  269. //
  270. WmipReleaseCollectionEnabled(GuidEntry);
  271. }
  272. }
  273. WmipUnreferenceGE(GuidEntry);
  274. WmipLeaveSMCritSection();
  275. } else {
  276. WmipAssert(FALSE);
  277. }
  278. }
  279. void WmipDisableCollectionForRemovedGuid(
  280. LPGUID Guid,
  281. PBINSTANCESET InstanceSet
  282. )
  283. {
  284. WNODE_HEADER Wnode;
  285. PBGUIDENTRY GuidEntry;
  286. ULONG Status;
  287. BOOLEAN IsTraceLog;
  288. PAGED_CODE();
  289. GuidEntry = WmipFindGEByGuid(Guid, FALSE);
  290. if (GuidEntry != NULL)
  291. {
  292. memset(&Wnode, 0, sizeof(WNODE_HEADER));
  293. memcpy(&Wnode.Guid, Guid, sizeof(GUID));
  294. Wnode.BufferSize = sizeof(WNODE_HEADER);
  295. WmipEnterSMCritSection();
  296. if ((GuidEntry->EventRefCount > 0) &&
  297. ((InstanceSet->Flags & IS_ENABLE_EVENT) != 0))
  298. {
  299. // Events were previously enabled for this guid, but not for this
  300. // instance set so call data source for instance set to enable
  301. // the events. First set the in progress flag and InstanceSet
  302. // set flag to denote that events have been enabled for the
  303. // instance set.
  304. InstanceSet->Flags &= ~IS_ENABLE_EVENT;
  305. //
  306. // If it is Tracelog, RemoveGuid notifications are handled
  307. // through UnregisterGuids call.
  308. //
  309. IsTraceLog = ((InstanceSet->Flags & IS_TRACED) == IS_TRACED) ? TRUE : FALSE;
  310. if (IsTraceLog)
  311. {
  312. if ( !(InstanceSet->DataSource->Flags & DS_KERNEL_MODE))
  313. {
  314. WmipUnreferenceGE(GuidEntry);
  315. WmipLeaveSMCritSection();
  316. return;
  317. }
  318. Wnode.HistoricalContext = GuidEntry->LoggerContext;
  319. }
  320. GuidEntry->Flags |= GE_FLAG_NOTIFICATION_IN_PROGRESS;
  321. WmipLeaveSMCritSection();
  322. WmipDeliverWnodeToDS(IRP_MN_DISABLE_EVENTS,
  323. InstanceSet->DataSource,
  324. &Wnode,
  325. Wnode.BufferSize);
  326. WmipEnterSMCritSection();
  327. //
  328. // Now we need to check if events were disabled while the enable
  329. // request was in progress. If so go do the work to actually
  330. // disable them.
  331. if (GuidEntry->EventRefCount == 0)
  332. {
  333. Status = WmipDoDisableRequest(GuidEntry,
  334. TRUE,
  335. IsTraceLog,
  336. GuidEntry->LoggerContext,
  337. GE_FLAG_NOTIFICATION_IN_PROGRESS);
  338. } else {
  339. GuidEntry->Flags &= ~GE_FLAG_NOTIFICATION_IN_PROGRESS;
  340. }
  341. }
  342. //
  343. // Now check to see if collection needs to be enabled for this guid
  344. if ((GuidEntry->CollectRefCount > 0) &&
  345. ((InstanceSet->Flags & IS_ENABLE_COLLECTION) != 0))
  346. {
  347. // Collection was previously enabled for this guid, but not
  348. // for this instance set so call data source for instance set
  349. // to enable collection. First set the in progress flag and
  350. // InstanceSet set flag to denote that collection has been enabled
  351. // for the instance set.
  352. GuidEntry->Flags |= GE_FLAG_COLLECTION_IN_PROGRESS;
  353. InstanceSet->Flags &= ~IS_ENABLE_COLLECTION;
  354. WmipLeaveSMCritSection();
  355. WmipDeliverWnodeToDS(IRP_MN_DISABLE_COLLECTION,
  356. InstanceSet->DataSource,
  357. &Wnode,
  358. Wnode.BufferSize);
  359. WmipEnterSMCritSection();
  360. //
  361. // Now we need to check if events were disabled while the enable
  362. // request was in progress. If so go do the work to actually
  363. // disable them.
  364. if (GuidEntry->CollectRefCount == 0)
  365. {
  366. Status = WmipDoDisableRequest(GuidEntry,
  367. FALSE,
  368. FALSE,
  369. 0,
  370. GE_FLAG_COLLECTION_IN_PROGRESS);
  371. } else {
  372. GuidEntry->Flags &= ~GE_FLAG_COLLECTION_IN_PROGRESS;
  373. //
  374. // If there are any other threads that were waiting
  375. // until all of the enable/disable work completed, we
  376. // close the event handle to release them from their wait.
  377. //
  378. WmipReleaseCollectionEnabled(GuidEntry);
  379. }
  380. }
  381. WmipUnreferenceGE(GuidEntry);
  382. WmipLeaveSMCritSection();
  383. } else {
  384. WmipAssert(FALSE);
  385. }
  386. }
  387. ULONG WmipDetermineInstanceBaseIndex(
  388. LPGUID Guid,
  389. PWCHAR BaseName,
  390. ULONG InstanceCount
  391. )
  392. /*++
  393. Routine Description:
  394. Figure out the base index for the instance names specified by a base
  395. instance name. We walk the list of instances sets for the guid and if
  396. there is a match in the base instance name we set the base instance index
  397. above that used by the previously registered instance set.
  398. Arguments:
  399. Guid points at guid for the instance names
  400. BaseName points at the base name for the instances
  401. InstanceCount is the count of instance names
  402. Return Value:
  403. Base index for instance name
  404. --*/
  405. {
  406. PBGUIDENTRY GuidEntry;
  407. ULONG BaseIndex = 0;
  408. PLIST_ENTRY InstanceSetList;
  409. PBINSTANCESET InstanceSet;
  410. ULONG LastBaseIndex;
  411. PAGED_CODE();
  412. UNREFERENCED_PARAMETER (InstanceCount);
  413. WmipEnterSMCritSection();
  414. GuidEntry = WmipFindGEByGuid(Guid, FALSE);
  415. if (GuidEntry != NULL)
  416. {
  417. InstanceSetList = GuidEntry->ISHead.Flink;
  418. while (InstanceSetList != &GuidEntry->ISHead)
  419. {
  420. InstanceSet = CONTAINING_RECORD(InstanceSetList,
  421. INSTANCESET,
  422. GuidISList);
  423. if (InstanceSet->Flags & IS_INSTANCE_BASENAME)
  424. {
  425. if (wcscmp(BaseName, InstanceSet->IsBaseName->BaseName) == 0)
  426. {
  427. LastBaseIndex = InstanceSet->IsBaseName->BaseIndex + InstanceSet->Count;
  428. if (BaseIndex <= LastBaseIndex)
  429. {
  430. BaseIndex = LastBaseIndex;
  431. }
  432. }
  433. }
  434. InstanceSetList = InstanceSetList->Flink;
  435. }
  436. WmipUnreferenceGE(GuidEntry);
  437. }
  438. WmipLeaveSMCritSection();
  439. WmipDebugPrintEx((DPFLTR_WMICORE_ID, DPFLTR_INFO_LEVEL,"WMI: Static instance name %ws has base index %x\n",
  440. BaseName, BaseIndex));
  441. return(BaseIndex);
  442. }
  443. ULONG WmipMangleInstanceName(
  444. LPGUID Guid,
  445. PWCHAR Name,
  446. ULONG MaxMangledNameLen,
  447. PWCHAR MangledName
  448. )
  449. /*++
  450. Routine Description:
  451. Copies a static instance name from the input buffer to the output
  452. buffer, mangling it if the name collides with another name for the
  453. same guid.
  454. Arguments:
  455. Guid points at guid for the instance name
  456. Name points at the proposed instance name
  457. MaxMangledNameLen has the maximum number of chars in mangled name buffer
  458. MangledName points at buffer to return mangled name
  459. Return Value:
  460. Actual length of mangled name
  461. --*/
  462. {
  463. PBGUIDENTRY GuidEntry;
  464. WCHAR ManglingChar;
  465. ULONG ManglePos;
  466. ULONG InstanceIndex;
  467. PBINSTANCESET InstanceSet;
  468. PAGED_CODE();
  469. WmipAssert(MaxMangledNameLen >= wcslen(Name));
  470. wcsncpy(MangledName, Name, MaxMangledNameLen);
  471. GuidEntry = WmipFindGEByGuid(Guid, FALSE);
  472. if (GuidEntry != NULL)
  473. {
  474. ManglePos = (ULONG)wcslen(MangledName)-1;
  475. ManglingChar = L'Z';
  476. //
  477. // Loop until we get a unique name
  478. InstanceSet = WmipFindISinGEbyName(GuidEntry,
  479. MangledName,
  480. &InstanceIndex);
  481. while (InstanceSet != NULL)
  482. {
  483. WmipUnreferenceIS(InstanceSet);
  484. WmipDebugPrintEx((DPFLTR_WMICORE_ID, DPFLTR_INFO_LEVEL,"WMI: Need to mangle name %ws\n",
  485. MangledName));
  486. if (ManglingChar == L'Z')
  487. {
  488. ManglingChar = L'A';
  489. if (++ManglePos == MaxMangledNameLen)
  490. {
  491. WmipDebugPrintEx((DPFLTR_WMICORE_ID, DPFLTR_INFO_LEVEL,"WMI: Instance Name could not be mangled\n"));
  492. break;
  493. }
  494. MangledName[ManglePos+1] = UNICODE_NULL;
  495. } else {
  496. ManglingChar++;
  497. }
  498. MangledName[ManglePos] = ManglingChar;
  499. InstanceSet = WmipFindISinGEbyName(GuidEntry,
  500. MangledName,
  501. &InstanceIndex) ;
  502. }
  503. WmipUnreferenceGE(GuidEntry);
  504. }
  505. return(ULONG)(wcslen(MangledName)+1);
  506. }
  507. NTSTATUS WmipBuildInstanceSet(
  508. PWMIREGGUID RegGuid,
  509. PWMIREGINFOW WmiRegInfo,
  510. ULONG BufferSize,
  511. PBINSTANCESET InstanceSet,
  512. ULONG ProviderId,
  513. LPCTSTR MofImagePath
  514. )
  515. {
  516. PWCHAR InstanceName, InstanceNamePtr;
  517. PBISBASENAME IsBaseName;
  518. PBISSTATICNAMES IsStaticName;
  519. ULONG SizeNeeded;
  520. ULONG SuffixSize;
  521. PWCHAR StaticNames;
  522. ULONG Len;
  523. ULONG InstanceCount;
  524. ULONG j;
  525. ULONG MaxStaticInstanceNameSize;
  526. PWCHAR StaticInstanceNameBuffer;
  527. ULONG InstanceNameOffset;
  528. NTSTATUS Status;
  529. PAGED_CODE();
  530. UNREFERENCED_PARAMETER (MofImagePath);
  531. //
  532. // Remember the count of instances for the guid in the DS
  533. //
  534. InstanceCount = RegGuid->InstanceCount;
  535. InstanceSet->Count = InstanceCount;
  536. InstanceSet->ProviderId = ProviderId;
  537. //
  538. // Reset any flags that might be changed by a new REGGUID
  539. //
  540. InstanceSet->Flags &= ~(IS_EXPENSIVE |
  541. IS_EVENT_ONLY |
  542. IS_PDO_INSTANCENAME |
  543. IS_INSTANCE_STATICNAMES |
  544. IS_INSTANCE_BASENAME);
  545. //
  546. // Finish initializing the Instance Set flags
  547. //
  548. if (RegGuid->Flags & WMIREG_FLAG_EXPENSIVE)
  549. {
  550. InstanceSet->Flags |= IS_EXPENSIVE;
  551. }
  552. if (RegGuid->Flags & WMIREG_FLAG_TRACED_GUID)
  553. {
  554. //
  555. // This guid is not queryable, but is used for sending trace
  556. // events. We mark the InstanceSet as special
  557. InstanceSet->Flags |= IS_TRACED;
  558. if (RegGuid->Flags & WMIREG_FLAG_TRACE_CONTROL_GUID)
  559. {
  560. InstanceSet->Flags |= IS_CONTROL_GUID;
  561. }
  562. }
  563. if (RegGuid->Flags & WMIREG_FLAG_EVENT_ONLY_GUID)
  564. {
  565. //
  566. // This guid is not queryable, but is only used for sending
  567. // events. We mark the InstanceSet as special
  568. InstanceSet->Flags |= IS_EVENT_ONLY;
  569. }
  570. InstanceName = (LPWSTR)OffsetToPtr(WmiRegInfo,
  571. RegGuid->BaseNameOffset);
  572. InstanceNameOffset = RegGuid->BaseNameOffset;
  573. if (RegGuid->Flags & WMIREG_FLAG_INSTANCE_LIST)
  574. {
  575. //
  576. // We have static list of instance names that might need mangling
  577. // We assume that any name mangling that must occur can be
  578. // done with a suffix of 5 or fewer characters. This allows
  579. // up to 100,000 identical static instance names within the
  580. // same guid. First lets get the amount of memory we'll need
  581. //
  582. SizeNeeded = FIELD_OFFSET(ISSTATICENAMES, StaticNamePtr) + 1;
  583. SuffixSize = MAXBASENAMESUFFIXSIZE;
  584. MaxStaticInstanceNameSize = 0;
  585. for (j = 0; j < InstanceCount; j++)
  586. {
  587. Status = WmipValidateWmiRegInfoString(WmiRegInfo,
  588. BufferSize,
  589. InstanceNameOffset,
  590. &InstanceNamePtr);
  591. if ((! NT_SUCCESS(Status)) || (InstanceNamePtr == NULL))
  592. {
  593. WmipDebugPrintEx((DPFLTR_WMICORE_ID, DPFLTR_INFO_LEVEL,"WMI: WmipAddDataSource: bad static instance name %x\n", InstanceNamePtr));
  594. WmipReportEventLog(EVENT_WMI_INVALID_REGINFO,
  595. EVENTLOG_WARNING_TYPE,
  596. 0,
  597. WmiRegInfo->BufferSize,
  598. WmiRegInfo,
  599. 1,
  600. MofImagePath ? MofImagePath : TEXT("Unknown"));
  601. return(STATUS_INVALID_PARAMETER);
  602. }
  603. if (*InstanceNamePtr > MaxStaticInstanceNameSize)
  604. {
  605. MaxStaticInstanceNameSize = *InstanceNamePtr;
  606. }
  607. SizeNeeded += *InstanceNamePtr + 1 + SuffixSize +
  608. (sizeof(PWCHAR) / sizeof(WCHAR));
  609. InstanceNameOffset += *InstanceNamePtr + 2;
  610. }
  611. IsStaticName = (PBISSTATICNAMES)WmipAllocString(SizeNeeded);
  612. if (IsStaticName == NULL)
  613. {
  614. WmipDebugPrintEx((DPFLTR_WMICORE_ID, DPFLTR_INFO_LEVEL,"WMI: WmipAddDataSource: alloc static instance names\n"));
  615. return(STATUS_INSUFFICIENT_RESOURCES);
  616. }
  617. InstanceSet->Flags |= IS_INSTANCE_STATICNAMES;
  618. InstanceSet->IsStaticNames = IsStaticName;
  619. StaticNames = (PWCHAR) ((PUCHAR)IsStaticName +
  620. (InstanceCount * sizeof(PWCHAR)));
  621. InstanceNamePtr = InstanceName;
  622. StaticInstanceNameBuffer = WmipAlloc(MaxStaticInstanceNameSize + sizeof(WCHAR));
  623. if (StaticInstanceNameBuffer == NULL)
  624. {
  625. WmipDebugPrintEx((DPFLTR_WMICORE_ID, DPFLTR_INFO_LEVEL,"WMI: WmipAddDataSource: couldn't alloc StaticInstanceNameBuffer\n"));
  626. return(STATUS_INSUFFICIENT_RESOURCES);
  627. }
  628. for (j = 0; j < InstanceCount; j++)
  629. {
  630. IsStaticName->StaticNamePtr[j] = StaticNames;
  631. memcpy(StaticInstanceNameBuffer, InstanceNamePtr+1, *InstanceNamePtr);
  632. StaticInstanceNameBuffer[*InstanceNamePtr/sizeof(WCHAR)] = UNICODE_NULL;
  633. Len = WmipMangleInstanceName(&RegGuid->Guid,
  634. StaticInstanceNameBuffer,
  635. *InstanceNamePtr +
  636. SuffixSize + 1,
  637. StaticNames);
  638. StaticNames += Len;
  639. InstanceNamePtr += (*((USHORT *)InstanceNamePtr) + 2)/sizeof(WCHAR);
  640. }
  641. WmipFree(StaticInstanceNameBuffer);
  642. } else if (RegGuid->Flags & WMIREG_FLAG_INSTANCE_BASENAME) {
  643. //
  644. // We have static instance names built from a base name
  645. Status = WmipValidateWmiRegInfoString(WmiRegInfo,
  646. BufferSize,
  647. InstanceNameOffset,
  648. &InstanceNamePtr);
  649. if (! NT_SUCCESS(Status))
  650. {
  651. WmipDebugPrintEx((DPFLTR_WMICORE_ID, DPFLTR_INFO_LEVEL,"WMI: WmipAddDataSource: Invalid instance base name %x\n",
  652. InstanceName));
  653. WmipReportEventLog(EVENT_WMI_INVALID_REGINFO,
  654. EVENTLOG_WARNING_TYPE,
  655. 0,
  656. WmiRegInfo->BufferSize,
  657. WmiRegInfo,
  658. 1,
  659. MofImagePath ? MofImagePath : TEXT("Unknown"));
  660. return(STATUS_INVALID_PARAMETER);
  661. }
  662. InstanceSet->Flags |= IS_INSTANCE_BASENAME;
  663. if (RegGuid->Flags & WMIREG_FLAG_INSTANCE_PDO)
  664. {
  665. InstanceSet->Flags |= IS_PDO_INSTANCENAME;
  666. }
  667. IsBaseName = (PBISBASENAME)WmipAlloc(*InstanceName +
  668. sizeof(WCHAR) +
  669. FIELD_OFFSET(ISBASENAME,
  670. BaseName));
  671. if (IsBaseName == NULL)
  672. {
  673. WmipDebugPrintEx((DPFLTR_WMICORE_ID, DPFLTR_INFO_LEVEL,"WMI: WmipAddDataSource: alloc ISBASENAME failed\n"));
  674. return(STATUS_INSUFFICIENT_RESOURCES);
  675. }
  676. InstanceSet->IsBaseName = IsBaseName;
  677. memcpy(IsBaseName->BaseName, InstanceName+1, *InstanceName);
  678. IsBaseName->BaseName[*InstanceName/sizeof(WCHAR)] = UNICODE_NULL;
  679. IsBaseName->BaseIndex = WmipDetermineInstanceBaseIndex(
  680. &RegGuid->Guid,
  681. IsBaseName->BaseName,
  682. RegGuid->InstanceCount);
  683. }
  684. return(STATUS_SUCCESS);
  685. }
  686. NTSTATUS WmipLinkDataSourceToList(
  687. PBDATASOURCE DataSource,
  688. BOOLEAN AddDSToList
  689. )
  690. /*++
  691. Routine Description:
  692. This routine will take a DataSource that was just registered or updated
  693. and link any new InstanceSets to an appropriate GuidEntry. Then if the
  694. AddDSToList is TRUE the DataSource itself will be added to the main
  695. data source list.
  696. This routine will do all of the linkages within a critical section so the
  697. data source and its new instances are added atomically. The routine will
  698. also determine if the guid entry associated with a InstanceSet is a
  699. duplicate of another that is already on the main guid entry list and if
  700. so will use the preexisting guid entry.
  701. This routine assumes that the SM critical section has been taken
  702. Arguments:
  703. DataSource is a based pointer to a DataSource structure
  704. AddDSToList is TRUE then data source will be added to the main list
  705. of data sources
  706. Return Value:
  707. ERROR_SUCCESS or an error code
  708. --*/
  709. {
  710. PBINSTANCESET InstanceSet;
  711. PLIST_ENTRY InstanceSetList;
  712. PBGUIDENTRY GuidEntry;
  713. PAGED_CODE();
  714. InstanceSetList = DataSource->ISHead.Flink;
  715. while (InstanceSetList != &DataSource->ISHead)
  716. {
  717. InstanceSet = CONTAINING_RECORD(InstanceSetList,
  718. INSTANCESET,
  719. DSISList);
  720. //
  721. // If this instance set has just been registered then we need to
  722. // get it on a GuidEntry list.
  723. if (InstanceSet->Flags & IS_NEWLY_REGISTERED)
  724. {
  725. //
  726. // See if there is already a GUID entry for the instance set.
  727. // If not go allocate a new guid entry and place it on the
  728. // main guid list. If there already is a GuidEntry for the
  729. // InstanceSet we will assign the ref count that was given by
  730. // the WmipFindGEByGuid to the DataSource which will unreference
  731. // the GuidEntry when the DataSource is unregistered.
  732. GuidEntry = WmipFindGEByGuid((LPGUID)InstanceSet->GuidEntry,
  733. FALSE);
  734. if (GuidEntry == NULL)
  735. {
  736. GuidEntry = WmipAllocGuidEntry();
  737. if (GuidEntry == NULL)
  738. {
  739. WmipDebugPrintEx((DPFLTR_WMICORE_ID, DPFLTR_INFO_LEVEL,"WMI: WmipLinkDataSourceToList: WmipAllocGuidEntry failed\n"));
  740. return(STATUS_INSUFFICIENT_RESOURCES);
  741. }
  742. //
  743. // Initialize the new GuidEntry and place it on the master
  744. // GuidEntry list.
  745. memcpy(&GuidEntry->Guid,
  746. (LPGUID)InstanceSet->GuidEntry,
  747. sizeof(GUID));
  748. InsertHeadList(WmipGEHeadPtr, &GuidEntry->MainGEList);
  749. }
  750. InstanceSet->GuidEntry = GuidEntry;
  751. InstanceSet->Flags &= ~IS_NEWLY_REGISTERED;
  752. InsertTailList(&GuidEntry->ISHead, &InstanceSet->GuidISList);
  753. GuidEntry->ISCount++;
  754. }
  755. InstanceSetList = InstanceSetList->Flink;
  756. }
  757. if (AddDSToList)
  758. {
  759. WmipAssert(! (DataSource->Flags & FLAG_ENTRY_ON_INUSE_LIST));
  760. DataSource->Flags |= FLAG_ENTRY_ON_INUSE_LIST;
  761. InsertTailList(WmipDSHeadPtr, &DataSource->MainDSList);
  762. }
  763. return(STATUS_SUCCESS);
  764. }
  765. void WmipSendGuidUpdateNotifications(
  766. NOTIFICATIONTYPES NotificationType,
  767. ULONG GuidCount,
  768. PTRCACHE *GuidList
  769. )
  770. {
  771. PUCHAR WnodeBuffer;
  772. PWNODE_SINGLE_INSTANCE Wnode;
  773. ULONG WnodeSize;
  774. LPGUID GuidPtr;
  775. ULONG i;
  776. PWCHAR InstanceName;
  777. PMSWmi_GuidRegistrationInfo RegInfo;
  778. ULONG DataBlockSize;
  779. GUID RegChangeGuid = MSWmi_GuidRegistrationInfoGuid;
  780. #define REGUPDATENAME L"REGUPDATEINFO"
  781. PAGED_CODE();
  782. DataBlockSize = sizeof(MSWmi_GuidRegistrationInfo) +
  783. GuidCount*sizeof(GUID) - sizeof(GUID);
  784. WnodeSize = sizeof(WNODE_SINGLE_INSTANCE) +
  785. sizeof(USHORT) + sizeof(REGUPDATENAME) + 8 + DataBlockSize;
  786. WnodeBuffer = WmipAlloc(WnodeSize);
  787. if (WnodeBuffer != NULL)
  788. {
  789. Wnode = (PWNODE_SINGLE_INSTANCE)WnodeBuffer;
  790. //
  791. // Setup a WNODE_SINGLE_INSTANCE event with the updated guid
  792. // registration information
  793. //
  794. memset(Wnode, 0, sizeof(WNODE_HEADER));
  795. Wnode->WnodeHeader.Guid = RegChangeGuid;
  796. Wnode->WnodeHeader.BufferSize = WnodeSize;
  797. Wnode->WnodeHeader.Flags = WNODE_FLAG_SINGLE_INSTANCE |
  798. WNODE_FLAG_EVENT_ITEM;
  799. Wnode->OffsetInstanceName = sizeof(WNODE_SINGLE_INSTANCE);
  800. Wnode->DataBlockOffset = ((Wnode->OffsetInstanceName +
  801. sizeof(USHORT) + sizeof(REGUPDATENAME) + 7) & ~7);
  802. Wnode->SizeDataBlock = DataBlockSize;
  803. InstanceName = (PWCHAR)OffsetToPtr(Wnode, Wnode->OffsetInstanceName);
  804. *InstanceName++ = sizeof(REGUPDATENAME);
  805. StringCbCopy(InstanceName, sizeof(REGUPDATENAME), REGUPDATENAME);
  806. RegInfo = (PMSWmi_GuidRegistrationInfo)OffsetToPtr(Wnode,
  807. Wnode->DataBlockOffset);
  808. RegInfo->Operation = NotificationType;
  809. RegInfo->GuidCount = GuidCount;
  810. GuidPtr = (LPGUID)RegInfo->GuidList;
  811. for (i = 0; i < GuidCount; i++)
  812. {
  813. *GuidPtr++ = *GuidList[i].Guid;
  814. }
  815. WmipProcessEvent((PWNODE_HEADER)Wnode, TRUE, FALSE);
  816. WmipFree(WnodeBuffer);
  817. }
  818. }
  819. void WmipGenerateBinaryMofNotification(
  820. PBINSTANCESET BinaryMofInstanceSet,
  821. LPCGUID Guid
  822. )
  823. {
  824. PWNODE_SINGLE_INSTANCE Wnode;
  825. SIZE_T ImagePathLen, ResourceNameLen, InstanceNameLen, BufferSize;
  826. PWCHAR Ptr;
  827. ULONG i;
  828. HRESULT hr;
  829. PAGED_CODE();
  830. if (BinaryMofInstanceSet->Count == 0)
  831. {
  832. return;
  833. }
  834. for (i = 0; i < BinaryMofInstanceSet->Count; i++)
  835. {
  836. ImagePathLen = sizeof(USHORT);
  837. InstanceNameLen = (sizeof(USHORT) + 7) & ~7;
  838. if (BinaryMofInstanceSet->Flags & IS_INSTANCE_STATICNAMES)
  839. {
  840. ResourceNameLen = ((wcslen(BinaryMofInstanceSet->IsStaticNames->StaticNamePtr[i])+1) * sizeof(WCHAR)) + sizeof(USHORT);
  841. } else if (BinaryMofInstanceSet->Flags & IS_INSTANCE_BASENAME) {
  842. ResourceNameLen = (((wcslen(BinaryMofInstanceSet->IsBaseName->BaseName) +
  843. MAXBASENAMESUFFIXSIZE) * sizeof(WCHAR)) + sizeof(USHORT));
  844. } else {
  845. return;
  846. }
  847. BufferSize = FIELD_OFFSET(WNODE_SINGLE_INSTANCE, VariableData) +
  848. InstanceNameLen +
  849. ImagePathLen +
  850. ResourceNameLen;
  851. Wnode = (PWNODE_SINGLE_INSTANCE)WmipAlloc(BufferSize);
  852. if (Wnode != NULL)
  853. {
  854. Wnode->WnodeHeader.BufferSize = (ULONG) BufferSize;
  855. Wnode->WnodeHeader.ProviderId = MOFEVENT_ACTION_BINARY_MOF;
  856. Wnode->WnodeHeader.Version = 1;
  857. Wnode->WnodeHeader.Linkage = 0;
  858. Wnode->WnodeHeader.Flags = (WNODE_FLAG_EVENT_ITEM |
  859. WNODE_FLAG_SINGLE_INSTANCE);
  860. memcpy(&Wnode->WnodeHeader.Guid,
  861. Guid,
  862. sizeof(GUID));
  863. WmiInsertTimestamp(&Wnode->WnodeHeader);
  864. Wnode->OffsetInstanceName = FIELD_OFFSET(WNODE_SINGLE_INSTANCE,
  865. VariableData);
  866. Wnode->DataBlockOffset = (ULONG)(Wnode->OffsetInstanceName +
  867. InstanceNameLen);
  868. Wnode->SizeDataBlock = (ULONG)(ImagePathLen + ResourceNameLen);
  869. Ptr = (PWCHAR)&Wnode->VariableData;
  870. *Ptr++ = 0; // Empty instance name
  871. Ptr = (PWCHAR)OffsetToPtr(Wnode, Wnode->DataBlockOffset);
  872. *Ptr++ = 0; // Empty image path
  873. // Instance name for binary mof resource
  874. ResourceNameLen -= sizeof(USHORT);
  875. if (BinaryMofInstanceSet->Flags & IS_INSTANCE_STATICNAMES)
  876. {
  877. *Ptr++ = (USHORT)ResourceNameLen;
  878. hr = StringCbCopy(Ptr,
  879. ResourceNameLen,
  880. BinaryMofInstanceSet->IsStaticNames->StaticNamePtr[i]);
  881. WmipAssert(hr == S_OK);
  882. } else if (BinaryMofInstanceSet->Flags & IS_INSTANCE_BASENAME) {
  883. hr = (USHORT)StringCbPrintfEx(Ptr+1,
  884. ResourceNameLen,
  885. NULL,
  886. NULL,
  887. STRSAFE_FILL_BEHIND_NULL,
  888. L"%ws%d",
  889. BinaryMofInstanceSet->IsBaseName->BaseName,
  890. BinaryMofInstanceSet->IsBaseName->BaseIndex+i) * sizeof(WCHAR);
  891. WmipAssert(hr == S_OK);
  892. *Ptr = (USHORT)ResourceNameLen;
  893. }
  894. WmipProcessEvent((PWNODE_HEADER)Wnode, TRUE, FALSE);
  895. WmipFree(Wnode);
  896. }
  897. }
  898. }
  899. void WmipGenerateMofResourceNotification(
  900. LPWSTR ImagePath,
  901. LPWSTR ResourceName,
  902. LPCGUID Guid,
  903. ULONG ActionCode
  904. )
  905. {
  906. PWNODE_SINGLE_INSTANCE Wnode;
  907. SIZE_T ImagePathLen, ResourceNameLen, InstanceNameLen, BufferSize;
  908. PWCHAR Ptr;
  909. PAGED_CODE();
  910. ImagePathLen = (wcslen(ImagePath) + 2) * sizeof(WCHAR);
  911. ResourceNameLen = (wcslen(ResourceName) + 2) * sizeof(WCHAR);
  912. InstanceNameLen = ( sizeof(USHORT)+7 ) & ~7;
  913. BufferSize = FIELD_OFFSET(WNODE_SINGLE_INSTANCE, VariableData) +
  914. InstanceNameLen +
  915. ImagePathLen +
  916. ResourceNameLen;
  917. Wnode = (PWNODE_SINGLE_INSTANCE)WmipAlloc(BufferSize);
  918. if (Wnode != NULL)
  919. {
  920. Wnode->WnodeHeader.BufferSize = (ULONG) BufferSize;
  921. Wnode->WnodeHeader.ProviderId = ActionCode;
  922. Wnode->WnodeHeader.Version = 1;
  923. Wnode->WnodeHeader.Linkage = 0;
  924. Wnode->WnodeHeader.Flags = (WNODE_FLAG_EVENT_ITEM |
  925. WNODE_FLAG_SINGLE_INSTANCE |
  926. WNODE_FLAG_INTERNAL);
  927. memcpy(&Wnode->WnodeHeader.Guid,
  928. Guid,
  929. sizeof(GUID));
  930. WmiInsertTimestamp(&Wnode->WnodeHeader);
  931. Wnode->OffsetInstanceName = FIELD_OFFSET(WNODE_SINGLE_INSTANCE,
  932. VariableData);
  933. Wnode->DataBlockOffset = (ULONG)(Wnode->OffsetInstanceName + InstanceNameLen);
  934. Wnode->SizeDataBlock = (ULONG)(ImagePathLen + ResourceNameLen);
  935. Ptr = (PWCHAR)&Wnode->VariableData;
  936. *Ptr = 0; // Empty instance name
  937. // ImagePath name
  938. Ptr = (PWCHAR)OffsetToPtr(Wnode, Wnode->DataBlockOffset);
  939. ImagePathLen -= sizeof(USHORT);
  940. *Ptr++ = (USHORT)ImagePathLen;
  941. memcpy(Ptr, ImagePath, ImagePathLen);
  942. Ptr += (ImagePathLen / sizeof(WCHAR));
  943. // MofResource Name
  944. ResourceNameLen -= sizeof(USHORT);
  945. *Ptr++ = (USHORT)ResourceNameLen;
  946. memcpy(Ptr, ResourceName, ResourceNameLen);
  947. WmipProcessEvent((PWNODE_HEADER)Wnode, TRUE, FALSE);
  948. WmipFree(Wnode);
  949. }
  950. }
  951. void WmipGenerateRegistrationNotification(
  952. PBDATASOURCE DataSource,
  953. NOTIFICATIONTYPES NotificationType
  954. )
  955. {
  956. PTRCACHE *Guids;
  957. ULONG GuidCount, GuidMax;
  958. PLIST_ENTRY InstanceSetList;
  959. PBINSTANCESET InstanceSet;
  960. LPGUID Guid;
  961. PAGED_CODE();
  962. WmipReferenceDS(DataSource);
  963. //
  964. // Loop over all instance sets for this data source
  965. //
  966. GuidCount = 0;
  967. GuidMax = 0;
  968. Guids = NULL;
  969. InstanceSetList = DataSource->ISHead.Flink;
  970. while (InstanceSetList != &DataSource->ISHead)
  971. {
  972. InstanceSet = CONTAINING_RECORD(InstanceSetList,
  973. INSTANCESET,
  974. DSISList);
  975. //
  976. // Cache the guid and instance set so we can send registration
  977. // change notifications
  978. //
  979. Guid = &InstanceSet->GuidEntry->Guid;
  980. WmipCachePtrs(Guid,
  981. InstanceSet,
  982. &GuidCount,
  983. &GuidMax,
  984. &Guids);
  985. //
  986. // If we are adding a guid and it is already enabled then we
  987. // need to send an enable irp. Likewise if the guid is being
  988. // removed and is enabled then we need to send a disable
  989. //
  990. if (NotificationType == RegistrationAdd)
  991. {
  992. WmipEnableCollectionForNewGuid(Guid, InstanceSet);
  993. } else if (NotificationType == RegistrationDelete) {
  994. WmipDisableCollectionForRemovedGuid(Guid, InstanceSet);
  995. }
  996. InstanceSetList = InstanceSetList->Flink;
  997. }
  998. //
  999. // Send out event that informs about guid registration changes
  1000. //
  1001. WmipSendGuidUpdateNotifications(NotificationType,
  1002. GuidCount,
  1003. Guids);
  1004. if (Guids != NULL)
  1005. {
  1006. WmipFree(Guids);
  1007. }
  1008. WmipUnreferenceDS(DataSource);
  1009. }
  1010. NTSTATUS WmipAddMofResource(
  1011. PBDATASOURCE DataSource,
  1012. LPWSTR ImagePath,
  1013. BOOLEAN IsImagePath,
  1014. LPWSTR MofResourceName,
  1015. PBOOLEAN NewMofResource
  1016. )
  1017. /*++
  1018. Routine Description:
  1019. This routine will build MOFCLASSINFO structures for each guid that is
  1020. described in the MOF for the data source. If there are any errors in the
  1021. mof resource then no mof information from the resource is retained and the
  1022. resource data is unloaded.
  1023. Arguments:
  1024. DataSource is the data source structure of the data provider
  1025. ImagePath points at a string that has the full path to the image
  1026. file that contains the MOF resource
  1027. MofResourceName points at a string that has the name of the MOF
  1028. resource
  1029. Return Value:
  1030. --*/
  1031. {
  1032. PMOFRESOURCE MofResource;
  1033. ULONG NewMofResourceCount;
  1034. ULONG i;
  1035. BOOLEAN FreeBuffer;
  1036. size_t RegPathLen, ResNameLen;
  1037. HRESULT hr;
  1038. PAGED_CODE();
  1039. MofResource = WmipFindMRByNames(ImagePath,
  1040. MofResourceName);
  1041. if (MofResource == NULL)
  1042. {
  1043. //
  1044. // Mof Resource not previously specified, so allocate a new one
  1045. MofResource = WmipAllocMofResource();
  1046. if (MofResource == NULL)
  1047. {
  1048. return(STATUS_INSUFFICIENT_RESOURCES);
  1049. }
  1050. if (IsImagePath)
  1051. {
  1052. MofResource->Flags |= MR_FLAG_USER_MODE;
  1053. }
  1054. RegPathLen = (wcslen(ImagePath)+1) * sizeof(WCHAR);
  1055. MofResource->RegistryPath = WmipAlloc(RegPathLen);
  1056. ResNameLen = (wcslen(MofResourceName) + 1) * sizeof(WCHAR);
  1057. MofResource->MofResourceName = WmipAlloc(ResNameLen);
  1058. if ((MofResource->RegistryPath == NULL) ||
  1059. (MofResource->MofResourceName == NULL))
  1060. {
  1061. //
  1062. // Allocation cleanup routine will free any memory alloced for MR
  1063. WmipUnreferenceMR(MofResource);
  1064. return(STATUS_INSUFFICIENT_RESOURCES);
  1065. }
  1066. hr = StringCbCopy(MofResource->RegistryPath, RegPathLen, ImagePath);
  1067. WmipAssert(hr == S_OK);
  1068. hr = StringCbCopy(MofResource->MofResourceName, ResNameLen, MofResourceName);
  1069. WmipAssert(hr == S_OK);
  1070. WmipEnterSMCritSection();
  1071. InsertTailList(WmipMRHeadPtr, &MofResource->MainMRList);
  1072. WmipLeaveSMCritSection();
  1073. *NewMofResource = TRUE;
  1074. } else {
  1075. *NewMofResource = FALSE;
  1076. }
  1077. if (DataSource != NULL)
  1078. {
  1079. WmipEnterSMCritSection();
  1080. for (i = 0; i < DataSource->MofResourceCount; i++)
  1081. {
  1082. if (DataSource->MofResources[i] == MofResource)
  1083. {
  1084. //
  1085. // If this mof resource is already been registered for
  1086. // this data source then we do not need to worry about
  1087. // it anymore.
  1088. //
  1089. WmipUnreferenceMR(MofResource);
  1090. break;
  1091. }
  1092. if (DataSource->MofResources[i] == NULL)
  1093. {
  1094. DataSource->MofResources[i] = MofResource;
  1095. break;
  1096. }
  1097. }
  1098. if (i == DataSource->MofResourceCount)
  1099. {
  1100. NewMofResourceCount = DataSource->MofResourceCount +
  1101. AVGMOFRESOURCECOUNT;
  1102. if (DataSource->MofResources !=
  1103. DataSource->StaticMofResources)
  1104. {
  1105. FreeBuffer = TRUE;
  1106. } else {
  1107. FreeBuffer = FALSE;
  1108. }
  1109. if (WmipRealloc((PVOID *)&DataSource->MofResources,
  1110. DataSource->MofResourceCount * sizeof(PMOFRESOURCE),
  1111. NewMofResourceCount * sizeof(PMOFRESOURCE),
  1112. FreeBuffer ) )
  1113. {
  1114. DataSource->MofResourceCount = NewMofResourceCount;
  1115. DataSource->MofResources[i] = MofResource;
  1116. }
  1117. }
  1118. WmipLeaveSMCritSection();
  1119. }
  1120. return(STATUS_SUCCESS);
  1121. }
  1122. NTSTATUS WmipAddDataSource(
  1123. IN PREGENTRY RegEntry,
  1124. IN PWMIREGINFOW WmiRegInfo,
  1125. IN ULONG BufferSize,
  1126. IN PWCHAR RegPath,
  1127. IN PWCHAR ResourceName,
  1128. IN PWMIGUIDOBJECT RequestObject,
  1129. IN BOOLEAN IsUserMode
  1130. )
  1131. /*+++
  1132. Routine Description:
  1133. This routine will register a information in the WMI database for a
  1134. new DataSource or add additional guids to an existing data source.
  1135. Arguments:
  1136. RegEntry is the regentry for the data provider
  1137. WmiRegInfo is the registration information to register
  1138. BufferSize is the size of WmiRegInfo in bytes
  1139. RegPath is a pointer into WmiRegInfo to a counted string that is the
  1140. registry path (or image path for UM providers).
  1141. ResourceName is a pointer into WmiRegInfo to a counted string that is the
  1142. resource name
  1143. RequestObject is the request object associated with the UM provider.
  1144. If this is NULL then the registration is for a driver
  1145. Return Value:
  1146. STATUS_SUCCESS or an error code
  1147. ---*/
  1148. {
  1149. PBDATASOURCE DataSource;
  1150. PWMIREGGUID RegGuid;
  1151. ULONG i;
  1152. NTSTATUS Status, Status2;
  1153. PBINSTANCESET InstanceSet;
  1154. PBINSTANCESET BinaryMofInstanceSet = NULL;
  1155. PWCHAR MofRegistryPath;
  1156. PWCHAR MofResourceName;
  1157. BOOLEAN AppendToDS;
  1158. BOOLEAN NewMofResource;
  1159. PAGED_CODE();
  1160. if (RegEntry->DataSource != NULL)
  1161. {
  1162. DataSource = RegEntry->DataSource;
  1163. WmipAssert(DataSource != NULL);
  1164. AppendToDS = TRUE;
  1165. } else {
  1166. DataSource = WmipAllocDataSource();
  1167. AppendToDS = FALSE;
  1168. }
  1169. if (DataSource != NULL)
  1170. {
  1171. //
  1172. // Loop over each guid being registered and build instance sets and
  1173. // guid entries.
  1174. //
  1175. if (! AppendToDS)
  1176. {
  1177. DataSource->ProviderId = RegEntry->ProviderId;
  1178. if (RequestObject != NULL)
  1179. {
  1180. DataSource->Flags |= DS_USER_MODE;
  1181. DataSource->RequestObject = RequestObject;
  1182. } else {
  1183. DataSource->Flags |= DS_KERNEL_MODE;
  1184. }
  1185. }
  1186. RegGuid = WmiRegInfo->WmiRegGuid;
  1187. for (i = 0; i < WmiRegInfo->GuidCount; i++, RegGuid++)
  1188. {
  1189. if (! (RegGuid->Flags & WMIREG_FLAG_REMOVE_GUID))
  1190. {
  1191. //
  1192. // Only trace control guids are registered. Trace transaction
  1193. // guids will not be registered since they can not be enabled or
  1194. // disabled individually. They will be kept on the ControlGuids'
  1195. // instance set structure.
  1196. //
  1197. if ( ( (RegGuid->Flags & WMIREG_FLAG_TRACED_GUID) != WMIREG_FLAG_TRACED_GUID ) ||
  1198. (RegGuid->Flags & WMIREG_FLAG_TRACE_CONTROL_GUID) )
  1199. {
  1200. //
  1201. // Allocate an instance set for this new set of instances
  1202. //
  1203. InstanceSet = WmipAllocInstanceSet();
  1204. if (InstanceSet == NULL)
  1205. {
  1206. WmipUnreferenceDS(DataSource);
  1207. WmipDebugPrintEx((DPFLTR_WMICORE_ID, DPFLTR_INFO_LEVEL,"WMI: WmipAddDataSource: WmipAllocInstanceSet failed\n"));
  1208. return(STATUS_INSUFFICIENT_RESOURCES);
  1209. }
  1210. //
  1211. // We will allocate a proper guid entry for the instance
  1212. // set when the data source gets linked into the main data
  1213. // source list so we stash a pointer to the guid away now.
  1214. //
  1215. InstanceSet->GuidEntry = (PBGUIDENTRY)&RegGuid->Guid;
  1216. //
  1217. // Minimally initialize the InstanceSet and add it to
  1218. // the DataSource's list of InstanceSets. We do this
  1219. // first so that if there is any failure below and
  1220. // the DataSource can'e be fully registered the instance
  1221. // set and guid entry will be free when the DataSource is
  1222. // freed.
  1223. //
  1224. InstanceSet->DataSource = DataSource;
  1225. InstanceSet->Flags |= IS_NEWLY_REGISTERED;
  1226. Status = WmipBuildInstanceSet(RegGuid,
  1227. WmiRegInfo,
  1228. BufferSize,
  1229. InstanceSet,
  1230. RegEntry->ProviderId,
  1231. RegPath);
  1232. //
  1233. // If this is the guid that represents the binary mof data
  1234. // then remember the InstanceSet for later
  1235. //
  1236. if (IsEqualGUID(&RegGuid->Guid, &WmipBinaryMofGuid))
  1237. {
  1238. BinaryMofInstanceSet = InstanceSet;
  1239. }
  1240. InsertHeadList(&DataSource->ISHead, &InstanceSet->DSISList);
  1241. if (! NT_SUCCESS(Status))
  1242. {
  1243. WmipUnreferenceDS(DataSource);
  1244. return(Status);
  1245. }
  1246. }
  1247. }
  1248. }
  1249. //
  1250. // Now that the instance sets have been built successfully we
  1251. // can link them into the master list.
  1252. //
  1253. WmipEnterSMCritSection();
  1254. Status = WmipLinkDataSourceToList(DataSource, (BOOLEAN)(! AppendToDS));
  1255. WmipLeaveSMCritSection();
  1256. if (! NT_SUCCESS(Status))
  1257. {
  1258. WmipUnreferenceDS(DataSource);
  1259. return(Status);
  1260. }
  1261. RegEntry->DataSource = DataSource;
  1262. //
  1263. // We need to send out notification of new guids and mofs.
  1264. //
  1265. if (BinaryMofInstanceSet != NULL)
  1266. {
  1267. //
  1268. // Send binary mof guid arrival notification
  1269. //
  1270. WmipGenerateBinaryMofNotification(BinaryMofInstanceSet,
  1271. &GUID_MOF_RESOURCE_ADDED_NOTIFICATION);
  1272. }
  1273. //
  1274. // Convert Registry path to a sz string so we can assign it to
  1275. // the DS if the DS is a new one
  1276. //
  1277. if (RegPath != NULL)
  1278. {
  1279. MofRegistryPath = WmipCountedToSz(RegPath);
  1280. } else {
  1281. MofRegistryPath = NULL;
  1282. }
  1283. if ((AppendToDS == FALSE) && (MofRegistryPath != NULL))
  1284. {
  1285. DataSource->RegistryPath = MofRegistryPath;
  1286. }
  1287. if (ResourceName != NULL)
  1288. {
  1289. MofResourceName = WmipCountedToSz(ResourceName);
  1290. } else {
  1291. MofResourceName = NULL;
  1292. }
  1293. //
  1294. // Finally if we created a new data source we need to register
  1295. // the mof for it. Only register those that have a RegistryPath
  1296. // and a ResourceName
  1297. //
  1298. if ((MofRegistryPath != NULL) &&
  1299. (*MofRegistryPath != 0) &&
  1300. (MofResourceName != NULL) &&
  1301. (*MofResourceName != 0))
  1302. {
  1303. //
  1304. // If a mof is specified then add it to the list
  1305. //
  1306. Status2 = WmipAddMofResource(DataSource,
  1307. MofRegistryPath,
  1308. IsUserMode,
  1309. MofResourceName,
  1310. &NewMofResource);
  1311. if (NT_SUCCESS(Status2) && NewMofResource)
  1312. {
  1313. //
  1314. // We successfully added a brand new MOF resource so
  1315. // we need to fire an event for wbem.
  1316. //
  1317. WmipGenerateMofResourceNotification(MofRegistryPath,
  1318. MofResourceName,
  1319. &GUID_MOF_RESOURCE_ADDED_NOTIFICATION,
  1320. IsUserMode ?
  1321. MOFEVENT_ACTION_IMAGE_PATH :
  1322. MOFEVENT_ACTION_REGISTRY_PATH);
  1323. }
  1324. }
  1325. //
  1326. // Clean up registry path and mof resource name strings
  1327. //
  1328. if ((MofRegistryPath != NULL) && AppendToDS)
  1329. {
  1330. //
  1331. // Only free if registry path not saved in DataSource
  1332. //
  1333. WmipAssert(MofRegistryPath != DataSource->RegistryPath);
  1334. WmipFree(MofRegistryPath);
  1335. }
  1336. if (MofResourceName != NULL)
  1337. {
  1338. WmipFree(MofResourceName);
  1339. }
  1340. //
  1341. // Send a notification about new/changed guids
  1342. //
  1343. WmipGenerateRegistrationNotification(DataSource,
  1344. RegistrationAdd);
  1345. } else {
  1346. Status = STATUS_INSUFFICIENT_RESOURCES;
  1347. }
  1348. return(Status);
  1349. }
  1350. PBINSTANCESET WmipFindISInDSByGuid(
  1351. PBDATASOURCE DataSource,
  1352. LPGUID Guid
  1353. )
  1354. /*++
  1355. Routine Description:
  1356. This routine will find the InstanceSet in the passed DataSource for the
  1357. guid passed.
  1358. This routine assumes that the SM critical section is held before it is
  1359. called.
  1360. Arguments:
  1361. DataSource is the data source from which the guid is to be removed
  1362. Guid has the Guid for the InstanceSet to find
  1363. Return Value:
  1364. --*/
  1365. {
  1366. PLIST_ENTRY InstanceSetList;
  1367. PBINSTANCESET InstanceSet;
  1368. PAGED_CODE();
  1369. InstanceSetList = DataSource->ISHead.Flink;
  1370. while (InstanceSetList != &DataSource->ISHead)
  1371. {
  1372. InstanceSet = CONTAINING_RECORD(InstanceSetList,
  1373. INSTANCESET,
  1374. DSISList);
  1375. if ((InstanceSet->GuidEntry != NULL) &&
  1376. (IsEqualGUID(Guid, &InstanceSet->GuidEntry->Guid)))
  1377. {
  1378. WmipReferenceIS(InstanceSet);
  1379. return(InstanceSet);
  1380. }
  1381. InstanceSetList = InstanceSetList->Flink;
  1382. }
  1383. return(NULL);
  1384. }
  1385. ULONG WmipUpdateAddGuid(
  1386. PBDATASOURCE DataSource,
  1387. PWMIREGGUID RegGuid,
  1388. PWMIREGINFO WmiRegInfo,
  1389. ULONG BufferSize,
  1390. PBINSTANCESET *AddModInstanceSet
  1391. )
  1392. /*++
  1393. Routine Description:
  1394. This routine will add a new guid for the data source and send notification
  1395. This routine assumes that the SM critical section is held before it is
  1396. called.
  1397. Arguments:
  1398. DataSource is the data source from which the guid is to be removed
  1399. RegGuid has the Guid update data structure
  1400. WmiRegInfo points at the beginning of the registration update info
  1401. Return Value:
  1402. 1 if guid was added or 0
  1403. --*/
  1404. {
  1405. PBINSTANCESET InstanceSet;
  1406. LPGUID Guid = &RegGuid->Guid;
  1407. NTSTATUS Status;
  1408. PAGED_CODE();
  1409. //
  1410. // Allocate an instance set for this new set of instances
  1411. InstanceSet = WmipAllocInstanceSet();
  1412. if (InstanceSet == NULL)
  1413. {
  1414. WmipDebugPrintEx((DPFLTR_WMICORE_ID, DPFLTR_INFO_LEVEL,"WMI: WmipUpdateAddGuid: WmipAllocInstanceSet failed\n"));
  1415. return(0);
  1416. }
  1417. //
  1418. // We will allocate a proper guid entry for the instance set when
  1419. // the data source gets linked into the main data source list so
  1420. // we stash a pointer to the guid away now.
  1421. InstanceSet->GuidEntry = (PBGUIDENTRY)Guid;
  1422. //
  1423. // Minimally initialize the InstanceSet and add it to the DataSource's
  1424. // list of InstanceSets. We do this first so that if there is any
  1425. // failure below and the DataSource can'e be fully registered the
  1426. // instance set and guid entry will be free when the DataSource is
  1427. // freed.
  1428. InstanceSet->DataSource = DataSource;
  1429. InstanceSet->Flags |= IS_NEWLY_REGISTERED;
  1430. InsertHeadList(&DataSource->ISHead, &InstanceSet->DSISList);
  1431. Status = WmipBuildInstanceSet(RegGuid,
  1432. WmiRegInfo,
  1433. BufferSize,
  1434. InstanceSet,
  1435. DataSource->ProviderId,
  1436. DataSource->RegistryPath);
  1437. if (! NT_SUCCESS(Status))
  1438. {
  1439. WmipUnreferenceIS(InstanceSet);
  1440. return(0);
  1441. }
  1442. Status = WmipLinkDataSourceToList(DataSource,
  1443. FALSE);
  1444. *AddModInstanceSet = InstanceSet;
  1445. return( NT_SUCCESS(Status) ? 1 : 0);
  1446. }
  1447. #if DBG
  1448. PWCHAR GuidToString(
  1449. PWCHAR s,
  1450. ULONG SizeInBytes,
  1451. LPGUID piid
  1452. )
  1453. {
  1454. HRESULT hr;
  1455. PAGED_CODE();
  1456. hr = StringCbPrintf(s, SizeInBytes, L"%x-%x-%x-%x%x%x%x%x%x%x%x",
  1457. piid->Data1, piid->Data2,
  1458. piid->Data3,
  1459. piid->Data4[0], piid->Data4[1],
  1460. piid->Data4[2], piid->Data4[3],
  1461. piid->Data4[4], piid->Data4[5],
  1462. piid->Data4[6], piid->Data4[7]);
  1463. WmipAssert(hr == S_OK);
  1464. return(s);
  1465. }
  1466. #endif
  1467. BOOLEAN WmipUpdateRemoveGuid(
  1468. PBDATASOURCE DataSource,
  1469. PWMIREGGUID RegGuid,
  1470. PBINSTANCESET *AddModInstanceSet
  1471. )
  1472. /*++
  1473. Routine Description:
  1474. This routine will remove the guid for the data source and send notification
  1475. This routine assumes that the SM critical section is held before it is
  1476. called.
  1477. Arguments:
  1478. DataSource is the data source from which the guid is to be removed
  1479. RegGuid has the Guid update data structure
  1480. Return Value:
  1481. TRUE if guid was removed else FALSE
  1482. --*/
  1483. {
  1484. PBINSTANCESET InstanceSet;
  1485. LPGUID Guid = &RegGuid->Guid;
  1486. BOOLEAN SendNotification;
  1487. PAGED_CODE();
  1488. InstanceSet = WmipFindISInDSByGuid(DataSource,
  1489. Guid);
  1490. if (InstanceSet != NULL)
  1491. {
  1492. WmipUnreferenceIS(InstanceSet);
  1493. *AddModInstanceSet = InstanceSet;
  1494. SendNotification = TRUE;
  1495. } else {
  1496. #if DBG
  1497. WCHAR s[256];
  1498. WmipDebugPrintEx((DPFLTR_WMICORE_ID, DPFLTR_INFO_LEVEL,"WMI: UpdateRemoveGuid %ws not registered by %ws\n",
  1499. GuidToString(s, sizeof(s), Guid), DataSource->RegistryPath));
  1500. #endif
  1501. SendNotification = FALSE;
  1502. }
  1503. return(SendNotification);
  1504. }
  1505. BOOLEAN WmipIsEqualInstanceSets(
  1506. PBINSTANCESET InstanceSet1,
  1507. PBINSTANCESET InstanceSet2
  1508. )
  1509. {
  1510. ULONG i;
  1511. ULONG Flags1, Flags2;
  1512. PAGED_CODE();
  1513. Flags1 = InstanceSet1->Flags & ~(IS_ENABLE_EVENT | IS_ENABLE_COLLECTION);
  1514. Flags2 = InstanceSet2->Flags & ~(IS_ENABLE_EVENT | IS_ENABLE_COLLECTION);
  1515. if (Flags1 == Flags2)
  1516. {
  1517. if (InstanceSet1->Flags & IS_INSTANCE_BASENAME)
  1518. {
  1519. if ((InstanceSet1->Count == InstanceSet2->Count) &&
  1520. (wcscmp(InstanceSet1->IsBaseName->BaseName,
  1521. InstanceSet1->IsBaseName->BaseName) == 0))
  1522. {
  1523. return(TRUE);
  1524. }
  1525. } else if (InstanceSet1->Flags & IS_INSTANCE_BASENAME) {
  1526. if (InstanceSet1->Count == InstanceSet2->Count)
  1527. {
  1528. for (i = 0; i < InstanceSet1->Count; i++)
  1529. {
  1530. if (wcscmp(InstanceSet1->IsStaticNames->StaticNamePtr[i],
  1531. InstanceSet2->IsStaticNames->StaticNamePtr[i]) != 0)
  1532. {
  1533. return(FALSE);
  1534. }
  1535. }
  1536. return(TRUE);
  1537. }
  1538. } else {
  1539. return(TRUE);
  1540. }
  1541. }
  1542. return(FALSE);
  1543. }
  1544. ULONG WmipUpdateModifyGuid(
  1545. PBDATASOURCE DataSource,
  1546. PWMIREGGUID RegGuid,
  1547. PWMIREGINFO WmiRegInfo,
  1548. ULONG BufferSize,
  1549. PBINSTANCESET *AddModInstanceSet
  1550. )
  1551. /*++
  1552. Routine Description:
  1553. This routine will modify an existing guid for the data source and
  1554. send notification
  1555. This routine assumes that the SM critical section is held before it is
  1556. called.
  1557. HEHEY: If a guid was opened when it was registered as cheap, but closed
  1558. when the guid was registered expensive a disable collection will
  1559. NOT be sent. Conversely if a guid was opened when it was
  1560. registered as expensive and is closed when registed as cheap a
  1561. disable collection may be sent.
  1562. Arguments:
  1563. DataSource is the data source from which the guid is to be removed
  1564. RegGuid has the Guid update data structure
  1565. WmiRegInfo points at the beginning of the registration update info
  1566. Return Value:
  1567. 1 if guid was added or 2 if guid was modified else 0
  1568. --*/
  1569. {
  1570. PBINSTANCESET InstanceSet;
  1571. LPGUID Guid = &RegGuid->Guid;
  1572. ULONG SendNotification;
  1573. PBINSTANCESET InstanceSetNew;
  1574. PVOID ToFree;
  1575. NTSTATUS Status;
  1576. PAGED_CODE();
  1577. InstanceSet = WmipFindISInDSByGuid(DataSource,
  1578. Guid);
  1579. if (InstanceSet != NULL)
  1580. {
  1581. //
  1582. // See if anything has changed with the instance names and if not
  1583. // then don't bother to recreate the instance set
  1584. InstanceSetNew = WmipAllocInstanceSet();
  1585. if (InstanceSetNew == NULL)
  1586. {
  1587. WmipDebugPrintEx((DPFLTR_WMICORE_ID, DPFLTR_INFO_LEVEL,"WMI: UpdateModifyGuid Not enough memory to alloc InstanceSet\n"));
  1588. WmipUnreferenceIS(InstanceSet);
  1589. return(0);
  1590. }
  1591. Status = WmipBuildInstanceSet(RegGuid,
  1592. WmiRegInfo,
  1593. BufferSize,
  1594. InstanceSetNew,
  1595. DataSource->ProviderId,
  1596. DataSource->RegistryPath);
  1597. if (NT_SUCCESS(Status))
  1598. {
  1599. if (! WmipIsEqualInstanceSets(InstanceSet,
  1600. InstanceSetNew))
  1601. {
  1602. ToFree = NULL;
  1603. if (InstanceSet->IsBaseName != NULL) {
  1604. ToFree = (PVOID)InstanceSet->IsBaseName;
  1605. }
  1606. RemoveEntryList(&InstanceSet->GuidISList);
  1607. Status = WmipBuildInstanceSet(RegGuid,
  1608. WmiRegInfo,
  1609. BufferSize,
  1610. InstanceSet,
  1611. DataSource->ProviderId,
  1612. DataSource->RegistryPath);
  1613. if (NT_SUCCESS(Status))
  1614. {
  1615. InsertHeadList(&InstanceSet->GuidEntry->ISHead,
  1616. &InstanceSet->GuidISList);
  1617. } else {
  1618. //
  1619. // It is sad, but we weren't able to rebuild the instance
  1620. // set so the old one is gone. This is an unlikely
  1621. // situation that can really only occur when the machine
  1622. // is out of memory.
  1623. //
  1624. }
  1625. if (ToFree != NULL)
  1626. {
  1627. WmipFree(ToFree);
  1628. }
  1629. *AddModInstanceSet = InstanceSet;
  1630. SendNotification = 2;
  1631. } else {
  1632. //
  1633. // The InstanceSets are identical so just delete the new one
  1634. SendNotification = 0;
  1635. }
  1636. WmipUnreferenceIS(InstanceSetNew);
  1637. WmipUnreferenceIS(InstanceSet);
  1638. } else {
  1639. //
  1640. // We could not parse the new instance set so leave the old
  1641. // one alone
  1642. //
  1643. WmipUnreferenceIS(InstanceSet);
  1644. WmipUnreferenceIS(InstanceSetNew);
  1645. SendNotification = FALSE;
  1646. }
  1647. } else {
  1648. //
  1649. // Guid not already registered so try to add it
  1650. SendNotification = WmipUpdateAddGuid(DataSource,
  1651. RegGuid,
  1652. WmiRegInfo,
  1653. BufferSize,
  1654. AddModInstanceSet);
  1655. }
  1656. return(SendNotification);
  1657. }
  1658. void WmipCachePtrs(
  1659. LPGUID Ptr1,
  1660. PBINSTANCESET Ptr2,
  1661. ULONG *PtrCount,
  1662. ULONG *PtrMax,
  1663. PTRCACHE **PtrArray
  1664. )
  1665. {
  1666. PTRCACHE *NewPtrArray;
  1667. PTRCACHE *OldPtrArray;
  1668. PTRCACHE *ActualPtrArray;
  1669. PAGED_CODE();
  1670. if (*PtrCount == *PtrMax)
  1671. {
  1672. NewPtrArray = WmipAlloc((*PtrMax + PTRCACHEGROWSIZE) * sizeof(PTRCACHE));
  1673. if (NewPtrArray != NULL)
  1674. {
  1675. OldPtrArray = *PtrArray;
  1676. memcpy(NewPtrArray, OldPtrArray, *PtrMax * sizeof(PTRCACHE));
  1677. *PtrMax += PTRCACHEGROWSIZE;
  1678. if (*PtrArray != NULL)
  1679. {
  1680. WmipFree(*PtrArray);
  1681. }
  1682. *PtrArray = NewPtrArray;
  1683. } else {
  1684. WmipDebugPrintEx((DPFLTR_WMICORE_ID, DPFLTR_INFO_LEVEL,"WMI: Couldn't alloc memory for pointer cache\n"));
  1685. return;
  1686. }
  1687. }
  1688. ActualPtrArray = *PtrArray;
  1689. ActualPtrArray[*PtrCount].Guid = Ptr1;
  1690. ActualPtrArray[*PtrCount].InstanceSet = Ptr2;
  1691. (*PtrCount)++;
  1692. }
  1693. NTSTATUS WmipUpdateDataSource(
  1694. PREGENTRY RegEntry,
  1695. PWMIREGINFOW WmiRegInfo,
  1696. ULONG RetSize
  1697. )
  1698. /*++
  1699. Routine Description:
  1700. This routine will update a data source with changes to already registered
  1701. guids.
  1702. Arguments:
  1703. ProviderId is the provider id of the DataSource whose guids are being
  1704. updated.
  1705. WmiRegInfo has the registration update information
  1706. RetSize has the size of the registration information returned from
  1707. kernel mode.
  1708. Return Value:
  1709. --*/
  1710. {
  1711. PBDATASOURCE DataSource;
  1712. PUCHAR RegInfo;
  1713. ULONG RetSizeLeft;
  1714. ULONG i;
  1715. PWMIREGGUID RegGuid;
  1716. ULONG NextWmiRegInfo;
  1717. PTRCACHE *RemovedGuids;
  1718. PTRCACHE *AddedGuids;
  1719. PTRCACHE *ModifiedGuids;
  1720. ULONG RemovedGuidCount;
  1721. ULONG AddedGuidCount;
  1722. ULONG ModifiedGuidCount;
  1723. ULONG RemovedGuidMax;
  1724. ULONG AddedGuidMax;
  1725. ULONG ModifiedGuidMax;
  1726. PBINSTANCESET InstanceSet;
  1727. ULONG Action;
  1728. PAGED_CODE();
  1729. DataSource = RegEntry->DataSource;
  1730. if (DataSource == NULL)
  1731. {
  1732. WmipDebugPrintEx((DPFLTR_WMICORE_ID, DPFLTR_INFO_LEVEL,"WMI: RegEntry %p requested update but is not registered\n",
  1733. RegEntry));
  1734. return(STATUS_OBJECT_NAME_NOT_FOUND);
  1735. }
  1736. WmipReferenceDS(DataSource);
  1737. AddedGuidCount = 0;
  1738. ModifiedGuidCount = 0;
  1739. RemovedGuidCount = 0;
  1740. AddedGuidMax = 0;
  1741. ModifiedGuidMax = 0;
  1742. RemovedGuidMax = 0;
  1743. ModifiedGuids = NULL;
  1744. AddedGuids = NULL;
  1745. RemovedGuids = NULL;
  1746. NextWmiRegInfo = 0;
  1747. RetSizeLeft = RetSize;
  1748. WmipEnterSMCritSection();
  1749. RegInfo = (PUCHAR)WmiRegInfo;
  1750. for (i = 0; i < WmiRegInfo->GuidCount; i++)
  1751. {
  1752. RegGuid = &WmiRegInfo->WmiRegGuid[i];
  1753. if (RegGuid->Flags & WMIREG_FLAG_REMOVE_GUID)
  1754. {
  1755. if (WmipUpdateRemoveGuid(DataSource,
  1756. RegGuid,
  1757. &InstanceSet))
  1758. {
  1759. WmipCachePtrs(&RegGuid->Guid,
  1760. InstanceSet,
  1761. &RemovedGuidCount,
  1762. &RemovedGuidMax,
  1763. &RemovedGuids);
  1764. }
  1765. } else {
  1766. Action = WmipUpdateModifyGuid(DataSource,
  1767. RegGuid,
  1768. WmiRegInfo,
  1769. RetSize,
  1770. &InstanceSet);
  1771. if (Action == 1)
  1772. {
  1773. WmipCachePtrs(&RegGuid->Guid,
  1774. InstanceSet,
  1775. &AddedGuidCount,
  1776. &AddedGuidMax,
  1777. &AddedGuids);
  1778. } else if (Action == 2) {
  1779. WmipCachePtrs(&RegGuid->Guid,
  1780. InstanceSet,
  1781. &ModifiedGuidCount,
  1782. &ModifiedGuidMax,
  1783. &ModifiedGuids);
  1784. }
  1785. }
  1786. }
  1787. WmipLeaveSMCritSection();
  1788. WmipUnreferenceDS(DataSource);
  1789. if (RemovedGuidCount > 0)
  1790. {
  1791. for (i = 0; i < RemovedGuidCount; i++)
  1792. {
  1793. if (IsEqualGUID(RemovedGuids[i].Guid,
  1794. &WmipBinaryMofGuid))
  1795. {
  1796. WmipGenerateBinaryMofNotification(RemovedGuids[i].InstanceSet,
  1797. &GUID_MOF_RESOURCE_REMOVED_NOTIFICATION);
  1798. }
  1799. InstanceSet = RemovedGuids[i].InstanceSet;
  1800. WmipDisableCollectionForRemovedGuid(RemovedGuids[i].Guid,
  1801. InstanceSet);
  1802. WmipEnterSMCritSection();
  1803. //
  1804. // If IS is on the GE list then remove it
  1805. if (InstanceSet->GuidISList.Flink != NULL)
  1806. {
  1807. RemoveEntryList(&InstanceSet->GuidISList);
  1808. InstanceSet->GuidEntry->ISCount--;
  1809. }
  1810. if (! (InstanceSet->Flags & IS_NEWLY_REGISTERED))
  1811. {
  1812. WmipUnreferenceGE(InstanceSet->GuidEntry);
  1813. }
  1814. InstanceSet->GuidEntry = NULL;
  1815. //
  1816. // Remove IS from the DS List
  1817. RemoveEntryList(&InstanceSet->DSISList);
  1818. WmipUnreferenceIS(InstanceSet);
  1819. WmipLeaveSMCritSection();
  1820. }
  1821. WmipSendGuidUpdateNotifications(RegistrationDelete,
  1822. RemovedGuidCount,
  1823. RemovedGuids);
  1824. WmipFree(RemovedGuids);
  1825. }
  1826. if (ModifiedGuidCount > 0)
  1827. {
  1828. for (i = 0; i < ModifiedGuidCount; i++)
  1829. {
  1830. if (IsEqualGUID(ModifiedGuids[i].Guid,
  1831. &WmipBinaryMofGuid))
  1832. {
  1833. WmipGenerateBinaryMofNotification(ModifiedGuids[i].InstanceSet,
  1834. &GUID_MOF_RESOURCE_ADDED_NOTIFICATION);
  1835. }
  1836. }
  1837. WmipSendGuidUpdateNotifications(RegistrationUpdate,
  1838. ModifiedGuidCount,
  1839. ModifiedGuids);
  1840. WmipFree(ModifiedGuids);
  1841. }
  1842. if (AddedGuidCount > 0)
  1843. {
  1844. for (i = 0; i < AddedGuidCount; i++)
  1845. {
  1846. if (IsEqualGUID(AddedGuids[i].Guid,
  1847. &WmipBinaryMofGuid))
  1848. {
  1849. WmipGenerateBinaryMofNotification(AddedGuids[i].InstanceSet,
  1850. &GUID_MOF_RESOURCE_ADDED_NOTIFICATION);
  1851. }
  1852. WmipEnableCollectionForNewGuid(AddedGuids[i].Guid,
  1853. AddedGuids[i].InstanceSet);
  1854. }
  1855. WmipSendGuidUpdateNotifications(RegistrationAdd,
  1856. AddedGuidCount,
  1857. AddedGuids);
  1858. WmipFree(AddedGuids);
  1859. }
  1860. return(STATUS_SUCCESS);
  1861. }
  1862. void WmipRemoveDataSourceByDS(
  1863. PBDATASOURCE DataSource
  1864. )
  1865. {
  1866. PAGED_CODE();
  1867. WmipGenerateRegistrationNotification(DataSource,
  1868. RegistrationDelete);
  1869. WmipUnreferenceDS(DataSource);
  1870. }
  1871. NTSTATUS WmipRemoveDataSource(
  1872. PREGENTRY RegEntry
  1873. )
  1874. {
  1875. PBDATASOURCE DataSource;
  1876. NTSTATUS Status;
  1877. PAGED_CODE();
  1878. DataSource = RegEntry->DataSource;
  1879. if (DataSource != NULL)
  1880. {
  1881. WmipReferenceDS(DataSource);
  1882. WmipRemoveDataSourceByDS(DataSource);
  1883. WmipUnreferenceDS(DataSource);
  1884. Status = STATUS_SUCCESS;
  1885. } else {
  1886. WmipDebugPrintEx((DPFLTR_WMICORE_ID, DPFLTR_INFO_LEVEL,"WMI: Attempt to remove non existant data source %p\n",
  1887. RegEntry));
  1888. Status = STATUS_OBJECT_NAME_NOT_FOUND;
  1889. }
  1890. return(Status);
  1891. }
  1892. NTSTATUS WmipEnumerateMofResources(
  1893. PWMIMOFLIST MofList,
  1894. ULONG BufferSize,
  1895. ULONG *RetSize
  1896. )
  1897. {
  1898. PLIST_ENTRY MofResourceList;
  1899. PMOFRESOURCE MofResource;
  1900. ULONG MRCount;
  1901. SIZE_T SizeNeeded, MRSize;
  1902. PWMIMOFENTRY MofEntry;
  1903. PWCHAR MRBuffer;
  1904. ULONG i;
  1905. HRESULT hr;
  1906. PAGED_CODE();
  1907. WmipEnterSMCritSection();
  1908. MRCount = 0;
  1909. SizeNeeded = 0;
  1910. MofResourceList = WmipMRHeadPtr->Flink;
  1911. while (MofResourceList != WmipMRHeadPtr)
  1912. {
  1913. MofResource = CONTAINING_RECORD(MofResourceList,
  1914. MOFRESOURCE,
  1915. MainMRList);
  1916. MRCount++;
  1917. SizeNeeded += (wcslen(MofResource->RegistryPath) +
  1918. wcslen(MofResource->MofResourceName) + 2) *
  1919. sizeof(WCHAR);
  1920. MofResourceList = MofResourceList->Flink;
  1921. }
  1922. if (MRCount != 0)
  1923. {
  1924. MRSize = sizeof(WMIMOFLIST) + ((MRCount-1) * sizeof(WMIMOFENTRY));
  1925. SizeNeeded += MRSize;
  1926. if (BufferSize >= SizeNeeded)
  1927. {
  1928. MofList->MofListCount = MRCount;
  1929. MofResourceList = WmipMRHeadPtr->Flink;
  1930. i = 0;
  1931. while (MofResourceList != WmipMRHeadPtr)
  1932. {
  1933. MofResource = CONTAINING_RECORD(MofResourceList,
  1934. MOFRESOURCE,
  1935. MainMRList);
  1936. MofEntry = &MofList->MofEntry[i++];
  1937. MofEntry->Flags = MofResource->Flags & MR_FLAG_USER_MODE ?
  1938. WMIMOFENTRY_FLAG_USERMODE :
  1939. 0;
  1940. MofEntry->RegPathOffset = (ULONG) MRSize;
  1941. MRBuffer = (PWCHAR)OffsetToPtr(MofList, MRSize);
  1942. hr = StringCbCopy(MRBuffer,
  1943. (BufferSize - MRSize),
  1944. MofResource->RegistryPath);
  1945. WmipAssert(hr == S_OK);
  1946. MRSize += (wcslen(MofResource->RegistryPath) + 1) * sizeof(WCHAR);
  1947. MofEntry->ResourceOffset = (ULONG) MRSize;
  1948. MRBuffer = (PWCHAR)OffsetToPtr(MofList, MRSize);
  1949. hr = StringCbCopy(MRBuffer,
  1950. (BufferSize - MRSize),
  1951. MofResource->MofResourceName);
  1952. WmipAssert(hr == S_OK);
  1953. MRSize += (wcslen(MofResource->MofResourceName) + 1) * sizeof(WCHAR);
  1954. MofResourceList = MofResourceList->Flink;
  1955. }
  1956. } else {
  1957. //
  1958. // Buffer not large enough, return size needed
  1959. //
  1960. MofList->MofListCount = (ULONG) SizeNeeded;
  1961. *RetSize = sizeof(ULONG);
  1962. }
  1963. } else {
  1964. //
  1965. // No mof resources
  1966. //
  1967. MofList->MofListCount = 0;
  1968. *RetSize = sizeof(WMIMOFLIST);
  1969. }
  1970. WmipLeaveSMCritSection();
  1971. return(STATUS_SUCCESS);
  1972. }
  1973. NTSTATUS WmipInitializeDataStructs(
  1974. void
  1975. )
  1976. /*++
  1977. Routine Description:
  1978. This routine will do the work of initializing the WMI service
  1979. Arguments:
  1980. Return Value:
  1981. Error status value
  1982. --*/
  1983. {
  1984. ULONG Status;
  1985. UCHAR RegInfoBuffer[sizeof(WMIREGINFOW) + 2 * sizeof(WMIREGGUIDW)];
  1986. PWMIREGINFOW RegInfo = (PWMIREGINFOW)RegInfoBuffer;
  1987. GUID InstanceInfoGuid = INSTANCE_INFO_GUID;
  1988. GUID EnumerateGuidsGuid = ENUMERATE_GUIDS_GUID;
  1989. PREGENTRY RegEntry;
  1990. PDEVICE_OBJECT Callback;
  1991. PLIST_ENTRY GuidEntryList;
  1992. PBGUIDENTRY GuidEntry;
  1993. BOOLEAN NewResource;
  1994. PAGED_CODE();
  1995. //
  1996. // Initialize the various data structure lists that we maintain
  1997. //
  1998. WmipDSHeadPtr = &WmipDSHead;
  1999. InitializeListHead(WmipDSHeadPtr);
  2000. InitializeListHead(&WmipDSChunkInfo.ChunkHead);
  2001. WmipGEHeadPtr = &WmipGEHead;
  2002. InitializeListHead(WmipGEHeadPtr);
  2003. InitializeListHead(&WmipGEChunkInfo.ChunkHead);
  2004. WmipMRHeadPtr = &WmipMRHead;
  2005. InitializeListHead(WmipMRHeadPtr);
  2006. InitializeListHead(&WmipMRChunkInfo.ChunkHead);
  2007. InitializeListHead(&WmipISChunkInfo.ChunkHead);
  2008. //
  2009. // Register any internal data provider guids and mark them as such
  2010. //
  2011. Callback = (PDEVICE_OBJECT)(ULONG_PTR) WmipUMProviderCallback;
  2012. //
  2013. // Establish a regentry for the data provider
  2014. //
  2015. RegEntry = WmipAllocRegEntry(Callback,
  2016. WMIREG_FLAG_CALLBACK |
  2017. REGENTRY_FLAG_TRACED |
  2018. REGENTRY_FLAG_NEWREGINFO |
  2019. REGENTRY_FLAG_INUSE |
  2020. REGENTRY_FLAG_REG_IN_PROGRESS);
  2021. if (RegEntry != NULL)
  2022. {
  2023. //
  2024. // This code assumes that no other data providers have
  2025. // yet registered.
  2026. //
  2027. WmipAssert(WmipGEHeadPtr->Flink == WmipGEHeadPtr);
  2028. RtlZeroMemory(RegInfo, sizeof(RegInfoBuffer));
  2029. RegInfo->BufferSize = sizeof(RegInfoBuffer);
  2030. RegInfo->GuidCount = 2;
  2031. RegInfo->WmiRegGuid[0].Guid = InstanceInfoGuid;
  2032. RegInfo->WmiRegGuid[1].Guid = EnumerateGuidsGuid;
  2033. Status = WmipAddDataSource(RegEntry,
  2034. RegInfo,
  2035. RegInfo->BufferSize,
  2036. NULL,
  2037. NULL,
  2038. NULL,
  2039. FALSE);
  2040. if (NT_SUCCESS(Status))
  2041. {
  2042. GuidEntryList = WmipGEHeadPtr->Flink;
  2043. while (GuidEntryList != WmipGEHeadPtr)
  2044. {
  2045. GuidEntry = CONTAINING_RECORD(GuidEntryList,
  2046. GUIDENTRY,
  2047. MainGEList);
  2048. GuidEntry->Flags |= GE_FLAG_INTERNAL;
  2049. GuidEntryList = GuidEntryList->Flink;
  2050. }
  2051. } else {
  2052. RegEntry->Flags |= (REGENTRY_FLAG_RUNDOWN |
  2053. REGENTRY_FLAG_NOT_ACCEPTING_IRPS);
  2054. WmipUnreferenceRegEntry(RegEntry);
  2055. }
  2056. Status = WmipAddMofResource(RegEntry->DataSource,
  2057. WMICOREIMAGEPATH,
  2058. TRUE,
  2059. WMICORERESOURCENAME,
  2060. &NewResource);
  2061. WmipAssert(NewResource);
  2062. }
  2063. return(STATUS_SUCCESS);
  2064. }
  2065. #ifdef ALLOC_DATA_PRAGMA
  2066. #pragma const_seg()
  2067. #endif