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.

1584 lines
50 KiB

  1. /*++
  2. Copyright (c) 1997-1999 Microsoft Corporation
  3. Module Name:
  4. DataProv.c
  5. Abstract:
  6. WMI internal data provider interface
  7. Author:
  8. AlanWar
  9. Environment:
  10. Kernel mode
  11. Revision History:
  12. --*/
  13. #include "wmikmp.h"
  14. NTSTATUS
  15. WmipQueryWmiDataBlock(
  16. IN PDEVICE_OBJECT DeviceObject,
  17. IN PIRP Irp,
  18. IN ULONG GuidIndex,
  19. IN ULONG InstanceIndex,
  20. IN ULONG InstanceCount,
  21. IN OUT PULONG InstanceLengthArray,
  22. IN ULONG BufferAvail,
  23. OUT PUCHAR Buffer
  24. );
  25. NTSTATUS
  26. WmipQueryWmiRegInfo(
  27. IN PDEVICE_OBJECT DeviceObject,
  28. OUT ULONG *RegFlags,
  29. OUT PUNICODE_STRING InstanceName,
  30. OUT PUNICODE_STRING *RegistryPath
  31. );
  32. NTSTATUS WmipSetWmiDataBlock(
  33. PDEVICE_OBJECT DeviceObject,
  34. PIRP Irp,
  35. ULONG GuidIndex,
  36. ULONG InstanceIndex,
  37. ULONG BufferSize,
  38. PUCHAR Buffer
  39. );
  40. NTSTATUS
  41. WmipExecuteWmiMethod (
  42. IN PDEVICE_OBJECT DeviceObject,
  43. IN PIRP Irp,
  44. IN ULONG GuidIndex,
  45. IN ULONG InstanceIndex,
  46. IN ULONG MethodId,
  47. IN ULONG InBufferSize,
  48. IN ULONG OutBufferSize,
  49. IN OUT PUCHAR Buffer
  50. );
  51. BOOLEAN
  52. WmipFindGuid(
  53. IN PGUIDREGINFO GuidList,
  54. IN ULONG GuidCount,
  55. IN LPGUID Guid,
  56. OUT PULONG GuidIndex,
  57. OUT PULONG InstanceCount
  58. );
  59. NTSTATUS
  60. IoWMICompleteRequest(
  61. IN PWMILIB_INFO WmiLibInfo,
  62. IN PDEVICE_OBJECT DeviceObject,
  63. IN PIRP Irp,
  64. IN NTSTATUS Status,
  65. IN ULONG BufferUsed,
  66. IN CCHAR PriorityBoost
  67. );
  68. NTSTATUS
  69. IoWMISystemControl(
  70. IN PWMILIB_INFO WmiLibInfo,
  71. IN PDEVICE_OBJECT DeviceObject,
  72. IN PIRP Irp
  73. );
  74. #ifdef ALLOC_DATA_PRAGMA
  75. #pragma const_seg("PAGECONST")
  76. #endif
  77. const GUIDREGINFO WmipGuidList[] =
  78. {
  79. //
  80. // This is the pnp id guid which is registered by wmi into other device
  81. // objects' registration info. And requests to the innocent devices
  82. // are hijacked by wmi so that wmi can complete the request for it. We
  83. // have the WMIREG_FLAG_REMOVE_GUID set so that the guid is not registered
  84. // for the wmi device which does not support it.
  85. {
  86. DATA_PROVIDER_PNPID_GUID,
  87. 0,
  88. WMIREG_FLAG_REMOVE_GUID
  89. },
  90. {
  91. DATA_PROVIDER_PNPID_INSTANCE_NAMES_GUID,
  92. 0,
  93. WMIREG_FLAG_REMOVE_GUID
  94. },
  95. {
  96. MSAcpiInfoGuid,
  97. 1,
  98. 0
  99. },
  100. #if defined(_AMD64_) || defined(_IA64_) || defined(i386) || defined(MEMPHIS)
  101. {
  102. SMBIOS_DATA_GUID,
  103. 1,
  104. 0
  105. },
  106. {
  107. SYSID_UUID_DATA_GUID,
  108. 1,
  109. 0
  110. },
  111. {
  112. SYSID_1394_DATA_GUID,
  113. 1,
  114. 0
  115. },
  116. {
  117. MSSmBios_SMBiosEventlogGuid,
  118. 1,
  119. 0
  120. },
  121. #endif
  122. #if defined(_IA64_) || defined(_X86_) || defined(_AMD64_)
  123. {
  124. MSMCAInfo_RawMCADataGuid,
  125. 1,
  126. 0
  127. },
  128. #ifdef CPE_CONTROL
  129. {
  130. MSMCAInfo_CPEControlGuid,
  131. 1,
  132. 0
  133. },
  134. #endif
  135. {
  136. MSMCAInfo_RawMCAEventGuid,
  137. 1,
  138. WMIREG_FLAG_EVENT_ONLY_GUID
  139. },
  140. {
  141. MSMCAInfo_RawCMCEventGuid,
  142. 1,
  143. WMIREG_FLAG_EVENT_ONLY_GUID
  144. },
  145. {
  146. MSMCAInfo_RawCorrectedPlatformEventGuid,
  147. 1,
  148. WMIREG_FLAG_EVENT_ONLY_GUID
  149. },
  150. #endif
  151. };
  152. #define WmipGuidCount (sizeof(WmipGuidList) / sizeof(GUIDREGINFO))
  153. typedef enum
  154. {
  155. PnPIdGuidIndex = 0,
  156. PnPIdInstanceNamesGuidIndex,
  157. MSAcpiInfoGuidIndex,
  158. #if defined(_AMD64_) || defined(_IA64_) || defined(i386) || defined(MEMPHIS)
  159. SmbiosDataGuidIndex,
  160. SysidUuidGuidIndex,
  161. Sysid1394GuidIndex,
  162. SmbiosEventGuidIndex,
  163. #endif
  164. #if defined(_IA64_) || defined(_X86_) || defined(_AMD64_)
  165. MCARawDataGuidIndex,
  166. #ifdef CPE_CONTROL
  167. CPEControlGuidIndex,
  168. #endif
  169. RawMCAEventGuidIndex,
  170. RawCMCEventGuidIndex,
  171. RawCPEEventGuidIndex,
  172. #endif
  173. } WMIGUIDINDEXES;
  174. const WMILIB_INFO WmipWmiLibInfo =
  175. {
  176. NULL,
  177. NULL,
  178. WmipGuidCount,
  179. (PGUIDREGINFO)WmipGuidList,
  180. WmipQueryWmiRegInfo,
  181. WmipQueryWmiDataBlock,
  182. #ifdef CPE_CONTROL
  183. WmipSetWmiDataBlock,
  184. #else
  185. NULL,
  186. #endif
  187. NULL,
  188. NULL,
  189. NULL
  190. };
  191. #ifdef ALLOC_PRAGMA
  192. #pragma alloc_text(PAGE,WmipQueryWmiRegInfo)
  193. #pragma alloc_text(PAGE,WmipQueryWmiDataBlock)
  194. #pragma alloc_text(PAGE,WmipSetWmiDataBlock)
  195. #pragma alloc_text(PAGE,WmipExecuteWmiMethod)
  196. #pragma alloc_text(PAGE,WmipFindGuid)
  197. #pragma alloc_text(PAGE,IoWMISystemControl)
  198. #pragma alloc_text(PAGE,IoWMICompleteRequest)
  199. #endif
  200. NTSTATUS
  201. WmipQueryWmiRegInfo(
  202. IN PDEVICE_OBJECT DeviceObject,
  203. OUT ULONG *RegFlags,
  204. OUT PUNICODE_STRING InstanceName,
  205. OUT PUNICODE_STRING *RegistryPath
  206. )
  207. /*++
  208. Routine Description:
  209. This routine is a callback into the driver to retrieve the list of
  210. guids or data blocks that the driver wants to register with WMI. This
  211. routine may not pend or block. Driver should NOT call
  212. ClassWmiCompleteRequest.
  213. Arguments:
  214. DeviceObject is the device whose data block is being queried
  215. *RegFlags returns with a set of flags that describe the guids being
  216. registered for this device. If the device wants enable and disable
  217. collection callbacks before receiving queries for the registered
  218. guids then it should return the WMIREG_FLAG_EXPENSIVE flag. Also the
  219. returned flags may specify WMIREG_FLAG_INSTANCE_PDO in which case
  220. the instance name is determined from the PDO associated with the
  221. device object. Note that the PDO must have an associated devnode. If
  222. WMIREG_FLAG_INSTANCE_PDO is not set then Name must return a unique
  223. name for the device.
  224. InstanceName returns with the instance name for the guids if
  225. WMIREG_FLAG_INSTANCE_PDO is not set in the returned *RegFlags. The
  226. caller will call ExFreePool with the buffer returned.
  227. *RegistryPath returns with the registry path of the driver
  228. Return Value:
  229. status
  230. --*/
  231. {
  232. ANSI_STRING AnsiString;
  233. NTSTATUS Status;
  234. PAGED_CODE();
  235. UNREFERENCED_PARAMETER (DeviceObject);
  236. UNREFERENCED_PARAMETER (RegFlags);
  237. *RegistryPath = &WmipRegistryPath;
  238. RtlInitAnsiString(&AnsiString, "SMBiosData");
  239. Status = RtlAnsiStringToUnicodeString(InstanceName, &AnsiString, TRUE);
  240. return(Status);
  241. }
  242. NTSTATUS
  243. WmipQueryWmiDataBlock(
  244. IN PDEVICE_OBJECT DeviceObject,
  245. IN PIRP Irp,
  246. IN ULONG GuidIndex,
  247. IN ULONG InstanceIndex,
  248. IN ULONG InstanceCount,
  249. IN OUT PULONG InstanceLengthArray,
  250. IN ULONG BufferAvail,
  251. OUT PUCHAR Buffer
  252. )
  253. /*++
  254. Routine Description:
  255. This routine is a callback into the driver to query for the contents of
  256. all instances of a data block. When the driver has finished filling the
  257. data block it must call IoWMICompleteRequest to complete the irp. The
  258. driver can return STATUS_PENDING if the irp cannot be completed
  259. immediately.
  260. Arguments:
  261. DeviceObject is the device whose data block is being queried. In the case
  262. of the PnPId guid this is the device object of the device on whose
  263. behalf the request is being processed.
  264. Irp is the Irp that makes this request
  265. GuidIndex is the index into the list of guids provided when the
  266. device registered
  267. InstanceCount is the number of instnaces expected to be returned for
  268. the data block.
  269. InstanceLengthArray is a pointer to an array of ULONG that returns the
  270. lengths of each instance of the data block. If this is NULL then
  271. there was not enough space in the output buffer to fufill the request
  272. so the irp should be completed with the buffer needed.
  273. BufferAvail on entry has the maximum size available to write the data
  274. blocks.
  275. Buffer on return is filled with the returned data blocks. Note that each
  276. instance of the data block must be aligned on a 8 byte boundry.
  277. Return Value:
  278. status
  279. --*/
  280. {
  281. NTSTATUS status = STATUS_UNSUCCESSFUL;
  282. ULONG sizeNeeded = 0, sizeSMBios;
  283. PUCHAR BufferPtr;
  284. PSMBIOSVERSIONINFO SMBiosVersionInfo;
  285. PULONG TableSize = NULL;
  286. PAGED_CODE();
  287. switch (GuidIndex)
  288. {
  289. case SmbiosDataGuidIndex:
  290. {
  291. //
  292. // SMBIOS data table query
  293. #if defined(_AMD64_) || defined(_IA64_) || defined(i386) || defined(MEMPHIS)
  294. WmipAssert((InstanceIndex == 0) && (InstanceCount == 1));
  295. sizeNeeded = sizeof(SMBIOSVERSIONINFO) + sizeof(ULONG);
  296. if (BufferAvail >= sizeNeeded)
  297. {
  298. sizeSMBios = BufferAvail - sizeNeeded;
  299. SMBiosVersionInfo = (PSMBIOSVERSIONINFO)Buffer;
  300. TableSize = (PULONG) (Buffer + sizeof(SMBIOSVERSIONINFO));
  301. BufferPtr = Buffer + sizeNeeded;
  302. } else {
  303. sizeSMBios = 0;
  304. BufferPtr = NULL;
  305. SMBiosVersionInfo = NULL;
  306. }
  307. status = WmipGetSMBiosTableData(BufferPtr,
  308. &sizeSMBios,
  309. SMBiosVersionInfo);
  310. sizeNeeded += sizeSMBios;
  311. if (NT_SUCCESS(status))
  312. {
  313. *(TableSize) = sizeSMBios;
  314. *InstanceLengthArray = sizeNeeded;
  315. }
  316. #else
  317. status = STATUS_WMI_GUID_NOT_FOUND;
  318. #endif
  319. break;
  320. }
  321. case PnPIdGuidIndex:
  322. {
  323. PDEVICE_OBJECT pDO;
  324. UNICODE_STRING instancePath;
  325. PREGENTRY regEntry;
  326. ULONG dataBlockSize, paddedDataBlockSize, padSize;
  327. ULONG i;
  328. regEntry = WmipFindRegEntryByDevice(DeviceObject, FALSE);
  329. if (regEntry != NULL)
  330. {
  331. pDO = regEntry->PDO;
  332. WmipAssert(pDO != NULL);
  333. if (pDO != NULL)
  334. {
  335. status = WmipPDOToDeviceInstanceName(pDO, &instancePath);
  336. if (NT_SUCCESS(status))
  337. {
  338. dataBlockSize = instancePath.Length + sizeof(USHORT);
  339. paddedDataBlockSize = (dataBlockSize + 7) & ~7;
  340. padSize = paddedDataBlockSize - dataBlockSize;
  341. sizeNeeded = paddedDataBlockSize * InstanceCount;
  342. if (sizeNeeded <= BufferAvail)
  343. {
  344. for (i = InstanceIndex;
  345. i < (InstanceIndex + InstanceCount);
  346. i++)
  347. {
  348. *InstanceLengthArray++ = dataBlockSize;
  349. *((PUSHORT)Buffer) = instancePath.Length;
  350. Buffer += sizeof(USHORT);
  351. RtlCopyMemory(Buffer,
  352. instancePath.Buffer,
  353. instancePath.Length);
  354. Buffer += instancePath.Length;
  355. RtlZeroMemory(Buffer, padSize);
  356. Buffer += padSize;
  357. }
  358. } else {
  359. status = STATUS_BUFFER_TOO_SMALL;
  360. }
  361. RtlFreeUnicodeString(&instancePath);
  362. } else {
  363. status = STATUS_WMI_GUID_NOT_FOUND;
  364. }
  365. } else {
  366. status = STATUS_UNSUCCESSFUL;
  367. }
  368. WmipUnreferenceRegEntry(regEntry);
  369. } else {
  370. WmipAssert(FALSE);
  371. status = STATUS_WMI_GUID_NOT_FOUND;
  372. }
  373. break;
  374. }
  375. case PnPIdInstanceNamesGuidIndex:
  376. {
  377. PDEVICE_OBJECT pDO;
  378. UNICODE_STRING instancePath;
  379. PREGENTRY regEntry;
  380. regEntry = WmipFindRegEntryByDevice(DeviceObject, FALSE);
  381. if (regEntry != NULL)
  382. {
  383. pDO = regEntry->PDO;
  384. WmipAssert(pDO != NULL);
  385. if (pDO != NULL)
  386. {
  387. status = WmipPDOToDeviceInstanceName(pDO, &instancePath);
  388. if (NT_SUCCESS(status))
  389. {
  390. sizeNeeded = sizeof(ULONG) +
  391. instancePath.Length + 2 * sizeof(WCHAR) +
  392. sizeof(USHORT);
  393. if (sizeNeeded <= BufferAvail)
  394. {
  395. *((PULONG)Buffer) = 1;
  396. Buffer += sizeof(ULONG);
  397. *InstanceLengthArray = sizeNeeded;
  398. *((PUSHORT)Buffer) = instancePath.Length + 2*sizeof(WCHAR);
  399. Buffer += sizeof(USHORT);
  400. RtlCopyMemory(Buffer,
  401. instancePath.Buffer,
  402. instancePath.Length);
  403. Buffer += instancePath.Length;
  404. *((PWCHAR)Buffer) = '_';
  405. Buffer += sizeof(WCHAR);
  406. *((PWCHAR)Buffer) = '0';
  407. } else {
  408. status = STATUS_BUFFER_TOO_SMALL;
  409. }
  410. RtlFreeUnicodeString(&instancePath);
  411. } else {
  412. status = STATUS_WMI_GUID_NOT_FOUND;
  413. }
  414. } else {
  415. status = STATUS_UNSUCCESSFUL;
  416. }
  417. WmipUnreferenceRegEntry(regEntry);
  418. } else {
  419. WmipAssert(FALSE);
  420. status = STATUS_WMI_GUID_NOT_FOUND;
  421. }
  422. break;
  423. }
  424. case MSAcpiInfoGuidIndex:
  425. {
  426. RTL_QUERY_REGISTRY_TABLE queryTable[4];
  427. ULONG bootArchitecture = 0;
  428. ULONG preferredProfile = 0;
  429. ULONG capabilities = 0;
  430. queryTable[0].QueryRoutine = NULL;
  431. queryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT |
  432. RTL_QUERY_REGISTRY_REQUIRED;
  433. queryTable[0].Name = L"BootArchitecture";
  434. queryTable[0].EntryContext = &bootArchitecture;
  435. queryTable[0].DefaultType = REG_NONE;
  436. queryTable[1].QueryRoutine = NULL;
  437. queryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT |
  438. RTL_QUERY_REGISTRY_REQUIRED;
  439. queryTable[1].Name = L"PreferredProfile";
  440. queryTable[1].EntryContext = &preferredProfile;
  441. queryTable[1].DefaultType = REG_NONE;
  442. queryTable[2].QueryRoutine = NULL;
  443. queryTable[2].Flags = RTL_QUERY_REGISTRY_DIRECT |
  444. RTL_QUERY_REGISTRY_REQUIRED;
  445. queryTable[2].Name = L"Capabilities";
  446. queryTable[2].EntryContext = &capabilities;
  447. queryTable[2].DefaultType = REG_NONE;
  448. queryTable[3].QueryRoutine = NULL;
  449. queryTable[3].Flags = 0;
  450. status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
  451. L"\\Registry\\Machine\\Hardware\\Description\\System",
  452. queryTable,
  453. NULL,
  454. NULL);
  455. if (NT_SUCCESS(status))
  456. {
  457. sizeNeeded = sizeof(MSAcpiInfo);
  458. if (sizeNeeded <= BufferAvail)
  459. {
  460. PMSAcpiInfo info = (PMSAcpiInfo)Buffer;
  461. info->BootArchitecture = bootArchitecture;
  462. info->PreferredProfile = preferredProfile;
  463. info->Capabilities = capabilities;
  464. status = STATUS_SUCCESS;
  465. } else {
  466. status = STATUS_BUFFER_TOO_SMALL;
  467. }
  468. } else {
  469. status = STATUS_WMI_GUID_NOT_FOUND;
  470. }
  471. break;
  472. }
  473. case Sysid1394GuidIndex:
  474. case SysidUuidGuidIndex:
  475. {
  476. PSYSID_UUID uuid;
  477. ULONG uuidCount;
  478. PSYSID_1394 x1394;
  479. ULONG x1394Count;
  480. PUCHAR data;
  481. ULONG count;
  482. #if defined(_AMD64_) || defined(_IA64_) || defined(i386) || defined(MEMPHIS)
  483. status = WmipGetSysIds(&uuid,
  484. &uuidCount,
  485. &x1394,
  486. &x1394Count);
  487. if (NT_SUCCESS(status))
  488. {
  489. if (GuidIndex == Sysid1394GuidIndex)
  490. {
  491. sizeNeeded = x1394Count * sizeof(SYSID_1394) +
  492. sizeof(ULONG);
  493. data = (PUCHAR)x1394;
  494. count = x1394Count;
  495. } else {
  496. sizeNeeded = uuidCount * sizeof(SYSID_UUID) +
  497. sizeof(ULONG);
  498. data = (PUCHAR)uuid;
  499. count = uuidCount;
  500. }
  501. if (BufferAvail >= sizeNeeded)
  502. {
  503. *InstanceLengthArray = sizeNeeded;
  504. *((PULONG)Buffer) = count;
  505. Buffer += sizeof(ULONG);
  506. RtlCopyMemory(Buffer, data, sizeNeeded-sizeof(ULONG));
  507. status = STATUS_SUCCESS;
  508. } else {
  509. status = STATUS_BUFFER_TOO_SMALL;
  510. }
  511. }
  512. #else
  513. status = STATUS_WMI_GUID_NOT_FOUND;
  514. #endif
  515. break;
  516. }
  517. case SmbiosEventGuidIndex:
  518. {
  519. //
  520. // SMBIOS eventlog query
  521. #if defined(_AMD64_) || defined(_IA64_) || defined(i386) || defined(MEMPHIS)
  522. WmipAssert((InstanceIndex == 0) && (InstanceCount == 1));
  523. if (BufferAvail == 0)
  524. {
  525. sizeNeeded = 0;
  526. BufferPtr = NULL;
  527. } else {
  528. sizeNeeded = BufferAvail;
  529. BufferPtr = Buffer;
  530. }
  531. status = WmipGetSMBiosEventlog(BufferPtr, &sizeNeeded);
  532. if (NT_SUCCESS(status))
  533. {
  534. *InstanceLengthArray = sizeNeeded;
  535. }
  536. #else
  537. status = STATUS_WMI_GUID_NOT_FOUND;
  538. #endif
  539. break;
  540. }
  541. #if defined(_IA64_) || defined(_X86_) || defined(_AMD64_)
  542. case MCARawDataGuidIndex:
  543. {
  544. sizeNeeded = BufferAvail;
  545. status = WmipGetRawMCAInfo(Buffer,
  546. &sizeNeeded);
  547. if (NT_SUCCESS(status))
  548. {
  549. *InstanceLengthArray = sizeNeeded;
  550. }
  551. break;
  552. }
  553. #endif
  554. //
  555. // For now don't expose the CPE control guid
  556. //
  557. #ifdef CPE_CONTROL
  558. case CPEControlGuidIndex:
  559. {
  560. sizeNeeded = sizeof(MSMCAInfo_CPEControl);
  561. if (BufferAvail >= sizeNeeded)
  562. {
  563. PMSMCAInfo_CPEControl cpeControl;
  564. cpeControl = (PMSMCAInfo_CPEControl)Buffer;
  565. cpeControl->CPEPollingInterval = WmipCpePollInterval;
  566. cpeControl->CPEGenerationEnabled = (WmipCpePollInterval != HAL_CPE_DISABLED) ?
  567. TRUE :
  568. FALSE;
  569. *InstanceLengthArray = sizeNeeded;
  570. status = STATUS_SUCCESS;
  571. } else {
  572. status = STATUS_BUFFER_TOO_SMALL;
  573. }
  574. break;
  575. }
  576. #endif
  577. default:
  578. {
  579. WmipAssert(FALSE);
  580. status = STATUS_WMI_GUID_NOT_FOUND;
  581. break;
  582. }
  583. }
  584. status = IoWMICompleteRequest((PWMILIB_INFO)&WmipWmiLibInfo,
  585. DeviceObject,
  586. Irp,
  587. status,
  588. sizeNeeded,
  589. IO_NO_INCREMENT);
  590. return(status);
  591. }
  592. #ifdef CPE_CONTROL
  593. NTSTATUS WmipSetWmiDataBlock(
  594. PDEVICE_OBJECT DeviceObject,
  595. PIRP Irp,
  596. ULONG GuidIndex,
  597. ULONG InstanceIndex,
  598. ULONG BufferSize,
  599. PUCHAR Buffer
  600. )
  601. {
  602. NTSTATUS status;
  603. ULONG sizeNeeded;
  604. PAGED_CODE();
  605. if (GuidIndex == CPEControlGuidIndex)
  606. {
  607. sizeNeeded = FIELD_OFFSET(MSMCAInfo_CPEControl,
  608. CPEGenerationEnabled) +
  609. sizeof(BOOLEAN);
  610. if (BufferSize == sizeNeeded)
  611. {
  612. PMSMCAInfo_CPEControl cpeControl;
  613. cpeControl = (PMSMCAInfo_CPEControl)Buffer;
  614. status = WmipSetCPEPolling(cpeControl->CPEGenerationEnabled,
  615. cpeControl->CPEPollingInterval);
  616. } else {
  617. status = STATUS_INVALID_PARAMETER;
  618. }
  619. } else {
  620. status = STATUS_WMI_READ_ONLY;
  621. }
  622. status = IoWMICompleteRequest((PWMILIB_INFO)&WmipWmiLibInfo,
  623. DeviceObject,
  624. Irp,
  625. status,
  626. 0,
  627. IO_NO_INCREMENT);
  628. return(status);
  629. }
  630. #endif
  631. BOOLEAN
  632. WmipFindGuid(
  633. IN PGUIDREGINFO GuidList,
  634. IN ULONG GuidCount,
  635. IN LPGUID Guid,
  636. OUT PULONG GuidIndex,
  637. OUT PULONG InstanceCount
  638. )
  639. /*++
  640. Routine Description:
  641. This routine will search the list of guids registered and return
  642. the index for the one that was registered.
  643. Arguments:
  644. GuidList is the list of guids to search
  645. GuidCount is the count of guids in the list
  646. Guid is the guid being searched for
  647. *GuidIndex returns the index to the guid
  648. *InstanceCount returns the count of instances for the guid
  649. Return Value:
  650. TRUE if guid is found else FALSE
  651. --*/
  652. {
  653. ULONG i;
  654. PAGED_CODE();
  655. for (i = 0; i < GuidCount; i++)
  656. {
  657. if (IsEqualGUID(Guid, &GuidList[i].Guid))
  658. {
  659. *GuidIndex = i;
  660. *InstanceCount = GuidList[i].InstanceCount;
  661. return(TRUE);
  662. }
  663. }
  664. return(FALSE);
  665. }
  666. NTSTATUS
  667. IoWMISystemControl(
  668. IN PWMILIB_INFO WmiLibInfo,
  669. IN PDEVICE_OBJECT DeviceObject,
  670. IN PIRP Irp
  671. )
  672. /*++
  673. Routine Description:
  674. Dispatch routine for IRP_MJ_SYSTEM_CONTROL. This routine will process
  675. all wmi requests received, forwarding them if they are not for this
  676. driver or determining if the guid is valid and if so passing it to
  677. the driver specific function for handing wmi requests.
  678. Arguments:
  679. WmiLibInfo has the WMI information control block
  680. DeviceObject - Supplies a pointer to the device object for this request.
  681. Irp - Supplies the Irp making the request.
  682. Return Value:
  683. status
  684. --*/
  685. {
  686. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  687. ULONG bufferSize;
  688. PUCHAR buffer;
  689. NTSTATUS status;
  690. ULONG retSize;
  691. UCHAR minorFunction;
  692. ULONG guidIndex = 0;
  693. ULONG instanceCount = 0;
  694. ULONG instanceIndex = 0;
  695. PAGED_CODE();
  696. //
  697. // If the irp is not a WMI irp or it is not targetted at this device
  698. // or this device has not regstered with WMI then just forward it on.
  699. minorFunction = irpStack->MinorFunction;
  700. if ((minorFunction > IRP_MN_REGINFO_EX) ||
  701. (irpStack->Parameters.WMI.ProviderId != (ULONG_PTR)DeviceObject) ||
  702. (((minorFunction != IRP_MN_REGINFO) &&
  703. ((minorFunction != IRP_MN_REGINFO_EX))) &&
  704. (WmiLibInfo->GuidList == NULL)))
  705. {
  706. //
  707. // IRP is not for us so forward if there is a lower device object
  708. if (WmiLibInfo->LowerDeviceObject != NULL)
  709. {
  710. IoSkipCurrentIrpStackLocation(Irp);
  711. return(IoCallDriver(WmiLibInfo->LowerDeviceObject, Irp));
  712. } else {
  713. status = STATUS_INVALID_DEVICE_REQUEST;
  714. Irp->IoStatus.Status = status;
  715. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  716. return(status);
  717. }
  718. }
  719. buffer = (PUCHAR)irpStack->Parameters.WMI.Buffer;
  720. bufferSize = irpStack->Parameters.WMI.BufferSize;
  721. if ((minorFunction != IRP_MN_REGINFO) &&
  722. (minorFunction != IRP_MN_REGINFO_EX))
  723. {
  724. //
  725. // For all requests other than query registration info we are passed
  726. // a guid. Determine if the guid is one that is supported by the
  727. // device.
  728. if (WmipFindGuid(WmiLibInfo->GuidList,
  729. WmiLibInfo->GuidCount,
  730. (LPGUID)irpStack->Parameters.WMI.DataPath,
  731. &guidIndex,
  732. &instanceCount))
  733. {
  734. status = STATUS_SUCCESS;
  735. } else {
  736. status = STATUS_WMI_GUID_NOT_FOUND;
  737. }
  738. if (NT_SUCCESS(status) &&
  739. ((minorFunction == IRP_MN_QUERY_SINGLE_INSTANCE) ||
  740. (minorFunction == IRP_MN_CHANGE_SINGLE_INSTANCE) ||
  741. (minorFunction == IRP_MN_CHANGE_SINGLE_ITEM) ||
  742. (minorFunction == IRP_MN_EXECUTE_METHOD)))
  743. {
  744. instanceIndex = ((PWNODE_SINGLE_INSTANCE)buffer)->InstanceIndex;
  745. if ( ((((PWNODE_HEADER)buffer)->Flags) &
  746. WNODE_FLAG_STATIC_INSTANCE_NAMES) == 0)
  747. {
  748. status = STATUS_WMI_INSTANCE_NOT_FOUND;
  749. }
  750. }
  751. if (! NT_SUCCESS(status))
  752. {
  753. Irp->IoStatus.Status = status;
  754. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  755. return(status);
  756. }
  757. }
  758. switch(minorFunction)
  759. {
  760. case IRP_MN_REGINFO:
  761. case IRP_MN_REGINFO_EX:
  762. {
  763. ULONG guidCount;
  764. PGUIDREGINFO guidList;
  765. PWMIREGINFOW wmiRegInfo;
  766. PWMIREGGUIDW wmiRegGuid;
  767. PUNICODE_STRING regPath;
  768. PWCHAR stringPtr;
  769. ULONG registryPathOffset;
  770. ULONG mofResourceOffset;
  771. ULONG bufferNeeded;
  772. ULONG i;
  773. ULONG_PTR nameInfo;
  774. ULONG nameSize, nameOffset, nameFlags;
  775. UNICODE_STRING name;
  776. UNICODE_STRING nullRegistryPath;
  777. WmipAssert(WmiLibInfo->QueryWmiRegInfo != NULL);
  778. WmipAssert(WmiLibInfo->QueryWmiDataBlock != NULL);
  779. name.Buffer = NULL;
  780. name.Length = 0;
  781. name.MaximumLength = 0;
  782. nameFlags = 0;
  783. status = WmiLibInfo->QueryWmiRegInfo(
  784. DeviceObject,
  785. &nameFlags,
  786. &name,
  787. &regPath);
  788. if (NT_SUCCESS(status) &&
  789. (! (nameFlags & WMIREG_FLAG_INSTANCE_PDO) &&
  790. (name.Buffer == NULL)))
  791. {
  792. //
  793. // if PDO flag not specified then an instance name must be
  794. status = STATUS_INVALID_DEVICE_REQUEST;
  795. }
  796. #if DBG
  797. if (nameFlags & WMIREG_FLAG_INSTANCE_PDO)
  798. {
  799. WmipAssert(WmiLibInfo->LowerPDO != NULL);
  800. }
  801. #endif
  802. if (NT_SUCCESS(status))
  803. {
  804. WmipAssert(WmiLibInfo->GuidList != NULL);
  805. guidList = WmiLibInfo->GuidList;
  806. guidCount = WmiLibInfo->GuidCount;
  807. nameOffset = FIELD_OFFSET(WMIREGINFOW, WmiRegGuid) +
  808. guidCount * sizeof(WMIREGGUIDW);
  809. if (nameFlags & WMIREG_FLAG_INSTANCE_PDO)
  810. {
  811. nameSize = 0;
  812. nameInfo = (ULONG_PTR)WmiLibInfo->LowerPDO;
  813. } else {
  814. nameFlags |= WMIREG_FLAG_INSTANCE_LIST;
  815. nameSize = name.Length + sizeof(USHORT);
  816. nameInfo = nameOffset;
  817. }
  818. if (regPath == NULL)
  819. {
  820. //
  821. // No registry path specified. This is a bad thing for
  822. // the device to do, but is not fatal
  823. nullRegistryPath.Buffer = NULL;
  824. nullRegistryPath.Length = 0;
  825. nullRegistryPath.MaximumLength = 0;
  826. regPath = &nullRegistryPath;
  827. }
  828. mofResourceOffset = 0;
  829. registryPathOffset = nameOffset + nameSize;
  830. bufferNeeded = registryPathOffset +
  831. regPath->Length + sizeof(USHORT);
  832. if (bufferNeeded <= bufferSize)
  833. {
  834. retSize = bufferNeeded;
  835. wmiRegInfo = (PWMIREGINFO)buffer;
  836. wmiRegInfo->BufferSize = bufferNeeded;
  837. wmiRegInfo->NextWmiRegInfo = 0;
  838. wmiRegInfo->MofResourceName = mofResourceOffset;
  839. wmiRegInfo->RegistryPath = registryPathOffset;
  840. wmiRegInfo->GuidCount = guidCount;
  841. for (i = 0; i < guidCount; i++)
  842. {
  843. wmiRegGuid = &wmiRegInfo->WmiRegGuid[i];
  844. wmiRegGuid->Guid = guidList[i].Guid;
  845. wmiRegGuid->Flags = guidList[i].Flags | nameFlags;
  846. wmiRegGuid->InstanceInfo = nameInfo;
  847. wmiRegGuid->InstanceCount = guidList[i].InstanceCount;
  848. }
  849. if ( nameFlags & WMIREG_FLAG_INSTANCE_LIST)
  850. {
  851. stringPtr = (PWCHAR)((PUCHAR)buffer + nameOffset);
  852. *stringPtr++ = name.Length;
  853. RtlCopyMemory(stringPtr,
  854. name.Buffer,
  855. name.Length);
  856. }
  857. stringPtr = (PWCHAR)((PUCHAR)buffer + registryPathOffset);
  858. *stringPtr++ = regPath->Length;
  859. RtlCopyMemory(stringPtr,
  860. regPath->Buffer,
  861. regPath->Length);
  862. } else {
  863. *((PULONG)buffer) = bufferNeeded;
  864. retSize = sizeof(ULONG);
  865. }
  866. } else {
  867. retSize = 0;
  868. }
  869. if (name.Buffer != NULL)
  870. {
  871. ExFreePool(name.Buffer);
  872. }
  873. Irp->IoStatus.Status = status;
  874. Irp->IoStatus.Information = retSize;
  875. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  876. return(status);
  877. }
  878. case IRP_MN_QUERY_ALL_DATA:
  879. {
  880. PWNODE_ALL_DATA wnode;
  881. ULONG bufferAvail;
  882. PULONG instanceLengthArray;
  883. PUCHAR dataBuffer;
  884. ULONG instanceLengthArraySize;
  885. ULONG dataBlockOffset;
  886. PREGENTRY regEntry;
  887. wnode = (PWNODE_ALL_DATA)buffer;
  888. if (bufferSize < FIELD_OFFSET(WNODE_ALL_DATA,
  889. OffsetInstanceDataAndLength))
  890. {
  891. //
  892. // The buffer should never be smaller than the size of
  893. // WNODE_ALL_DATA, however if it is then return with an
  894. // error requesting the minimum sized buffer.
  895. WmipAssert(FALSE);
  896. status = IoWMICompleteRequest(WmiLibInfo,
  897. DeviceObject,
  898. Irp,
  899. STATUS_BUFFER_TOO_SMALL,
  900. FIELD_OFFSET(WNODE_ALL_DATA,
  901. OffsetInstanceDataAndLength),
  902. IO_NO_INCREMENT);
  903. break;
  904. }
  905. //
  906. // If this is the pnp id guid then we need to get the instance
  907. // count from the regentry for the device and switch the
  908. // device object.
  909. if ((guidIndex == PnPIdGuidIndex) ||
  910. (guidIndex == PnPIdInstanceNamesGuidIndex))
  911. {
  912. regEntry = WmipFindRegEntryByProviderId(wnode->WnodeHeader.ProviderId,
  913. FALSE);
  914. if (regEntry == NULL)
  915. {
  916. //
  917. // Why couldn't we get the regentry again ??
  918. WmipAssert(FALSE);
  919. status = IoWMICompleteRequest(WmiLibInfo,
  920. DeviceObject,
  921. Irp,
  922. STATUS_WMI_GUID_NOT_FOUND,
  923. 0,
  924. IO_NO_INCREMENT);
  925. break;
  926. }
  927. DeviceObject = regEntry->DeviceObject;
  928. instanceCount = (guidIndex == PnPIdGuidIndex) ? regEntry->MaxInstanceNames : 1;
  929. WmipUnreferenceRegEntry(regEntry);
  930. }
  931. wnode->InstanceCount = instanceCount;
  932. wnode->WnodeHeader.Flags &= ~WNODE_FLAG_FIXED_INSTANCE_SIZE;
  933. instanceLengthArraySize = instanceCount * sizeof(OFFSETINSTANCEDATAANDLENGTH);
  934. dataBlockOffset = (FIELD_OFFSET(WNODE_ALL_DATA, OffsetInstanceDataAndLength) + instanceLengthArraySize + 7) & ~7;
  935. wnode->DataBlockOffset = dataBlockOffset;
  936. if (dataBlockOffset <= bufferSize)
  937. {
  938. instanceLengthArray = (PULONG)&wnode->OffsetInstanceDataAndLength[0];
  939. dataBuffer = buffer + dataBlockOffset;
  940. bufferAvail = bufferSize - dataBlockOffset;
  941. } else {
  942. //
  943. // There is not enough room in the WNODE to complete
  944. // the query
  945. instanceLengthArray = NULL;
  946. dataBuffer = NULL;
  947. bufferAvail = 0;
  948. }
  949. status = WmiLibInfo->QueryWmiDataBlock(
  950. DeviceObject,
  951. Irp,
  952. guidIndex,
  953. 0,
  954. instanceCount,
  955. instanceLengthArray,
  956. bufferAvail,
  957. dataBuffer);
  958. break;
  959. }
  960. case IRP_MN_QUERY_SINGLE_INSTANCE:
  961. {
  962. PWNODE_SINGLE_INSTANCE wnode;
  963. ULONG dataBlockOffset;
  964. PREGENTRY regEntry;
  965. wnode = (PWNODE_SINGLE_INSTANCE)buffer;
  966. if ((guidIndex == PnPIdGuidIndex) ||
  967. (guidIndex == PnPIdInstanceNamesGuidIndex))
  968. {
  969. regEntry = WmipFindRegEntryByProviderId(wnode->WnodeHeader.ProviderId,
  970. FALSE);
  971. if (regEntry != NULL)
  972. {
  973. DeviceObject = regEntry->DeviceObject;
  974. WmipUnreferenceRegEntry(regEntry);
  975. } else {
  976. //
  977. // Why couldn't we get the regentry again ??
  978. WmipAssert(FALSE);
  979. status = IoWMICompleteRequest(WmiLibInfo,
  980. DeviceObject,
  981. Irp,
  982. STATUS_WMI_GUID_NOT_FOUND,
  983. 0,
  984. IO_NO_INCREMENT);
  985. break;
  986. }
  987. }
  988. dataBlockOffset = wnode->DataBlockOffset;
  989. status = WmiLibInfo->QueryWmiDataBlock(
  990. DeviceObject,
  991. Irp,
  992. guidIndex,
  993. instanceIndex,
  994. 1,
  995. &wnode->SizeDataBlock,
  996. bufferSize - dataBlockOffset,
  997. (PUCHAR)wnode + dataBlockOffset);
  998. break;
  999. }
  1000. case IRP_MN_CHANGE_SINGLE_INSTANCE:
  1001. {
  1002. PWNODE_SINGLE_INSTANCE wnode;
  1003. if (WmiLibInfo->SetWmiDataBlock != NULL)
  1004. {
  1005. wnode = (PWNODE_SINGLE_INSTANCE)buffer;
  1006. status = WmiLibInfo->SetWmiDataBlock(
  1007. DeviceObject,
  1008. Irp,
  1009. guidIndex,
  1010. instanceIndex,
  1011. wnode->SizeDataBlock,
  1012. (PUCHAR)wnode + wnode->DataBlockOffset);
  1013. } else {
  1014. //
  1015. // If set callback is not filled in then it must be readonly
  1016. status = STATUS_WMI_READ_ONLY;
  1017. Irp->IoStatus.Status = status;
  1018. Irp->IoStatus.Information = 0;
  1019. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1020. }
  1021. break;
  1022. }
  1023. case IRP_MN_CHANGE_SINGLE_ITEM:
  1024. {
  1025. PWNODE_SINGLE_ITEM wnode;
  1026. if (WmiLibInfo->SetWmiDataItem != NULL)
  1027. {
  1028. wnode = (PWNODE_SINGLE_ITEM)buffer;
  1029. status = WmiLibInfo->SetWmiDataItem(
  1030. DeviceObject,
  1031. Irp,
  1032. guidIndex,
  1033. instanceIndex,
  1034. wnode->ItemId,
  1035. wnode->SizeDataItem,
  1036. (PUCHAR)wnode + wnode->DataBlockOffset);
  1037. } else {
  1038. //
  1039. // If set callback is not filled in then it must be readonly
  1040. status = STATUS_WMI_READ_ONLY;
  1041. Irp->IoStatus.Status = status;
  1042. Irp->IoStatus.Information = 0;
  1043. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1044. }
  1045. break;
  1046. }
  1047. case IRP_MN_EXECUTE_METHOD:
  1048. {
  1049. PWNODE_METHOD_ITEM wnode;
  1050. if (WmiLibInfo->ExecuteWmiMethod != NULL)
  1051. {
  1052. wnode = (PWNODE_METHOD_ITEM)buffer;
  1053. status = WmiLibInfo->ExecuteWmiMethod(
  1054. DeviceObject,
  1055. Irp,
  1056. guidIndex,
  1057. instanceIndex,
  1058. wnode->MethodId,
  1059. wnode->SizeDataBlock,
  1060. bufferSize - wnode->DataBlockOffset,
  1061. buffer + wnode->DataBlockOffset);
  1062. } else {
  1063. //
  1064. // If method callback is not filled in then it must be error
  1065. status = STATUS_INVALID_DEVICE_REQUEST;
  1066. Irp->IoStatus.Status = status;
  1067. Irp->IoStatus.Information = 0;
  1068. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1069. }
  1070. break;
  1071. }
  1072. case IRP_MN_ENABLE_EVENTS:
  1073. {
  1074. if (WmiLibInfo->WmiFunctionControl != NULL)
  1075. {
  1076. status = WmiLibInfo->WmiFunctionControl(
  1077. DeviceObject,
  1078. Irp,
  1079. guidIndex,
  1080. WmiEventGeneration,
  1081. TRUE);
  1082. } else {
  1083. //
  1084. // If callback is not filled in then just succeed
  1085. status = STATUS_SUCCESS;
  1086. Irp->IoStatus.Status = status;
  1087. Irp->IoStatus.Information = 0;
  1088. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1089. }
  1090. break;
  1091. }
  1092. case IRP_MN_DISABLE_EVENTS:
  1093. {
  1094. if (WmiLibInfo->WmiFunctionControl != NULL)
  1095. {
  1096. status = WmiLibInfo->WmiFunctionControl(
  1097. DeviceObject,
  1098. Irp,
  1099. guidIndex,
  1100. WmiEventGeneration,
  1101. FALSE);
  1102. } else {
  1103. //
  1104. // If callback is not filled in then just succeed
  1105. status = STATUS_SUCCESS;
  1106. Irp->IoStatus.Status = status;
  1107. Irp->IoStatus.Information = 0;
  1108. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1109. }
  1110. break;
  1111. }
  1112. case IRP_MN_ENABLE_COLLECTION:
  1113. {
  1114. if (WmiLibInfo->WmiFunctionControl != NULL)
  1115. {
  1116. status = WmiLibInfo->WmiFunctionControl(
  1117. DeviceObject,
  1118. Irp,
  1119. guidIndex,
  1120. WmiDataBlockCollection,
  1121. TRUE);
  1122. } else {
  1123. //
  1124. // If callback is not filled in then just succeed
  1125. status = STATUS_SUCCESS;
  1126. Irp->IoStatus.Status = status;
  1127. Irp->IoStatus.Information = 0;
  1128. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1129. }
  1130. break;
  1131. }
  1132. case IRP_MN_DISABLE_COLLECTION:
  1133. {
  1134. if (WmiLibInfo->WmiFunctionControl != NULL)
  1135. {
  1136. status = WmiLibInfo->WmiFunctionControl(
  1137. DeviceObject,
  1138. Irp,
  1139. guidIndex,
  1140. WmiDataBlockCollection,
  1141. FALSE);
  1142. } else {
  1143. //
  1144. // If callback is not filled in then just succeed
  1145. status = STATUS_SUCCESS;
  1146. Irp->IoStatus.Status = status;
  1147. Irp->IoStatus.Information = 0;
  1148. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1149. }
  1150. break;
  1151. }
  1152. default:
  1153. {
  1154. status = STATUS_INVALID_DEVICE_REQUEST;
  1155. break;
  1156. }
  1157. }
  1158. return(status);
  1159. }
  1160. NTSTATUS
  1161. IoWMICompleteRequest(
  1162. IN PWMILIB_INFO WmiLibInfo,
  1163. IN PDEVICE_OBJECT DeviceObject,
  1164. IN PIRP Irp,
  1165. IN NTSTATUS Status,
  1166. IN ULONG BufferUsed,
  1167. IN CCHAR PriorityBoost
  1168. )
  1169. /*++
  1170. Routine Description:
  1171. This routine will do the work of completing a WMI irp. Depending upon the
  1172. the WMI request this routine will fixup the returned WNODE appropriately.
  1173. Arguments:
  1174. WmiLibInfo has the WMI information control block
  1175. DeviceObject - Supplies a pointer to the device object for this request.
  1176. Irp - Supplies the Irp making the request.
  1177. Status has the return status code for the IRP
  1178. BufferUsed has the number of bytes needed by the device to return the
  1179. data requested in any query. In the case that the buffer passed to
  1180. the device is too small this has the number of bytes needed for the
  1181. return data. If the buffer passed is large enough then this has the
  1182. number of bytes actually used by the device.
  1183. PriorityBoost is the value used for the IoCompleteRequest call.
  1184. Return Value:
  1185. status
  1186. --*/
  1187. {
  1188. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  1189. PUCHAR buffer;
  1190. ULONG retSize;
  1191. UCHAR minorFunction;
  1192. ULONG bufferSize;
  1193. PAGED_CODE();
  1194. UNREFERENCED_PARAMETER (WmiLibInfo);
  1195. UNREFERENCED_PARAMETER (DeviceObject);
  1196. minorFunction = irpStack->MinorFunction;
  1197. buffer = (PUCHAR)irpStack->Parameters.WMI.Buffer;
  1198. bufferSize = irpStack->Parameters.WMI.BufferSize;
  1199. switch(minorFunction)
  1200. {
  1201. case IRP_MN_QUERY_ALL_DATA:
  1202. {
  1203. PWNODE_ALL_DATA wnode;
  1204. PWNODE_TOO_SMALL wnodeTooSmall;
  1205. ULONG bufferNeeded;
  1206. ULONG instanceCount;
  1207. POFFSETINSTANCEDATAANDLENGTH offsetInstanceDataAndLength;
  1208. ULONG i;
  1209. PULONG instanceLengthArray;
  1210. ULONG dataBlockOffset;
  1211. wnode = (PWNODE_ALL_DATA)buffer;
  1212. dataBlockOffset = wnode->DataBlockOffset;
  1213. instanceCount = wnode->InstanceCount;
  1214. bufferNeeded = dataBlockOffset + BufferUsed;
  1215. if ((NT_SUCCESS(Status)) &&
  1216. (bufferNeeded > irpStack->Parameters.WMI.BufferSize))
  1217. {
  1218. Status = STATUS_BUFFER_TOO_SMALL;
  1219. }
  1220. if (! NT_SUCCESS(Status))
  1221. {
  1222. if (Status == STATUS_BUFFER_TOO_SMALL)
  1223. {
  1224. wnodeTooSmall = (PWNODE_TOO_SMALL)wnode;
  1225. wnodeTooSmall->WnodeHeader.BufferSize = sizeof(WNODE_TOO_SMALL);
  1226. wnodeTooSmall->WnodeHeader.Flags = WNODE_FLAG_TOO_SMALL;
  1227. wnodeTooSmall->SizeNeeded = bufferNeeded;
  1228. retSize = sizeof(WNODE_TOO_SMALL);
  1229. Status = STATUS_SUCCESS;
  1230. } else {
  1231. retSize = 0;
  1232. }
  1233. break;
  1234. }
  1235. KeQuerySystemTime(&wnode->WnodeHeader.TimeStamp);
  1236. instanceLengthArray = (PULONG)&wnode->OffsetInstanceDataAndLength[0];
  1237. offsetInstanceDataAndLength = (POFFSETINSTANCEDATAANDLENGTH)instanceLengthArray;
  1238. wnode->WnodeHeader.BufferSize = bufferNeeded;
  1239. retSize = bufferNeeded;
  1240. for (i = instanceCount; i != 0; i--)
  1241. {
  1242. offsetInstanceDataAndLength[i-1].LengthInstanceData = instanceLengthArray[i-1];
  1243. }
  1244. for (i = 0; i < instanceCount; i++)
  1245. {
  1246. offsetInstanceDataAndLength[i].OffsetInstanceData = dataBlockOffset;
  1247. dataBlockOffset = (dataBlockOffset + offsetInstanceDataAndLength[i].LengthInstanceData + 7) & ~7;
  1248. }
  1249. break;
  1250. }
  1251. case IRP_MN_QUERY_SINGLE_INSTANCE:
  1252. {
  1253. PWNODE_SINGLE_INSTANCE wnode;
  1254. PWNODE_TOO_SMALL wnodeTooSmall;
  1255. ULONG bufferNeeded;
  1256. wnode = (PWNODE_SINGLE_INSTANCE)buffer;
  1257. bufferNeeded = wnode->DataBlockOffset + BufferUsed;
  1258. if (NT_SUCCESS(Status))
  1259. {
  1260. retSize = bufferNeeded;
  1261. wnode->WnodeHeader.BufferSize = bufferNeeded;
  1262. KeQuerySystemTime(&wnode->WnodeHeader.TimeStamp);
  1263. WmipAssert(wnode->SizeDataBlock <= BufferUsed);
  1264. } else if (Status == STATUS_BUFFER_TOO_SMALL) {
  1265. wnodeTooSmall = (PWNODE_TOO_SMALL)wnode;
  1266. wnodeTooSmall->WnodeHeader.BufferSize = sizeof(WNODE_TOO_SMALL);
  1267. wnodeTooSmall->WnodeHeader.Flags = WNODE_FLAG_TOO_SMALL;
  1268. wnodeTooSmall->SizeNeeded = bufferNeeded;
  1269. retSize = sizeof(WNODE_TOO_SMALL);
  1270. Status = STATUS_SUCCESS;
  1271. } else {
  1272. retSize = 0;
  1273. }
  1274. break;
  1275. }
  1276. case IRP_MN_EXECUTE_METHOD:
  1277. {
  1278. PWNODE_METHOD_ITEM wnode;
  1279. PWNODE_TOO_SMALL wnodeTooSmall;
  1280. ULONG bufferNeeded;
  1281. wnode = (PWNODE_METHOD_ITEM)buffer;
  1282. bufferNeeded = wnode->DataBlockOffset + BufferUsed;
  1283. if (NT_SUCCESS(Status))
  1284. {
  1285. retSize = bufferNeeded;
  1286. wnode->WnodeHeader.BufferSize = bufferNeeded;
  1287. KeQuerySystemTime(&wnode->WnodeHeader.TimeStamp);
  1288. wnode->SizeDataBlock = BufferUsed;
  1289. } else if (Status == STATUS_BUFFER_TOO_SMALL) {
  1290. wnodeTooSmall = (PWNODE_TOO_SMALL)wnode;
  1291. wnodeTooSmall->WnodeHeader.BufferSize = sizeof(WNODE_TOO_SMALL);
  1292. wnodeTooSmall->WnodeHeader.Flags = WNODE_FLAG_TOO_SMALL;
  1293. wnodeTooSmall->SizeNeeded = bufferNeeded;
  1294. retSize = sizeof(WNODE_TOO_SMALL);
  1295. Status = STATUS_SUCCESS;
  1296. } else {
  1297. retSize = 0;
  1298. }
  1299. break;
  1300. }
  1301. default:
  1302. {
  1303. //
  1304. // All other requests don't return any data
  1305. retSize = 0;
  1306. break;
  1307. }
  1308. }
  1309. Irp->IoStatus.Status = Status;
  1310. Irp->IoStatus.Information = retSize;
  1311. IoCompleteRequest(Irp, PriorityBoost);
  1312. return(Status);
  1313. }
  1314. #ifdef ALLOC_DATA_PRAGMA
  1315. #pragma const_seg()
  1316. #endif