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.

1126 lines
30 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. vfddi.c
  5. Abstract:
  6. This module contains the list of device driver interfaces exported by the
  7. driver verifier and the kernel. Note that thunked exports are *not* placed
  8. here.
  9. All the exports are concentrated in one file because
  10. 1) There are relatively few driver verifier exports
  11. 2) The function naming convention differs from that used elsewhere in
  12. the driver verifier.
  13. Author:
  14. Adrian J. Oney (adriao) 26-Apr-2001
  15. Environment:
  16. Kernel mode
  17. Revision History:
  18. --*/
  19. #include "vfdef.h"
  20. #include "viddi.h"
  21. #ifdef ALLOC_PRAGMA
  22. #pragma alloc_text(INIT, VfDdiInit)
  23. #pragma alloc_text(PAGEVRFY, VfDdiExposeWmiObjects)
  24. //#pragma alloc_text(NONPAGED, VfFailDeviceNode)
  25. //#pragma alloc_text(NONPAGED, VfFailSystemBIOS)
  26. //#pragma alloc_text(NONPAGED, VfFailDriver)
  27. //#pragma alloc_text(NONPAGED, VfIsVerificationEnabled)
  28. #pragma alloc_text(PAGEVRFY, ViDdiThrowException)
  29. #pragma alloc_text(PAGEVRFY, ViDdiDriverEntry)
  30. #pragma alloc_text(PAGEVRFY, ViDdiDispatchWmi)
  31. #pragma alloc_text(PAGEVRFY, ViDdiDispatchWmiRegInfoEx)
  32. #pragma alloc_text(PAGEVRFY, ViDdiBuildWmiRegInfoData)
  33. #pragma alloc_text(PAGEVRFY, ViDdiDispatchWmiQueryAllData)
  34. #endif // ALLOC_PRAGMA
  35. LOGICAL ViDdiInitialized = FALSE;
  36. #ifdef ALLOC_DATA_PRAGMA
  37. #pragma data_seg("PAGEVRFD")
  38. #endif
  39. UNICODE_STRING ViDdiWmiMofKey;
  40. UNICODE_STRING ViDdiWmiMofResourceName;
  41. PDEVICE_OBJECT *ViDdiDeviceObjectArray = NULL;
  42. #ifdef ALLOC_DATA_PRAGMA
  43. #pragma const_seg("PAGEVRFC")
  44. #endif
  45. //
  46. // These are the general "classifications" of device errors, along with the
  47. // default flags that will be applied the first time this is hit.
  48. //
  49. const VFMESSAGE_CLASS ViDdiClassFailDeviceInField = {
  50. VFM_FLAG_BEEP | VFM_LOGO_FAILURE | VFM_DEPLOYMENT_FAILURE,
  51. "DEVICE FAILURE"
  52. };
  53. // VFM_DEPLOYMENT_FAILURE is set here because we don't yet have a "logo" mode
  54. const VFMESSAGE_CLASS ViDdiClassFailDeviceLogo = {
  55. VFM_FLAG_BEEP | VFM_LOGO_FAILURE | VFM_DEPLOYMENT_FAILURE,
  56. "DEVICE FAILURE"
  57. };
  58. const VFMESSAGE_CLASS ViDdiClassFailDeviceUnderDebugger = {
  59. VFM_FLAG_BEEP,
  60. "DEVICE FAILURE"
  61. };
  62. WCHAR VerifierDdiDriverName[] = L"\\DRIVER\\VERIFIER_DDI";
  63. #include <initguid.h>
  64. // Define the verifier WMI GUID (1E2C2980-F7DB-46AA-820E-8734FCC21F4C)
  65. DEFINE_GUID( GUID_VERIFIER_WMI_INTERFACE, 0x1E2C2980L, 0xF7DB, 0x46AA,
  66. 0x82, 0x0E, 0x87, 0x34, 0xFC, 0xC2, 0x1F, 0x4C);
  67. #ifdef ALLOC_DATA_PRAGMA
  68. #pragma const_seg()
  69. #endif // ALLOC_DATA_PRAGMA
  70. #define POOLTAG_DDI_WMIDO_ARRAY 'aDfV'
  71. VOID
  72. VfDdiInit(
  73. VOID
  74. )
  75. /*++
  76. Routine Description:
  77. This routine initializes the Device Driver Interface support.
  78. Arguments:
  79. None.
  80. Return Value:
  81. None.
  82. --*/
  83. {
  84. ViDdiInitialized = TRUE;
  85. }
  86. VOID
  87. VfDdiExposeWmiObjects(
  88. VOID
  89. )
  90. /*++
  91. Routine Description:
  92. This routine exposes verifier WMI objects.
  93. Arguments:
  94. None.
  95. Return Value:
  96. None.
  97. --*/
  98. {
  99. UNICODE_STRING driverString;
  100. // L"\\Machine\\Registry\\System\\CurrentControlSet\\Services\\Verifier");
  101. RtlInitUnicodeString(&ViDdiWmiMofKey, L"");
  102. // L"VerifierMof"
  103. RtlInitUnicodeString(&ViDdiWmiMofResourceName, L"");
  104. RtlInitUnicodeString(&driverString, VerifierDdiDriverName);
  105. IoCreateDriver(&driverString, ViDdiDriverEntry);
  106. }
  107. VOID
  108. VfFailDeviceNode(
  109. IN PDEVICE_OBJECT PhysicalDeviceObject,
  110. IN ULONG BugCheckMajorCode,
  111. IN ULONG BugCheckMinorCode,
  112. IN VF_FAILURE_CLASS FailureClass,
  113. IN OUT PULONG AssertionControl,
  114. IN PSTR DebuggerMessageText,
  115. IN PSTR ParameterFormatString,
  116. ...
  117. )
  118. /*++
  119. Routine Description:
  120. This routine fails a Pnp enumerated hardware or virtual device if
  121. verification is enabled against it.
  122. Arguments:
  123. PhysicalDeviceObject - Bottom of the stack that identifies the PnP
  124. device.
  125. BugCheckMajorCode - BugCheck Major Code
  126. BugCheckMinorCode - BugCheck Minor Code
  127. Note - Zero is reserved!!!
  128. FailureClass - Either VFFAILURE_FAIL_IN_FIELD,
  129. VFFAILURE_FAIL_LOGO, or
  130. VFFAILURE_FAIL_UNDER_DEBUGGER
  131. AssertionControl - Points to a ULONG associated with the failure,
  132. used to store information across multiple calls.
  133. Must be statically preinitialized to zero.
  134. DebuggerMessageText - Text to be displayed in the debugger. Note that
  135. the text may reference parameters such as:
  136. %Routine - passed in Routine
  137. %Irp - passed in Irp
  138. %DevObj - passed in DevObj
  139. %Status - passed in Status
  140. %Ulong - passed in ULONG
  141. %Ulong1 - first passed in ULONG
  142. %Ulong3 - third passed in ULONG (max 3, any param)
  143. %Pvoid2 - second passed in PVOID
  144. etc
  145. (note, capitalization matters)
  146. ParameterFormatString - Contains ordered list of parameters referenced by
  147. above debugger text. For instance,
  148. (..., "%Status1%Status2%Ulong1%Ulong2", Status1, Status2, Ulong1, Ulong2);
  149. Note - If %Routine/%Routine1 is supplied as a param,
  150. the driver at %Routine must also be under verification.
  151. ... - Actual parameters
  152. Return Value:
  153. None.
  154. Note - this function may return if the device is not currently being
  155. verified.
  156. --*/
  157. {
  158. va_list arglist;
  159. if (!VfIsVerificationEnabled(VFOBJTYPE_DEVICE, (PVOID) PhysicalDeviceObject)) {
  160. return;
  161. }
  162. va_start(arglist, ParameterFormatString);
  163. ViDdiThrowException(
  164. BugCheckMajorCode,
  165. BugCheckMinorCode,
  166. FailureClass,
  167. AssertionControl,
  168. DebuggerMessageText,
  169. ParameterFormatString,
  170. &arglist
  171. );
  172. va_end(arglist);
  173. }
  174. VOID
  175. VfFailSystemBIOS(
  176. IN ULONG BugCheckMajorCode,
  177. IN ULONG BugCheckMinorCode,
  178. IN VF_FAILURE_CLASS FailureClass,
  179. IN OUT PULONG AssertionControl,
  180. IN PSTR DebuggerMessageText,
  181. IN PSTR ParameterFormatString,
  182. ...
  183. )
  184. /*++
  185. Routine Description:
  186. This routine fails the system BIOS if verification is enabled against it.
  187. Arguments:
  188. BugCheckMajorCode - BugCheck Major Code
  189. BugCheckMinorCode - BugCheck Minor Code
  190. Note - Zero is reserved!!!
  191. FailureClass - Either VFFAILURE_FAIL_IN_FIELD,
  192. VFFAILURE_FAIL_LOGO, or
  193. VFFAILURE_FAIL_UNDER_DEBUGGER
  194. AssertionControl - Points to a ULONG associated with the failure,
  195. used to store information across multiple calls.
  196. Must be statically preinitialized to zero.
  197. DebuggerMessageText - Text to be displayed in the debugger. Note that
  198. the text may reference parameters such as:
  199. %Routine - passed in Routine
  200. %Irp - passed in Irp
  201. %DevObj - passed in DevObj
  202. %Status - passed in Status
  203. %Ulong - passed in ULONG
  204. %Ulong1 - first passed in ULONG
  205. %Ulong3 - third passed in ULONG (max 3, any param)
  206. %Pvoid2 - second passed in PVOID
  207. etc
  208. (note, capitalization matters)
  209. ParameterFormatString - Contains ordered list of parameters referenced by
  210. above debugger text. For instance,
  211. (..., "%Status1%Status2%Ulong1%Ulong2", Status1, Status2, Ulong1, Ulong2);
  212. Note - If %Routine/%Routine1 is supplied as a param,
  213. the driver at %Routine must also be under verification.
  214. ... - Actual parameters
  215. Return Value:
  216. None.
  217. Note - this function may return if the device is not currently being
  218. verified.
  219. --*/
  220. {
  221. va_list arglist;
  222. if (!VfIsVerificationEnabled(VFOBJTYPE_SYSTEM_BIOS, NULL)) {
  223. return;
  224. }
  225. va_start(arglist, ParameterFormatString);
  226. ViDdiThrowException(
  227. BugCheckMajorCode,
  228. BugCheckMinorCode,
  229. FailureClass,
  230. AssertionControl,
  231. DebuggerMessageText,
  232. ParameterFormatString,
  233. &arglist
  234. );
  235. va_end(arglist);
  236. }
  237. VOID
  238. VfFailDriver(
  239. IN ULONG BugCheckMajorCode,
  240. IN ULONG BugCheckMinorCode,
  241. IN VF_FAILURE_CLASS FailureClass,
  242. IN OUT PULONG AssertionControl,
  243. IN PSTR DebuggerMessageText,
  244. IN PSTR ParameterFormatString,
  245. ...
  246. )
  247. /*++
  248. Routine Description:
  249. This routine fails a driver if verification is enabled against it.
  250. Arguments:
  251. BugCheckMajorCode - BugCheck Major Code
  252. BugCheckMinorCode - BugCheck Minor Code
  253. Note - Zero is reserved!!!
  254. FailureClass - Either VFFAILURE_FAIL_IN_FIELD,
  255. VFFAILURE_FAIL_LOGO, or
  256. VFFAILURE_FAIL_UNDER_DEBUGGER
  257. AssertionControl - Points to a ULONG associated with the failure.
  258. Must be preinitialized to zero!!!
  259. DebuggerMessageText - Text to be displayed in the debugger. Note that
  260. the text may reference parameters such as:
  261. %Routine - passed in Routine
  262. %Irp - passed in Irp
  263. %DevObj - passed in DevObj
  264. %Status - passed in Status
  265. %Ulong - passed in ULONG
  266. %Ulong1 - first passed in ULONG
  267. %Ulong3 - third passed in ULONG (max 3, any param)
  268. %Pvoid2 - second passed in PVOID
  269. etc
  270. (note, capitalization matters)
  271. ParameterFormatString - Contains ordered list of parameters referenced by
  272. above debugger text. For instance,
  273. (..., "%Status1%Status2%Ulong1%Ulong2", Status1, Status2, Ulong1, Ulong2);
  274. One of these parameters should be %Routine. This will
  275. be what the OS uses to identify the driver.
  276. static minorFlags = 0;
  277. VfFailDriver(
  278. major,
  279. minor,
  280. VFFAILURE_FAIL_LOGO,
  281. &minorFlags,
  282. "Driver at %Routine returned %Ulong",
  283. "%Ulong%Routine",
  284. value,
  285. routine
  286. );
  287. Return Value:
  288. None.
  289. Note - this function may return if the driver is not currently being
  290. verified.
  291. --*/
  292. {
  293. va_list arglist;
  294. if (!ViDdiInitialized) {
  295. return;
  296. }
  297. va_start(arglist, ParameterFormatString);
  298. ViDdiThrowException(
  299. BugCheckMajorCode,
  300. BugCheckMinorCode,
  301. FailureClass,
  302. AssertionControl,
  303. DebuggerMessageText,
  304. ParameterFormatString,
  305. &arglist
  306. );
  307. va_end(arglist);
  308. }
  309. VOID
  310. ViDdiThrowException(
  311. IN ULONG BugCheckMajorCode,
  312. IN ULONG BugCheckMinorCode,
  313. IN VF_FAILURE_CLASS FailureClass,
  314. IN OUT PULONG AssertionControl,
  315. IN PSTR DebuggerMessageText,
  316. IN PSTR ParameterFormatString,
  317. IN va_list * MessageParameters
  318. )
  319. /*++
  320. Routine Description:
  321. This routine fails either a devnode or a driver.
  322. Arguments:
  323. BugCheckMajorCode - BugCheck Major Code
  324. BugCheckMinorCode - BugCheck Minor Code
  325. Note - Zero is reserved!!!
  326. FailureClass - Either VFFAILURE_FAIL_IN_FIELD,
  327. VFFAILURE_FAIL_LOGO, or
  328. VFFAILURE_FAIL_UNDER_DEBUGGER
  329. AssertionControl - Points to a ULONG associated with the failure.
  330. Must be preinitialized to zero.
  331. DebuggerMessageText - Text to be displayed in the debugger. Note that
  332. the text may reference parameters such as:
  333. %Routine - passed in Routine
  334. %Irp - passed in Irp
  335. %DevObj - passed in DevObj
  336. %Status - passed in Status
  337. %Ulong - passed in ULONG
  338. %Ulong1 - first passed in ULONG
  339. %Ulong3 - third passed in ULONG (max 3, any param)
  340. %Pvoid2 - second passed in PVOID
  341. etc
  342. (note, capitalization matters)
  343. ParameterFormatString - Contains ordered list of parameters referenced by
  344. above debugger text. For instance,
  345. (..., "%Status1%Status2%Ulong1%Ulong2", Status1, Status2, Ulong1, Ulong2);
  346. MessageParameters - arg list of parameters matching
  347. ParameterFormatString
  348. Return Value:
  349. None.
  350. Note - this function may return if the device is not currently being
  351. verified.
  352. --*/
  353. {
  354. PCVFMESSAGE_CLASS messageClass;
  355. VFMESSAGE_TEMPLATE messageTemplates[2];
  356. VFMESSAGE_TEMPLATE_TABLE messageTable;
  357. NTSTATUS status;
  358. ASSERT(BugCheckMinorCode != 0);
  359. switch(FailureClass) {
  360. case VFFAILURE_FAIL_IN_FIELD:
  361. messageClass = &ViDdiClassFailDeviceInField;
  362. break;
  363. case VFFAILURE_FAIL_LOGO:
  364. messageClass = &ViDdiClassFailDeviceLogo;
  365. break;
  366. case VFFAILURE_FAIL_UNDER_DEBUGGER:
  367. messageClass = &ViDdiClassFailDeviceUnderDebugger;
  368. break;
  369. default:
  370. ASSERT(0);
  371. messageClass = NULL;
  372. break;
  373. }
  374. //
  375. // Program the template.
  376. //
  377. RtlZeroMemory(messageTemplates, sizeof(messageTemplates));
  378. messageTemplates[0].MessageID = BugCheckMinorCode-1;
  379. messageTemplates[1].MessageID = BugCheckMinorCode;
  380. messageTemplates[1].MessageClass = messageClass;
  381. messageTemplates[1].Flags = *AssertionControl;
  382. messageTemplates[1].ParamString = ParameterFormatString;
  383. messageTemplates[1].MessageText = DebuggerMessageText;
  384. //
  385. // Fill out the message table.
  386. //
  387. messageTable.TableID = 0;
  388. messageTable.BugCheckMajor = BugCheckMajorCode;
  389. messageTable.TemplateArray = messageTemplates;
  390. messageTable.TemplateCount = ARRAY_COUNT(messageTemplates);
  391. messageTable.OverrideArray = NULL;
  392. messageTable.OverrideCount = 0;
  393. status = VfBugcheckThrowException(
  394. &messageTable,
  395. BugCheckMinorCode,
  396. ParameterFormatString,
  397. MessageParameters
  398. );
  399. //
  400. // Write back the assertion control.
  401. //
  402. *AssertionControl = messageTemplates[1].Flags;
  403. }
  404. BOOLEAN
  405. VfIsVerificationEnabled(
  406. IN VF_OBJECT_TYPE VfObjectType,
  407. IN PVOID Object
  408. )
  409. {
  410. if (!ViDdiInitialized) {
  411. return FALSE;
  412. }
  413. switch(VfObjectType) {
  414. case VFOBJTYPE_DRIVER:
  415. return (BOOLEAN) MmIsDriverVerifying((PDRIVER_OBJECT) Object);
  416. case VFOBJTYPE_DEVICE:
  417. if (!VfSettingsIsOptionEnabled(NULL, VERIFIER_OPTION_HARDWARE_VERIFICATION)) {
  418. return FALSE;
  419. }
  420. return PpvUtilIsHardwareBeingVerified((PDEVICE_OBJECT) Object);
  421. case VFOBJTYPE_SYSTEM_BIOS:
  422. return VfSettingsIsOptionEnabled(NULL, VERIFIER_OPTION_SYSTEM_BIOS_VERIFICATION);
  423. }
  424. return FALSE;
  425. }
  426. NTSTATUS
  427. ViDdiDriverEntry(
  428. IN PDRIVER_OBJECT DriverObject,
  429. IN PUNICODE_STRING RegistryPath
  430. )
  431. /*++
  432. Routine Description:
  433. This is the callback function when we call IoCreateDriver to create a
  434. Verifier Ddi Object.
  435. Arguments:
  436. DriverObject - Pointer to the driver object created by the system.
  437. RegistryPath - is NULL.
  438. Return Value:
  439. STATUS_SUCCESS
  440. --*/
  441. {
  442. PDEVICE_OBJECT deviceObject;
  443. ULONG siloCount;
  444. NTSTATUS status;
  445. ULONG i;
  446. UNREFERENCED_PARAMETER(RegistryPath);
  447. //
  448. // This driver exposes a WMI interface, and that's it.
  449. //
  450. DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = ViDdiDispatchWmi;
  451. siloCount = VfIrpLogGetIrpDatabaseSiloCount();
  452. ViDdiDeviceObjectArray = (PDEVICE_OBJECT *) ExAllocatePoolWithTag(
  453. NonPagedPool,
  454. sizeof(PDEVICE_OBJECT) * siloCount,
  455. POOLTAG_DDI_WMIDO_ARRAY
  456. );
  457. if (ViDdiDeviceObjectArray == NULL) {
  458. return STATUS_INSUFFICIENT_RESOURCES;
  459. }
  460. //
  461. // Create device objects that will expose IRP history via WMI. We expose
  462. // multiple as WMI has a maximum of 64K data per transfer.
  463. //
  464. for(i=0; i < siloCount; i++) {
  465. status = IoCreateDevice(
  466. DriverObject,
  467. sizeof(VFWMI_DEVICE_EXTENSION),
  468. NULL, // The name will be autogenerated
  469. FILE_DEVICE_UNKNOWN,
  470. FILE_AUTOGENERATED_DEVICE_NAME | FILE_DEVICE_SECURE_OPEN,
  471. FALSE,
  472. &deviceObject
  473. );
  474. if (!NT_SUCCESS(status)) {
  475. while(i) {
  476. IoDeleteDevice(ViDdiDeviceObjectArray[--i]);
  477. }
  478. return status;
  479. }
  480. ViDdiDeviceObjectArray[i] = deviceObject;
  481. ((PVFWMI_DEVICE_EXTENSION) deviceObject->DeviceExtension)->SiloNumber = i;
  482. }
  483. for(i=0; i < siloCount; i++) {
  484. deviceObject = ViDdiDeviceObjectArray[i];
  485. //
  486. // Let the operating system know this device object is now online (we
  487. // can now receive IRPs, such as WMI).
  488. //
  489. deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  490. //
  491. // Tell WMI to query our device object for WMI information.
  492. //
  493. status = IoWMIRegistrationControl(deviceObject, WMIREG_ACTION_REGISTER);
  494. if (!NT_SUCCESS(status)) {
  495. IoDeleteDevice(deviceObject);
  496. while(i) {
  497. IoDeleteDevice(ViDdiDeviceObjectArray[--i]);
  498. }
  499. return status;
  500. }
  501. }
  502. return STATUS_SUCCESS;
  503. }
  504. NTSTATUS
  505. ViDdiDispatchWmi(
  506. IN PDEVICE_OBJECT DeviceObject,
  507. IN PIRP Irp
  508. )
  509. /*++
  510. Routine Description:
  511. This is the Verifier Ddi dispatch handler for WMI IRPs.
  512. Arguments:
  513. DeviceObject - Pointer to the verifier device object.
  514. Irp - Pointer to the incoming IRP.
  515. Return Value:
  516. NTSTATUS
  517. --*/
  518. {
  519. PIO_STACK_LOCATION irpSp;
  520. NTSTATUS status;
  521. irpSp = IoGetCurrentIrpStackLocation(Irp);
  522. switch(irpSp->MinorFunction) {
  523. case IRP_MN_REGINFO_EX:
  524. status = ViDdiDispatchWmiRegInfoEx(DeviceObject, Irp);
  525. break;
  526. case IRP_MN_QUERY_ALL_DATA:
  527. status = ViDdiDispatchWmiQueryAllData(DeviceObject, Irp);
  528. break;
  529. default:
  530. status = STATUS_NOT_SUPPORTED;
  531. break;
  532. }
  533. if (status == STATUS_NOT_SUPPORTED) {
  534. status = Irp->IoStatus.Status;
  535. } else {
  536. Irp->IoStatus.Status = status;
  537. }
  538. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  539. return status;
  540. }
  541. NTSTATUS
  542. ViDdiDispatchWmiRegInfoEx(
  543. IN PDEVICE_OBJECT DeviceObject,
  544. IN PIRP Irp
  545. )
  546. /*++
  547. Routine Description:
  548. This is the Verifier Ddi dispatch handler for the WMI IRP_MN_REGINFO_EX IRP.
  549. Arguments:
  550. DeviceObject - Pointer to the verifier device object.
  551. Irp - Pointer to the incoming IRP.
  552. Return Value:
  553. NTSTATUS
  554. --*/
  555. {
  556. PIO_STACK_LOCATION irpSp;
  557. PWMIREGINFO wmiRegInfo;
  558. ULONG sizeSupplied;
  559. ULONG sizeRequired;
  560. irpSp = IoGetCurrentIrpStackLocation(Irp);
  561. if ((PDEVICE_OBJECT) irpSp->Parameters.WMI.ProviderId != DeviceObject) {
  562. //
  563. // Huh? This is a single device object legacy stack!
  564. //
  565. ASSERT(0);
  566. return STATUS_NOT_SUPPORTED;
  567. }
  568. wmiRegInfo = (PWMIREGINFO) irpSp->Parameters.WMI.Buffer;
  569. sizeSupplied = irpSp->Parameters.WMI.BufferSize;
  570. sizeRequired = ViDdiBuildWmiRegInfoData((ULONG) (ULONG_PTR) irpSp->Parameters.WMI.DataPath, NULL);
  571. if (sizeRequired > sizeSupplied) {
  572. //
  573. // Not large enough, indicate the required size and fail the IRP.
  574. //
  575. if (sizeSupplied < sizeof(ULONG)) {
  576. //
  577. // WMI must give us at least a ULONG!
  578. //
  579. ASSERT(0);
  580. return STATUS_NOT_SUPPORTED;
  581. }
  582. //
  583. // Per spec, write to only the first ULONG in the supplied buffer.
  584. //
  585. wmiRegInfo->BufferSize = sizeRequired;
  586. Irp->IoStatus.Information = sizeof(ULONG);
  587. return STATUS_BUFFER_TOO_SMALL;
  588. }
  589. ViDdiBuildWmiRegInfoData((ULONG) (ULONG_PTR) irpSp->Parameters.WMI.DataPath, wmiRegInfo);
  590. Irp->IoStatus.Information = sizeRequired;
  591. return STATUS_SUCCESS;
  592. }
  593. ULONG
  594. ViDdiBuildWmiRegInfoData(
  595. IN ULONG Datapath,
  596. OUT PWMIREGINFOW WmiRegInfo OPTIONAL
  597. )
  598. /*++
  599. Routine Description:
  600. This function calculates and optionally builds the data block to return
  601. back to WMI in response to IRP_MN_REGINFO_EX.
  602. Arguments:
  603. Datapath - Either WMIREGISTER or WMIUPDATE.
  604. WmiRegInfo - Buffer supplied by OS to optionally fill in.
  605. Return Value:
  606. Size in bytes of buffer (required or written)
  607. --*/
  608. {
  609. PUNICODE_STRING unicodeDestString;
  610. PUNICODE_STRING unicodeSrcString;
  611. PWMIREGGUIDW wmiRegGuid;
  612. ULONG bufferSize;
  613. ULONG guidCount;
  614. //
  615. // Start with the basic WMI structure size.
  616. //
  617. bufferSize = sizeof(WMIREGINFO);
  618. //
  619. // Add our one interface GUID structure. We are using dynamic instance
  620. // names for this interface, so we'll provide them in response to a query.
  621. // Consequently, we don't have any trailing static instance info.
  622. //
  623. guidCount = 1;
  624. if (ARGUMENT_PRESENT(WmiRegInfo)) {
  625. WmiRegInfo->GuidCount = guidCount;
  626. wmiRegGuid = &WmiRegInfo->WmiRegGuid[0];
  627. wmiRegGuid->Guid = GUID_VERIFIER_WMI_INTERFACE;
  628. wmiRegGuid->Flags = 0;
  629. //
  630. // These fields don't need to be zeroed, but we make them consistant
  631. // just in case a bug exists somewhere downstream.
  632. //
  633. wmiRegGuid->InstanceCount = 0;
  634. wmiRegGuid->InstanceInfo = 0;
  635. }
  636. bufferSize += guidCount * sizeof(WMIREGGUIDW);
  637. if (Datapath == WMIREGISTER) {
  638. //
  639. // The registry path begins here. Adjust bufferSize to point to the
  640. // next field.
  641. //
  642. bufferSize = ALIGN_UP_ULONG(bufferSize, 2);
  643. unicodeSrcString = &ViDdiWmiMofKey;
  644. if (ARGUMENT_PRESENT(WmiRegInfo)) {
  645. WmiRegInfo->RegistryPath = bufferSize;
  646. unicodeDestString = (PUNICODE_STRING) (((PUCHAR) WmiRegInfo) + bufferSize);
  647. unicodeDestString->Length = unicodeSrcString->Length;
  648. unicodeDestString->MaximumLength = unicodeSrcString->Length;
  649. unicodeDestString->Buffer = (PWCHAR) (unicodeDestString+1);
  650. RtlCopyMemory(unicodeDestString->Buffer,
  651. unicodeSrcString->Buffer,
  652. unicodeSrcString->Length);
  653. }
  654. bufferSize += sizeof(UNICODE_STRING) + unicodeSrcString->Length;
  655. //
  656. // The Mof resource name begins here. Adjust buffersize to point to the
  657. // next field.
  658. //
  659. bufferSize = ALIGN_UP_ULONG(bufferSize, 2);
  660. unicodeSrcString = &ViDdiWmiMofResourceName;
  661. if (ARGUMENT_PRESENT(WmiRegInfo)) {
  662. WmiRegInfo->MofResourceName = bufferSize;
  663. unicodeDestString = (PUNICODE_STRING) (((PUCHAR) WmiRegInfo) + bufferSize);
  664. unicodeDestString->Length = unicodeSrcString->Length;
  665. unicodeDestString->MaximumLength = unicodeSrcString->Length;
  666. unicodeDestString->Buffer = (PWCHAR) (unicodeDestString+1);
  667. RtlCopyMemory(unicodeDestString->Buffer,
  668. unicodeSrcString->Buffer,
  669. unicodeSrcString->Length);
  670. }
  671. bufferSize += sizeof(UNICODE_STRING) + unicodeSrcString->Length;
  672. }
  673. //
  674. // That's it, close up the structures.
  675. //
  676. if (ARGUMENT_PRESENT(WmiRegInfo)) {
  677. WmiRegInfo->NextWmiRegInfo = 0;
  678. WmiRegInfo->BufferSize = bufferSize;
  679. }
  680. return bufferSize;
  681. }
  682. NTSTATUS
  683. ViDdiDispatchWmiQueryAllData(
  684. IN PDEVICE_OBJECT DeviceObject,
  685. IN PIRP Irp
  686. )
  687. /*++
  688. Routine Description:
  689. This is the Verifier Ddi dispatch handler for the WMI IRP_MN_QUERY_ALL_DATA
  690. IRP.
  691. Arguments:
  692. DeviceObject - Pointer to the verifier device object.
  693. Irp - Pointer to the incoming IRP.
  694. Return Value:
  695. NTSTATUS
  696. --*/
  697. {
  698. PVFWMI_DEVICE_EXTENSION wmiDeviceExtension;
  699. PIO_STACK_LOCATION irpSp;
  700. PWNODE_HEADER wnodeHeader;
  701. PWNODE_ALL_DATA wmiAllData;
  702. PWNODE_TOO_SMALL tooSmall;
  703. ULONG sizeSupplied;
  704. ULONG offsetInstanceNameOffsets;
  705. ULONG instanceCount;
  706. ULONG dataBlockOffset;
  707. ULONG totalRequiredSize;
  708. NTSTATUS status;
  709. irpSp = IoGetCurrentIrpStackLocation(Irp);
  710. if ((PDEVICE_OBJECT) irpSp->Parameters.WMI.ProviderId != DeviceObject) {
  711. //
  712. // Huh? This is a single device object legacy stack!
  713. //
  714. ASSERT(0);
  715. return STATUS_NOT_SUPPORTED;
  716. }
  717. if (!IS_EQUAL_GUID(irpSp->Parameters.WMI.DataPath, &GUID_VERIFIER_WMI_INTERFACE)) {
  718. //
  719. // We only support one Guid. WMI shouldn't be able to come up with
  720. // another...
  721. //
  722. ASSERT(0);
  723. return STATUS_WMI_GUID_NOT_FOUND;
  724. }
  725. wmiDeviceExtension = (PVFWMI_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
  726. sizeSupplied = irpSp->Parameters.WMI.BufferSize;
  727. //
  728. // Not large enough, indicate the required size and fail the IRP.
  729. //
  730. if (sizeSupplied < sizeof(WNODE_TOO_SMALL)) {
  731. //
  732. // WMI must give us at least a WNODE_TOO_SMALL structure!
  733. //
  734. ASSERT(0);
  735. return STATUS_BUFFER_TOO_SMALL;
  736. }
  737. wmiAllData = (PWNODE_ALL_DATA) irpSp->Parameters.WMI.Buffer;
  738. wnodeHeader = &wmiAllData->WnodeHeader;
  739. //
  740. // These fields should already be populated by WMI...
  741. //
  742. ASSERT(wnodeHeader->Flags & WNODE_FLAG_ALL_DATA);
  743. ASSERT(IS_EQUAL_GUID(&wnodeHeader->Guid, &GUID_VERIFIER_WMI_INTERFACE));
  744. //
  745. // Fill in the time stamp before we lock the Irp log database.
  746. //
  747. KeQuerySystemTime(&wnodeHeader->TimeStamp);
  748. //
  749. // Lock the Irp Log Database so that we can query entries from it.
  750. //
  751. status = VfIrpLogLockDatabase(wmiDeviceExtension->SiloNumber);
  752. if (!NT_SUCCESS(status)) {
  753. return status;
  754. }
  755. status = VfIrpLogRetrieveWmiData(
  756. wmiDeviceExtension->SiloNumber,
  757. NULL,
  758. &offsetInstanceNameOffsets,
  759. &instanceCount,
  760. &dataBlockOffset,
  761. &totalRequiredSize
  762. );
  763. if (!NT_SUCCESS(status)) {
  764. VfIrpLogUnlockDatabase(wmiDeviceExtension->SiloNumber);
  765. return status;
  766. }
  767. totalRequiredSize += sizeof(WNODE_ALL_DATA);
  768. if (totalRequiredSize > sizeSupplied) {
  769. VfIrpLogUnlockDatabase(wmiDeviceExtension->SiloNumber);
  770. //
  771. // Per spec, write to a WNODE_TOO_SMALL structure into the buffer.
  772. // Note that the structure does *not* follow wmiAllData! Rather,
  773. // the same structure is interpretted two
  774. //
  775. //
  776. wnodeHeader->Flags |= WNODE_FLAG_TOO_SMALL;
  777. tooSmall = (PWNODE_TOO_SMALL) wmiAllData;
  778. tooSmall->SizeNeeded = totalRequiredSize;
  779. Irp->IoStatus.Information = sizeof(WNODE_TOO_SMALL);
  780. //
  781. // Yes, STATUS_SUCCESS is returned here. This is very asymetric when
  782. // compared to IRP_MN_QUERY_REGINFO_EX.
  783. //
  784. return STATUS_SUCCESS;
  785. } else if (instanceCount) {
  786. status = VfIrpLogRetrieveWmiData(
  787. wmiDeviceExtension->SiloNumber,
  788. (PUCHAR) wmiAllData,
  789. &offsetInstanceNameOffsets,
  790. &instanceCount,
  791. &dataBlockOffset,
  792. &totalRequiredSize
  793. );
  794. }
  795. VfIrpLogUnlockDatabase(wmiDeviceExtension->SiloNumber);
  796. if (!NT_SUCCESS(status)) {
  797. return status;
  798. }
  799. if (instanceCount) {
  800. wnodeHeader->Flags |= WNODE_FLAG_ALL_DATA;
  801. wnodeHeader->Flags &= ~WNODE_FLAG_FIXED_INSTANCE_SIZE;
  802. wnodeHeader->BufferSize = totalRequiredSize;
  803. wmiAllData->InstanceCount = instanceCount;
  804. wmiAllData->DataBlockOffset = dataBlockOffset;
  805. wmiAllData->OffsetInstanceNameOffsets = offsetInstanceNameOffsets;
  806. } else {
  807. totalRequiredSize = sizeof(WNODE_ALL_DATA);
  808. wnodeHeader->BufferSize = totalRequiredSize;
  809. wmiAllData->InstanceCount = 0;
  810. wmiAllData->FixedInstanceSize = 0;
  811. wmiAllData->DataBlockOffset = 0;
  812. wmiAllData->OffsetInstanceNameOffsets = 0;
  813. }
  814. Irp->IoStatus.Information = totalRequiredSize;
  815. return STATUS_SUCCESS;
  816. }