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.

1054 lines
33 KiB

  1. /*++
  2. Copyright (c) 1997-1999 Microsoft Corporation
  3. Module Name:
  4. intrnldp.c
  5. Abstract:
  6. Implements WMI internal data provider
  7. Author:
  8. 21-Feb-1998 AlanWar
  9. Revision History:
  10. --*/
  11. #include "wmiump.h"
  12. #include "wmidata.h"
  13. #include <cfgmgr32.h>
  14. #define INSTANCE_INFO_GUID_INDEX 0
  15. #define ENUMERATE_GUIDS_GUID_INDEX 1
  16. #define DEFAULT_GUID_COUNT 100
  17. GUID EtwpInternalGuidList[] =
  18. {
  19. INSTANCE_INFO_GUID,
  20. ENUMERATE_GUIDS_GUID
  21. };
  22. #define EtwpInternalGuidCount (sizeof(EtwpInternalGuidList) / sizeof(GUID))
  23. PWCHAR GuidToWString(
  24. PWCHAR s,
  25. LPGUID piid
  26. )
  27. {
  28. swprintf(s, (L"{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}"),
  29. piid->Data1, piid->Data2,
  30. piid->Data3,
  31. piid->Data4[0], piid->Data4[1],
  32. piid->Data4[2], piid->Data4[3],
  33. piid->Data4[4], piid->Data4[5],
  34. piid->Data4[6], piid->Data4[7]);
  35. return(s);
  36. }
  37. ULONG EtwpFindGuid(
  38. LPGUID Guid
  39. )
  40. {
  41. ULONG i;
  42. for (i = 0; i < EtwpInternalGuidCount; i++)
  43. {
  44. if (memcmp(Guid, &EtwpInternalGuidList[i], sizeof(GUID)) == 0)
  45. {
  46. break;
  47. }
  48. }
  49. return(i);
  50. }
  51. typedef
  52. DWORD
  53. (*PCMGETDEVNODEREGISTRYPROPERTYW)(
  54. IN DEVINST dnDevInst,
  55. IN ULONG ulProperty,
  56. OUT PULONG pulRegDataType, OPTIONAL
  57. OUT PVOID Buffer, OPTIONAL
  58. IN OUT PULONG pulLength,
  59. IN ULONG ulFlags
  60. );
  61. typedef
  62. DWORD
  63. (*PCMLOCATEDEVNODEW)(
  64. OUT PDEVINST pdnDevInst,
  65. IN DEVINSTID_W pDeviceID, OPTIONAL
  66. IN ULONG ulFlags
  67. );
  68. typedef
  69. DWORD
  70. (*PCMLOCATEDEVNODEA)(
  71. OUT PDEVINST pdnDevInst,
  72. IN DEVINSTID_A pDeviceID, OPTIONAL
  73. IN ULONG ulFlags
  74. );
  75. #ifdef UNICODE
  76. #define PCMLOCATEDEVNODE PCMLOCATEDEVNODEW
  77. #else
  78. #define PCMLOCATEDEVNODE PCMLOCATEDEVNODEA
  79. #endif
  80. void EtwpGetDevInstProperty(
  81. IN DEVINST DevInst,
  82. IN ULONG Property,
  83. IN OUT PBOOLEAN BufferFull,
  84. IN OUT PUCHAR *OutBuffer,
  85. IN OUT PULONG BufferLeft,
  86. IN OUT PULONG BufferNeeded,
  87. IN PCMGETDEVNODEREGISTRYPROPERTYW CMGetDevNodeRegistryProperty
  88. )
  89. {
  90. PWCHAR WCharPtr;
  91. PUCHAR PropertyBuffer;
  92. ULONG PropertyBufferLength;
  93. ULONG Type;
  94. ULONG Status;
  95. ULONG BufferUsed;
  96. ULONG Size;
  97. #ifdef MEMPHIS
  98. ULONG PropertyBufferLengthAnsi;
  99. PCHAR PropertyBufferAnsi;
  100. CHAR AnsiBuffer[MAX_PATH];
  101. #endif
  102. #ifdef MEMPHIS
  103. PropertyBufferAnsi = AnsiBuffer;
  104. PropertyBufferLengthAnsi = sizeof(AnsiBuffer);
  105. Status = (*CMGetDevNodeRegistryProperty)(DevInst,
  106. Property,
  107. &Type,
  108. PropertyBufferAnsi,
  109. &PropertyBufferLengthAnsi,
  110. 0);
  111. if (Status == CR_BUFFER_SMALL)
  112. {
  113. PropertyBufferAnsi = EtwpAlloc(PropertyBufferLengthAnsi);
  114. if (PropertyBufferAnsi != NULL)
  115. {
  116. Status = (*CMGetDevNodeRegistryProperty)(DevInst,
  117. Property,
  118. &Type,
  119. PropertyBufferAnsi,
  120. &PropertyBufferLengthAnsi,
  121. 0);
  122. } else {
  123. Status = CR_OUT_OF_MEMORY;
  124. }
  125. }
  126. if (Status == CR_SUCCESS)
  127. {
  128. if (UnicodeSizeForAnsiString(PropertyBufferAnsi,
  129. &Size) != ERROR_SUCCESS)
  130. {
  131. Status = CR_FAILURE;
  132. }
  133. }
  134. #endif
  135. if ((*BufferFull) || (*BufferLeft == 0))
  136. {
  137. PropertyBufferLength = 0;
  138. PropertyBuffer = NULL;
  139. } else {
  140. PropertyBufferLength = *BufferLeft - sizeof(USHORT);
  141. PropertyBuffer = *OutBuffer + sizeof(USHORT);
  142. }
  143. #ifdef MEMPHIS
  144. if (Status == CR_SUCCESS)
  145. {
  146. if (PropertyBufferLength >= Size)
  147. {
  148. if (AnsiToUnicode(PropertyBufferAnsi,
  149. (PWCHAR *)&PropertyBuffer) != ERROR_SUCCESS)
  150. {
  151. Status = CR_FAILURE;
  152. }
  153. } else {
  154. Status = CR_BUFFER_SMALL;
  155. }
  156. PropertyBufferLength = Size;
  157. }
  158. if (PropertyBufferAnsi != AnsiBuffer)
  159. {
  160. EtwpFree(PropertyBufferAnsi);
  161. }
  162. #else
  163. Status = (*CMGetDevNodeRegistryProperty)(DevInst,
  164. Property,
  165. &Type,
  166. PropertyBuffer,
  167. &PropertyBufferLength,
  168. 0);
  169. #endif
  170. BufferUsed = PropertyBufferLength + sizeof(USHORT);
  171. if (Status == CR_SUCCESS)
  172. {
  173. PropertyBuffer -= sizeof(USHORT);
  174. *((PUSHORT)PropertyBuffer) = (USHORT)PropertyBufferLength;
  175. *BufferLeft -= BufferUsed;
  176. *OutBuffer += BufferUsed;
  177. *BufferNeeded += BufferUsed;
  178. } else if (Status == CR_BUFFER_SMALL) {
  179. *BufferNeeded += BufferUsed;
  180. *BufferFull = TRUE;
  181. } else {
  182. *BufferNeeded += 2;
  183. if ((! *BufferFull) && (*BufferLeft >= sizeof(USHORT)))
  184. {
  185. PropertyBuffer -= sizeof(USHORT);
  186. *((PUSHORT)PropertyBuffer) = 0;
  187. *BufferLeft -= sizeof(USHORT);
  188. *OutBuffer += sizeof(USHORT);
  189. } else {
  190. *BufferFull = TRUE;
  191. }
  192. }
  193. }
  194. ULONG EtwpGetDevInstInfo(
  195. PWCHAR DevInstName,
  196. ULONG MaxSize,
  197. PUCHAR OutBuffer,
  198. ULONG *RetSize,
  199. PCMLOCATEDEVNODE CMLocateDevNode,
  200. PCMGETDEVNODEREGISTRYPROPERTYW CMGetDevNodeRegistryProperty
  201. )
  202. {
  203. PUCHAR Buffer;
  204. DEVINST DevInst;
  205. ULONG Status;
  206. ULONG BufferNeeded;
  207. ULONG BufferLeft;
  208. BOOLEAN BufferFull;
  209. PWCHAR WCharPtr;
  210. #ifdef MEMPHIS
  211. PCHAR AnsiDevInstName;
  212. #endif
  213. // TODO: Memphis string translations
  214. #ifdef MEMPHIS
  215. AnsiDevInstName = NULL;
  216. Status = UnicodeToAnsi(DevInstName,
  217. &AnsiDevInstName,
  218. NULL);
  219. if (Status == ERROR_SUCCESS)
  220. {
  221. Status = (*CMLocateDevNode)(&DevInst,
  222. AnsiDevInstName,
  223. CM_LOCATE_DEVNODE_NORMAL);
  224. EtwpFree(AnsiDevInstName);
  225. }
  226. #else
  227. Status = (*CMLocateDevNode)(&DevInst,
  228. DevInstName,
  229. CM_LOCATE_DEVNODE_NORMAL);
  230. #endif
  231. if (Status == CR_SUCCESS)
  232. {
  233. BufferFull = (MaxSize == 0);
  234. BufferNeeded = 0;
  235. BufferLeft = MaxSize;
  236. WCharPtr = (PWCHAR)OutBuffer;
  237. EtwpGetDevInstProperty(DevInst,
  238. CM_DRP_FRIENDLYNAME,
  239. &BufferFull,
  240. &((PUCHAR)WCharPtr),
  241. &BufferLeft,
  242. &BufferNeeded,
  243. CMGetDevNodeRegistryProperty);
  244. EtwpGetDevInstProperty(DevInst,
  245. CM_DRP_DEVICEDESC,
  246. &BufferFull,
  247. &((PUCHAR)WCharPtr),
  248. &BufferLeft,
  249. &BufferNeeded,
  250. CMGetDevNodeRegistryProperty);
  251. EtwpGetDevInstProperty(DevInst,
  252. CM_DRP_LOCATION_INFORMATION,
  253. &BufferFull,
  254. &((PUCHAR)WCharPtr),
  255. &BufferLeft,
  256. &BufferNeeded,
  257. CMGetDevNodeRegistryProperty);
  258. EtwpGetDevInstProperty(DevInst,
  259. CM_DRP_MFG,
  260. &BufferFull,
  261. &((PUCHAR)WCharPtr),
  262. &BufferLeft,
  263. &BufferNeeded,
  264. CMGetDevNodeRegistryProperty);
  265. EtwpGetDevInstProperty(DevInst,
  266. CM_DRP_SERVICE,
  267. &BufferFull,
  268. &((PUCHAR)WCharPtr),
  269. &BufferLeft,
  270. &BufferNeeded,
  271. CMGetDevNodeRegistryProperty);
  272. Status = BufferFull ? ERROR_INSUFFICIENT_BUFFER : ERROR_SUCCESS;
  273. *RetSize = BufferNeeded;
  274. } else {
  275. Status = ERROR_INVALID_DATA;
  276. }
  277. return(Status);
  278. }
  279. PWCHAR EtwpCountedToSzAndTrim(
  280. PWCHAR InNamePtr,
  281. PWCHAR OutNameBuffer,
  282. ULONG OutNameSizeInBytes,
  283. BOOLEAN Trim
  284. )
  285. {
  286. PWCHAR WCharPtr, DevInstName;
  287. ULONG DevInstNameLength;
  288. ULONG i;
  289. WCharPtr = InNamePtr;
  290. DevInstNameLength = *WCharPtr++;
  291. if (DevInstNameLength >= OutNameSizeInBytes)
  292. {
  293. DevInstName = EtwpAlloc( DevInstNameLength + sizeof(USHORT));
  294. } else {
  295. DevInstName = OutNameBuffer;
  296. }
  297. if (DevInstName != NULL)
  298. {
  299. memcpy(DevInstName, WCharPtr, DevInstNameLength);
  300. DevInstNameLength /= sizeof(WCHAR);
  301. DevInstName[DevInstNameLength--] = UNICODE_NULL;
  302. if (Trim)
  303. {
  304. //
  305. // Trim off the final _xxx from the Instance name to convert it to
  306. // the Device Instance Name
  307. WCharPtr = DevInstName + DevInstNameLength;
  308. i = DevInstNameLength;
  309. while ((*WCharPtr != L'_') && (i-- != 0))
  310. {
  311. WCharPtr--;
  312. }
  313. *WCharPtr = UNICODE_NULL;
  314. }
  315. }
  316. return(DevInstName);
  317. }
  318. ULONG EtwpQuerySingleInstanceInfo(
  319. PWNODE_SINGLE_INSTANCE Wnode,
  320. ULONG MaxWnodeSize,
  321. PVOID OutBuffer,
  322. ULONG *RetWnodeSize,
  323. PCMLOCATEDEVNODE CMLocateDevNode,
  324. PCMGETDEVNODEREGISTRYPROPERTYW CMGetDevNodeRegistryProperty
  325. )
  326. {
  327. WCHAR DevInstBuffer[MAX_PATH];
  328. PWCHAR WCharPtr;
  329. PWCHAR DevInstName;
  330. ULONG DevInstNameLength;
  331. ULONG i;
  332. ULONG BufferSize;
  333. ULONG MaxBufferSize;
  334. ULONG WnodeNeeded;
  335. PUCHAR Buffer;
  336. ULONG Status;
  337. EtwpAssert(! (Wnode->WnodeHeader.Flags & WNODE_FLAG_STATIC_INSTANCE_NAMES));
  338. EtwpAssert(Wnode->OffsetInstanceName < Wnode->WnodeHeader.BufferSize);
  339. EtwpAssert(Wnode->DataBlockOffset <= MaxWnodeSize);
  340. WCharPtr = (PWCHAR)((PUCHAR)Wnode + Wnode->OffsetInstanceName);
  341. DevInstName = EtwpCountedToSzAndTrim(WCharPtr,
  342. DevInstBuffer,
  343. MAX_PATH * sizeof(WCHAR),
  344. TRUE);
  345. if (DevInstName != NULL)
  346. {
  347. Buffer = (PUCHAR)OffsetToPtr(Wnode, Wnode->DataBlockOffset);
  348. MaxBufferSize = MaxWnodeSize - Wnode->DataBlockOffset;
  349. BufferSize = 0;
  350. Status = EtwpGetDevInstInfo(DevInstName,
  351. MaxBufferSize,
  352. Buffer,
  353. &BufferSize,
  354. CMLocateDevNode,
  355. CMGetDevNodeRegistryProperty);
  356. WnodeNeeded = Wnode->DataBlockOffset + BufferSize;
  357. if (Status == ERROR_SUCCESS)
  358. {
  359. WmiInsertTimestamp((PWNODE_HEADER)Wnode);
  360. Wnode->WnodeHeader.BufferSize = WnodeNeeded;
  361. Wnode->SizeDataBlock = BufferSize;
  362. *RetWnodeSize = WnodeNeeded;
  363. } else if (Status == ERROR_INSUFFICIENT_BUFFER) {
  364. EtwpAssert(MaxWnodeSize > sizeof(WNODE_TOO_SMALL));
  365. Wnode->WnodeHeader.Flags = WNODE_FLAG_TOO_SMALL;
  366. ((PWNODE_TOO_SMALL)Wnode)->SizeNeeded = WnodeNeeded;
  367. Wnode->WnodeHeader.BufferSize = sizeof(WNODE_TOO_SMALL);
  368. *RetWnodeSize = sizeof(WNODE_TOO_SMALL);
  369. Status = ERROR_SUCCESS;
  370. }
  371. if (DevInstName != DevInstBuffer)
  372. {
  373. EtwpFree(DevInstName);
  374. }
  375. } else {
  376. Status = ERROR_NOT_ENOUGH_MEMORY;
  377. }
  378. return(Status);
  379. }
  380. GUID PnPDeviceIdGuid = DATA_PROVIDER_PNPID_GUID;
  381. ULONG EtwpComputeInstanceCount(
  382. PWNODE_ALL_DATA WAD,
  383. ULONG WnodeSize,
  384. PULONG InstanceCount
  385. )
  386. {
  387. ULONG Linkage;
  388. ULONG Count = 0;
  389. do
  390. {
  391. Linkage = WAD->WnodeHeader.Linkage;
  392. if (Linkage > WnodeSize)
  393. {
  394. EtwpDebugPrint(("WMI: Badly formed Wnode %x\n", WAD));
  395. EtwpAssert(FALSE);
  396. return(ERROR_INVALID_DATA);
  397. }
  398. Count += WAD->InstanceCount;
  399. WnodeSize -= Linkage;
  400. WAD = (PWNODE_ALL_DATA)OffsetToPtr(WAD, WAD->WnodeHeader.Linkage);
  401. } while (Linkage != 0);
  402. *InstanceCount = Count;
  403. return(ERROR_SUCCESS);
  404. }
  405. ULONG EtwpQueryAllInstanceInfo(
  406. PWNODE_ALL_DATA OutWAD,
  407. ULONG MaxWnodeSize,
  408. PVOID OutBuffer,
  409. ULONG *RetSize,
  410. PCMLOCATEDEVNODE CMLocateDevNode,
  411. PCMGETDEVNODEREGISTRYPROPERTYW CMGetDevNodeRegistryProperty
  412. )
  413. {
  414. ULONG Status;
  415. PWNODE_ALL_DATA PnPIdWAD;
  416. WMIHANDLE PnPIdHandle;
  417. ULONG Size, Retries;
  418. ULONG InstanceCount;
  419. POFFSETINSTANCEDATAANDLENGTH OutOffsetNameLenPtr;
  420. ULONG OutOffsetInstanceNameOffsets;
  421. PULONG OutOffsetInstanceNameOffsetsPtr;
  422. ULONG OutSizeNeeded, OutInstanceCounter = 0;
  423. BOOLEAN OutIsFull = FALSE;
  424. ULONG OutNameOffset;
  425. ULONG OutNameSizeNeeded;
  426. ULONG OutSizeLeft;
  427. ULONG OutDataSize;
  428. PWCHAR OutNamePtr;
  429. PWNODE_ALL_DATA InWAD;
  430. BOOLEAN IsFixedSize;
  431. PWCHAR InNamePtr;
  432. PWCHAR InPnPIdPtr;
  433. ULONG FixedNameSize;
  434. ULONG i;
  435. PWCHAR DevInstName;
  436. WCHAR DevInstBuffer[MAX_PATH];
  437. POFFSETINSTANCEDATAANDLENGTH InOffsetNameLenPtr;
  438. PUCHAR Buffer;
  439. ULONG Linkage;
  440. PULONG InOffsetInstanceNamePtr;
  441. PWNODE_TOO_SMALL WTS;
  442. ULONG OutDataOffset;
  443. //
  444. // Obtain the complete list of device instance ids
  445. //
  446. Status = WmiOpenBlock(&PnPDeviceIdGuid, WMIGUID_QUERY, &PnPIdHandle);
  447. if (Status == ERROR_SUCCESS)
  448. {
  449. Size = 0x1000;
  450. Retries = 0;
  451. PnPIdWAD = NULL;
  452. do
  453. {
  454. if (PnPIdWAD != NULL)
  455. {
  456. EtwpFree(PnPIdWAD);
  457. }
  458. PnPIdWAD = (PWNODE_ALL_DATA)EtwpAlloc(Size);
  459. if (PnPIdWAD != NULL)
  460. {
  461. Status = WmiQueryAllDataW(PnPIdHandle,
  462. &Size,
  463. PnPIdWAD);
  464. } else {
  465. Status = ERROR_NOT_ENOUGH_MEMORY;
  466. }
  467. } while ((Status == ERROR_INSUFFICIENT_BUFFER) &&
  468. (Retries++ < 5));
  469. if (Status == ERROR_INSUFFICIENT_BUFFER)
  470. {
  471. EtwpAssert(FALSE);
  472. Status = ERROR_WMI_DP_NOT_FOUND;
  473. }
  474. WmiCloseBlock(PnPIdHandle);
  475. }
  476. if (Status == ERROR_SUCCESS)
  477. {
  478. Status = EtwpComputeInstanceCount(PnPIdWAD,
  479. Size,
  480. &InstanceCount);
  481. if (Status == ERROR_SUCCESS)
  482. {
  483. //
  484. // Prepare output WNODE
  485. OutOffsetNameLenPtr = OutWAD->OffsetInstanceDataAndLength;
  486. OutOffsetInstanceNameOffsets = sizeof(WNODE_ALL_DATA) +
  487. (InstanceCount * sizeof(OFFSETINSTANCEDATAANDLENGTH));
  488. OutOffsetInstanceNameOffsetsPtr = (PULONG)OffsetToPtr(OutWAD,
  489. OutOffsetInstanceNameOffsets);
  490. OutSizeNeeded = ((OutOffsetInstanceNameOffsets +
  491. (InstanceCount * sizeof(ULONG))) + 7) & ~7;
  492. EtwpDebugPrint(("WMI: Basic OutSizeNeeded = 0x%x\n", OutSizeNeeded));
  493. //
  494. // Loop over all device instance ids returned and build
  495. // output wnode
  496. InWAD = PnPIdWAD;
  497. do
  498. {
  499. //
  500. // Get Instance and device instance id from input wnode
  501. InOffsetInstanceNamePtr = (PULONG)OffsetToPtr(InWAD,
  502. InWAD->OffsetInstanceNameOffsets);
  503. // TODO: Validate InOffsetInstanceNamePtr
  504. if (InWAD->WnodeHeader.Flags & WNODE_FLAG_FIXED_INSTANCE_SIZE)
  505. {
  506. IsFixedSize = TRUE;
  507. InPnPIdPtr = (PWCHAR)OffsetToPtr(InWAD,
  508. InWAD->DataBlockOffset);
  509. FixedNameSize = (InWAD->FixedInstanceSize + 7) & ~7;
  510. } else {
  511. IsFixedSize = FALSE;
  512. InOffsetNameLenPtr = InWAD->OffsetInstanceDataAndLength;
  513. }
  514. for (i = 0; i < InWAD->InstanceCount; i++)
  515. {
  516. if (! IsFixedSize)
  517. {
  518. InPnPIdPtr = (PWCHAR)OffsetToPtr(InWAD,
  519. InOffsetNameLenPtr[i].OffsetInstanceData);
  520. }
  521. InNamePtr = (PWCHAR)OffsetToPtr(InWAD,
  522. InOffsetInstanceNamePtr[i]);
  523. //
  524. // TODO: Validate InNamePtr and InPnPIdPtr
  525. if (FALSE)
  526. {
  527. //
  528. // If we hit a bad instance name then we throw out the
  529. // entire wnode
  530. EtwpDebugPrint(("WMI: Badly formed instance name %x\n",
  531. InNamePtr));
  532. EtwpAssert(FALSE);
  533. break;
  534. }
  535. DevInstName = EtwpCountedToSzAndTrim(InPnPIdPtr,
  536. DevInstBuffer,
  537. MAX_PATH * sizeof(WCHAR),
  538. FALSE);
  539. if (DevInstName != NULL)
  540. {
  541. EtwpDebugPrint(("WMI: Processing %ws\n", DevInstName));
  542. //
  543. // Compute size and location of the output instance name
  544. // It needs to start on a word boundry and end on a 8 byte
  545. // boundry
  546. OutNameOffset = (OutSizeNeeded+1) & ~1;
  547. OutNameSizeNeeded = OutNameOffset - OutSizeNeeded;
  548. OutNameSizeNeeded += *InNamePtr + sizeof(USHORT);
  549. OutNameSizeNeeded = ((OutNameOffset + OutNameSizeNeeded + 7) & ~7) - OutNameOffset;
  550. EtwpDebugPrint(("WMI: OutNameSizeNeeded = 0x%x\n", OutNameSizeNeeded));
  551. OutDataOffset = OutSizeNeeded + OutNameSizeNeeded;
  552. if ((OutIsFull) ||
  553. (OutDataOffset > MaxWnodeSize))
  554. {
  555. EtwpDebugPrint((" WMI: OutIsFull\n"));
  556. Buffer = NULL;
  557. OutSizeLeft = 0;
  558. OutIsFull = TRUE;
  559. } else {
  560. Buffer = (PUCHAR)OffsetToPtr(OutWAD,
  561. OutDataOffset);
  562. OutSizeLeft = MaxWnodeSize - OutDataOffset;
  563. EtwpDebugPrint((" WMI: Out Not Full, OutSizeLeft = 0x%x at 0x%x\n", OutSizeLeft, OutDataOffset));
  564. }
  565. //
  566. // Now that we have the name, lets get the vital info
  567. Status = EtwpGetDevInstInfo(DevInstName,
  568. OutSizeLeft,
  569. Buffer,
  570. &OutDataSize,
  571. CMLocateDevNode,
  572. CMGetDevNodeRegistryProperty);
  573. EtwpDebugPrint((" WMI: GetInfo -> %d, OutDataSize 0x%x\n", Status, OutDataSize));
  574. if (Status == ERROR_SUCCESS)
  575. {
  576. //
  577. // We were able to get all of the data so fill in the
  578. // instance name
  579. OutNamePtr = (PWCHAR)OffsetToPtr(OutWAD,
  580. OutNameOffset);
  581. *OutOffsetInstanceNameOffsetsPtr++ = OutNameOffset;
  582. *OutNamePtr++ = *InNamePtr;
  583. memcpy(OutNamePtr, InNamePtr+1, *InNamePtr);
  584. //
  585. // Now fill in the output data
  586. OutOffsetNameLenPtr[OutInstanceCounter].OffsetInstanceData = OutDataOffset;
  587. OutOffsetNameLenPtr[OutInstanceCounter].LengthInstanceData = OutDataSize;
  588. OutInstanceCounter++;
  589. } else if (Status == ERROR_INSUFFICIENT_BUFFER) {
  590. OutIsFull = TRUE;
  591. OutInstanceCounter++;
  592. } else {
  593. OutNameSizeNeeded = 0;
  594. OutDataSize = 0;
  595. }
  596. OutSizeNeeded += (OutNameSizeNeeded + OutDataSize);
  597. EtwpDebugPrint((" WMI: OutSizeNeeded = 0x%x\n", OutSizeNeeded));
  598. if (DevInstName != DevInstBuffer)
  599. {
  600. EtwpFree(DevInstName);
  601. }
  602. } else {
  603. return(ERROR_NOT_ENOUGH_MEMORY);
  604. }
  605. if (IsFixedSize)
  606. {
  607. InPnPIdPtr = (PWCHAR)((PUCHAR)InPnPIdPtr + FixedNameSize);
  608. }
  609. }
  610. Linkage = InWAD->WnodeHeader.Linkage;
  611. InWAD = (PWNODE_ALL_DATA)OffsetToPtr(InWAD,
  612. InWAD->WnodeHeader.Linkage);
  613. } while (Linkage != 0);
  614. }
  615. }
  616. //
  617. // Output wnode post processing. If not enough room then return a
  618. // WNODE_TOO_SMALL, otherwise fill in WNODE_ALL_DATA fields
  619. if ((OutInstanceCounter > 0) || (Status == ERROR_SUCCESS))
  620. {
  621. if (OutIsFull)
  622. {
  623. WTS = (PWNODE_TOO_SMALL)OutWAD;
  624. WTS->WnodeHeader.BufferSize = sizeof(WNODE_TOO_SMALL);
  625. WTS->WnodeHeader.Flags = WNODE_FLAG_TOO_SMALL;
  626. WTS->SizeNeeded = OutSizeNeeded;
  627. *RetSize = sizeof(WNODE_TOO_SMALL);
  628. } else {
  629. OutWAD->WnodeHeader.BufferSize = OutSizeNeeded;
  630. OutWAD->InstanceCount = OutInstanceCounter;
  631. OutWAD->OffsetInstanceNameOffsets = OutOffsetInstanceNameOffsets;
  632. *RetSize = OutSizeNeeded;
  633. }
  634. Status = ERROR_SUCCESS;
  635. }
  636. return(Status);
  637. }
  638. #ifdef MEMPHIS
  639. #define CFGMGRDLL TEXT("cfgmgr32.dll")
  640. #else
  641. #define CFGMGRDLL TEXT("setupapi.dll")
  642. #endif
  643. ULONG EtwpQueryInstanceInfo(
  644. ULONG ActionCode,
  645. PWNODE_HEADER Wnode,
  646. ULONG MaxWnodeSize,
  647. PVOID OutBuffer,
  648. ULONG *RetSize
  649. )
  650. {
  651. HMODULE CfgMgr32ModuleHandle;
  652. PCMGETDEVNODEREGISTRYPROPERTYW CMGetDevNodeRegistryProperty;
  653. PCMLOCATEDEVNODE CMLocateDevNode;
  654. ULONG Status;
  655. //
  656. // Ensure this is a request we support
  657. if ((ActionCode != WmiGetSingleInstance) &&
  658. (ActionCode != WmiGetAllData))
  659. {
  660. return(ERROR_INVALID_FUNCTION);
  661. }
  662. //
  663. // First we try to demand load cfgmgr32.dll
  664. CfgMgr32ModuleHandle = LoadLibrary(CFGMGRDLL);
  665. if (CfgMgr32ModuleHandle != NULL)
  666. {
  667. #ifdef MEMPHIS
  668. CMLocateDevNode = (PCMLOCATEDEVNODEA)GetProcAddress(CfgMgr32ModuleHandle,
  669. "CM_Locate_DevNodeA");
  670. #else
  671. CMLocateDevNode = (PCMLOCATEDEVNODEW)GetProcAddress(CfgMgr32ModuleHandle,
  672. "CM_Locate_DevNodeW");
  673. #endif
  674. CMGetDevNodeRegistryProperty = (PCMGETDEVNODEREGISTRYPROPERTYW)
  675. GetProcAddress(CfgMgr32ModuleHandle,
  676. #ifdef MEMPHIS
  677. "CM_Get_DevNode_Registry_PropertyA");
  678. #else
  679. "CM_Get_DevNode_Registry_PropertyW");
  680. #endif
  681. if ((CMLocateDevNode == NULL) ||
  682. (CMGetDevNodeRegistryProperty == NULL))
  683. {
  684. FreeLibrary(CfgMgr32ModuleHandle);
  685. EtwpDebugPrint(("WMI: Couldn't get CfgMgr32 prog addresses %d\n",
  686. GetLastError()));
  687. return(GetLastError());
  688. }
  689. } else {
  690. EtwpDebugPrint(("WMI: Couldn't load CfgMgr32 %d\n",
  691. GetLastError()));
  692. return(GetLastError());
  693. }
  694. if (ActionCode == WmiGetSingleInstance)
  695. {
  696. Status = EtwpQuerySingleInstanceInfo((PWNODE_SINGLE_INSTANCE)Wnode,
  697. MaxWnodeSize,
  698. OutBuffer,
  699. RetSize,
  700. CMLocateDevNode,
  701. CMGetDevNodeRegistryProperty);
  702. } else if (ActionCode == WmiGetAllData) {
  703. Status = EtwpQueryAllInstanceInfo((PWNODE_ALL_DATA)Wnode,
  704. MaxWnodeSize,
  705. OutBuffer,
  706. RetSize,
  707. CMLocateDevNode,
  708. CMGetDevNodeRegistryProperty);
  709. } else {
  710. EtwpAssert(FALSE);
  711. }
  712. FreeLibrary(CfgMgr32ModuleHandle);
  713. return(Status);
  714. }
  715. ULONG
  716. EtwpEnumRegGuids(
  717. PWMIGUIDLISTINFO *pGuidInfo
  718. )
  719. {
  720. ULONG Status = ERROR_SUCCESS;
  721. ULONG MaxGuidCount = 0;
  722. PWMIGUIDLISTINFO GuidInfo;
  723. ULONG RetSize;
  724. ULONG GuidInfoSize;
  725. MaxGuidCount = DEFAULT_GUID_COUNT;
  726. retry:
  727. GuidInfoSize = FIELD_OFFSET(WMIGUIDLISTINFO, GuidList) +
  728. MaxGuidCount * sizeof(WMIGUIDPROPERTIES);
  729. GuidInfo = (PWMIGUIDLISTINFO)EtwpAlloc(GuidInfoSize);
  730. if (GuidInfo == NULL)
  731. {
  732. return (ERROR_NOT_ENOUGH_MEMORY);
  733. }
  734. RtlZeroMemory(GuidInfo, GuidInfoSize);
  735. Status = EtwpSendWmiKMRequest(NULL,
  736. IOCTL_WMI_ENUMERATE_GUIDS_AND_PROPERTIES,
  737. GuidInfo,
  738. GuidInfoSize,
  739. GuidInfo,
  740. GuidInfoSize,
  741. &RetSize,
  742. NULL);
  743. if (Status == ERROR_SUCCESS)
  744. {
  745. if ((RetSize < FIELD_OFFSET(WMIGUIDLISTINFO, GuidList)) ||
  746. (RetSize < (FIELD_OFFSET(WMIGUIDLISTINFO, GuidList) +
  747. GuidInfo->ReturnedGuidCount * sizeof(WMIGUIDPROPERTIES))))
  748. {
  749. //
  750. // WMI KM returned to us a bad size which should not happen
  751. //
  752. Status = ERROR_WMI_DP_FAILED;
  753. EtwpAssert(FALSE);
  754. EtwpFree(GuidInfo);
  755. } else {
  756. //
  757. // If RPC was successful, then build a WMI DataBlock with the data
  758. //
  759. if (GuidInfo->TotalGuidCount > GuidInfo->ReturnedGuidCount) {
  760. MaxGuidCount = GuidInfo->TotalGuidCount;
  761. EtwpFree(GuidInfo);
  762. goto retry;
  763. }
  764. }
  765. //
  766. // If the call was successful, return the pointers and the caller
  767. // must free the storage.
  768. //
  769. *pGuidInfo = GuidInfo;
  770. }
  771. return Status;
  772. }
  773. ULONG
  774. EtwpEnumerateGuids(
  775. PWNODE_ALL_DATA Wnode,
  776. ULONG MaxWnodeSize,
  777. PVOID OutBuffer,
  778. ULONG *RetSize)
  779. {
  780. ULONG Status = ERROR_SUCCESS;
  781. PWMIGUIDLISTINFO GuidInfo = NULL;
  782. ULONG ReturnGuidCount = 0;
  783. Status = EtwpEnumRegGuids(&GuidInfo);
  784. if (Status == ERROR_SUCCESS) {
  785. PWMIGUIDPROPERTIES pGuidProperties = GuidInfo->GuidList;
  786. LPGUID pGuid;
  787. WCHAR s[256];
  788. ULONG InstanceNameOffset;
  789. ULONG i;
  790. ULONG InstanceDataSize = sizeof(WMIGUIDPROPERTIES) -
  791. FIELD_OFFSET(WMIGUIDPROPERTIES, GuidType);
  792. ULONG FixedInstanceSizeWithPadding = (InstanceDataSize+7) & ~7;
  793. USHORT GuidStringSize = 76;
  794. ULONG SizeNeeded;
  795. PUCHAR BytePtr;
  796. PULONG UlongPtr;
  797. PUCHAR NamePtr;
  798. ULONG DataBlockOffset;
  799. EtwpAssert(GuidInfo->ReturnedGuidCount == GuidInfo->TotalGuidCount);
  800. ReturnGuidCount = GuidInfo->ReturnedGuidCount;
  801. SizeNeeded = sizeof(WNODE_ALL_DATA) +
  802. ReturnGuidCount * (FixedInstanceSizeWithPadding +
  803. GuidStringSize +
  804. sizeof(ULONG) +
  805. sizeof(WCHAR));
  806. if (MaxWnodeSize < SizeNeeded) {
  807. //
  808. // Build WNODE_TOO_SMALL
  809. //
  810. EtwpAssert(MaxWnodeSize > sizeof(WNODE_TOO_SMALL));
  811. Wnode->WnodeHeader.Flags = WNODE_FLAG_TOO_SMALL;
  812. ((PWNODE_TOO_SMALL)Wnode)->SizeNeeded = SizeNeeded;
  813. Wnode->WnodeHeader.BufferSize = sizeof(WNODE_TOO_SMALL);
  814. *RetSize = sizeof(WNODE_TOO_SMALL);
  815. EtwpFree(GuidInfo);
  816. return ERROR_SUCCESS;
  817. }
  818. Wnode->InstanceCount = ReturnGuidCount;
  819. Wnode->FixedInstanceSize = InstanceDataSize;
  820. Wnode->WnodeHeader.Flags |= WNODE_FLAG_FIXED_INSTANCE_SIZE;
  821. DataBlockOffset = sizeof(WNODE_ALL_DATA);
  822. //
  823. // pad out to an 8 byte boundary.
  824. //
  825. DataBlockOffset = (DataBlockOffset + 7) & ~7;
  826. Wnode->DataBlockOffset = DataBlockOffset;
  827. BytePtr = (PUCHAR)((PUCHAR)Wnode + DataBlockOffset);
  828. InstanceNameOffset = DataBlockOffset +
  829. (ReturnGuidCount * FixedInstanceSizeWithPadding);
  830. Wnode->OffsetInstanceNameOffsets = InstanceNameOffset;
  831. UlongPtr = (PULONG)((PUCHAR)Wnode + InstanceNameOffset);
  832. NamePtr = (PUCHAR)UlongPtr;
  833. NamePtr = (PUCHAR)((PUCHAR)NamePtr + (ReturnGuidCount * sizeof(ULONG)));
  834. for (i=0; i < ReturnGuidCount; i++) {
  835. //
  836. // Copy the fixed instance datablock
  837. //
  838. RtlCopyMemory(BytePtr,
  839. &pGuidProperties->GuidType,
  840. Wnode->FixedInstanceSize);
  841. BytePtr += FixedInstanceSizeWithPadding;
  842. //
  843. // Set the Offset to InstanceName
  844. //
  845. *UlongPtr++ = (ULONG)((PCHAR)NamePtr - (PCHAR)Wnode);
  846. //
  847. // Copy over the Instance Name
  848. //
  849. *((USHORT *)NamePtr) = GuidStringSize;
  850. NamePtr += sizeof(USHORT);
  851. GuidToWString(s, &pGuidProperties->Guid);
  852. RtlCopyMemory(NamePtr, s, GuidStringSize);
  853. NamePtr += GuidStringSize;
  854. pGuidProperties++;
  855. }
  856. WmiInsertTimestamp((PWNODE_HEADER)Wnode);
  857. *RetSize = SizeNeeded;
  858. Wnode->WnodeHeader.BufferSize = SizeNeeded;
  859. EtwpFree(GuidInfo);
  860. }
  861. return Status;
  862. }
  863. ULONG EtwpInternalProvider(
  864. ULONG ActionCode,
  865. PWNODE_HEADER Wnode,
  866. ULONG MaxWnodeSize,
  867. PVOID OutBuffer,
  868. ULONG *RetSize
  869. )
  870. {
  871. ULONG GuidIndex;
  872. ULONG Status;
  873. EtwpAssert((PVOID)Wnode == OutBuffer);
  874. GuidIndex = EtwpFindGuid(&Wnode->Guid);
  875. switch(GuidIndex)
  876. {
  877. case INSTANCE_INFO_GUID_INDEX:
  878. {
  879. Status = EtwpQueryInstanceInfo(ActionCode,
  880. Wnode,
  881. MaxWnodeSize,
  882. OutBuffer,
  883. RetSize);
  884. break;
  885. }
  886. case ENUMERATE_GUIDS_GUID_INDEX:
  887. {
  888. //
  889. //
  890. // Need an RPC call to the server to get the desired data.
  891. //
  892. if (ActionCode == WmiGetAllData)
  893. Status = EtwpEnumerateGuids((PWNODE_ALL_DATA)Wnode,
  894. MaxWnodeSize,
  895. OutBuffer,
  896. RetSize);
  897. else
  898. Status = ERROR_INVALID_FUNCTION;
  899. break;
  900. }
  901. default:
  902. {
  903. Status = ERROR_WMI_GUID_NOT_FOUND;
  904. }
  905. }
  906. return(Status);
  907. }