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.

460 lines
17 KiB

  1. /*++
  2. Copyright (c) 1997-1999 Microsoft Corporation
  3. Module Name:
  4. mofapi.c
  5. Abstract:
  6. WMI MOF access apis
  7. Author:
  8. 16-Jan-1997 AlanWar
  9. Revision History:
  10. --*/
  11. #include "wmiump.h"
  12. #include "trcapi.h"
  13. #include "common.h"
  14. BOOLEAN EtwpCopyCountedString(
  15. PUCHAR Base,
  16. PULONG Offset,
  17. PULONG BufferRemaining,
  18. PWCHAR SourceString
  19. )
  20. {
  21. PWCHAR w;
  22. ULONG BufferUsed;
  23. ULONG BytesUsed;
  24. BOOLEAN BufferNotFull;
  25. if (*BufferRemaining > 1)
  26. {
  27. w = (PWCHAR)OffsetToPtr(Base, *Offset);
  28. (*BufferRemaining)--;
  29. BufferNotFull = EtwpCopyMRString(w+1,
  30. *BufferRemaining,
  31. &BufferUsed,
  32. SourceString);
  33. if (BufferNotFull)
  34. {
  35. BytesUsed = BufferUsed * sizeof(WCHAR);
  36. *w = (USHORT)BytesUsed;
  37. (*BufferRemaining) -= BufferUsed;
  38. (*Offset) += BytesUsed + sizeof(USHORT);
  39. }
  40. } else {
  41. BufferNotFull = FALSE;
  42. }
  43. return(BufferNotFull);
  44. }
  45. ULONG EtwpBuildMofAddRemoveEvent(
  46. IN PWNODE_SINGLE_INSTANCE WnodeSI,
  47. IN PWMIMOFLIST MofList,
  48. IN PWCHAR *LanguageList,
  49. IN ULONG LanguageCount,
  50. IN BOOLEAN IncludeNeutralLanguage,
  51. IN NOTIFICATIONCALLBACK Callback,
  52. IN ULONG_PTR DeliveryContext,
  53. IN BOOLEAN IsAnsi
  54. )
  55. {
  56. PWNODE_ALL_DATA WnodeAD;
  57. ULONG BytesUsed, BufferUsed;
  58. BOOLEAN BufferNotFull;
  59. PWCHAR RegPath, ImagePath, ResourceName;
  60. ULONG SizeNeeded;
  61. ULONG InstanceCount, MaxInstanceCount;
  62. ULONG Status;
  63. ULONG Offset;
  64. POFFSETINSTANCEDATAANDLENGTH DataLenPtr;
  65. PWCHAR w;
  66. PULONG InstanceNamesOffsets;
  67. PWCHAR InstanceNames;
  68. ULONG BufferRemaining;
  69. ULONG i,j;
  70. PWMIMOFENTRY MofEntry;
  71. PWCHAR ImagePathStatic;
  72. EtwpAssert(WnodeSI->WnodeHeader.Flags & WNODE_FLAG_SINGLE_INSTANCE);
  73. ImagePathStatic = EtwpAlloc(MAX_PATH * sizeof(WCHAR));
  74. if (ImagePathStatic != NULL)
  75. {
  76. //
  77. // Figure out how large the WNODE_ALL_DATA will need to be and
  78. // guess at how much space to allocate for the image paths and
  79. // resource names
  80. //
  81. if (IncludeNeutralLanguage)
  82. {
  83. MaxInstanceCount = (LanguageCount + 1);
  84. } else {
  85. MaxInstanceCount = LanguageCount;
  86. }
  87. MaxInstanceCount *= MofList->MofListCount;
  88. #if DBG
  89. SizeNeeded = sizeof(WNODE_ALL_DATA) +
  90. (MaxInstanceCount *
  91. (sizeof(ULONG) + // offset to instance name
  92. sizeof(USHORT) + // instance name length
  93. sizeof(OFFSETINSTANCEDATAANDLENGTH))) +
  94. 64;
  95. #else
  96. SizeNeeded = sizeof(WNODE_ALL_DATA) +
  97. (MaxInstanceCount *
  98. (sizeof(ULONG) + // offset to instance name
  99. sizeof(USHORT) + // instance name length
  100. sizeof(OFFSETINSTANCEDATAANDLENGTH))) +
  101. 0x1000;
  102. #endif
  103. WnodeAD = NULL;
  104. do
  105. {
  106. TryAgain:
  107. if (WnodeAD != NULL)
  108. {
  109. EtwpFree(WnodeAD);
  110. }
  111. WnodeAD = EtwpAlloc(SizeNeeded);
  112. if (WnodeAD != NULL)
  113. {
  114. //
  115. // Build up WNODE_ALL_DATA with all mof resources
  116. //
  117. memset(WnodeAD, 0, SizeNeeded);
  118. WnodeAD->WnodeHeader = WnodeSI->WnodeHeader;
  119. WnodeAD->WnodeHeader.Flags = WNODE_FLAG_ALL_DATA |
  120. WNODE_FLAG_EVENT_ITEM;
  121. WnodeAD->WnodeHeader.BufferSize = SizeNeeded;
  122. WnodeAD->WnodeHeader.Linkage = 0;
  123. //
  124. // Establish pointer to the data offset and length
  125. // structure and allocate space for all instances
  126. //
  127. Offset = FIELD_OFFSET(WNODE_ALL_DATA,
  128. OffsetInstanceDataAndLength);
  129. DataLenPtr = (POFFSETINSTANCEDATAANDLENGTH)OffsetToPtr(WnodeAD,
  130. Offset);
  131. Offset = (Offset +
  132. (MaxInstanceCount *
  133. sizeof(OFFSETINSTANCEDATAANDLENGTH)) + 7) & ~7;
  134. //
  135. // Establish the instance name offsets and fill in
  136. // the empty instance names. Note we point them all
  137. // to the same offset which is an empty instance
  138. // name.
  139. //
  140. InstanceNamesOffsets = (PULONG)OffsetToPtr(WnodeAD,
  141. Offset);
  142. WnodeAD->OffsetInstanceNameOffsets = Offset;
  143. Offset = Offset + (MaxInstanceCount * sizeof(ULONG));
  144. InstanceNames = (PWCHAR)OffsetToPtr(WnodeAD, Offset);
  145. *InstanceNames = 0;
  146. for (i = 0; i < MaxInstanceCount; i++)
  147. {
  148. InstanceNamesOffsets[i] = Offset;
  149. }
  150. //
  151. // Establish a pointer to the data block for all of
  152. // the instances
  153. //
  154. Offset = (Offset +
  155. (MaxInstanceCount * sizeof(USHORT)) + 7) & ~7;
  156. WnodeAD->DataBlockOffset = Offset;
  157. BufferRemaining = (SizeNeeded - Offset) / sizeof(WCHAR);
  158. InstanceCount = 0;
  159. //
  160. // Loop over all mof resources in list
  161. //
  162. for (j = 0; j < MofList->MofListCount; j++)
  163. {
  164. MofEntry = &MofList->MofEntry[j];
  165. RegPath = (PWCHAR)OffsetToPtr(MofList,
  166. MofEntry->RegPathOffset);
  167. //
  168. // Convert regpath to image path if needed
  169. //
  170. if ((MofEntry->Flags & WMIMOFENTRY_FLAG_USERMODE) == 0)
  171. {
  172. ImagePath = EtwpRegistryToImagePath(ImagePathStatic,
  173. RegPath+1);
  174. } else {
  175. ImagePath = RegPath;
  176. }
  177. if (ImagePath != NULL)
  178. {
  179. ResourceName = (PWCHAR)OffsetToPtr(MofList,
  180. MofEntry->ResourceOffset);
  181. //
  182. // Now lets go and build up the data for each
  183. // instance. First fill in the language neutral mof
  184. // if we are supposed to
  185. //
  186. if (IncludeNeutralLanguage)
  187. {
  188. DataLenPtr[InstanceCount].OffsetInstanceData = Offset;
  189. if ((! EtwpCopyCountedString((PUCHAR)WnodeAD,
  190. &Offset,
  191. &BufferRemaining,
  192. ImagePath)) ||
  193. (! EtwpCopyCountedString((PUCHAR)WnodeAD,
  194. &Offset,
  195. &BufferRemaining,
  196. ResourceName)))
  197. {
  198. SizeNeeded *=2;
  199. goto TryAgain;
  200. }
  201. DataLenPtr[InstanceCount].LengthInstanceData = Offset -
  202. DataLenPtr[InstanceCount].OffsetInstanceData;
  203. InstanceCount++;
  204. //
  205. // We cheat here and do not align the offset on an
  206. // 8 byte boundry for the next data block since we
  207. // know the data type is a WCHAR and we know we are
  208. // on a 2 byte boundry.
  209. //
  210. }
  211. //
  212. // Now loop over and build language specific mof
  213. // resources
  214. //
  215. for (i = 0; i < LanguageCount; i++)
  216. {
  217. DataLenPtr[InstanceCount].OffsetInstanceData = Offset;
  218. if (BufferRemaining > 1)
  219. {
  220. w = (PWCHAR)OffsetToPtr(WnodeAD, Offset);
  221. Status = EtwpBuildMUIPath(w+1,
  222. BufferRemaining - 1,
  223. &BufferUsed,
  224. ImagePath,
  225. LanguageList[i],
  226. &BufferNotFull);
  227. if (Status == ERROR_SUCCESS)
  228. {
  229. if (BufferNotFull)
  230. {
  231. BufferRemaining--;
  232. BytesUsed = BufferUsed * sizeof(WCHAR);
  233. *w = (USHORT)BytesUsed;
  234. BufferRemaining -= BufferUsed;
  235. Offset += (BytesUsed + sizeof(USHORT));
  236. if (! EtwpCopyCountedString((PUCHAR)WnodeAD,
  237. &Offset,
  238. &BufferRemaining,
  239. ResourceName))
  240. {
  241. SizeNeeded *=2;
  242. goto TryAgain;
  243. }
  244. DataLenPtr[InstanceCount].LengthInstanceData = Offset - DataLenPtr[InstanceCount].OffsetInstanceData;
  245. //
  246. // We cheat here and do not align the offset on an
  247. // 8 byte boundry for the next data block since we
  248. // know the data type is a WCHAR and we know we are
  249. // on a 2 byte boundry.
  250. //
  251. InstanceCount++;
  252. } else {
  253. SizeNeeded *=2;
  254. goto TryAgain;
  255. }
  256. }
  257. } else {
  258. SizeNeeded *=2;
  259. goto TryAgain;
  260. }
  261. }
  262. }
  263. }
  264. } else {
  265. Status = ERROR_NOT_ENOUGH_MEMORY;
  266. }
  267. } while (FALSE);
  268. if (WnodeAD != NULL)
  269. {
  270. WnodeAD->InstanceCount = InstanceCount;
  271. EtwpMakeEventCallbacks((PWNODE_HEADER)WnodeAD,
  272. Callback,
  273. DeliveryContext,
  274. IsAnsi);
  275. EtwpFree(WnodeAD);
  276. Status = ERROR_SUCCESS;
  277. }
  278. EtwpFree(ImagePathStatic);
  279. } else {
  280. Status = ERROR_NOT_ENOUGH_MEMORY;
  281. }
  282. return(Status);
  283. }
  284. void EtwpProcessMofAddRemoveEvent(
  285. IN PWNODE_SINGLE_INSTANCE WnodeSI,
  286. IN NOTIFICATIONCALLBACK Callback,
  287. IN ULONG_PTR DeliveryContext,
  288. IN BOOLEAN IsAnsi
  289. )
  290. {
  291. PWCHAR RegPath, ResourceName;
  292. PWCHAR *LanguageList;
  293. ULONG LanguageCount;
  294. ULONG Status;
  295. PWMIMOFLIST MofList;
  296. ULONG i;
  297. PWMIMOFENTRY MofEntry;
  298. ULONG Offset;
  299. ULONG SizeNeeded;
  300. PWCHAR w;
  301. RegPath = (PWCHAR)OffsetToPtr(WnodeSI, WnodeSI->DataBlockOffset);
  302. EtwpAssert(*RegPath != 0);
  303. ResourceName = (PWCHAR)OffsetToPtr(WnodeSI,
  304. WnodeSI->DataBlockOffset +
  305. sizeof(USHORT) +
  306. *RegPath++ +
  307. sizeof(USHORT));
  308. SizeNeeded = sizeof(WMIMOFLIST) + ((wcslen(RegPath) +
  309. (wcslen(ResourceName) + 2)) * sizeof(WCHAR));
  310. MofList = (PWMIMOFLIST)EtwpAlloc(SizeNeeded);
  311. if (MofList != NULL)
  312. {
  313. Status = EtwpGetLanguageList(&LanguageList,
  314. &LanguageCount);
  315. if (Status == ERROR_SUCCESS)
  316. {
  317. MofList->MofListCount = 1;
  318. MofEntry = &MofList->MofEntry[0];
  319. Offset = sizeof(WMIMOFLIST);
  320. MofEntry->RegPathOffset = Offset;
  321. w = (PWCHAR)OffsetToPtr(MofList, Offset);
  322. wcscpy(w, RegPath);
  323. Offset += (wcslen(RegPath) + 1) * sizeof(WCHAR);
  324. MofEntry->ResourceOffset = Offset;
  325. w = (PWCHAR)OffsetToPtr(MofList, Offset);
  326. wcscpy(w, ResourceName);
  327. if (WnodeSI->WnodeHeader.ProviderId == MOFEVENT_ACTION_REGISTRY_PATH)
  328. {
  329. MofEntry->Flags = 0;
  330. } else {
  331. MofEntry->Flags = WMIMOFENTRY_FLAG_USERMODE;
  332. }
  333. Status = EtwpBuildMofAddRemoveEvent(WnodeSI,
  334. MofList,
  335. LanguageList,
  336. LanguageCount,
  337. TRUE,
  338. Callback,
  339. DeliveryContext,
  340. IsAnsi);
  341. //
  342. // Free up memory used to hold the language list
  343. //
  344. for (i = 0; i < LanguageCount; i++)
  345. {
  346. EtwpFree(LanguageList[i]);
  347. }
  348. EtwpFree(LanguageList);
  349. }
  350. EtwpFree(MofList);
  351. } else {
  352. Status = ERROR_NOT_ENOUGH_MEMORY;
  353. }
  354. if (Status != ERROR_SUCCESS)
  355. {
  356. //
  357. // If the WNODE_ALL_DATA event wasn't fired then just fire the
  358. // WNDOE_SINGLE_INSTANCE event so at least we get the language
  359. // neutral mof
  360. //
  361. WnodeSI->WnodeHeader.Flags &= ~WNODE_FLAG_INTERNAL;
  362. EtwpMakeEventCallbacks((PWNODE_HEADER)WnodeSI,
  363. Callback,
  364. DeliveryContext,
  365. IsAnsi);
  366. }
  367. }
  368. void EtwpProcessLanguageAddRemoveEvent(
  369. IN PWNODE_SINGLE_INSTANCE WnodeSI,
  370. IN NOTIFICATIONCALLBACK Callback,
  371. IN ULONG_PTR DeliveryContext,
  372. IN BOOLEAN IsAnsi
  373. )
  374. {
  375. ULONG Status;
  376. PWMIMOFLIST MofList;
  377. PWCHAR Language;
  378. //
  379. // Get list of mof resources and build an event with the list of
  380. // resources for the language that is coming or going
  381. //
  382. Status = EtwpGetMofResourceList(&MofList);
  383. if (Status == ERROR_SUCCESS)
  384. {
  385. Language = (PWCHAR)OffsetToPtr(WnodeSI,
  386. WnodeSI->DataBlockOffset + sizeof(USHORT));
  387. Status = EtwpBuildMofAddRemoveEvent(WnodeSI,
  388. MofList,
  389. &Language,
  390. 1,
  391. FALSE,
  392. Callback,
  393. DeliveryContext,
  394. IsAnsi);
  395. }
  396. }