Source code of Windows XP (NT5)
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.

3238 lines
105 KiB

  1. /*++
  2. Copyright (c) 1997-1999 Microsoft Corporation
  3. Module Name:
  4. wmi.c
  5. Abstract:
  6. Device driver interface for WMI
  7. Author:
  8. AlanWar
  9. Environment:
  10. Kernel mode
  11. Revision History:
  12. --*/
  13. #include "wmikmp.h"
  14. #ifndef MEMPHIS
  15. #include "evntrace.h"
  16. #include "tracep.h"
  17. #endif
  18. NTSTATUS
  19. WmipOpenCloseCleanup(
  20. IN PDEVICE_OBJECT DeviceObject,
  21. IN PIRP Irp
  22. );
  23. NTSTATUS
  24. WmipIoControl(
  25. IN PDEVICE_OBJECT DeviceObject,
  26. IN PIRP Irp
  27. );
  28. NTSTATUS WmipObjectToPDO(
  29. PFILE_OBJECT FileObject,
  30. PDEVICE_OBJECT DeviceObject,
  31. PDEVICE_OBJECT *PDO
  32. );
  33. BOOLEAN
  34. WmipFastIoDeviceControl(
  35. IN PFILE_OBJECT FileObject,
  36. IN BOOLEAN Wait,
  37. IN PVOID InputBuffer OPTIONAL,
  38. IN ULONG InputBufferLength,
  39. OUT PVOID OutputBuffer OPTIONAL,
  40. IN ULONG OutputBufferLength,
  41. IN ULONG IoControlCode,
  42. OUT PIO_STATUS_BLOCK IoStatus,
  43. IN struct _DEVICE_OBJECT *DeviceObject
  44. );
  45. NTSTATUS
  46. DriverEntry(
  47. IN PDRIVER_OBJECT DriverObject,
  48. IN PUNICODE_STRING RegistryPath
  49. );
  50. NTSTATUS WmipProbeWnodeAllData(
  51. PWNODE_ALL_DATA Wnode,
  52. ULONG InBufferLen,
  53. ULONG OutBufferLen
  54. );
  55. NTSTATUS WmipProbeWnodeSingleInstance(
  56. PWNODE_SINGLE_INSTANCE Wnode,
  57. ULONG InBufferLen,
  58. ULONG OutBufferLen,
  59. BOOLEAN OutBound
  60. );
  61. NTSTATUS WmipProbeWnodeSingleItem(
  62. PWNODE_SINGLE_ITEM Wnode,
  63. ULONG InBufferLen
  64. );
  65. NTSTATUS WmipProbeWnodeMethodItem(
  66. PWNODE_METHOD_ITEM Wnode,
  67. ULONG InBufferLen,
  68. ULONG OutBufferLen
  69. );
  70. NTSTATUS WmipProbeWnodeWorker(
  71. PWNODE_HEADER WnodeHeader,
  72. ULONG MinWnodeSize,
  73. ULONG InstanceNameOffset,
  74. ULONG DataBlockOffset,
  75. ULONG DataBlockSize,
  76. ULONG InBufferLen,
  77. ULONG OutBufferLen,
  78. BOOLEAN CheckOutBound,
  79. BOOLEAN CheckInBound
  80. );
  81. NTSTATUS
  82. WmipSystemControl(
  83. IN PDEVICE_OBJECT DeviceObject,
  84. IN PIRP Irp
  85. );
  86. NTSTATUS WmipSendWmiIrp(
  87. UCHAR MinorFunction,
  88. ULONG ProviderId,
  89. PVOID DataPath,
  90. ULONG BufferLength,
  91. PVOID Buffer,
  92. PIO_STATUS_BLOCK Iosb
  93. );
  94. NTSTATUS WmipProbeWmiRegRequest(
  95. IN PWMIREGREQUEST Buffer,
  96. IN ULONG InBufferLen,
  97. IN ULONG OutBufferLen
  98. );
  99. #ifdef ALLOC_PRAGMA
  100. #pragma alloc_text(INIT,WmipDriverEntry)
  101. #pragma alloc_text(INIT,DriverEntry)
  102. #pragma alloc_text(PAGE,WmipOpenCloseCleanup)
  103. #pragma alloc_text(PAGE,WmipIoControl)
  104. #pragma alloc_text(PAGE,WmipForwardWmiIrp)
  105. #pragma alloc_text(PAGE,WmipObjectToPDO)
  106. #pragma alloc_text(PAGE,WmipTranslateFileHandle)
  107. #pragma alloc_text(PAGE,WmipProbeWnodeAllData)
  108. #pragma alloc_text(PAGE,WmipProbeWnodeSingleInstance)
  109. #pragma alloc_text(PAGE,WmipProbeWnodeSingleItem)
  110. #pragma alloc_text(PAGE,WmipProbeWnodeMethodItem)
  111. #pragma alloc_text(PAGE,WmipProbeWnodeWorker)
  112. #pragma alloc_text(PAGE,WmipProbeWmiOpenGuidBlock)
  113. #pragma alloc_text(PAGE,WmipProbeAndCaptureGuidObjectAttributes)
  114. #pragma alloc_text(PAGE,WmipUpdateDeviceStackSize)
  115. #pragma alloc_text(PAGE,WmipSystemControl)
  116. #pragma alloc_text(PAGE,WmipGetDevicePDO)
  117. #pragma alloc_text(PAGE,WmipSendWmiIrp)
  118. #pragma alloc_text(PAGE,WmipProbeWmiRegRequest)
  119. #ifndef MEMPHIS
  120. #pragma alloc_text(PAGE,WmipFastIoDeviceControl)
  121. #endif
  122. #endif
  123. PDEVICE_OBJECT WmipServiceDeviceObject;
  124. //
  125. // This specifies the maximum size that an event can be
  126. ULONG WmipMaxKmWnodeEventSize = DEFAULTMAXKMWNODEEVENTSIZE;
  127. #ifdef ALLOC_DATA_PRAGMA
  128. #pragma data_seg("PAGEDATA")
  129. #endif
  130. #if defined(_AMD64_) || defined(_IA64_) || defined(i386)
  131. PVOID WmipDockUndockNotificationEntry;
  132. #endif
  133. KMUTEX WmipSMMutex;
  134. KMUTEX WmipTLMutex;
  135. //
  136. // This maintains the registry path for the wmi device
  137. UNICODE_STRING WmipRegistryPath;
  138. #ifndef MEMPHIS
  139. FAST_IO_DISPATCH WmipFastIoDispatch;
  140. #endif
  141. #ifdef ALLOC_DATA_PRAGMA
  142. #pragma const_seg("PAGECONST")
  143. #endif
  144. NTSTATUS
  145. DriverEntry(
  146. IN PDRIVER_OBJECT DriverObject,
  147. IN PUNICODE_STRING RegistryPath
  148. )
  149. {
  150. UNREFERENCED_PARAMETER(DriverObject);
  151. UNREFERENCED_PARAMETER(RegistryPath);
  152. // Never called
  153. return(STATUS_SUCCESS);
  154. }
  155. NTSTATUS
  156. WmipDriverEntry(
  157. IN PDRIVER_OBJECT DriverObject,
  158. IN PUNICODE_STRING RegistryPath
  159. )
  160. /*++
  161. Routine Description:
  162. This is the callback function when we call IoCreateDriver to create a
  163. WMI Driver Object. In this function, we need to remember the
  164. DriverObject, create a device object and then create a Win32 visible
  165. symbolic link name so that the WMI user mode component can access us.
  166. Arguments:
  167. DriverObject - Pointer to the driver object created by the system.
  168. RegistryPath - is NULL.
  169. Return Value:
  170. STATUS_SUCCESS
  171. --*/
  172. {
  173. NTSTATUS Status;
  174. UNICODE_STRING DeviceName;
  175. UNICODE_STRING ServiceSymbolicLinkName;
  176. #ifndef MEMPHIS
  177. PFAST_IO_DISPATCH fastIoDispatch;
  178. #endif
  179. ANSI_STRING AnsiString;
  180. PAGED_CODE();
  181. UNREFERENCED_PARAMETER(RegistryPath);
  182. //
  183. // First thing to do is make sure our critical section has been initalized
  184. //
  185. KeInitializeMutex(&WmipSMMutex, 0);
  186. KeInitializeMutex(&WmipTLMutex, 0);
  187. //
  188. // Initialize internal WMI data structrurs
  189. //
  190. WmipInitializeRegistration(0);
  191. WmipInitializeNotifications();
  192. Status = WmipInitializeDataStructs();
  193. if (! NT_SUCCESS(Status))
  194. {
  195. return(Status);
  196. }
  197. //
  198. // Since Io does not pass a registry path for this device we need to make
  199. // up one
  200. RtlInitAnsiString(&AnsiString,
  201. "\\Registry\\Machine\\System\\CurrentControlSet\\Services\\WMI");
  202. Status = RtlAnsiStringToUnicodeString(&WmipRegistryPath,
  203. &AnsiString,
  204. TRUE);
  205. #ifndef MEMPHIS
  206. Status = WmipInitializeSecurity();
  207. if (!NT_SUCCESS(Status))
  208. {
  209. return(Status);
  210. }
  211. #endif
  212. //
  213. // Create the service device object and symbolic link
  214. //
  215. RtlInitUnicodeString( &DeviceName, WMIServiceDeviceObjectName );
  216. Status = IoCreateDevice(
  217. DriverObject,
  218. 0,
  219. &DeviceName,
  220. FILE_DEVICE_UNKNOWN,
  221. #ifdef MEMPHIS
  222. 0,
  223. #else
  224. FILE_DEVICE_SECURE_OPEN, // No standard device characteristics
  225. #endif
  226. FALSE, // This isn't an exclusive device
  227. &WmipServiceDeviceObject
  228. );
  229. if (! NT_SUCCESS(Status))
  230. {
  231. return(Status);
  232. }
  233. RtlInitUnicodeString( &ServiceSymbolicLinkName,
  234. WMIServiceSymbolicLinkName );
  235. Status = IoCreateSymbolicLink( &ServiceSymbolicLinkName,
  236. &DeviceName );
  237. if (! NT_SUCCESS(Status))
  238. {
  239. IoDeleteDevice( WmipServiceDeviceObject );
  240. return(Status);
  241. }
  242. //
  243. // Establish an initial irp stack size
  244. WmipServiceDeviceObject->StackSize = WmiDeviceStackSize;
  245. //
  246. // Create dispatch entrypoints
  247. //
  248. DriverObject->MajorFunction[IRP_MJ_CREATE] = WmipOpenCloseCleanup;
  249. DriverObject->MajorFunction[IRP_MJ_CLOSE] = WmipOpenCloseCleanup;
  250. DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = WmipIoControl;
  251. DriverObject->MajorFunction[IRP_MJ_CLEANUP] = WmipOpenCloseCleanup;
  252. DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = WmipSystemControl;
  253. DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = WmipShutdown;
  254. //
  255. // Register for notification of docking events
  256. #if defined(_AMD64_) || defined(_IA64_) || defined(i386)
  257. IoRegisterPlugPlayNotification(
  258. EventCategoryHardwareProfileChange,
  259. 0,
  260. NULL,
  261. DriverObject,
  262. WmipDockUndockEventCallback,
  263. NULL,
  264. &WmipDockUndockNotificationEntry);
  265. #endif
  266. //
  267. // We reset this flag to let the IO manager know that the device
  268. // is ready to receive requests. We only do this for the kernel
  269. // dll since the IO manager does it when WMI loads as a normal
  270. // device.
  271. WmipServiceDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  272. #ifndef MEMPHIS
  273. IoWMIRegistrationControl(WmipServiceDeviceObject,
  274. WMIREG_ACTION_REGISTER);
  275. #endif
  276. #ifndef MEMPHIS
  277. fastIoDispatch = &WmipFastIoDispatch;
  278. RtlZeroMemory(fastIoDispatch, sizeof(FAST_IO_DISPATCH));
  279. fastIoDispatch->SizeOfFastIoDispatch = sizeof(FAST_IO_DISPATCH);
  280. fastIoDispatch->FastIoDeviceControl = WmipFastIoDeviceControl;
  281. DriverObject->FastIoDispatch = fastIoDispatch;
  282. RtlZeroMemory(&WmipRefCount[0], MAXLOGGERS*sizeof(ULONG));
  283. RtlZeroMemory(&WmipLoggerContext[0], MAXLOGGERS*sizeof(PWMI_LOGGER_CONTEXT));
  284. WmipStartGlobalLogger(); // Try and see if we need to start this
  285. IoRegisterShutdownNotification(WmipServiceDeviceObject);
  286. #endif // MEMPHIS
  287. SharedUserData->TraceLogging = 0; //Initialize the Heap and Crisec Coll tracing status off
  288. return(Status);
  289. }
  290. NTSTATUS
  291. WmipOpenCloseCleanup(
  292. IN PDEVICE_OBJECT DeviceObject,
  293. IN PIRP Irp
  294. )
  295. {
  296. PAGED_CODE();
  297. UNREFERENCED_PARAMETER(DeviceObject);
  298. Irp->IoStatus.Status = STATUS_SUCCESS;
  299. Irp->IoStatus.Information = 0;
  300. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  301. return STATUS_SUCCESS;
  302. }
  303. void WmipUpdateDeviceStackSize(
  304. CCHAR NewStackSize
  305. )
  306. /*++
  307. Routine Description:
  308. This routine will update the stack size that is specified in the WMI
  309. device's device object. This needs to be protected since it can be updated
  310. when a device registers and whenever an irp is forwarded to a device.
  311. WMI needs to maintain a stack size one greater than the stack size of the
  312. largest device stack to which it forwards irps to. Consider a bottom
  313. driver that registers with WMI and has a stack size of 1. If 2 device
  314. attach on top of it then WMI will forward to the topmost in the stack
  315. which would need a stack size of 3, so the original WMI irp (ie the one
  316. created by the IOCTL to the WMI device) would need a stack size of 4.
  317. Arguments:
  318. NewStackSize is the new stack size needed
  319. Return Value:
  320. NT status ccode
  321. --*/
  322. {
  323. PAGED_CODE();
  324. WmipEnterSMCritSection();
  325. if (WmipServiceDeviceObject->StackSize < NewStackSize)
  326. {
  327. WmipServiceDeviceObject->StackSize = NewStackSize;
  328. }
  329. WmipLeaveSMCritSection();
  330. }
  331. NTSTATUS
  332. WmipIoControl(
  333. IN PDEVICE_OBJECT DeviceObject,
  334. IN PIRP Irp
  335. )
  336. {
  337. NTSTATUS Status;
  338. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  339. ULONG InBufferLen = irpStack->Parameters.DeviceIoControl.InputBufferLength;
  340. ULONG OutBufferLen = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
  341. PVOID Buffer = Irp->AssociatedIrp.SystemBuffer;
  342. PWNODE_HEADER Wnode = (PWNODE_HEADER)Buffer;
  343. ULONG SizeNeeded;
  344. ULONG Ioctl;
  345. PAGED_CODE();
  346. UNREFERENCED_PARAMETER(DeviceObject);
  347. Ioctl = irpStack->Parameters.DeviceIoControl.IoControlCode;
  348. switch (Ioctl)
  349. {
  350. #ifndef MEMPHIS
  351. case IOCTL_WMI_OPEN_GUID:
  352. case IOCTL_WMI_OPEN_GUID_FOR_QUERYSET:
  353. case IOCTL_WMI_OPEN_GUID_FOR_EVENTS:
  354. {
  355. WMIOPENGUIDBLOCK CapturedGuidBlock;
  356. OBJECT_ATTRIBUTES CapturedObjectAttributes;
  357. UNICODE_STRING CapturedGuidString;
  358. WCHAR CapturedGuidBuffer[WmiGuidObjectNameLength + 1];
  359. PWMIOPENGUIDBLOCK InGuidBlock;
  360. HANDLE Handle;
  361. ULONG DesiredAccess;
  362. InGuidBlock = (PWMIOPENGUIDBLOCK)Buffer;
  363. Status = WmipProbeWmiOpenGuidBlock(&CapturedObjectAttributes,
  364. &CapturedGuidString,
  365. CapturedGuidBuffer,
  366. &DesiredAccess,
  367. InGuidBlock,
  368. InBufferLen,
  369. OutBufferLen);
  370. if (NT_SUCCESS(Status))
  371. {
  372. Status = WmipOpenBlock(Ioctl,
  373. UserMode,
  374. &CapturedObjectAttributes,
  375. DesiredAccess,
  376. &Handle);
  377. if (NT_SUCCESS(Status))
  378. {
  379. #if defined(_WIN64)
  380. if (IoIs32bitProcess(NULL))
  381. {
  382. ((PWMIOPENGUIDBLOCK32)InGuidBlock)->Handle.Handle32 = PtrToUlong(Handle);
  383. }
  384. else
  385. #endif
  386. {
  387. InGuidBlock->Handle.Handle = Handle;
  388. }
  389. }
  390. }
  391. break;
  392. }
  393. #endif
  394. case IOCTL_WMI_QUERY_ALL_DATA:
  395. {
  396. if (OutBufferLen < sizeof(WNODE_ALL_DATA))
  397. {
  398. //
  399. // WMI will not send any request whose output buffer is not
  400. // at least the size of a WNODE_TOO_SMALL.
  401. Status = STATUS_BUFFER_TOO_SMALL;
  402. break;
  403. }
  404. Status = WmipProbeWnodeAllData((PWNODE_ALL_DATA)Wnode,
  405. InBufferLen,
  406. OutBufferLen);
  407. if (NT_SUCCESS(Status))
  408. {
  409. Status = WmipQueryAllData(NULL,
  410. Irp,
  411. UserMode,
  412. (PWNODE_ALL_DATA)Wnode,
  413. OutBufferLen,
  414. &OutBufferLen);
  415. } else {
  416. WmipDebugPrintEx((DPFLTR_WMICORE_ID, DPFLTR_INFO_LEVEL,"WMI: Invalid IOCTL_WMI_QUERY_ALL_DATA Wnode\n"));
  417. }
  418. break;
  419. }
  420. case IOCTL_WMI_QAD_MULTIPLE:
  421. {
  422. PWMIQADMULTIPLE QadMultiple;
  423. if ((InBufferLen >= sizeof(WMIQADMULTIPLE)) &&
  424. (OutBufferLen >= sizeof(WNODE_TOO_SMALL)))
  425. {
  426. QadMultiple = (PWMIQADMULTIPLE)Buffer;
  427. if ((QadMultiple->HandleCount < QUERYMULIPLEHANDLELIMIT) &&
  428. (InBufferLen >= (FIELD_OFFSET(WMIQADMULTIPLE, Handles) +
  429. (QadMultiple->HandleCount * sizeof(HANDLE3264)))))
  430. {
  431. Status = WmipQueryAllDataMultiple(0,
  432. NULL,
  433. Irp,
  434. UserMode,
  435. Buffer,
  436. OutBufferLen,
  437. QadMultiple,
  438. &OutBufferLen);
  439. } else {
  440. Status = STATUS_INVALID_PARAMETER;
  441. }
  442. } else {
  443. Status = STATUS_INVALID_PARAMETER;
  444. }
  445. break;
  446. }
  447. case IOCTL_WMI_QUERY_SINGLE_INSTANCE:
  448. {
  449. if (OutBufferLen < sizeof(WNODE_TOO_SMALL))
  450. {
  451. //
  452. // WMI will not send any request whose output buffer is not
  453. // at least the size of a WNODE_TOO_SMALL.
  454. Status = STATUS_BUFFER_TOO_SMALL;
  455. break;
  456. }
  457. Status = WmipProbeWnodeSingleInstance((PWNODE_SINGLE_INSTANCE)Wnode,
  458. InBufferLen,
  459. OutBufferLen,
  460. TRUE);
  461. if (NT_SUCCESS(Status))
  462. {
  463. Status = WmipQuerySetExecuteSI(NULL,
  464. Irp,
  465. UserMode,
  466. IRP_MN_QUERY_SINGLE_INSTANCE,
  467. Wnode,
  468. OutBufferLen,
  469. &OutBufferLen);
  470. if (NT_SUCCESS(Status))
  471. {
  472. WmipAssert(Irp->IoStatus.Information <= OutBufferLen);
  473. }
  474. } else {
  475. WmipDebugPrintEx((DPFLTR_WMICORE_ID, DPFLTR_INFO_LEVEL,"WMI: Invalid IOCTL_WMI_SINGLE_INSTANCE Wnode\n"));
  476. }
  477. break;
  478. }
  479. case IOCTL_WMI_QSI_MULTIPLE:
  480. {
  481. PWMIQSIMULTIPLE QsiMultiple;
  482. if ((InBufferLen >= sizeof(WMIQSIMULTIPLE)) &&
  483. (OutBufferLen >= sizeof(WNODE_TOO_SMALL)))
  484. {
  485. QsiMultiple = (PWMIQSIMULTIPLE)Buffer;
  486. if ((QsiMultiple->QueryCount < QUERYMULIPLEHANDLELIMIT) &&
  487. (InBufferLen >= (FIELD_OFFSET(WMIQSIMULTIPLE, QsiInfo) +
  488. (QsiMultiple->QueryCount * sizeof(WMIQSIINFO)))))
  489. {
  490. Status = WmipQuerySingleMultiple(Irp,
  491. UserMode,
  492. Buffer,
  493. OutBufferLen,
  494. QsiMultiple,
  495. QsiMultiple->QueryCount,
  496. NULL,
  497. NULL,
  498. &OutBufferLen);
  499. } else {
  500. Status = STATUS_INVALID_PARAMETER;
  501. }
  502. } else {
  503. Status = STATUS_INVALID_PARAMETER;
  504. }
  505. break;
  506. }
  507. case IOCTL_WMI_SET_SINGLE_INSTANCE:
  508. {
  509. Status = WmipProbeWnodeSingleInstance((PWNODE_SINGLE_INSTANCE)Wnode,
  510. InBufferLen,
  511. OutBufferLen,
  512. FALSE);
  513. if (NT_SUCCESS(Status))
  514. {
  515. Status = WmipQuerySetExecuteSI(NULL,
  516. Irp,
  517. UserMode,
  518. IRP_MN_CHANGE_SINGLE_INSTANCE,
  519. Wnode,
  520. InBufferLen,
  521. &OutBufferLen);
  522. OutBufferLen = 0;
  523. } else {
  524. WmipDebugPrintEx((DPFLTR_WMICORE_ID, DPFLTR_INFO_LEVEL,"WMI: Invalid IOCTL_WMI_SET_SINGLE_INSTANCE Wnode\n"));
  525. }
  526. break;
  527. }
  528. case IOCTL_WMI_SET_SINGLE_ITEM:
  529. {
  530. Status = WmipProbeWnodeSingleItem((PWNODE_SINGLE_ITEM)Wnode,
  531. InBufferLen);
  532. if (NT_SUCCESS(Status))
  533. {
  534. Status = WmipQuerySetExecuteSI(NULL,
  535. Irp,
  536. UserMode,
  537. IRP_MN_CHANGE_SINGLE_ITEM,
  538. Wnode,
  539. InBufferLen,
  540. &OutBufferLen);
  541. OutBufferLen = 0;
  542. } else {
  543. WmipDebugPrintEx((DPFLTR_WMICORE_ID, DPFLTR_INFO_LEVEL,"WMI: Invalid IOCTL_WMI_SET_SINGLE_ITEM Wnode\n"));
  544. }
  545. break;
  546. }
  547. case IOCTL_WMI_EXECUTE_METHOD:
  548. {
  549. //
  550. // The buffer passed is the InputWnode directly followed by the
  551. // method wnode. This is so that the driver can fill in the
  552. // output WNODE directly on top of the input wnode.
  553. PWNODE_METHOD_ITEM MethodWnode = (PWNODE_METHOD_ITEM)Wnode;
  554. Status = WmipProbeWnodeMethodItem(MethodWnode,
  555. InBufferLen,
  556. OutBufferLen);
  557. if (NT_SUCCESS(Status))
  558. {
  559. Status = WmipQuerySetExecuteSI(NULL,
  560. Irp,
  561. UserMode,
  562. IRP_MN_EXECUTE_METHOD,
  563. Wnode,
  564. OutBufferLen,
  565. &OutBufferLen);
  566. if (NT_SUCCESS(Status))
  567. {
  568. WmipAssert(Irp->IoStatus.Information <= OutBufferLen);
  569. }
  570. }
  571. break;
  572. }
  573. case IOCTL_WMI_TRANSLATE_FILE_HANDLE:
  574. {
  575. if (InBufferLen != FIELD_OFFSET(WMIFHTOINSTANCENAME,
  576. InstanceNames))
  577. {
  578. Status = STATUS_UNSUCCESSFUL;
  579. } else {
  580. Status = WmipTranslateFileHandle((PWMIFHTOINSTANCENAME)Buffer,
  581. &OutBufferLen,
  582. NULL,
  583. NULL,
  584. NULL,
  585. NULL);
  586. }
  587. break;
  588. }
  589. case IOCTL_WMI_GET_VERSION:
  590. {
  591. if (OutBufferLen < sizeof(WMIVERSIONINFO))
  592. {
  593. Status = STATUS_BUFFER_TOO_SMALL;
  594. } else {
  595. ((PWMIVERSIONINFO)Buffer)->Version = WMI_CURRENT_VERSION;
  596. OutBufferLen = sizeof(WMIVERSIONINFO);
  597. Status = STATUS_SUCCESS;
  598. }
  599. break;
  600. }
  601. case IOCTL_WMI_ENUMERATE_GUIDS_AND_PROPERTIES:
  602. case IOCTL_WMI_ENUMERATE_GUIDS:
  603. {
  604. if (OutBufferLen < FIELD_OFFSET(WMIGUIDLISTINFO, GuidList))
  605. {
  606. Status = STATUS_BUFFER_TOO_SMALL;
  607. } else {
  608. Status = WmipEnumerateGuids(Ioctl,
  609. (PWMIGUIDLISTINFO)Buffer,
  610. OutBufferLen,
  611. &OutBufferLen);
  612. }
  613. break;
  614. }
  615. case IOCTL_WMI_QUERY_GUID_INFO:
  616. {
  617. if (OutBufferLen < sizeof(WMIQUERYGUIDINFO))
  618. {
  619. Status = STATUS_BUFFER_TOO_SMALL;
  620. } else {
  621. Status = WmipQueryGuidInfo((PWMIQUERYGUIDINFO)Buffer);
  622. OutBufferLen = sizeof(WMIQUERYGUIDINFO);
  623. }
  624. break;
  625. }
  626. case IOCTL_WMI_ENUMERATE_MOF_RESOURCES:
  627. {
  628. if (OutBufferLen >= sizeof(WMIMOFLIST))
  629. {
  630. Status = WmipEnumerateMofResources((PWMIMOFLIST)Buffer,
  631. OutBufferLen,
  632. &OutBufferLen);
  633. } else {
  634. Status = STATUS_INVALID_PARAMETER;
  635. }
  636. break;
  637. }
  638. case IOCTL_WMI_RECEIVE_NOTIFICATIONS:
  639. {
  640. PWMIRECEIVENOTIFICATION ReceiveNotification;
  641. ULONG CountExpected;
  642. if ((InBufferLen >= sizeof(WMIRECEIVENOTIFICATION)) &&
  643. (OutBufferLen >= sizeof(WNODE_TOO_SMALL)))
  644. {
  645. ReceiveNotification = (PWMIRECEIVENOTIFICATION)Buffer;
  646. CountExpected = (InBufferLen -
  647. FIELD_OFFSET(WMIRECEIVENOTIFICATION, Handles)) /
  648. sizeof(HANDLE3264);
  649. if (ReceiveNotification->HandleCount <= CountExpected)
  650. {
  651. Status = WmipReceiveNotifications(ReceiveNotification,
  652. &OutBufferLen,
  653. Irp);
  654. } else {
  655. //
  656. // Input buffer not large enough which is an error
  657. //
  658. Status = STATUS_INVALID_DEVICE_REQUEST;
  659. }
  660. } else {
  661. //
  662. // Input and or output buffers not large enough
  663. // which is an error
  664. //
  665. Status = STATUS_INVALID_DEVICE_REQUEST;
  666. }
  667. break;
  668. }
  669. case IOCTL_WMI_MARK_HANDLE_AS_CLOSED:
  670. {
  671. PWMIMARKASCLOSED MarkAsClosed;
  672. if (InBufferLen >= sizeof(WMIMARKASCLOSED))
  673. {
  674. MarkAsClosed = (PWMIMARKASCLOSED)Buffer;
  675. Status = WmipMarkHandleAsClosed(MarkAsClosed->Handle.Handle);
  676. OutBufferLen = 0;
  677. } else {
  678. Status = STATUS_INVALID_DEVICE_REQUEST;
  679. }
  680. break;
  681. }
  682. case IOCTL_WMI_NOTIFY_LANGUAGE_CHANGE:
  683. {
  684. LPGUID LanguageGuid;
  685. PWMILANGUAGECHANGE LanguageChange;
  686. if (InBufferLen == sizeof(WMILANGUAGECHANGE))
  687. {
  688. LanguageChange = (PWMILANGUAGECHANGE)Buffer;
  689. if (LanguageChange->Flags & WMILANGUAGECHANGE_FLAG_ADDED)
  690. {
  691. LanguageGuid = &GUID_MOF_RESOURCE_ADDED_NOTIFICATION;
  692. } else if (LanguageChange->Flags & WMILANGUAGECHANGE_FLAG_REMOVED) {
  693. LanguageGuid = &GUID_MOF_RESOURCE_REMOVED_NOTIFICATION;
  694. } else {
  695. Status = STATUS_INVALID_DEVICE_REQUEST;
  696. break;
  697. }
  698. WmipGenerateMofResourceNotification(LanguageChange->Language,
  699. L"",
  700. LanguageGuid,
  701. MOFEVENT_ACTION_LANGUAGE_CHANGE);
  702. OutBufferLen = 0;
  703. Status = STATUS_SUCCESS;
  704. } else {
  705. Status = STATUS_INVALID_DEVICE_REQUEST;
  706. }
  707. break;
  708. }
  709. #ifndef MEMPHIS
  710. // Event trace logging IOCTLS
  711. case IOCTL_WMI_UNREGISTER_GUIDS:
  712. {
  713. if ((InBufferLen == sizeof(WMIUNREGGUIDS)) &&
  714. (OutBufferLen == sizeof(WMIUNREGGUIDS)))
  715. {
  716. Status = WmipUnregisterGuids((PWMIUNREGGUIDS)Buffer);
  717. } else {
  718. Status = STATUS_INVALID_PARAMETER;
  719. }
  720. break;
  721. }
  722. case IOCTL_WMI_REGISTER_GUIDS:
  723. {
  724. //
  725. // Register guids for user mode provider
  726. //
  727. Status = WmipProbeWmiRegRequest(
  728. Buffer,
  729. InBufferLen,
  730. OutBufferLen
  731. );
  732. if (NT_SUCCESS(Status))
  733. {
  734. HANDLE RequestHandle;
  735. PWMIREGREQUEST WmiRegRequest;
  736. PWMIREGINFOW WmiRegInfo;
  737. ULONG WmiRegInfoSize;
  738. ULONG GuidCount;
  739. ULONG TraceGuidMapSize;
  740. PWMIREGRESULTS WmiRegResults;
  741. PWMIREGINFOW WmiRegInfoThunk = NULL;
  742. WmiRegRequest = (PWMIREGREQUEST)Buffer;
  743. WmiRegInfo = (PWMIREGINFOW)OffsetToPtr(Buffer, sizeof(WMIREGREQUEST));
  744. WmiRegInfoSize = InBufferLen - sizeof(WMIREGREQUEST);
  745. GuidCount = WmiRegRequest->GuidCount;
  746. TraceGuidMapSize = GuidCount * sizeof(TRACEGUIDMAP);
  747. WmiRegResults = (PWMIREGRESULTS)OffsetToPtr(Buffer, TraceGuidMapSize);
  748. //
  749. // For WOW64, WMIREGINFOW and WMIREGGUIDW structures both need
  750. // to be thunked here because of padding and ULONG_PTR in them.
  751. //
  752. #if defined(_WIN64)
  753. if (IoIs32bitProcess(NULL))
  754. {
  755. ULONG SizeNeeded, SizeToCopy, i;
  756. PWMIREGINFOW WmiRegInfo32;
  757. PWMIREGGUIDW WmiRegGuid;
  758. PUCHAR pSource, pTarget;
  759. ULONG ImageNameLength = 0;
  760. ULONG ResourceNameLength = 0;
  761. ULONG Offset = 0;
  762. //
  763. // Find the GuidCount and allocate storage here.
  764. //
  765. if (WmiRegInfo->RegistryPath > 0)
  766. {
  767. pSource = OffsetToPtr(WmiRegInfo, WmiRegInfo->RegistryPath);
  768. ImageNameLength = *( (PUSHORT) pSource) + sizeof(USHORT);
  769. }
  770. if (WmiRegInfo->MofResourceName > 0)
  771. {
  772. pSource = OffsetToPtr(WmiRegInfo, WmiRegInfo->MofResourceName);
  773. ResourceNameLength = *((PUSHORT)pSource) + sizeof(USHORT);
  774. }
  775. SizeNeeded = sizeof(WMIREGINFOW) +
  776. GuidCount * sizeof(WMIREGGUIDW) +
  777. ImageNameLength + ResourceNameLength;
  778. SizeNeeded = (SizeNeeded + 7) & ~7;
  779. WmiRegInfoThunk = (PWMIREGINFOW) WmipAlloc(SizeNeeded);
  780. if (WmiRegInfoThunk == NULL)
  781. {
  782. Status = STATUS_INSUFFICIENT_RESOURCES;
  783. OutBufferLen = 0;
  784. break;
  785. }
  786. RtlZeroMemory(WmiRegInfoThunk, SizeNeeded);
  787. pTarget = (PUCHAR)WmiRegInfoThunk;
  788. pSource = (PUCHAR)WmiRegInfo;
  789. SizeToCopy = WmiRegRequest->WmiRegInfo32Size;
  790. RtlCopyMemory(pTarget, pSource, SizeToCopy);
  791. pTarget += FIELD_OFFSET(WMIREGINFOW, WmiRegGuid);
  792. pSource += SizeToCopy;
  793. SizeToCopy = WmiRegRequest->WmiRegGuid32Size;
  794. Offset = FIELD_OFFSET(WMIREGINFOW, WmiRegGuid);
  795. for (i=0; i < GuidCount; i++)
  796. {
  797. RtlCopyMemory(pTarget, pSource, SizeToCopy);
  798. //
  799. // The InstanceCount checks are done here because the
  800. // source may not be aligned.
  801. //
  802. WmiRegGuid = (PWMIREGGUIDW) pTarget;
  803. if ( (WmiRegGuid->InstanceCount > 0) ||
  804. (WmiRegGuid->InstanceNameList > 0) )
  805. {
  806. return STATUS_UNSUCCESSFUL;
  807. }
  808. pTarget += sizeof(WMIREGGUIDW);
  809. pSource += SizeToCopy;
  810. Offset += sizeof(WMIREGGUIDW);
  811. }
  812. if (ImageNameLength > 0)
  813. {
  814. pSource = OffsetToPtr(WmiRegInfo, WmiRegInfo->RegistryPath);
  815. RtlCopyMemory(pTarget, pSource, ImageNameLength);
  816. pTarget += ImageNameLength;
  817. WmiRegInfoThunk->RegistryPath = Offset;
  818. Offset += ImageNameLength;
  819. }
  820. if (ResourceNameLength > 0)
  821. {
  822. pSource = OffsetToPtr(WmiRegInfo, WmiRegInfo->MofResourceName);
  823. RtlCopyMemory(pTarget, pSource, ResourceNameLength);
  824. pTarget += ResourceNameLength;
  825. WmiRegInfoThunk->MofResourceName = Offset;
  826. Offset += ResourceNameLength;
  827. }
  828. WmiRegInfo = WmiRegInfoThunk;
  829. WmiRegInfoSize = SizeNeeded;
  830. WmiRegInfo->BufferSize = SizeNeeded;
  831. }
  832. #endif
  833. Status = WmipRegisterUMGuids(WmiRegRequest->ObjectAttributes,
  834. WmiRegRequest->Cookie,
  835. WmiRegInfo,
  836. WmiRegInfoSize,
  837. (PTRACEGUIDMAP)Buffer,
  838. GuidCount,
  839. &RequestHandle,
  840. &WmiRegResults->LoggerContext);
  841. if (NT_SUCCESS(Status))
  842. {
  843. #if defined(_WIN64)
  844. if (IoIs32bitProcess(NULL))
  845. {
  846. WmiRegResults->RequestHandle.Handle64 = 0;
  847. WmiRegResults->RequestHandle.Handle32 = PtrToUlong(RequestHandle);
  848. }
  849. else
  850. #endif
  851. {
  852. WmiRegResults->RequestHandle.Handle = RequestHandle;
  853. }
  854. OutBufferLen = sizeof(WMIREGRESULTS) + TraceGuidMapSize;
  855. }
  856. if (WmiRegInfoThunk != NULL)
  857. {
  858. WmipFree(WmiRegInfoThunk);
  859. }
  860. }
  861. break;
  862. }
  863. case IOCTL_WMI_CREATE_UM_LOGGER:
  864. {
  865. //
  866. // Create User mode logger
  867. //
  868. PWNODE_HEADER Wnode;
  869. ULONG MinLength;
  870. #if defined(_WIN64)
  871. if (IoIs32bitProcess(NULL))
  872. {
  873. ULONG SizeNeeded;
  874. PUCHAR src, dest;
  875. PWMICREATEUMLOGGER32 WmiCreateUmLogger32 = (PWMICREATEUMLOGGER32)Buffer;
  876. PWMICREATEUMLOGGER WmiCreateUmLoggerThunk;
  877. MinLength = sizeof(WMICREATEUMLOGGER32) + sizeof(WNODE_HEADER);
  878. if (InBufferLen < MinLength) {
  879. Status = STATUS_INVALID_PARAMETER;
  880. OutBufferLen = 0;
  881. break;
  882. }
  883. Wnode = (PWNODE_HEADER)((PUCHAR)WmiCreateUmLogger32 + sizeof(WMICREATEUMLOGGER32));
  884. if (Wnode->BufferSize > (InBufferLen-sizeof(WMICREATEUMLOGGER32)) ) {
  885. Status = STATUS_INVALID_PARAMETER;
  886. OutBufferLen = 0;
  887. break;
  888. }
  889. SizeNeeded = InBufferLen + sizeof(WMICREATEUMLOGGER) - sizeof(WMICREATEUMLOGGER32);
  890. SizeNeeded = (SizeNeeded + 7) & ~7;
  891. WmiCreateUmLoggerThunk = (PWMICREATEUMLOGGER) WmipAlloc(SizeNeeded);
  892. if (WmiCreateUmLoggerThunk == NULL)
  893. {
  894. Status = STATUS_INSUFFICIENT_RESOURCES;
  895. OutBufferLen = 0;
  896. break;
  897. }
  898. RtlZeroMemory(WmiCreateUmLoggerThunk, SizeNeeded);
  899. WmiCreateUmLoggerThunk->ObjectAttributes =
  900. UlongToPtr(WmiCreateUmLogger32->ObjectAttributes);
  901. WmiCreateUmLoggerThunk->ControlGuid = WmiCreateUmLogger32->ControlGuid;
  902. dest = (PUCHAR)WmiCreateUmLoggerThunk + sizeof(WMICREATEUMLOGGER);
  903. src = (PUCHAR)WmiCreateUmLogger32 + sizeof(WMICREATEUMLOGGER32);
  904. RtlCopyMemory(dest, src, Wnode->BufferSize);
  905. Status = WmipCreateUMLogger(WmiCreateUmLoggerThunk);
  906. WmiCreateUmLogger32->ReplyHandle.Handle64 = 0;
  907. WmiCreateUmLogger32->ReplyHandle.Handle32 = PtrToUlong(WmiCreateUmLoggerThunk->ReplyHandle.Handle);
  908. WmiCreateUmLogger32->ReplyCount = WmiCreateUmLoggerThunk->ReplyCount;
  909. WmipFree(WmiCreateUmLoggerThunk);
  910. }
  911. else
  912. #endif
  913. {
  914. MinLength = sizeof(WMICREATEUMLOGGER) + sizeof(WNODE_HEADER);
  915. if (InBufferLen < MinLength) {
  916. Status = STATUS_INVALID_PARAMETER;
  917. OutBufferLen = 0;
  918. break;
  919. }
  920. Wnode = (PWNODE_HEADER) ((PUCHAR)Buffer + sizeof(WMICREATEUMLOGGER));
  921. if (Wnode->BufferSize > (InBufferLen-sizeof(WMICREATEUMLOGGER)) ) {
  922. Status = STATUS_INVALID_PARAMETER;
  923. OutBufferLen = 0;
  924. break;
  925. }
  926. Status = WmipCreateUMLogger((PWMICREATEUMLOGGER)Buffer);
  927. }
  928. break;
  929. }
  930. case IOCTL_WMI_MB_REPLY:
  931. {
  932. //
  933. // MB Reply message
  934. //
  935. PUCHAR Message;
  936. ULONG MessageSize;
  937. PWMIMBREPLY WmiMBReply;
  938. if (InBufferLen >= FIELD_OFFSET(WMIMBREPLY, Message))
  939. {
  940. WmiMBReply = (PWMIMBREPLY)Buffer;
  941. Message = (PUCHAR)Buffer + FIELD_OFFSET(WMIMBREPLY, Message);
  942. MessageSize = InBufferLen - FIELD_OFFSET(WMIMBREPLY, Message);
  943. Status = WmipMBReply(WmiMBReply->Handle.Handle,
  944. WmiMBReply->ReplyIndex,
  945. Message,
  946. MessageSize);
  947. } else {
  948. Status = STATUS_INVALID_PARAMETER;
  949. }
  950. OutBufferLen = 0;
  951. }
  952. case IOCTL_WMI_ENABLE_DISABLE_TRACELOG:
  953. {
  954. PWMITRACEENABLEDISABLEINFO TraceEnableInfo;
  955. OutBufferLen = 0;
  956. if (InBufferLen == sizeof(WMITRACEENABLEDISABLEINFO))
  957. {
  958. TraceEnableInfo = (PWMITRACEENABLEDISABLEINFO)Buffer;
  959. Status = WmipEnableDisableTrace(Ioctl,
  960. TraceEnableInfo);
  961. } else {
  962. Status = STATUS_UNSUCCESSFUL;
  963. }
  964. break;
  965. }
  966. case IOCTL_WMI_START_LOGGER:
  967. {
  968. PWMI_LOGGER_INFORMATION LoggerInfo;
  969. ULONG LoggerBuf, LogFileBuf;
  970. if ((InBufferLen < sizeof(WMI_LOGGER_INFORMATION)) ||
  971. (OutBufferLen < sizeof(WMI_LOGGER_INFORMATION)) ) {
  972. OutBufferLen = 0;
  973. Status = STATUS_UNSUCCESSFUL;
  974. break;
  975. }
  976. if ( !(Wnode->Flags & WNODE_FLAG_TRACED_GUID) ) {
  977. OutBufferLen = 0;
  978. Status = STATUS_UNSUCCESSFUL;
  979. break;
  980. }
  981. LoggerInfo = (PWMI_LOGGER_INFORMATION) Wnode;
  982. #ifdef _WIN64
  983. if (IoIs32bitProcess(Irp)) {
  984. LoggerBuf = ( (PUNICODE_STRING32) &LoggerInfo->LoggerName)->Buffer;
  985. LoggerInfo->LoggerName.Buffer = UlongToPtr(LoggerBuf);
  986. LogFileBuf = ( (PUNICODE_STRING32) &LoggerInfo->LogFileName)->Buffer;
  987. LoggerInfo->LogFileName.Buffer = UlongToPtr(LogFileBuf);
  988. }
  989. #endif
  990. Status = WmipStartLogger( LoggerInfo );
  991. OutBufferLen = sizeof (WMI_LOGGER_INFORMATION);
  992. #ifdef _WIN64
  993. if (IoIs32bitProcess(Irp)) {
  994. ( (PUNICODE_STRING32) &LoggerInfo->LoggerName)->Buffer = LoggerBuf;
  995. ( (PUNICODE_STRING32) &LoggerInfo->LogFileName)->Buffer = LogFileBuf;
  996. }
  997. #endif
  998. break;
  999. }
  1000. case IOCTL_WMI_STOP_LOGGER:
  1001. {
  1002. PWMI_LOGGER_INFORMATION LoggerInfo;
  1003. ULONG LoggerBuf, LogFileBuf;
  1004. if ((InBufferLen < sizeof(WMI_LOGGER_INFORMATION)) ||
  1005. (OutBufferLen < sizeof(WMI_LOGGER_INFORMATION)) ) {
  1006. OutBufferLen = 0;
  1007. Status = STATUS_UNSUCCESSFUL;
  1008. break;
  1009. }
  1010. if ( !(Wnode->Flags & WNODE_FLAG_TRACED_GUID) ) {
  1011. OutBufferLen = 0;
  1012. Status = STATUS_UNSUCCESSFUL;
  1013. break;
  1014. }
  1015. LoggerInfo = (PWMI_LOGGER_INFORMATION) Wnode;
  1016. #ifdef _WIN64
  1017. if (IoIs32bitProcess(Irp)) {
  1018. LoggerBuf = ( (PUNICODE_STRING32) &LoggerInfo->LoggerName)->Buffer;
  1019. LoggerInfo->LoggerName.Buffer = UlongToPtr(LoggerBuf);
  1020. LogFileBuf = ( (PUNICODE_STRING32) &LoggerInfo->LogFileName)->Buffer;
  1021. LoggerInfo->LogFileName.Buffer = UlongToPtr(LogFileBuf);
  1022. }
  1023. #endif
  1024. Status = WmiStopTrace( LoggerInfo );
  1025. OutBufferLen = sizeof (WMI_LOGGER_INFORMATION);
  1026. #ifdef _WIN64
  1027. if (IoIs32bitProcess(Irp)) {
  1028. ( (PUNICODE_STRING32) &LoggerInfo->LoggerName)->Buffer = LoggerBuf;
  1029. ( (PUNICODE_STRING32) &LoggerInfo->LogFileName)->Buffer = LogFileBuf;
  1030. }
  1031. #endif
  1032. break;
  1033. }
  1034. case IOCTL_WMI_QUERY_LOGGER:
  1035. {
  1036. PWMI_LOGGER_INFORMATION LoggerInfo;
  1037. ULONG LoggerBuf, LogFileBuf;
  1038. if ((InBufferLen < sizeof(WMI_LOGGER_INFORMATION)) ||
  1039. (OutBufferLen < sizeof(WMI_LOGGER_INFORMATION)) ) {
  1040. OutBufferLen = 0;
  1041. Status = STATUS_UNSUCCESSFUL;
  1042. break;
  1043. }
  1044. if ( !(Wnode->Flags & WNODE_FLAG_TRACED_GUID) ) {
  1045. OutBufferLen = 0;
  1046. Status = STATUS_UNSUCCESSFUL;
  1047. break;
  1048. }
  1049. LoggerInfo = (PWMI_LOGGER_INFORMATION) Wnode;
  1050. #ifdef _WIN64
  1051. if (IoIs32bitProcess(Irp)) {
  1052. LoggerBuf = ( (PUNICODE_STRING32) &LoggerInfo->LoggerName)->Buffer;
  1053. LoggerInfo->LoggerName.Buffer = UlongToPtr(LoggerBuf);
  1054. LogFileBuf = ( (PUNICODE_STRING32) &LoggerInfo->LogFileName)->Buffer;
  1055. LoggerInfo->LogFileName.Buffer = UlongToPtr(LogFileBuf);
  1056. }
  1057. #endif
  1058. Status = WmipQueryLogger( LoggerInfo, NULL );
  1059. OutBufferLen = sizeof (WMI_LOGGER_INFORMATION);
  1060. #ifdef _WIN64
  1061. if (IoIs32bitProcess(Irp)) {
  1062. ( (PUNICODE_STRING32) &LoggerInfo->LoggerName)->Buffer = LoggerBuf;
  1063. ( (PUNICODE_STRING32) &LoggerInfo->LogFileName)->Buffer = LogFileBuf;
  1064. }
  1065. #endif
  1066. break;
  1067. }
  1068. case IOCTL_WMI_UPDATE_LOGGER:
  1069. {
  1070. PWMI_LOGGER_INFORMATION LoggerInfo;
  1071. ULONG LoggerBuf, LogFileBuf;
  1072. if ((InBufferLen < sizeof(WMI_LOGGER_INFORMATION)) ||
  1073. (OutBufferLen < sizeof(WMI_LOGGER_INFORMATION)) ) {
  1074. OutBufferLen = 0;
  1075. Status = STATUS_UNSUCCESSFUL;
  1076. break;
  1077. }
  1078. if ( !(Wnode->Flags & WNODE_FLAG_TRACED_GUID) ) {
  1079. OutBufferLen = 0;
  1080. Status = STATUS_UNSUCCESSFUL;
  1081. break;
  1082. }
  1083. LoggerInfo = (PWMI_LOGGER_INFORMATION) Wnode;
  1084. #ifdef _WIN64
  1085. if (IoIs32bitProcess(Irp)) {
  1086. LoggerBuf = ( (PUNICODE_STRING32) &LoggerInfo->LoggerName)->Buffer;
  1087. LoggerInfo->LoggerName.Buffer = UlongToPtr(LoggerBuf);
  1088. LogFileBuf = ( (PUNICODE_STRING32) &LoggerInfo->LogFileName)->Buffer;
  1089. LoggerInfo->LogFileName.Buffer = UlongToPtr(LogFileBuf);
  1090. }
  1091. #endif
  1092. Status = WmiUpdateTrace( LoggerInfo );
  1093. OutBufferLen = sizeof (WMI_LOGGER_INFORMATION);
  1094. #ifdef _WIN64
  1095. if (IoIs32bitProcess(Irp)) {
  1096. ( (PUNICODE_STRING32) &LoggerInfo->LoggerName)->Buffer = LoggerBuf;
  1097. ( (PUNICODE_STRING32) &LoggerInfo->LogFileName)->Buffer = LogFileBuf;
  1098. }
  1099. #endif
  1100. break;
  1101. }
  1102. case IOCTL_WMI_FLUSH_LOGGER:
  1103. {
  1104. PWMI_LOGGER_INFORMATION LoggerInfo;
  1105. ULONG LoggerBuf, LogFileBuf;
  1106. if ((InBufferLen < sizeof(WMI_LOGGER_INFORMATION)) ||
  1107. (OutBufferLen < sizeof(WMI_LOGGER_INFORMATION)) ) {
  1108. OutBufferLen = 0;
  1109. Status = STATUS_UNSUCCESSFUL;
  1110. break;
  1111. }
  1112. if ( !(Wnode->Flags & WNODE_FLAG_TRACED_GUID) ) {
  1113. OutBufferLen = 0;
  1114. Status = STATUS_UNSUCCESSFUL;
  1115. break;
  1116. }
  1117. LoggerInfo = (PWMI_LOGGER_INFORMATION) Wnode;
  1118. #ifdef _WIN64
  1119. if (IoIs32bitProcess(Irp)) {
  1120. LoggerBuf = ( (PUNICODE_STRING32) &LoggerInfo->LoggerName)->Buffer;
  1121. LoggerInfo->LoggerName.Buffer = UlongToPtr(LoggerBuf);
  1122. LogFileBuf = ( (PUNICODE_STRING32) &LoggerInfo->LogFileName)->Buffer;
  1123. LoggerInfo->LogFileName.Buffer = UlongToPtr(LogFileBuf);
  1124. }
  1125. #endif
  1126. Status = WmiFlushTrace( LoggerInfo );
  1127. OutBufferLen = sizeof (WMI_LOGGER_INFORMATION);
  1128. #ifdef _WIN64
  1129. if (IoIs32bitProcess(Irp)) {
  1130. ( (PUNICODE_STRING32) &LoggerInfo->LoggerName)->Buffer = LoggerBuf;
  1131. ( (PUNICODE_STRING32) &LoggerInfo->LogFileName)->Buffer = LogFileBuf;
  1132. }
  1133. #endif
  1134. break;
  1135. }
  1136. case IOCTL_WMI_TRACE_EVENT:
  1137. { // NOTE: This relies on WmiTraceEvent to probe the buffer!
  1138. OutBufferLen = 0;
  1139. if ( InBufferLen < sizeof(WNODE_HEADER) ) {
  1140. Status = STATUS_UNSUCCESSFUL;
  1141. break;
  1142. }
  1143. Status = WmiTraceEvent(
  1144. (PWNODE_HEADER)
  1145. irpStack->Parameters.DeviceIoControl.Type3InputBuffer,
  1146. KeGetPreviousMode()
  1147. );
  1148. break;
  1149. }
  1150. case IOCTL_WMI_TRACE_MESSAGE:
  1151. { // NOTE: This relies on WmiTraceUserMessage to probe the buffer!
  1152. OutBufferLen = 0;
  1153. if ( InBufferLen < sizeof(MESSAGE_TRACE_USER) ) {
  1154. Status = STATUS_UNSUCCESSFUL;
  1155. break;
  1156. }
  1157. Status = WmiTraceUserMessage(
  1158. (PMESSAGE_TRACE_USER)
  1159. irpStack->Parameters.DeviceIoControl.Type3InputBuffer,
  1160. InBufferLen
  1161. );
  1162. break;
  1163. }
  1164. case IOCTL_WMI_SET_MARK:
  1165. {
  1166. OutBufferLen = 0;
  1167. if ( InBufferLen <= FIELD_OFFSET(WMI_SET_MARK_INFORMATION, Mark)) {
  1168. Status = STATUS_UNSUCCESSFUL;
  1169. break;
  1170. }
  1171. Status = WmiSetMark( (PVOID) Wnode, InBufferLen );
  1172. break;
  1173. }
  1174. case IOCTL_WMI_CLOCK_TYPE:
  1175. {
  1176. if ((InBufferLen < sizeof(WMI_LOGGER_INFORMATION)) ||
  1177. (OutBufferLen < sizeof(WMI_LOGGER_INFORMATION))) {
  1178. OutBufferLen = 0;
  1179. Status = STATUS_INFO_LENGTH_MISMATCH;
  1180. break;
  1181. }
  1182. WmipValidateClockType((PWMI_LOGGER_INFORMATION) Wnode);
  1183. Status = STATUS_SUCCESS;
  1184. break;
  1185. }
  1186. #ifdef NTPERF
  1187. case IOCTL_WMI_SWITCH_BUFFER:
  1188. {
  1189. if ((InBufferLen < sizeof(PWMI_SWITCH_PERFMEM_BUFFER_INFORMATION)) ||
  1190. (OutBufferLen < sizeof(PWMI_SWITCH_PERFMEM_BUFFER_INFORMATION)) ) {
  1191. OutBufferLen = 0;
  1192. Status = STATUS_UNSUCCESSFUL;
  1193. break;
  1194. }
  1195. Status = WmipSwitchPerfmemBuffer((PWMI_SWITCH_PERFMEM_BUFFER_INFORMATION) Wnode );
  1196. OutBufferLen = sizeof (PVOID);
  1197. break;
  1198. }
  1199. #endif
  1200. #endif // if not MEMPHIS
  1201. case IOCTL_WMI_NTDLL_LOGGERINFO:
  1202. {
  1203. if ((InBufferLen < sizeof(WMINTDLLLOGGERINFO)) ||
  1204. (OutBufferLen < sizeof(WMINTDLLLOGGERINFO))) {
  1205. OutBufferLen = 0;
  1206. Status = STATUS_UNSUCCESSFUL;
  1207. break;
  1208. }
  1209. Status = WmipNtDllLoggerInfo((PWMINTDLLLOGGERINFO)Buffer);
  1210. break;
  1211. }
  1212. default:
  1213. {
  1214. WmipDebugPrintEx((DPFLTR_WMICORE_ID, DPFLTR_INFO_LEVEL,"WMI: Unsupported IOCTL %x\n",
  1215. irpStack->Parameters.DeviceIoControl.IoControlCode));
  1216. Status = STATUS_INVALID_DEVICE_REQUEST;
  1217. }
  1218. }
  1219. if (Status != STATUS_PENDING)
  1220. {
  1221. Irp->IoStatus.Status = Status;
  1222. Irp->IoStatus.Information = NT_SUCCESS(Status) ? OutBufferLen : 0;
  1223. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  1224. }
  1225. return(Status);
  1226. }
  1227. NTSTATUS
  1228. WmipSystemControl(
  1229. IN PDEVICE_OBJECT DeviceObject,
  1230. IN PIRP Irp
  1231. )
  1232. {
  1233. PAGED_CODE();
  1234. return(IoWMISystemControl((PWMILIB_INFO)&WmipWmiLibInfo,
  1235. DeviceObject,
  1236. Irp));
  1237. }
  1238. NTSTATUS WmipWmiIrpCompletion(
  1239. IN PDEVICE_OBJECT DeviceObject,
  1240. IN PIRP Irp,
  1241. IN PVOID Context
  1242. )
  1243. /*++
  1244. Routine Description:
  1245. WMI forwarded IRP completion routine. Set an event and return
  1246. STATUS_MORE_PROCESSING_REQUIRED. WmipForwardWmiIrp will wait on this
  1247. event and then re-complete the irp after cleaning up.
  1248. Arguments:
  1249. DeviceObject is the device object of the WMI driver
  1250. Irp is the WMI irp that was just completed
  1251. Context is a PKEVENT that WmipForwardWmiIrp will wait on
  1252. Return Value:
  1253. NT status code
  1254. --*/
  1255. {
  1256. PIRPCOMPCTX IrpCompCtx;
  1257. PREGENTRY RegEntry;
  1258. PKEVENT Event;
  1259. UNREFERENCED_PARAMETER(DeviceObject);
  1260. UNREFERENCED_PARAMETER(Irp);
  1261. IrpCompCtx = (PIRPCOMPCTX)Context;
  1262. RegEntry = IrpCompCtx->RegEntry;
  1263. Event = &IrpCompCtx->Event;
  1264. WmipDecrementIrpCount(RegEntry);
  1265. KeSetEvent(Event, IO_NO_INCREMENT, FALSE);
  1266. return(STATUS_MORE_PROCESSING_REQUIRED);
  1267. }
  1268. NTSTATUS WmipGetDevicePDO(
  1269. PDEVICE_OBJECT DeviceObject,
  1270. PDEVICE_OBJECT *PDO
  1271. )
  1272. {
  1273. PIRP Irp;
  1274. PIO_STACK_LOCATION IrpSp;
  1275. IO_STATUS_BLOCK IoStatusBlock;
  1276. PDEVICE_RELATIONS DeviceRelations;
  1277. NTSTATUS Status;
  1278. KEVENT Event;
  1279. PAGED_CODE();
  1280. *PDO = NULL;
  1281. KeInitializeEvent( &Event,
  1282. NotificationEvent,
  1283. FALSE );
  1284. Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
  1285. DeviceObject,
  1286. NULL,
  1287. 0,
  1288. NULL,
  1289. &Event,
  1290. &IoStatusBlock );
  1291. if (Irp == NULL)
  1292. {
  1293. return(STATUS_INSUFFICIENT_RESOURCES);
  1294. }
  1295. IrpSp = IoGetNextIrpStackLocation( Irp );
  1296. IrpSp->MinorFunction = IRP_MN_QUERY_DEVICE_RELATIONS;
  1297. IrpSp->Parameters.QueryDeviceRelations.Type = TargetDeviceRelation;
  1298. Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
  1299. Status = IoCallDriver( DeviceObject, Irp );
  1300. if (Status == STATUS_PENDING)
  1301. {
  1302. KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL );
  1303. Status = IoStatusBlock.Status;
  1304. }
  1305. if (NT_SUCCESS(Status))
  1306. {
  1307. DeviceRelations = (PDEVICE_RELATIONS)IoStatusBlock.Information;
  1308. ASSERT(DeviceRelations);
  1309. ASSERT(DeviceRelations->Count == 1);
  1310. *PDO = DeviceRelations->Objects[0];
  1311. ExFreePool(DeviceRelations);
  1312. }
  1313. return(Status);
  1314. }
  1315. NTSTATUS WmipObjectToPDO(
  1316. PFILE_OBJECT FileObject,
  1317. PDEVICE_OBJECT DeviceObject,
  1318. PDEVICE_OBJECT *PDO
  1319. )
  1320. /*++
  1321. Routine Description:
  1322. This routine will determine the PDO which is the target of a file handle.
  1323. The mechananism is to build a IRP_MJ_PNP irp with IRP_MN_QUERY_RELATIONS
  1324. and query for TargetDeviceRelation. This irp is supposed to be passed down
  1325. a device stack until it hits the PDO which will fill in its device object
  1326. and return. Note that some drivers may not support this.
  1327. Arguments:
  1328. FileObject is the file object for device that is being queried
  1329. DeviceObject is the device object that is being queried
  1330. *PDO returns with the PDO that is targeted by the file object. When
  1331. the caller has finished using the PDO it must ObDereferenceObject it.
  1332. Return Value:
  1333. NT status code
  1334. --*/
  1335. {
  1336. NTSTATUS Status;
  1337. PAGED_CODE();
  1338. if (DeviceObject == NULL)
  1339. {
  1340. DeviceObject = IoGetRelatedDeviceObject(FileObject);
  1341. }
  1342. if (DeviceObject != NULL)
  1343. {
  1344. Status = WmipGetDevicePDO(DeviceObject, PDO);
  1345. } else {
  1346. Status = STATUS_NO_SUCH_DEVICE;
  1347. }
  1348. return(Status);
  1349. }
  1350. NTSTATUS WmipForwardWmiIrp(
  1351. PIRP Irp,
  1352. UCHAR MinorFunction,
  1353. ULONG ProviderId,
  1354. PVOID DataPath,
  1355. ULONG BufferLength,
  1356. PVOID Buffer
  1357. )
  1358. /*++
  1359. Routine Description:
  1360. If the provider is a driver then this routine will allocate a new irp
  1361. with the correct stack size and send it to the driver. If the provider
  1362. is a callback then it is called directly.
  1363. It is assumed that the caller has performed any security checks required
  1364. Arguments:
  1365. Irp is the IOCTL irp that initiated the request
  1366. MinorFunction specifies the minor function code of the WMI Irp
  1367. WmiRegistrationId is the id passed by the user mode code. This routine
  1368. will look it up to determine the device object pointer.
  1369. DataPath is the value for the DataPath parameter of the WMI irp
  1370. BufferLength is the value for the BufferLength parameter of the WMI irp
  1371. Buffer is the value for the Buffer parameter of the WMI irp
  1372. Return Value:
  1373. NT status code
  1374. --*/
  1375. {
  1376. PREGENTRY RegEntry;
  1377. NTSTATUS Status;
  1378. PIO_STACK_LOCATION irpStack;
  1379. PDEVICE_OBJECT TargetDeviceObject;
  1380. CCHAR DeviceStackSize;
  1381. IRPCOMPCTX IrpCompCtx;
  1382. PWNODE_HEADER Wnode = (PWNODE_HEADER)Buffer;
  1383. BOOLEAN IsPnPIdRequest;
  1384. PDEVICE_OBJECT DeviceObject;
  1385. PAGED_CODE();
  1386. WmipAssert( (MinorFunction >= IRP_MN_QUERY_ALL_DATA) &&
  1387. (MinorFunction <= IRP_MN_REGINFO_EX) );
  1388. irpStack = IoGetCurrentIrpStackLocation(Irp);
  1389. //
  1390. // For non-file handle based requests we get the registration entry
  1391. // to validate the target and check for a callback
  1392. RegEntry = WmipFindRegEntryByProviderId(ProviderId, TRUE);
  1393. if (RegEntry != NULL)
  1394. {
  1395. if (RegEntry->Flags & REGENTRY_FLAG_NOT_ACCEPTING_IRPS)
  1396. {
  1397. WmipUnreferenceRegEntry(RegEntry);
  1398. WmipDecrementIrpCount(RegEntry);
  1399. if ((MinorFunction == IRP_MN_QUERY_SINGLE_INSTANCE) ||
  1400. (MinorFunction == IRP_MN_CHANGE_SINGLE_INSTANCE))
  1401. {
  1402. Status = STATUS_WMI_INSTANCE_NOT_FOUND;
  1403. } else {
  1404. Status = STATUS_UNSUCCESSFUL;
  1405. }
  1406. return(Status);
  1407. }
  1408. DeviceObject = RegEntry->DeviceObject;
  1409. #ifndef MEMPHIS
  1410. if (RegEntry->Flags & REGENTRY_FLAG_CALLBACK)
  1411. {
  1412. ULONG Size = 0;
  1413. //
  1414. // This guy registered as a callback so do the callback and go.
  1415. Status = (*RegEntry->WmiEntry)(MinorFunction,
  1416. DataPath,
  1417. BufferLength,
  1418. Buffer,
  1419. RegEntry->WmiEntry,
  1420. &Size
  1421. );
  1422. Irp->IoStatus.Status = Status;
  1423. Irp->IoStatus.Information = Size;
  1424. WmipUnreferenceRegEntry(RegEntry);
  1425. WmipDecrementIrpCount(RegEntry);
  1426. return(Status);
  1427. }
  1428. #endif
  1429. } else {
  1430. WmipDebugPrintEx((DPFLTR_WMICORE_ID, DPFLTR_INFO_LEVEL,"WMI: Invalid device object passed from user mode %x\n",
  1431. ProviderId));
  1432. if ((MinorFunction == IRP_MN_QUERY_SINGLE_INSTANCE) ||
  1433. (MinorFunction == IRP_MN_CHANGE_SINGLE_INSTANCE))
  1434. {
  1435. Status = STATUS_WMI_INSTANCE_NOT_FOUND;
  1436. } else {
  1437. Status = STATUS_UNSUCCESSFUL;
  1438. }
  1439. return(Status);
  1440. }
  1441. //
  1442. // Determine if this is a query for the device pnp id guid
  1443. IsPnPIdRequest = ((MinorFunction != IRP_MN_REGINFO) &&
  1444. (MinorFunction != IRP_MN_REGINFO_EX)) &&
  1445. ((IsEqualGUID(&Wnode->Guid, &WmipDataProviderPnpidGuid)) ||
  1446. (IsEqualGUID(&Wnode->Guid, &WmipDataProviderPnPIdInstanceNamesGuid)));
  1447. if (IsPnPIdRequest && (RegEntry->PDO != NULL))
  1448. {
  1449. //
  1450. // Its the PnPId request and WMI is handling it on behalf of the
  1451. // device then switch the device object to our own
  1452. DeviceObject = WmipServiceDeviceObject;
  1453. IsPnPIdRequest = FALSE;
  1454. }
  1455. //
  1456. // Get the top of the device stack for our targer WMI device. Note that
  1457. // IoGetAttachedDeviceReference also takes an object reference
  1458. // which we get rid of after the the irp is completed by the
  1459. // data provider driver.
  1460. TargetDeviceObject = IoGetAttachedDeviceReference(DeviceObject);
  1461. DeviceStackSize = TargetDeviceObject->StackSize + 1;
  1462. //
  1463. // Check that there are enough stack locations in our irp so that we
  1464. // can forward it to the top of the device stack. We must also check
  1465. // if our target device is the WMI data or service device otherwise
  1466. // the number of stack locations for it will keep increementing until
  1467. // the machine crashes
  1468. if ((DeviceStackSize <= WmipServiceDeviceObject->StackSize) ||
  1469. (TargetDeviceObject == WmipServiceDeviceObject))
  1470. {
  1471. //
  1472. // There are enough stack locations in the WMI irp to forward
  1473. // Remember some context information in our irp stack and use
  1474. // it as our completion context value
  1475. KeInitializeEvent( &IrpCompCtx.Event,
  1476. SynchronizationEvent,
  1477. FALSE );
  1478. IrpCompCtx.RegEntry = RegEntry;
  1479. IoSetCompletionRoutine(Irp,
  1480. WmipWmiIrpCompletion,
  1481. (PVOID)&IrpCompCtx,
  1482. TRUE,
  1483. TRUE,
  1484. TRUE);
  1485. //
  1486. // Setup next irp stack location with WMI irp info
  1487. irpStack = IoGetNextIrpStackLocation(Irp);
  1488. irpStack->MajorFunction = IRP_MJ_SYSTEM_CONTROL;
  1489. irpStack->MinorFunction = MinorFunction;
  1490. irpStack->Parameters.WMI.ProviderId = (ULONG_PTR)DeviceObject;
  1491. irpStack->Parameters.WMI.DataPath = DataPath;
  1492. irpStack->Parameters.WMI.BufferSize = BufferLength;
  1493. irpStack->Parameters.WMI.Buffer = Buffer;
  1494. //
  1495. // Initialize irp status to STATUS_NOT_SUPPORTED so that we can
  1496. // detect the case where no data provider responded to the irp
  1497. Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
  1498. IoMarkIrpPending(Irp);
  1499. Status = IoCallDriver(TargetDeviceObject, Irp);
  1500. if (Status == STATUS_PENDING) {
  1501. KeWaitForSingleObject( &IrpCompCtx.Event,
  1502. Executive,
  1503. KernelMode,
  1504. FALSE,
  1505. (PLARGE_INTEGER) NULL );
  1506. Status = Irp->IoStatus.Status;
  1507. }
  1508. //
  1509. // Check if the status code is still STATUS_NOT_SUPPORTED. If this is
  1510. // the case then most likely no data provider responded to the irp.
  1511. // So we want to change the status code to something more relevant
  1512. // to WMI like STATUS_WMI_GUID_NOT_FOUND
  1513. if (Status == STATUS_NOT_SUPPORTED)
  1514. {
  1515. Status = STATUS_WMI_GUID_NOT_FOUND;
  1516. Irp->IoStatus.Status = STATUS_WMI_GUID_NOT_FOUND;
  1517. }
  1518. #if DBG
  1519. if (((MinorFunction == IRP_MN_REGINFO) || (MinorFunction == IRP_MN_REGINFO_EX)) &&
  1520. (NT_SUCCESS(Status)) &&
  1521. (Irp->IoStatus.Information == 0))
  1522. {
  1523. WmipDebugPrintEx((DPFLTR_WMICORE_ID, DPFLTR_INFO_LEVEL,"WMI: %p completed IRP_MN_REGINFO with size 0 (%p, %x)\n",
  1524. DeviceObject, Buffer, BufferLength));
  1525. }
  1526. #endif
  1527. //
  1528. // If this was a registration request then we need to see if there are
  1529. // any PDOs that need to be translated into static instance names.
  1530. if (((MinorFunction == IRP_MN_REGINFO) ||
  1531. (MinorFunction == IRP_MN_REGINFO_EX)) &&
  1532. (NT_SUCCESS(Status)) &&
  1533. (Irp->IoStatus.Information > FIELD_OFFSET(WMIREGINFOW,
  1534. WmiRegGuid)))
  1535. {
  1536. WmipTranslatePDOInstanceNames(Irp,
  1537. MinorFunction,
  1538. BufferLength,
  1539. RegEntry);
  1540. }
  1541. //
  1542. // Dereference regentry which was taken when forwarding the irp
  1543. WmipUnreferenceRegEntry(RegEntry);
  1544. } else {
  1545. //
  1546. // There are not enough stack locations to forward this irp.
  1547. // We bump the stack count for the WMI device and return
  1548. // an error asking to try the irp again.
  1549. WmipUnreferenceRegEntry(RegEntry);
  1550. WmipDecrementIrpCount(RegEntry);
  1551. WmipUpdateDeviceStackSize(DeviceStackSize);
  1552. Status = STATUS_WMI_TRY_AGAIN;
  1553. }
  1554. //
  1555. // Dereference the target device which was the top of the stack to
  1556. // which we forwarded the irp.
  1557. ObDereferenceObject(TargetDeviceObject);
  1558. return(Status);
  1559. }
  1560. NTSTATUS WmipSendWmiIrp(
  1561. UCHAR MinorFunction,
  1562. ULONG ProviderId,
  1563. PVOID DataPath,
  1564. ULONG BufferLength,
  1565. PVOID Buffer,
  1566. PIO_STATUS_BLOCK Iosb
  1567. )
  1568. /*++
  1569. Routine Description:
  1570. This routine will allocate a new irp and then forward it on as a WMI
  1571. irp appropriately. The routine handles the case where the stack size
  1572. is too small and will retry the irp.
  1573. Arguments:
  1574. See WmipForwardWmiIrp
  1575. Return Value:
  1576. NT status code
  1577. --*/
  1578. {
  1579. PIRP Irp;
  1580. PIO_STACK_LOCATION IrpStack;
  1581. NTSTATUS Status;
  1582. PAGED_CODE();
  1583. Irp = NULL;
  1584. do
  1585. {
  1586. Irp = IoAllocateIrp((CCHAR)(WmipServiceDeviceObject->StackSize+1),
  1587. FALSE);
  1588. if (Irp == NULL)
  1589. {
  1590. return(STATUS_INSUFFICIENT_RESOURCES);
  1591. }
  1592. IoSetNextIrpStackLocation(Irp);
  1593. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  1594. IrpStack->DeviceObject = WmipServiceDeviceObject;
  1595. Irp->Tail.Overlay.Thread = PsGetCurrentThread();
  1596. Irp->AssociatedIrp.SystemBuffer = Buffer;
  1597. Status = WmipForwardWmiIrp(
  1598. Irp,
  1599. MinorFunction,
  1600. ProviderId,
  1601. DataPath,
  1602. BufferLength,
  1603. Buffer);
  1604. *Iosb = Irp->IoStatus;
  1605. IoFreeIrp(Irp);
  1606. } while (Status == STATUS_WMI_TRY_AGAIN);
  1607. return(Status);
  1608. }
  1609. NTSTATUS WmipTranslateFileHandle(
  1610. IN OUT PWMIFHTOINSTANCENAME FhToInstanceName,
  1611. IN OUT PULONG OutBufferLen,
  1612. IN HANDLE FileHandle,
  1613. IN PDEVICE_OBJECT DeviceObject,
  1614. IN PWMIGUIDOBJECT GuidObject,
  1615. OUT PUNICODE_STRING InstanceNameString
  1616. )
  1617. /*++
  1618. Routine Description:
  1619. This routine will translate a file handle or device object into the
  1620. device instance name for the target PDO of the device object
  1621. pointed to by the file handle.
  1622. Arguments:
  1623. FhToInstanceName passes in the file handle and returns the device
  1624. instance name.
  1625. Return Value:
  1626. NT status code
  1627. --*/
  1628. {
  1629. PDEVICE_OBJECT PDO;
  1630. UNICODE_STRING DeviceInstanceName;
  1631. PFILE_OBJECT FileObject;
  1632. NTSTATUS Status;
  1633. ULONG SizeNeeded;
  1634. PWCHAR InstanceName;
  1635. ULONG Length;
  1636. PWCHAR HandleName;
  1637. ULONG HandleNameLen;
  1638. PWCHAR BaseName;
  1639. ULONG BaseNameLen;
  1640. PBGUIDENTRY GuidEntry;
  1641. PLIST_ENTRY InstanceSetList;
  1642. PBINSTANCESET InstanceSet;
  1643. ULONG BaseIndex;
  1644. PAGED_CODE();
  1645. if (FhToInstanceName != NULL)
  1646. {
  1647. WmipAssert(FileHandle == NULL);
  1648. WmipAssert(GuidObject == NULL);
  1649. WmipAssert(InstanceNameString == NULL);
  1650. WmipAssert(DeviceObject == NULL);
  1651. FileHandle = FhToInstanceName->FileHandle.Handle;
  1652. if (FileHandle == NULL)
  1653. {
  1654. return(STATUS_INVALID_HANDLE);
  1655. }
  1656. }
  1657. if (FileHandle != NULL)
  1658. {
  1659. //
  1660. // Make reference to the file object so it doesn't go away
  1661. //
  1662. Status = ObReferenceObjectByHandle(FileHandle,
  1663. 0,
  1664. IoFileObjectType,
  1665. KernelMode,
  1666. &FileObject,
  1667. NULL);
  1668. } else {
  1669. //
  1670. // Make regerence to the device object so it doesn't go away
  1671. //
  1672. Status = ObReferenceObjectByPointer(DeviceObject,
  1673. FILE_ALL_ACCESS,
  1674. NULL,
  1675. KernelMode);
  1676. }
  1677. if (NT_SUCCESS(Status))
  1678. {
  1679. Status = WmipObjectToPDO(FileObject,
  1680. DeviceObject,
  1681. &PDO);
  1682. if (NT_SUCCESS(Status))
  1683. {
  1684. //
  1685. // Map file object to PDO
  1686. Status = WmipPDOToDeviceInstanceName(PDO,
  1687. &DeviceInstanceName);
  1688. if (NT_SUCCESS(Status))
  1689. {
  1690. //
  1691. // Now see if we can find an instance name
  1692. //
  1693. HandleName = DeviceInstanceName.Buffer;
  1694. HandleNameLen = DeviceInstanceName.Length / sizeof(WCHAR);
  1695. if (FhToInstanceName != NULL)
  1696. {
  1697. Status = ObReferenceObjectByHandle(FhToInstanceName->KernelHandle.Handle,
  1698. WMIGUID_QUERY,
  1699. WmipGuidObjectType,
  1700. UserMode,
  1701. &GuidObject,
  1702. NULL);
  1703. } else {
  1704. Status = ObReferenceObjectByPointer(GuidObject,
  1705. WMIGUID_QUERY,
  1706. WmipGuidObjectType,
  1707. KernelMode);
  1708. }
  1709. if (NT_SUCCESS(Status))
  1710. {
  1711. Status = STATUS_WMI_INSTANCE_NOT_FOUND;
  1712. GuidEntry = GuidObject->GuidEntry;
  1713. WmipEnterSMCritSection();
  1714. if (GuidEntry->ISCount > 0)
  1715. {
  1716. InstanceSetList = GuidEntry->ISHead.Flink;
  1717. while ((InstanceSetList != &GuidEntry->ISHead) &&
  1718. ! NT_SUCCESS(Status))
  1719. {
  1720. InstanceSet = CONTAINING_RECORD(InstanceSetList,
  1721. INSTANCESET,
  1722. GuidISList);
  1723. if (InstanceSet->Flags & IS_INSTANCE_BASENAME)
  1724. {
  1725. BaseName = InstanceSet->IsBaseName->BaseName;
  1726. BaseNameLen = wcslen(BaseName);
  1727. //
  1728. // If the instance set has a base name
  1729. // and the beginning of it matches the
  1730. // PnPId and it has only an _ after it
  1731. // then we have got a match
  1732. //
  1733. if ((_wcsnicmp(BaseName,
  1734. HandleName,
  1735. HandleNameLen) == 0) &&
  1736. (BaseNameLen == (HandleNameLen+1)) &&
  1737. (BaseName[BaseNameLen-1] == L'_'))
  1738. {
  1739. BaseIndex = InstanceSet->IsBaseName->BaseIndex;
  1740. Status = STATUS_SUCCESS;
  1741. }
  1742. }
  1743. InstanceSetList = InstanceSetList->Flink;
  1744. }
  1745. }
  1746. WmipLeaveSMCritSection();
  1747. if (NT_SUCCESS(Status))
  1748. {
  1749. if (FhToInstanceName != NULL)
  1750. {
  1751. FhToInstanceName->BaseIndex = BaseIndex;
  1752. SizeNeeded = DeviceInstanceName.Length + 2 * sizeof(WCHAR) +
  1753. FIELD_OFFSET(WMIFHTOINSTANCENAME,
  1754. InstanceNames);
  1755. if (*OutBufferLen >= SizeNeeded)
  1756. {
  1757. InstanceName = &FhToInstanceName->InstanceNames[0];
  1758. Length = DeviceInstanceName.Length;
  1759. FhToInstanceName->InstanceNameLength = (USHORT)(Length + 2 * sizeof(WCHAR));
  1760. RtlCopyMemory(InstanceName,
  1761. DeviceInstanceName.Buffer,
  1762. DeviceInstanceName.Length);
  1763. //
  1764. // Double NUL terminate string
  1765. //
  1766. Length /= 2;
  1767. InstanceName[Length++] = UNICODE_NULL;
  1768. InstanceName[Length] = UNICODE_NULL;
  1769. *OutBufferLen = SizeNeeded;
  1770. } else if (*OutBufferLen >= sizeof(ULONG)) {
  1771. FhToInstanceName->SizeNeeded = SizeNeeded;
  1772. *OutBufferLen = sizeof(ULONG);
  1773. } else {
  1774. Status = STATUS_UNSUCCESSFUL;
  1775. }
  1776. } else {
  1777. InstanceName = ExAllocatePoolWithTag(PagedPool,
  1778. DeviceInstanceName.Length + 32,
  1779. WmipInstanceNameTag);
  1780. if (InstanceName != NULL)
  1781. {
  1782. Length = swprintf(InstanceName,
  1783. L"%ws_%d",
  1784. DeviceInstanceName.Buffer,
  1785. BaseIndex);
  1786. InstanceNameString->Buffer = InstanceName;
  1787. InstanceNameString->Length = (USHORT)Length * sizeof(WCHAR);
  1788. InstanceNameString->MaximumLength = (USHORT)Length * sizeof(WCHAR);
  1789. } else {
  1790. Status = STATUS_INSUFFICIENT_RESOURCES;
  1791. }
  1792. }
  1793. }
  1794. ObDereferenceObject(GuidObject);
  1795. }
  1796. RtlFreeUnicodeString(&DeviceInstanceName);
  1797. }
  1798. ObDereferenceObject(PDO);
  1799. }
  1800. if (FileHandle != NULL)
  1801. {
  1802. ObDereferenceObject(FileObject);
  1803. } else {
  1804. ObDereferenceObject(DeviceObject);
  1805. }
  1806. }
  1807. return(Status);
  1808. }
  1809. #ifndef MEMPHIS
  1810. BOOLEAN
  1811. WmipFastIoDeviceControl(
  1812. IN PFILE_OBJECT FileObject,
  1813. IN BOOLEAN Wait,
  1814. IN PVOID InputBuffer OPTIONAL,
  1815. IN ULONG InputBufferLength,
  1816. OUT PVOID OutputBuffer OPTIONAL,
  1817. IN ULONG OutputBufferLength,
  1818. IN ULONG IoControlCode,
  1819. OUT PIO_STATUS_BLOCK IoStatus,
  1820. IN struct _DEVICE_OBJECT *DeviceObject
  1821. )
  1822. {
  1823. PAGED_CODE();
  1824. UNREFERENCED_PARAMETER(FileObject);
  1825. UNREFERENCED_PARAMETER(Wait);
  1826. UNREFERENCED_PARAMETER(OutputBuffer);
  1827. UNREFERENCED_PARAMETER(OutputBufferLength);
  1828. UNREFERENCED_PARAMETER(DeviceObject);
  1829. if (IoControlCode == IOCTL_WMI_TRACE_EVENT) {
  1830. if (InputBufferLength < sizeof(EVENT_TRACE_HEADER))
  1831. return FALSE;
  1832. IoStatus->Status = WmiTraceEvent( InputBuffer, KeGetPreviousMode() );
  1833. return TRUE;
  1834. } else if (IoControlCode == IOCTL_WMI_TRACE_MESSAGE) {
  1835. if (InputBufferLength < sizeof(MESSAGE_TRACE_USER))
  1836. return FALSE;
  1837. IoStatus->Status = WmiTraceUserMessage( InputBuffer, InputBufferLength );
  1838. return TRUE;
  1839. }
  1840. return FALSE;
  1841. }
  1842. #endif
  1843. NTSTATUS WmipProbeWnodeWorker(
  1844. PWNODE_HEADER WnodeHeader,
  1845. ULONG MinWnodeSize,
  1846. ULONG InstanceNameOffset,
  1847. ULONG DataBlockOffset,
  1848. ULONG DataBlockSize,
  1849. ULONG InBufferLen,
  1850. ULONG OutBufferLen,
  1851. BOOLEAN CheckOutBound,
  1852. BOOLEAN CheckInBound
  1853. )
  1854. /*++
  1855. Routine Description:
  1856. Probe the incoming Wnode to ensure that any offsets in the
  1857. header point to memory that is valid within the buffer. Also validate
  1858. that the Wnode is properly formed.
  1859. This routine assumes that the input and output buffers has been
  1860. probed enough to determine that it is at least as large as
  1861. MinWnodeSize and MinWnodeSize must be at least as large as
  1862. sizeof(WNODE_HEADER)
  1863. WNODE Rules:
  1864. 9. For outbound data WnodeDataBlockOffset != 0
  1865. 5. For inbound Wnode->DataBlockOffset must be 0 (implying no data) or
  1866. Wnode->DataBlockOffset must be <= incoming buffer size and >=
  1867. sizeof(WNODE_SINGLE_INSTANCE), that is
  1868. the data block must start in the incoming buffer, but after the
  1869. WNODE_SINGLE_INSTANCE header.
  1870. 6. Wnode and Wnode->DataBlockOffset must be aligned on an 8 byte boundry.
  1871. 7. For inbound data (SetSingleInstance) (Wnode->DataBlockOffset +
  1872. Wnode->DataBlockSize) < incoming buffer length. That is the entire
  1873. data block must fit within the incoming buffer.
  1874. 8. For outbound data (QuerySingleInstance) Wnode->DataBlockOffset
  1875. must be <= outgoing buffer length. That is the start of the outgoing
  1876. data block must fit within the outgoing data buffer. Note that it is
  1877. the provider's responsibility to determine if there will be enough
  1878. space in the outgoing buffer to write the returned data.
  1879. 10. Wnode->OffsetInstanceNames must be aligned on a 2 byte boundry
  1880. 11. Wnode->OffsetInstanceNames must be <= (incoming buffer size) +
  1881. sizeof(USHORT), that is it must start within the incoming buffer and
  1882. the USHORT that specifies the length must be within the incoming
  1883. buffer.
  1884. 12. The entire instance name string must fit with the incoming buffer
  1885. 13. For outbound data (QuerySingleInstance) the entire instance name
  1886. must start and fit within the output buffer.
  1887. 14. Wnode->DataBlockOffset must be placed after any instance name and
  1888. not overlap the instance name.
  1889. Arguments:
  1890. WnodeHeader - pointer to WNODE to be probed
  1891. InBufferLen - Size of the incoming buffer
  1892. OutBufferLen - Size of the outgoing buffer
  1893. MinWnodeSize - minimum size that the WNODE can be
  1894. InstanceNameOffset - Offset within WNODE to instance name
  1895. DataBlockOffset - Offset within WNODE to data block
  1896. DataBlockSize - Size of data block
  1897. CheckOutBound - If TRUE, WNODE needs to be validated for provider to
  1898. return data.
  1899. CheckInBound - If TRUE WNODE needs to be validated for provider to
  1900. receive data
  1901. Return Value:
  1902. NT status code
  1903. --*/
  1904. {
  1905. NTSTATUS Status = STATUS_SUCCESS;
  1906. PWCHAR InstanceNamePtr;
  1907. PAGED_CODE();
  1908. if (InstanceNameOffset != 0)
  1909. {
  1910. #if DBG
  1911. //
  1912. // Validate instance name begins beyond WNODE header
  1913. if (InstanceNameOffset < MinWnodeSize)
  1914. {
  1915. return(STATUS_UNSUCCESSFUL);
  1916. }
  1917. #endif
  1918. //
  1919. // Validate InstanceName is aligned properly. This is left
  1920. // in the free build since alphas may have alignment requiremnts
  1921. // in handling USHORTs and WCHARs
  1922. //
  1923. // Validate that USHORT holding instance name length is within
  1924. // WNODE
  1925. if (( ! WmipIsAligned(InstanceNameOffset, 2)) ||
  1926. (InstanceNameOffset > InBufferLen - sizeof(USHORT)) )
  1927. {
  1928. return(STATUS_UNSUCCESSFUL);
  1929. }
  1930. //
  1931. // Validate Dynamic Instance Name text is fully within
  1932. // input buffer and output buffer for outbound WNODEs
  1933. InstanceNamePtr = (PWCHAR)OffsetToPtr(WnodeHeader,
  1934. InstanceNameOffset);
  1935. InstanceNameOffset += sizeof(USHORT) + *InstanceNamePtr;
  1936. if ( (InstanceNameOffset > InBufferLen) ||
  1937. ( (CheckOutBound) && (InstanceNameOffset > OutBufferLen)) )
  1938. {
  1939. return(STATUS_UNSUCCESSFUL);
  1940. }
  1941. #if DBG
  1942. //
  1943. // If data block is specified then it must be placed after the
  1944. // end of the instance name
  1945. if ((DataBlockOffset != 0) &&
  1946. (DataBlockOffset < InstanceNameOffset))
  1947. {
  1948. return(STATUS_UNSUCCESSFUL);
  1949. }
  1950. #endif
  1951. }
  1952. #if DBG
  1953. //
  1954. // Ensure data block offset is placed after the WNODE header
  1955. // header
  1956. if ((DataBlockOffset != 0) &&
  1957. (DataBlockOffset < MinWnodeSize))
  1958. {
  1959. return(STATUS_UNSUCCESSFUL);
  1960. }
  1961. #endif
  1962. //
  1963. // Ensure data block is aligned properly
  1964. if (! WmipIsAligned(DataBlockOffset, 8))
  1965. {
  1966. return(STATUS_UNSUCCESSFUL);
  1967. }
  1968. //
  1969. // For incoming WNODE, make sure the data block
  1970. // does not extend beyond the input buffer.
  1971. if ((CheckInBound) &&
  1972. (DataBlockOffset != 0) &&
  1973. ( (DataBlockSize > InBufferLen) ||
  1974. (DataBlockOffset > InBufferLen - DataBlockSize) ) )
  1975. {
  1976. return(STATUS_UNSUCCESSFUL);
  1977. }
  1978. if (CheckOutBound)
  1979. {
  1980. //
  1981. // For outgoing WNODE make sure there is
  1982. // enough room to write the WNODE header
  1983. //
  1984. // For outgoing WNODE make sure the data block
  1985. // offset is within the bounds of the output buffer
  1986. if ( (OutBufferLen < MinWnodeSize) ||
  1987. (DataBlockOffset > OutBufferLen) )
  1988. {
  1989. return(STATUS_UNSUCCESSFUL);
  1990. }
  1991. #if DBG
  1992. //
  1993. // Make sure that the data block offset is specified so provider
  1994. // can know where to write data
  1995. if (DataBlockOffset == 0)
  1996. {
  1997. return(STATUS_UNSUCCESSFUL);
  1998. }
  1999. #endif
  2000. }
  2001. return(Status);
  2002. }
  2003. NTSTATUS WmipProbeWnodeAllData(
  2004. PWNODE_ALL_DATA Wnode,
  2005. ULONG InBufferLen,
  2006. ULONG OutBufferLen
  2007. )
  2008. /*++
  2009. Routine Description:
  2010. Probe the incoming WNODE_ALL_DATA to ensure that any offsets in the
  2011. header point to memory that is valid within the buffer. Also validate
  2012. that the WNODE_ALL_DATA is properly formed.
  2013. This routine MUST succeed before any fields in the WNODE_ALL_DATA can be
  2014. used by any kernel components when passed in from user mode. Note that
  2015. we can trust that the input and output buffer are properly sized since
  2016. the WMI IOCTLs are METHOD_BUFFERED and the IO manager does that for us.
  2017. WNODE_ALL_DATA_RULES:
  2018. 1. Wnode is aligned on a 8 byte boundry
  2019. 2. The incoming buffer must be at least as large as sizeof(WNODE_HEADER)
  2020. 3. The outgoing buffer must be at least as large as sizeof(WNODE_ALL_DATA)
  2021. 5. WnodeHeader->BufferSize must equal incoming bufffer size
  2022. Arguments:
  2023. Wnode - WNODE_ALL_DATA to be validated
  2024. InBufferLen - Size of the incoming buffer
  2025. OutBufferLen - Size of the outgoing buffer
  2026. Return Value:
  2027. NT status code
  2028. --*/
  2029. {
  2030. NTSTATUS Status;
  2031. PWNODE_HEADER WnodeHeader = (PWNODE_HEADER)Wnode;
  2032. PAGED_CODE();
  2033. #if DBG
  2034. //
  2035. // Make sure WNODE is on a 8 byte boundry
  2036. // if (! WmipIsAligned((PUCHAR)Wnode, 8))
  2037. // {
  2038. // return(STATUS_UNSUCCESSFUL);
  2039. // }
  2040. #endif
  2041. //
  2042. // Make sure that enough of the WNODE_ALL_DATA was passed so that we
  2043. // can look at it and the drivers can fill it in
  2044. if ((InBufferLen < sizeof(WNODE_HEADER)) ||
  2045. (OutBufferLen < sizeof(WNODE_ALL_DATA)))
  2046. {
  2047. return(STATUS_UNSUCCESSFUL);
  2048. }
  2049. Status = WmipValidateWnodeHeader(WnodeHeader,
  2050. InBufferLen,
  2051. sizeof(WNODE_HEADER),
  2052. WNODE_FLAG_ALL_DATA,
  2053. 0xffffff7e);
  2054. return(Status);
  2055. }
  2056. NTSTATUS WmipProbeWnodeSingleInstance(
  2057. PWNODE_SINGLE_INSTANCE Wnode,
  2058. ULONG InBufferLen,
  2059. ULONG OutBufferLen,
  2060. BOOLEAN OutBound
  2061. )
  2062. /*++
  2063. Routine Description:
  2064. Probe the incoming WNODE_SINGLE_INSTANCE to ensure that any offsets in the
  2065. header point to memory that is valid within the buffer. Also validate
  2066. that the WNODE_SINGLE_INSTANCE is properly formed.
  2067. This routine MUST succeed before any fields in the WNODE_SINGLE_INSTANCE
  2068. can be used by any kernel components when passed in from user mode.
  2069. Note that we can trust that the input and output buffer are properly
  2070. sized since the WMI IOCTLs are METHOD_BUFFERED and the IO manager does
  2071. that for us.
  2072. WNODE_SINGLE_INSTANCE Rules:
  2073. 1. The incoming buffer must be at least as large as
  2074. sizeof(WNODE_SINGLE_INSTANCE)
  2075. 2. The outgoing buffer must be at least as large as
  2076. sizeof(WNODE_SINGLE_INSTANCE)
  2077. 3. WnodeHeader->ProviderId must be non null, Actual value validated when
  2078. irp is forwarded.
  2079. 4. WnodeHeader->BufferSize must equal incoming bufffer size
  2080. 5. Wnode->DataBlockOffset must be 0 (implying no data) or
  2081. Wnode->DataBlockOffset must be <= incoming buffer size and >=
  2082. sizeof(WNODE_SINGLE_INSTANCE), that is
  2083. the data block must start in the incoming buffer, but after the
  2084. WNODE_SINGLE_INSTANCE header.
  2085. 6. Wnode and Wnode->DataBlockOffset must be aligned on an 8 byte boundry.
  2086. 7. For inbound data (SetSingleInstance) (Wnode->DataBlockOffset +
  2087. Wnode->DataBlockSize) <= incoming buffer length. That is the entire
  2088. data block must fit within the incoming buffer.
  2089. 8. For outbound data (QuerySingleInstance) Wnode->DataBlockOffset
  2090. must be <= outgoing buffer length. That is the start of the outgoing
  2091. data block must fit within the outgoing data buffer. Note that it is
  2092. the provider's responsibility to determine if there will be enough
  2093. space in the outgoing buffer to write the returned data.
  2094. 9. For outbound data (QuerySingleInstance) WnodeDataBlockOffset != 0
  2095. 10. Wnode->OffsetInstanceNames must be aligned on a 2 byte boundry
  2096. 11. Wnode->OffsetInstanceNames + sizeof(USHORT) must be <= incoming
  2097. buffer size, that is it must start within the incoming buffer and
  2098. the USHORT that specifies the length must be within the incoming
  2099. buffer.
  2100. 12. The entire instance name string must fit with the incoming buffer
  2101. 13. For outbound data (QuerySingleInstance) the entire instance name
  2102. must start and fit within the output buffer.
  2103. 14. Wnode->DataBlockOffset must be placed after any instance name and
  2104. not overlap the instance name.
  2105. Arguments:
  2106. Wnode - WNODE_SINGLE_INSTANCE to be validated
  2107. InBufferLen - Size of the incoming buffer
  2108. OutBufferLen - Size of the outgoing buffer
  2109. OutBound - If FALSE, WNODE_SINGLE_INSTANCE has inbound data that must be
  2110. validated to be within the input buffer. If FALSE,
  2111. WNODE_SINGLE_INSTANCE is expected to be filled with data
  2112. by the driver so insure that data buffer is validated to
  2113. be within the output buffer.
  2114. Return Value:
  2115. NT status code
  2116. --*/
  2117. {
  2118. PWNODE_HEADER WnodeHeader = (PWNODE_HEADER)Wnode;
  2119. NTSTATUS Status;
  2120. PAGED_CODE();
  2121. //
  2122. // Make sure WNODE is on a 8 byte boundry
  2123. #if DBG
  2124. // if (! WmipIsAligned((PUCHAR)Wnode, 8))
  2125. // {
  2126. // return(STATUS_UNSUCCESSFUL);
  2127. // }
  2128. #endif
  2129. //
  2130. // Make sure that enough of the WNODE_SINGLE_INSTANCE was passed
  2131. // so that we can look at it
  2132. if ((InBufferLen < FIELD_OFFSET(WNODE_SINGLE_INSTANCE, VariableData)) ||
  2133. ( (OutBound) && (OutBufferLen < FIELD_OFFSET(WNODE_SINGLE_INSTANCE,
  2134. VariableData))))
  2135. {
  2136. return(STATUS_UNSUCCESSFUL);
  2137. }
  2138. Status = WmipProbeWnodeWorker(WnodeHeader,
  2139. FIELD_OFFSET(WNODE_SINGLE_INSTANCE,
  2140. VariableData),
  2141. Wnode->OffsetInstanceName,
  2142. Wnode->DataBlockOffset,
  2143. Wnode->SizeDataBlock,
  2144. InBufferLen,
  2145. OutBufferLen,
  2146. OutBound,
  2147. (BOOLEAN)(! OutBound));
  2148. if (NT_SUCCESS(Status))
  2149. {
  2150. Status = WmipValidateWnodeHeader(WnodeHeader,
  2151. InBufferLen,
  2152. FIELD_OFFSET(WNODE_SINGLE_INSTANCE,
  2153. VariableData),
  2154. WNODE_FLAG_SINGLE_INSTANCE,
  2155. 0xffffff7d);
  2156. }
  2157. return(Status);
  2158. }
  2159. NTSTATUS WmipProbeWnodeSingleItem(
  2160. PWNODE_SINGLE_ITEM Wnode,
  2161. ULONG InBufferLen
  2162. )
  2163. /*++
  2164. Routine Description:
  2165. Probe the incoming WNODE_SINGLE_ITEM to ensure that any offsets in the
  2166. header point to memory that is valid within the buffer. Also validate
  2167. that the WNODE_SINGLE_ITEM is properly formed.
  2168. This routine MUST succeed before any fields in the WNODE_SINGLE_INSTANCE
  2169. can be used by any kernel components when passed in from user mode.
  2170. Note that we can trust that the input and output buffer are properly
  2171. sized since the WMI IOCTLs are METHOD_BUFFERED and the IO manager does
  2172. that for us.
  2173. WNODE_SINGLE_ITEM rules:
  2174. 1. The incoming buffer must be at least as large as
  2175. sizeof(WNODE_SINGLE_ITEM)
  2176. 2. The outgoing buffer must be at least as large as
  2177. sizeof(WNODE_SINGLE_ITEM)
  2178. 3. WnodeHeader->ProviderId must be non null, Actual value validated when
  2179. irp is forwarded.
  2180. 4. WnodeHeader->BufferSize must equal incoming bufffer size
  2181. 5. Wnode->DataBlockOffset must be 0 (implying no data) or
  2182. Wnode->DataBlockOffset must be <= incoming buffer size and >=
  2183. sizeof(WNODE_SINGLE_ITEM), that is
  2184. the data block must start in the incoming buffer, but after the
  2185. WNODE_SINGLE_ITEM header.
  2186. 6. Wnode and Wnode->DataBlockOffset must be aligned on an 8 byte boundry.
  2187. 7. (Wnode->DataBlockOffset + Wnode->SizeDataItem) <
  2188. incoming buffer length. That is the entire
  2189. data block must fit within the incoming buffer.
  2190. 8. Wnode->DataItemId must not be 0
  2191. 9. Wnode->OffsetInstanceNames must be aligned on a 2 byte boundry
  2192. 10. Wnode->OffsetInstanceNames must be <= (incoming buffer size) +
  2193. sizeof(USHORT), that is it must start within the incoming buffer and
  2194. the USHORT that specifies the length must be within the incoming
  2195. buffer.
  2196. 11. The entire instance name string must fit with the incoming buffer
  2197. 12. Wnode->DataBlockOffset must be placed after any instance name and
  2198. not overlap the instance name.
  2199. Arguments:
  2200. Wnode - WNODE_SINGLE_ITEM to be validated
  2201. InBufferLen - Size of the incoming buffer
  2202. Return Value:
  2203. NT status code
  2204. --*/
  2205. {
  2206. PWNODE_HEADER WnodeHeader = (PWNODE_HEADER)Wnode;
  2207. NTSTATUS Status;
  2208. PAGED_CODE();
  2209. //
  2210. // Make sure WNODE is on a 8 byte boundry
  2211. #if DBG
  2212. // if (! WmipIsAligned((PUCHAR)Wnode, 8))
  2213. // {
  2214. // return(STATUS_UNSUCCESSFUL);
  2215. // }
  2216. #endif
  2217. //
  2218. // Make sure that enough of the WNODE_SINGLE_ITEM was passed
  2219. // so that we can look at it
  2220. if (InBufferLen < FIELD_OFFSET(WNODE_SINGLE_ITEM, VariableData))
  2221. {
  2222. return(STATUS_UNSUCCESSFUL);
  2223. }
  2224. #if DBG
  2225. // if (Wnode->ItemId == 0)
  2226. // {
  2227. // return(STATUS_UNSUCCESSFUL);
  2228. // }
  2229. #endif
  2230. //
  2231. // We don't use sizeof(WNODE_SINGLE_ITEM), but rather use the offset
  2232. // to the variable data since in the case of WNODE_SINGLE_ITEM they are
  2233. // different. The C compiler will round up the packing to 8 bytes so
  2234. // the former is 48 and the later is 44.
  2235. Status = WmipProbeWnodeWorker(WnodeHeader,
  2236. (ULONG)((ULONG_PTR)(&((PWNODE_SINGLE_ITEM)0)->VariableData)),
  2237. Wnode->OffsetInstanceName,
  2238. Wnode->DataBlockOffset,
  2239. Wnode->SizeDataItem,
  2240. InBufferLen,
  2241. 0,
  2242. FALSE,
  2243. TRUE);
  2244. if (NT_SUCCESS(Status))
  2245. {
  2246. Status = WmipValidateWnodeHeader(WnodeHeader,
  2247. InBufferLen,
  2248. FIELD_OFFSET(WNODE_SINGLE_ITEM,
  2249. VariableData),
  2250. WNODE_FLAG_SINGLE_ITEM,
  2251. 0xffffff7b);
  2252. }
  2253. return(Status);
  2254. }
  2255. NTSTATUS WmipProbeWnodeMethodItem(
  2256. PWNODE_METHOD_ITEM Wnode,
  2257. ULONG InBufferLen,
  2258. ULONG OutBufferLen
  2259. )
  2260. /*++
  2261. Routine Description:
  2262. Probe the incoming WNODE_METHOD_ITEM to ensure that any offsets in the
  2263. header point to memory that is valid within the buffer. Also validate
  2264. that the WNODE_METHOD_ITEM is properly formed.
  2265. This routine MUST succeed before any fields in the WNODE_METHOD_INSTANCE
  2266. can be used by any kernel components when passed in from user mode.
  2267. Note that we can trust that the input and output buffer are properly
  2268. sized since the WMI IOCTLs are METHOD_BUFFERED and the IO manager does
  2269. that for us.
  2270. WNODE_METHOD_ITEM Rules:
  2271. 1. The incoming buffer must be at least as large as
  2272. sizeof(WNODE_METHOD_ITEM)
  2273. 2. The outgoing buffer must be at least as large as
  2274. sizeof(WNODE_METHOD_ITEM)
  2275. 3. WnodeHeader->ProviderId must be non null, Actual value validated when
  2276. irp is forwarded and Wnode->MethodId must not be 0
  2277. 4. WnodeHeader->BufferSize must equal incoming bufffer size
  2278. 5. Wnode->DataBlockOffset must be 0 (implying no data) or
  2279. Wnode->DataBlockOffset must be <= incoming buffer size and >=
  2280. sizeof(WNODE_METHOD_ITEM), that is
  2281. the data block must start in the incoming buffer, but after the
  2282. WNODE_METHOD_ITEM header.
  2283. 6. Wnode and Wnode->DataBlockOffset must be aligned on an 8 byte boundry.
  2284. 7. For inbound data (Wnode->DataBlockOffset +
  2285. Wnode->DataBlockSize) < incoming buffer length. That is the entire
  2286. data block must fit within the incoming buffer.
  2287. 8. For outbound data Wnode->DataBlockOffset
  2288. must be <= outgoing buffer length. That is the start of the outgoing
  2289. data block must fit within the outgoing data buffer. Note that it is
  2290. the provider's responsibility to determine if there will be enough
  2291. space in the outgoing buffer to write the returned data.
  2292. 9. WnodeDataBlockOffset != 0
  2293. 10. Wnode->OffsetInstanceNames must be aligned on a 2 byte boundry
  2294. 11. Wnode->OffsetInstanceNames must be <= (incoming buffer size) +
  2295. sizeof(USHORT), that is it must start within the incoming buffer and
  2296. the USHORT that specifies the length must be within the incoming
  2297. buffer.
  2298. 12. The entire instance name string must fit with the incoming buffer
  2299. 13. For outbound data the entire instance name
  2300. must start and fit within the output buffer.
  2301. 14. Wnode->DataBlockOffset must be placed after any instance name and
  2302. not overlap the instance name.
  2303. Arguments:
  2304. Wnode - WNODE_METHOD_ITEM to be validated
  2305. InBufferLen - Size of the incoming buffer
  2306. OutBufferLen - Size of the Output buffer
  2307. Return Value:
  2308. NT status code
  2309. --*/
  2310. {
  2311. PWNODE_HEADER WnodeHeader = (PWNODE_HEADER)Wnode;
  2312. NTSTATUS Status;
  2313. PAGED_CODE();
  2314. //
  2315. // Make sure WNODE is on a 8 byte boundry
  2316. #if DBG
  2317. // if (! WmipIsAligned((PUCHAR)Wnode, 8))
  2318. // {
  2319. // return(STATUS_UNSUCCESSFUL);
  2320. // }
  2321. #endif
  2322. //
  2323. // Make sure that enough of the WNODE_METHOD_ITEM was passed
  2324. // so that we can look at it
  2325. if (InBufferLen < FIELD_OFFSET(WNODE_METHOD_ITEM, VariableData))
  2326. {
  2327. return(STATUS_UNSUCCESSFUL);
  2328. }
  2329. #if DBG
  2330. if (Wnode->MethodId == 0)
  2331. {
  2332. return(STATUS_UNSUCCESSFUL);
  2333. }
  2334. #endif
  2335. Status = WmipProbeWnodeWorker(WnodeHeader,
  2336. (ULONG)((ULONG_PTR)(&((PWNODE_METHOD_ITEM)0)->VariableData)),
  2337. Wnode->OffsetInstanceName,
  2338. Wnode->DataBlockOffset,
  2339. Wnode->SizeDataBlock,
  2340. InBufferLen,
  2341. OutBufferLen,
  2342. TRUE,
  2343. TRUE);
  2344. if (NT_SUCCESS(Status))
  2345. {
  2346. Status = WmipValidateWnodeHeader(WnodeHeader,
  2347. InBufferLen,
  2348. FIELD_OFFSET(WNODE_METHOD_ITEM,
  2349. VariableData),
  2350. WNODE_FLAG_METHOD_ITEM,
  2351. 0xffff7f7f);
  2352. }
  2353. return(Status);
  2354. }
  2355. NTSTATUS WmipProbeAndCaptureGuidObjectAttributes(
  2356. POBJECT_ATTRIBUTES CapturedObjectAttributes,
  2357. PUNICODE_STRING CapturedGuidString,
  2358. PWCHAR CapturedGuidBuffer,
  2359. POBJECT_ATTRIBUTES ObjectAttributes
  2360. )
  2361. {
  2362. PAGED_CODE();
  2363. #if defined(_WIN64)
  2364. if (IoIs32bitProcess(NULL))
  2365. {
  2366. POBJECT_ATTRIBUTES32 ObjectAttributes32;
  2367. PUNICODE_STRING32 GuidString32;
  2368. //
  2369. // Probe the embedded object attributes and string name
  2370. //
  2371. ObjectAttributes32 = (POBJECT_ATTRIBUTES32)ObjectAttributes;
  2372. try
  2373. {
  2374. //
  2375. // Probe, capture and validate the OBJECT_ATTRIBUTES
  2376. //
  2377. ProbeForRead( ObjectAttributes32,
  2378. sizeof(OBJECT_ATTRIBUTES32),
  2379. sizeof(ULONG) );
  2380. CapturedObjectAttributes->Length = sizeof(OBJECT_ATTRIBUTES);
  2381. CapturedObjectAttributes->RootDirectory = UlongToPtr(ObjectAttributes32->RootDirectory);
  2382. CapturedObjectAttributes->Attributes = ObjectAttributes32->Attributes;
  2383. CapturedObjectAttributes->SecurityDescriptor = UlongToPtr(ObjectAttributes32->SecurityDescriptor);
  2384. CapturedObjectAttributes->SecurityQualityOfService = UlongToPtr(ObjectAttributes32->SecurityQualityOfService);
  2385. //
  2386. // Now probe and validate the guid nane string passed
  2387. //
  2388. GuidString32 = UlongToPtr(ObjectAttributes32->ObjectName);
  2389. ProbeForRead(GuidString32,
  2390. sizeof(UNICODE_STRING32),
  2391. sizeof(ULONG));
  2392. CapturedGuidString->Length = GuidString32->Length;
  2393. CapturedGuidString->MaximumLength = GuidString32->MaximumLength;
  2394. CapturedGuidString->Buffer = UlongToPtr(GuidString32->Buffer);
  2395. if (CapturedGuidString->Length != (WmiGuidObjectNameLength * sizeof(WCHAR)))
  2396. {
  2397. return(STATUS_INVALID_PARAMETER);
  2398. }
  2399. ProbeForRead(CapturedGuidString->Buffer,
  2400. CapturedGuidString->Length,
  2401. sizeof(UCHAR));
  2402. RtlCopyMemory(CapturedGuidBuffer,
  2403. CapturedGuidString->Buffer,
  2404. WmiGuidObjectNameLength * sizeof(WCHAR));
  2405. CapturedGuidBuffer[WmiGuidObjectNameLength] = UNICODE_NULL;
  2406. CapturedGuidString->Buffer = CapturedGuidBuffer;
  2407. } except(EXCEPTION_EXECUTE_HANDLER) {
  2408. return(GetExceptionCode());
  2409. }
  2410. }
  2411. else
  2412. #endif
  2413. {
  2414. PUNICODE_STRING GuidString;
  2415. //
  2416. // Probe the embedded object attributes and string name
  2417. //
  2418. try
  2419. {
  2420. //
  2421. // Probe, capture and validate the OBJECT_ATTRIBUTES
  2422. //
  2423. *CapturedObjectAttributes = ProbeAndReadStructure( ObjectAttributes,
  2424. OBJECT_ATTRIBUTES);
  2425. //
  2426. // Now probe and validate the guid nane string passed
  2427. //
  2428. GuidString = CapturedObjectAttributes->ObjectName;
  2429. *CapturedGuidString = ProbeAndReadUnicodeString(GuidString);
  2430. if (CapturedGuidString->Length != (WmiGuidObjectNameLength * sizeof(WCHAR)))
  2431. {
  2432. return(STATUS_INVALID_PARAMETER);
  2433. }
  2434. ProbeForRead(CapturedGuidString->Buffer,
  2435. CapturedGuidString->Length,
  2436. sizeof(UCHAR));
  2437. RtlCopyMemory(CapturedGuidBuffer,
  2438. CapturedGuidString->Buffer,
  2439. WmiGuidObjectNameLength * sizeof(WCHAR));
  2440. CapturedGuidBuffer[WmiGuidObjectNameLength] = UNICODE_NULL;
  2441. CapturedGuidString->Buffer = CapturedGuidBuffer;
  2442. } except(EXCEPTION_EXECUTE_HANDLER) {
  2443. return(GetExceptionCode());
  2444. }
  2445. }
  2446. CapturedObjectAttributes->ObjectName = CapturedGuidString;
  2447. return(STATUS_SUCCESS);
  2448. }
  2449. NTSTATUS WmipProbeWmiOpenGuidBlock(
  2450. POBJECT_ATTRIBUTES CapturedObjectAttributes,
  2451. PUNICODE_STRING CapturedGuidString,
  2452. PWCHAR CapturedGuidBuffer,
  2453. PULONG DesiredAccess,
  2454. PWMIOPENGUIDBLOCK InGuidBlock,
  2455. ULONG InBufferLen,
  2456. ULONG OutBufferLen
  2457. )
  2458. {
  2459. NTSTATUS Status;
  2460. POBJECT_ATTRIBUTES ObjectAttributes;
  2461. PAGED_CODE();
  2462. #if defined(_WIN64)
  2463. if (IoIs32bitProcess(NULL))
  2464. {
  2465. PWMIOPENGUIDBLOCK32 InGuidBlock32;
  2466. if ((InBufferLen != sizeof(WMIOPENGUIDBLOCK32)) ||
  2467. (OutBufferLen != sizeof(WMIOPENGUIDBLOCK32)))
  2468. {
  2469. return(STATUS_UNSUCCESSFUL);
  2470. }
  2471. //
  2472. // Probe the embedded object attributes and string name
  2473. //
  2474. InGuidBlock32 = (PWMIOPENGUIDBLOCK32)InGuidBlock;
  2475. ObjectAttributes = ULongToPtr(InGuidBlock32->ObjectAttributes);
  2476. *DesiredAccess = InGuidBlock32->DesiredAccess;
  2477. }
  2478. else
  2479. #endif
  2480. {
  2481. //
  2482. // Ensure the input and output buffer sizes are correct
  2483. //
  2484. if ((InBufferLen != sizeof(WMIOPENGUIDBLOCK)) ||
  2485. (OutBufferLen != sizeof(WMIOPENGUIDBLOCK)))
  2486. {
  2487. return(STATUS_UNSUCCESSFUL);
  2488. }
  2489. //
  2490. // Probe the embedded object attributes and string name
  2491. //
  2492. ObjectAttributes = InGuidBlock->ObjectAttributes;
  2493. *DesiredAccess = InGuidBlock->DesiredAccess;
  2494. }
  2495. Status = WmipProbeAndCaptureGuidObjectAttributes(CapturedObjectAttributes,
  2496. CapturedGuidString,
  2497. CapturedGuidBuffer,
  2498. ObjectAttributes);
  2499. if (NT_SUCCESS(Status))
  2500. {
  2501. if ((CapturedObjectAttributes->RootDirectory != NULL) ||
  2502. (CapturedObjectAttributes->Attributes != 0) ||
  2503. (CapturedObjectAttributes->SecurityDescriptor != NULL) ||
  2504. (CapturedObjectAttributes->SecurityQualityOfService != NULL))
  2505. {
  2506. Status = STATUS_INVALID_PARAMETER;
  2507. }
  2508. }
  2509. return(Status);
  2510. }
  2511. NTSTATUS WmipProbeWmiRegRequest(
  2512. PWMIREGREQUEST Buffer,
  2513. ULONG InBufferLen,
  2514. ULONG OutBufferLen
  2515. )
  2516. /*++
  2517. Routine Description:
  2518. Probe the incoming WMIREGREQUEST to ensure that any offsets in the
  2519. header point to memory that is valid within the buffer. Also validate
  2520. that the WMIREGINFO is properly formed.
  2521. This routine MUST succeed before any fields in the WMI_REG_INFO
  2522. can be used by any kernel components when passed in from user mode.
  2523. Note that we can trust that the input and output buffer are properly
  2524. sized since the WMI IOCTLs are METHOD_BUFFERED and the IO manager does
  2525. that for us.
  2526. WMIREGREQUEST Rules:
  2527. 1. The incoming buffer must be at least as large as
  2528. sizeof(WMIREGREQUEST) + sizeof(WMIREGINFOW)
  2529. 2. The outgoing buffer must be at least as large as
  2530. sizeof(WMIREGRESULTS)
  2531. 3. WmiRegInfo->BufferSize must be less than incoming Buffer size minus
  2532. sizeof(WMIREGREQUEST)
  2533. 4. GuidCount must be at least 1 and less than MAXWMIGUIDCOUNT
  2534. 5. WmiRegInfo->BufferSize must be greater than equal to
  2535. sizeof(WMIREGINFOW) + WmiRegInfo->GuidCount * sizeof(WMIREGGUIDW)
  2536. 5. WmiRegInfo->RegistryPath offset must be within the incoming buffer
  2537. 6. WmiRegInfo->MofResourcePath offset must be within the incomoing buffer
  2538. 7. RegistryPath and MofResourceName strings are counted unicode strings.
  2539. Their length must be within the incoming buffer
  2540. 8. For WOW64, RefInfo32Size and RegGuid32Size passed in must be non-zero and
  2541. cannot be larger than their 64 bit counter part.
  2542. 9. Since we decipher the counted strings at a buffer offset, the offset
  2543. must be aligned to 2 bytes (for USHORT).
  2544. 10. Trace Registrations do not use InstanceNames within REGGUIDW.
  2545. Therefore InstanceCount and InstanceNameList fields must be zero.
  2546. Arguments:
  2547. Buffer - WMIREGREQUEST to be validated
  2548. InBufferLen - Size of the incoming buffer
  2549. OutBufferLen - Size of the Output buffer
  2550. Return Value:
  2551. NT status code
  2552. --*/
  2553. {
  2554. HANDLE RequestHandle;
  2555. ULONG WmiRegInfoSize;
  2556. PWMIREGINFOW WmiRegInfo;
  2557. PWMIREGRESULTS WmiRegResults;
  2558. PWMIREGREQUEST WmiRegRequest;
  2559. PWMIREGINFOW WmiRegInfoThunk = NULL;
  2560. PWMIREGGUIDW WmiRegGuid;
  2561. ULONG GuidCount;
  2562. ULONG SizeNeeded;
  2563. ULONG ImageNameLength=0;
  2564. ULONG ResourceNameLength=0;
  2565. PUCHAR pSource;
  2566. ULONG i;
  2567. PAGED_CODE();
  2568. //
  2569. // Incoming Buffer must be atleast the sizeof WMIREGREQUEST + WMIREGINFO
  2570. //
  2571. if (InBufferLen >= (sizeof(WMIREGREQUEST) + sizeof(WMIREGINFO)))
  2572. {
  2573. WmiRegRequest = (PWMIREGREQUEST)Buffer;
  2574. WmiRegInfo = (PWMIREGINFOW) OffsetToPtr (Buffer, sizeof(WMIREGREQUEST));
  2575. WmiRegInfoSize = WmiRegInfo->BufferSize;
  2576. GuidCount = WmiRegRequest->GuidCount;
  2577. // We are rejecting any MOF notifications.
  2578. WmiRegInfo->RegistryPath = 0;
  2579. WmiRegInfo->MofResourceName = 0;
  2580. //
  2581. // BufferSize specified must be within the size of incoming Buffer.
  2582. //
  2583. if (WmiRegInfoSize <= (InBufferLen - sizeof(WMIREGREQUEST)) )
  2584. {
  2585. if ((GuidCount == 0) || (GuidCount > WMIMAXREGGUIDCOUNT))
  2586. {
  2587. return STATUS_UNSUCCESSFUL;
  2588. }
  2589. //
  2590. // Make sure the RegistryPath and MofResourceName offsets are
  2591. // within the REGINFO buffer.
  2592. //
  2593. if ( (WmiRegInfo->RegistryPath >= WmiRegInfoSize) ||
  2594. (WmiRegInfo->MofResourceName >= WmiRegInfoSize) ) {
  2595. return STATUS_UNSUCCESSFUL;
  2596. }
  2597. //
  2598. // Validate the Counted Strings.
  2599. //
  2600. if (WmiRegInfo->RegistryPath > 0)
  2601. {
  2602. //
  2603. // String Offsets need to be aligned to 2 Bytes
  2604. //
  2605. if (( WmiRegInfo->RegistryPath & 1) != 0)
  2606. {
  2607. return STATUS_UNSUCCESSFUL;
  2608. }
  2609. ImageNameLength = *((PUSHORT)OffsetToPtr(WmiRegInfo, WmiRegInfo->RegistryPath) );
  2610. ImageNameLength += sizeof(USHORT);
  2611. if ((WmiRegInfo->RegistryPath + ImageNameLength ) > WmiRegInfoSize)
  2612. {
  2613. return STATUS_UNSUCCESSFUL;
  2614. }
  2615. }
  2616. if (WmiRegInfo->MofResourceName > 0)
  2617. {
  2618. if ((WmiRegInfo->MofResourceName & 1) != 0)
  2619. {
  2620. return STATUS_UNSUCCESSFUL;
  2621. }
  2622. ResourceNameLength = *((PUSHORT)OffsetToPtr(WmiRegInfo, WmiRegInfo->MofResourceName));
  2623. ResourceNameLength += sizeof(USHORT);
  2624. if ( (WmiRegInfo->MofResourceName + ResourceNameLength) > WmiRegInfoSize)
  2625. {
  2626. return STATUS_UNSUCCESSFUL;
  2627. }
  2628. }
  2629. // Note: If the ImagePath and MofResource trample over each other but stayed
  2630. // within BufferSize , we will not catch it.
  2631. #if defined(_WIN64)
  2632. if (IoIs32bitProcess(NULL))
  2633. {
  2634. //
  2635. // Check to make sure the 32 bit structure sizes passed in
  2636. // by the caller is comparable to the 64-bit counterparts
  2637. //
  2638. if ((WmiRegRequest->WmiRegInfo32Size == 0) ||
  2639. (WmiRegRequest->WmiRegInfo32Size > sizeof(WMIREGINFOW)) )
  2640. {
  2641. return STATUS_UNSUCCESSFUL;
  2642. }
  2643. if ((WmiRegRequest->WmiRegGuid32Size == 0) ||
  2644. (WmiRegRequest->WmiRegGuid32Size > sizeof(WMIREGGUIDW)) )
  2645. {
  2646. return STATUS_UNSUCCESSFUL;
  2647. }
  2648. //
  2649. // InstanceCount and InstanceNameList in
  2650. // WMIREGGUIDW structure must be zero. This check is
  2651. // done after thunking gor WOW64.
  2652. //
  2653. SizeNeeded = WmiRegRequest->WmiRegInfo32Size +
  2654. GuidCount * WmiRegRequest->WmiRegGuid32Size +
  2655. ImageNameLength +
  2656. ResourceNameLength;
  2657. }
  2658. else
  2659. #endif
  2660. {
  2661. //
  2662. // Check to see if the InstanceCount and InstanceNameList in
  2663. // WMIREGGUIDW structure is zero
  2664. //
  2665. pSource = OffsetToPtr(WmiRegInfo, sizeof(WMIREGINFOW) );
  2666. for (i=0; i < GuidCount; i++) {
  2667. WmiRegGuid = (PWMIREGGUIDW) pSource;
  2668. if ( (WmiRegGuid->InstanceCount > 0) ||
  2669. (WmiRegGuid->InstanceNameList > 0) )
  2670. {
  2671. return STATUS_UNSUCCESSFUL;
  2672. }
  2673. pSource += sizeof(WMIREGGUIDW);
  2674. }
  2675. SizeNeeded = sizeof(WMIREGINFOW) +
  2676. GuidCount * sizeof(WMIREGGUIDW) +
  2677. ImageNameLength +
  2678. ResourceNameLength;
  2679. }
  2680. if (SizeNeeded > WmiRegInfoSize) {
  2681. return STATUS_UNSUCCESSFUL;
  2682. }
  2683. //
  2684. // Now validate the OutBuffer size needed
  2685. //
  2686. SizeNeeded = sizeof(TRACEGUIDMAP) * GuidCount + sizeof(WMIREGRESULTS);
  2687. if (SizeNeeded > OutBufferLen)
  2688. {
  2689. return STATUS_UNSUCCESSFUL;
  2690. }
  2691. //
  2692. // All tests passed. Return SUCCESS
  2693. //
  2694. return STATUS_SUCCESS;
  2695. }
  2696. }
  2697. return STATUS_UNSUCCESSFUL;
  2698. }