Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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