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.

1306 lines
33 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. wmi.c
  5. Abstract:
  6. This file contains the code for handling WMI requests.
  7. Author:
  8. Jonathan Burstein (jonburs) 24-Jan-2000
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. #if NAT_WMI
  14. //
  15. // Data structures for identifying the guids and reporting them to
  16. // WMI. Since the WMILIB callbacks pass an index into the guid list we make
  17. // definitions for the various guids indicies.
  18. //
  19. GUID ConnectionCreationEventGuid = MSIPNAT_ConnectionCreationEventGuid;
  20. GUID ConnectionDeletionEventGuid = MSIPNAT_ConnectionDeletionEventGuid;
  21. GUID PacketDroppedEventGuid = MSIPNAT_PacketDroppedEventGuid;
  22. WMIGUIDREGINFO NatWmiGuidList[] =
  23. {
  24. {
  25. &ConnectionCreationEventGuid,
  26. 1,
  27. WMIREG_FLAG_TRACED_GUID | WMIREG_FLAG_TRACE_CONTROL_GUID
  28. },
  29. {
  30. &ConnectionDeletionEventGuid,
  31. 1,
  32. WMIREG_FLAG_TRACED_GUID
  33. },
  34. {
  35. &PacketDroppedEventGuid,
  36. 1,
  37. WMIREG_FLAG_TRACED_GUID | WMIREG_FLAG_TRACE_CONTROL_GUID
  38. }
  39. };
  40. #define NatWmiGuidCount (sizeof(NatWmiGuidList) / sizeof(WMIGUIDREGINFO))
  41. //
  42. // Enabled events and associated log handles.
  43. //
  44. // NatWmiLogHandles should only be accessed while holding
  45. // NatWmiLock.
  46. //
  47. // NatWmiEnabledEvents should only be modified while holding
  48. // NatWmiLock. It may be read without holding the lock, according
  49. // to these rules:
  50. //
  51. // If NatWmiEnabledEvents[ Event ] is 0, the that event is definately
  52. // _not_ enabled, and there is no need to grab the spin lock.
  53. //
  54. // If NatWmiEnabledEvents[ Event ] is 1, the event _may_ be enabled.
  55. // To determine if the event is truly enabled, grab the spin lock and
  56. // see if NatWmiLogHandles[ Event ] is not 0.
  57. //
  58. LONG NatWmiEnabledEvents[ NatWmiGuidCount ];
  59. UINT64 NatWmiLogHandles[ NatWmiGuidCount ];
  60. KSPIN_LOCK NatWmiLock;
  61. //
  62. // Context block for WMILib routines
  63. //
  64. WMILIB_CONTEXT WmilibContext;
  65. //
  66. // MOF Resource Name
  67. //
  68. WCHAR IPNATMofResource[] = L"IPNATMofResource";
  69. //
  70. // WMI Base instance name
  71. //
  72. WCHAR BaseInstanceName[] = L"IPNat";
  73. //
  74. // Function Prototypes
  75. //
  76. NTSTATUS
  77. NatpWmiFunctionControl(
  78. IN PDEVICE_OBJECT DeviceObject,
  79. IN PIRP Irp,
  80. IN ULONG GuidIndex,
  81. IN WMIENABLEDISABLECONTROL Function,
  82. IN BOOLEAN Enable
  83. );
  84. NTSTATUS
  85. NatpExecuteWmiMethod(
  86. IN PDEVICE_OBJECT DeviceObject,
  87. IN PIRP Irp,
  88. IN ULONG GuidIndex,
  89. IN ULONG InstanceIndex,
  90. IN ULONG MethodId,
  91. IN ULONG InBufferSize,
  92. IN ULONG OutBufferSize,
  93. IN PUCHAR Buffer
  94. );
  95. NTSTATUS
  96. NatpSetWmiDataItem(
  97. IN PDEVICE_OBJECT DeviceObject,
  98. IN PIRP Irp,
  99. IN ULONG InstanceIndex,
  100. IN ULONG GuidIndex,
  101. IN ULONG DataItemId,
  102. IN ULONG BufferSize,
  103. IN PUCHAR Buffer
  104. );
  105. NTSTATUS
  106. NatpSetWmiDataBlock(
  107. IN PDEVICE_OBJECT DeviceObject,
  108. IN PIRP Irp,
  109. IN ULONG GuidIndex,
  110. IN ULONG InstanceIndex,
  111. IN ULONG BufferSize,
  112. IN PUCHAR Buffer
  113. );
  114. NTSTATUS
  115. NatpQueryWmiDataBlock(
  116. IN PDEVICE_OBJECT DeviceObject,
  117. IN PIRP Irp,
  118. IN ULONG GuidIndex,
  119. IN ULONG InstanceIndex,
  120. IN ULONG InstanceCount,
  121. IN OUT PULONG InstanceLengthArray,
  122. IN ULONG BufferAvail,
  123. OUT PUCHAR Buffer
  124. );
  125. NTSTATUS
  126. NatpQueryWmiRegInfo(
  127. IN PDEVICE_OBJECT DeviceObject,
  128. OUT ULONG *RegFlags,
  129. OUT PUNICODE_STRING InstanceName,
  130. OUT PUNICODE_STRING *RegistryPath,
  131. OUT PUNICODE_STRING MofResourceName,
  132. OUT PDEVICE_OBJECT *Pdo
  133. );
  134. #ifdef ALLOC_PRAGMA
  135. #pragma alloc_text(PAGE, NatpQueryWmiRegInfo)
  136. #pragma alloc_text(PAGE, NatpQueryWmiDataBlock)
  137. #pragma alloc_text(PAGE, NatpSetWmiDataBlock)
  138. #pragma alloc_text(PAGE, NatpSetWmiDataItem)
  139. #pragma alloc_text(PAGE, NatpExecuteWmiMethod)
  140. #pragma alloc_text(PAGE, NatpWmiFunctionControl)
  141. #endif
  142. NTSTATUS
  143. NatExecuteSystemControl(
  144. PDEVICE_OBJECT DeviceObject,
  145. PIRP Irp,
  146. PBOOLEAN ShouldComplete
  147. )
  148. /*++
  149. Routine Description:
  150. Dispatch routine for System Control IRPs (MajorFunction ==
  151. IRP_MJ_SYSTEM_CONTROL)
  152. Arguments:
  153. DeviceObject - The device object for the firewall
  154. Irp - Io Request Packet
  155. ShouldComplete - [out] true on exit if the IRP needs to be complete
  156. Return Value:
  157. NT status code
  158. --*/
  159. {
  160. NTSTATUS status;
  161. SYSCTL_IRP_DISPOSITION disposition;
  162. CALLTRACE(( "NatExecuteSystemControl\n" ));
  163. *ShouldComplete = FALSE;
  164. //
  165. // Call Wmilib helper function to crack the irp. If this is a wmi irp
  166. // that is targetted for this device then WmiSystemControl will callback
  167. // at the appropriate callback routine.
  168. //
  169. status = WmiSystemControl(
  170. &WmilibContext,
  171. DeviceObject,
  172. Irp,
  173. &disposition
  174. );
  175. switch(disposition)
  176. {
  177. case IrpProcessed:
  178. {
  179. //
  180. // This irp has been processed and may be completed or pending.
  181. //
  182. break;
  183. }
  184. case IrpNotCompleted:
  185. {
  186. //
  187. // This irp has not been completed, but has been fully processed.
  188. // so we need to complete it
  189. //
  190. *ShouldComplete = TRUE;
  191. break;
  192. }
  193. case IrpNotWmi:
  194. {
  195. //
  196. // Not an WMI IRP -- just complete it. We don't handle
  197. // IRP_MJ_SYSTEM_CONTROL in any other way
  198. //
  199. *ShouldComplete = TRUE;
  200. break;
  201. }
  202. case IrpForward:
  203. default:
  204. {
  205. //
  206. // We really should never get here...
  207. //
  208. ASSERT(FALSE);
  209. break;
  210. }
  211. }
  212. if( !NT_SUCCESS( status ))
  213. {
  214. ERROR(( "NAT: Error (%08x) in NatExecuteSystemControl\n", status ));
  215. }
  216. return status;
  217. } //NatExecuteSystemControl
  218. VOID
  219. NatInitializeWMI(
  220. VOID
  221. )
  222. /*++
  223. Routine Description:
  224. This routine is called to initialize WMI.
  225. Arguments:
  226. none.
  227. Return Value:
  228. none.
  229. --*/
  230. {
  231. NTSTATUS status;
  232. CALLTRACE(( "NatInitializeWMI\n" ));
  233. //
  234. // Initialize the spinlock that protects the structure below.
  235. //
  236. KeInitializeSpinLock( &NatWmiLock );
  237. //
  238. // Zero-out the event tracking structure
  239. //
  240. RtlZeroMemory( NatWmiEnabledEvents, sizeof( NatWmiEnabledEvents ));
  241. RtlZeroMemory( NatWmiLogHandles, sizeof( NatWmiLogHandles ));
  242. //
  243. // Fill in the WMILIB_CONTEXT structure with a pointer to the
  244. // callback routines and a pointer to the list of guids
  245. // supported by the driver
  246. //
  247. WmilibContext.GuidCount = NatWmiGuidCount;
  248. WmilibContext.GuidList = NatWmiGuidList;
  249. WmilibContext.QueryWmiRegInfo = NatpQueryWmiRegInfo;
  250. WmilibContext.QueryWmiDataBlock = NatpQueryWmiDataBlock;
  251. WmilibContext.SetWmiDataBlock = NatpSetWmiDataBlock;
  252. WmilibContext.SetWmiDataItem = NatpSetWmiDataItem;
  253. WmilibContext.ExecuteWmiMethod = NatpExecuteWmiMethod;
  254. WmilibContext.WmiFunctionControl = NatpWmiFunctionControl;
  255. //
  256. // Register w/ WMI
  257. //
  258. status = IoWMIRegistrationControl(
  259. NatDeviceObject,
  260. WMIREG_ACTION_REGISTER
  261. );
  262. if( !NT_SUCCESS( status ))
  263. {
  264. ERROR(( "Nat: Error initializing WMI (%08x)\n", status ));
  265. }
  266. } // NatInitializeWMI
  267. VOID
  268. FASTCALL
  269. NatLogConnectionCreation(
  270. ULONG LocalAddress,
  271. ULONG RemoteAddress,
  272. USHORT LocalPort,
  273. USHORT RemotePort,
  274. UCHAR Protocol,
  275. BOOLEAN InboundConnection
  276. )
  277. /*++
  278. Routine Description:
  279. This routine is called to log the creation of a TCP/UDP connection
  280. (mapping). If this event is not enabled, no action is taken.
  281. Arguments:
  282. Return Value:
  283. none.
  284. --*/
  285. {
  286. NTSTATUS Status;
  287. KIRQL Irql;
  288. UINT64 Logger;
  289. ULONG Size;
  290. UCHAR Buffer[ sizeof(EVENT_TRACE_HEADER) + sizeof(MSIPNAT_ConnectionCreationEvent) ];
  291. PEVENT_TRACE_HEADER EventHeaderp;
  292. PMSIPNAT_ConnectionCreationEvent EventDatap;
  293. CALLTRACE(( "NatLogConnectionCreation\n" ));
  294. if( !NatWmiEnabledEvents[ NAT_WMI_CONNECTION_CREATION_EVENT ] )
  295. {
  296. //
  297. // Event not enabled -- exit quickly.
  298. //
  299. TRACE(WMI, ("NatLogConnectionCreation: Event not enabled\n"));
  300. return;
  301. }
  302. KeAcquireSpinLock( &NatWmiLock, &Irql );
  303. Logger = NatWmiLogHandles[ NAT_WMI_CONNECTION_CREATION_EVENT ];
  304. KeReleaseSpinLock( &NatWmiLock, Irql );
  305. if( Logger )
  306. {
  307. //
  308. // Zero out the buffer
  309. //
  310. RtlZeroMemory( Buffer, sizeof( Buffer ));
  311. //
  312. // Locate structure locations within the buffer
  313. //
  314. EventHeaderp = (PEVENT_TRACE_HEADER) Buffer;
  315. EventDatap =
  316. (PMSIPNAT_ConnectionCreationEvent) ((PUCHAR)Buffer + sizeof(EVENT_TRACE_HEADER));
  317. //
  318. // Fill out the event header
  319. //
  320. EventHeaderp->Size = sizeof( Buffer );
  321. EventHeaderp->Version = 0;
  322. EventHeaderp->GuidPtr = (ULONGLONG) &ConnectionCreationEventGuid;
  323. EventHeaderp->Flags = WNODE_FLAG_TRACED_GUID
  324. | WNODE_FLAG_USE_GUID_PTR
  325. | WNODE_FLAG_USE_TIMESTAMP;
  326. ((PWNODE_HEADER)EventHeaderp)->HistoricalContext = Logger;
  327. KeQuerySystemTime( &EventHeaderp->TimeStamp );
  328. //
  329. // Fill out event data
  330. //
  331. EventDatap->LocalAddress = LocalAddress;
  332. EventDatap->RemoteAddress = RemoteAddress,
  333. EventDatap->LocalPort = LocalPort;
  334. EventDatap->RemotePort = RemotePort;
  335. EventDatap->Protocol = Protocol;
  336. EventDatap->InboundConnection = InboundConnection;
  337. //
  338. // Fire the event. Since this is a trace event and not a standard
  339. // WMI event, IoWMIWriteEvent will not attempt to free the buffer
  340. // passed into it.
  341. //
  342. Status = IoWMIWriteEvent( Buffer );
  343. if( !NT_SUCCESS( Status ))
  344. {
  345. TRACE(
  346. WMI,
  347. ("NatLogConnectionCreation: IoWMIWriteEvent returned %08x\n", Status )
  348. );
  349. }
  350. }
  351. else
  352. {
  353. TRACE(WMI, ("NatLogConnectionCreation: No logging handle\n"));
  354. }
  355. } // NatLogConnectionCreation
  356. VOID
  357. FASTCALL
  358. NatLogConnectionDeletion(
  359. ULONG LocalAddress,
  360. ULONG RemoteAddress,
  361. USHORT LocalPort,
  362. USHORT RemotePort,
  363. UCHAR Protocol,
  364. BOOLEAN InboundConnection
  365. )
  366. /*++
  367. Routine Description:
  368. This routine is called to log the deletion of a TCP/UDP connection
  369. (mapping). If this event is not enabled, no action is taken.
  370. Arguments:
  371. Return Value:
  372. none.
  373. --*/
  374. {
  375. NTSTATUS Status;
  376. KIRQL Irql;
  377. UINT64 Logger;
  378. ULONG Size;
  379. UCHAR Buffer[ sizeof(EVENT_TRACE_HEADER) + sizeof(MSIPNAT_ConnectionDeletionEvent) ];
  380. PEVENT_TRACE_HEADER EventHeaderp;
  381. PMSIPNAT_ConnectionDeletionEvent EventDatap;
  382. CALLTRACE(( "NatLogConnectionDeletion\n" ));
  383. if( !NatWmiEnabledEvents[ NAT_WMI_CONNECTION_DELETION_EVENT ] )
  384. {
  385. //
  386. // Event not enabled -- exit quickly.
  387. //
  388. TRACE(WMI, ("NatLogConnectionDeletion: Event not enabled\n"));
  389. return;
  390. }
  391. KeAcquireSpinLock( &NatWmiLock, &Irql );
  392. Logger = NatWmiLogHandles[ NAT_WMI_CONNECTION_DELETION_EVENT ];
  393. KeReleaseSpinLock( &NatWmiLock, Irql );
  394. if( Logger )
  395. {
  396. //
  397. // Zero out the buffer
  398. //
  399. RtlZeroMemory( Buffer, sizeof( Buffer ));
  400. //
  401. // Locate structure locations within the buffer
  402. //
  403. EventHeaderp = (PEVENT_TRACE_HEADER) Buffer;
  404. EventDatap =
  405. (PMSIPNAT_ConnectionDeletionEvent) ((PUCHAR)Buffer + sizeof(EVENT_TRACE_HEADER));
  406. //
  407. // Fill out the event header
  408. //
  409. EventHeaderp->Size = sizeof( Buffer );
  410. EventHeaderp->Version = 0;
  411. EventHeaderp->GuidPtr = (ULONGLONG) &ConnectionDeletionEventGuid;
  412. EventHeaderp->Flags = WNODE_FLAG_TRACED_GUID
  413. | WNODE_FLAG_USE_GUID_PTR
  414. | WNODE_FLAG_USE_TIMESTAMP;
  415. ((PWNODE_HEADER)EventHeaderp)->HistoricalContext = Logger;
  416. KeQuerySystemTime( &EventHeaderp->TimeStamp );
  417. //
  418. // Fill out event data
  419. //
  420. EventDatap->LocalAddress = LocalAddress;
  421. EventDatap->RemoteAddress = RemoteAddress,
  422. EventDatap->LocalPort = LocalPort;
  423. EventDatap->RemotePort = RemotePort;
  424. EventDatap->Protocol = Protocol;
  425. EventDatap->InboundConnection = InboundConnection;
  426. //
  427. // Fire the event. Since this is a trace event and not a standard
  428. // WMI event, IoWMIWriteEvent will not attempt to free the buffer
  429. // passed into it.
  430. //
  431. Status = IoWMIWriteEvent( Buffer );
  432. if( !NT_SUCCESS( Status ))
  433. {
  434. TRACE(
  435. WMI,
  436. ("NatLogConnectionDeletion: IoWMIWriteEvent returned %08x\n", Status )
  437. );
  438. }
  439. }
  440. else
  441. {
  442. TRACE(WMI, ("NatLogConnectionDeletion: No logging handle\n"));
  443. }
  444. } // NatLogConnectionDeletion
  445. VOID
  446. FASTCALL
  447. NatLogDroppedPacket(
  448. NAT_XLATE_CONTEXT *Contextp
  449. )
  450. /*++
  451. Routine Description:
  452. This routine is called to log a dropped packet. If no packet dropped
  453. logging events are enabled, the routine will take no action.
  454. Arguments:
  455. Contextp - the translation context of the packet
  456. Return Value:
  457. none.
  458. --*/
  459. {
  460. NTSTATUS Status;
  461. KIRQL Irql;
  462. UINT64 Logger;
  463. ULONG Size;
  464. IPRcvBuf *PacketBuffer;
  465. UCHAR Protocol;
  466. UCHAR Buffer[ sizeof(EVENT_TRACE_HEADER) + sizeof(MSIPNAT_PacketDroppedEvent) ];
  467. PEVENT_TRACE_HEADER EventHeaderp;
  468. PMSIPNAT_PacketDroppedEvent EventDatap;
  469. CALLTRACE(( "NatLogDroppedPacket\n" ));
  470. if( !NatWmiEnabledEvents[ NAT_WMI_PACKET_DROPPED_EVENT ] )
  471. {
  472. //
  473. // Event not enabled -- exit quickly.
  474. //
  475. TRACE(WMI, ("NatLogDroppedPacket: Event not enabled\n"));
  476. return;
  477. }
  478. //
  479. // Exit if this packet has already been logged
  480. //
  481. if( NAT_XLATE_LOGGED( Contextp ))
  482. {
  483. TRACE( WMI, ("NatLogDroppedPacket: Duplicate dropped packet log attemp\n" ));
  484. return;
  485. }
  486. KeAcquireSpinLock( &NatWmiLock, &Irql );
  487. Logger = NatWmiLogHandles[ NAT_WMI_PACKET_DROPPED_EVENT ];
  488. KeReleaseSpinLock( &NatWmiLock, Irql );
  489. if( Logger )
  490. {
  491. //
  492. // Zero out the buffer
  493. //
  494. RtlZeroMemory( Buffer, sizeof( Buffer ));
  495. //
  496. // Locate structure locations within the buffer
  497. //
  498. EventHeaderp = (PEVENT_TRACE_HEADER) Buffer;
  499. EventDatap = (PMSIPNAT_PacketDroppedEvent) ((PUCHAR)Buffer + sizeof(EVENT_TRACE_HEADER));
  500. //
  501. // Fill out the event header
  502. //
  503. EventHeaderp->Size = sizeof( Buffer );
  504. EventHeaderp->Version = 0;
  505. EventHeaderp->GuidPtr = (ULONGLONG) &PacketDroppedEventGuid;
  506. EventHeaderp->Flags = WNODE_FLAG_TRACED_GUID
  507. | WNODE_FLAG_USE_GUID_PTR
  508. | WNODE_FLAG_USE_TIMESTAMP;
  509. ((PWNODE_HEADER)EventHeaderp)->HistoricalContext = Logger;
  510. KeQuerySystemTime( &EventHeaderp->TimeStamp );
  511. //
  512. // Fill out event data
  513. //
  514. Protocol = Contextp->Header->Protocol;
  515. EventDatap->SourceAddress = Contextp->SourceAddress;
  516. EventDatap->DestinationAddress = Contextp->DestinationAddress;
  517. EventDatap->Protocol = Protocol;
  518. EventDatap->PacketSize = NTOHS(Contextp->Header->TotalLength);
  519. if( NAT_PROTOCOL_TCP == Protocol || NAT_PROTOCOL_UDP == Protocol )
  520. {
  521. EventDatap->SourceIdentifier =
  522. ((PUSHORT)Contextp->ProtocolHeader)[0];
  523. EventDatap->DestinationIdentifier =
  524. ((PUSHORT)Contextp->ProtocolHeader)[1];
  525. if( NAT_PROTOCOL_TCP == Protocol )
  526. {
  527. EventDatap->ProtocolData1 =
  528. ((PTCP_HEADER)Contextp->ProtocolHeader)->SequenceNumber;
  529. EventDatap->ProtocolData2 =
  530. ((PTCP_HEADER)Contextp->ProtocolHeader)->AckNumber;
  531. EventDatap->ProtocolData3 =
  532. ((PTCP_HEADER)Contextp->ProtocolHeader)->WindowSize;
  533. EventDatap->ProtocolData4 =
  534. TCP_ALL_FLAGS( (PTCP_HEADER)Contextp->ProtocolHeader );
  535. }
  536. }
  537. else if( NAT_PROTOCOL_ICMP == Protocol )
  538. {
  539. EventDatap->ProtocolData1 =
  540. ((PICMP_HEADER)Contextp->ProtocolHeader)->Type;
  541. EventDatap->ProtocolData2 =
  542. ((PICMP_HEADER)Contextp->ProtocolHeader)->Code;
  543. }
  544. //
  545. // Fire the event. Since this is a trace event and not a standard
  546. // WMI event, IoWMIWriteEvent will not attempt to free the buffer
  547. // passed into it.
  548. //
  549. Status = IoWMIWriteEvent( Buffer );
  550. if( !NT_SUCCESS( Status ))
  551. {
  552. TRACE(
  553. WMI,
  554. ("NatLogDroppedPacket: IoWMIWriteEvent returned %08x\n", Status )
  555. );
  556. }
  557. Contextp->Flags |= NAT_XLATE_FLAG_LOGGED;
  558. }
  559. else
  560. {
  561. TRACE(WMI, ("NatLogDroppedPacket: No logging handle\n"));
  562. }
  563. } // NatLogDroppedPacket
  564. NTSTATUS
  565. NatpExecuteWmiMethod(
  566. IN PDEVICE_OBJECT DeviceObject,
  567. IN PIRP Irp,
  568. IN ULONG GuidIndex,
  569. IN ULONG InstanceIndex,
  570. IN ULONG MethodId,
  571. IN ULONG InBufferSize,
  572. IN ULONG OutBufferSize,
  573. IN PUCHAR Buffer
  574. )
  575. /*++
  576. Routine Description:
  577. This routine is a callback into the driver to execute a method. If
  578. the driver can complete the method within the callback it should
  579. call WmiCompleteRequest to complete the irp before returning to the
  580. caller. Or the driver can return STATUS_PENDING if the irp cannot be
  581. completed immediately and must then call WmiCompleteRequest once the
  582. data is changed.
  583. Arguments:
  584. DeviceObject is the device whose method is being executed
  585. Irp is the Irp that makes this request
  586. GuidIndex is the index into the list of guids provided when the
  587. device registered
  588. MethodId has the id of the method being called
  589. InBufferSize has the size of the data block passed in as the input to
  590. the method.
  591. OutBufferSize on entry has the maximum size available to write the
  592. returned data block.
  593. Buffer is filled with the input buffer on entry and returns with
  594. the output data block
  595. Return Value:
  596. status
  597. --*/
  598. {
  599. NTSTATUS status;
  600. PAGED_CODE();
  601. CALLTRACE(( "NatpExecuteWmiMethod\n" ));
  602. status = WmiCompleteRequest(
  603. DeviceObject,
  604. Irp,
  605. STATUS_WMI_GUID_NOT_FOUND,
  606. 0,
  607. IO_NO_INCREMENT
  608. );
  609. return status;
  610. } // NatpExecuteWmiMethod
  611. NTSTATUS
  612. NatpQueryWmiDataBlock(
  613. IN PDEVICE_OBJECT DeviceObject,
  614. IN PIRP Irp,
  615. IN ULONG GuidIndex,
  616. IN ULONG InstanceIndex,
  617. IN ULONG InstanceCount,
  618. IN OUT PULONG InstanceLengthArray,
  619. IN ULONG BufferAvail,
  620. OUT PUCHAR Buffer
  621. )
  622. /*++
  623. Routine Description:
  624. This routine is a callback into the driver to query for the contents of
  625. all instances of a data block. If the driver can satisfy the query within
  626. the callback it should call WmiCompleteRequest to complete the irp before
  627. returning to the caller. Or the driver can return STATUS_PENDING if the
  628. irp cannot be completed immediately and must then call WmiCompleteRequest
  629. once the query is satisfied.
  630. Arguments:
  631. DeviceObject is the device whose data block is being queried
  632. Irp is the Irp that makes this request
  633. GuidIndex is the index into the list of guids provided when the
  634. device registered
  635. InstanceCount is the number of instances expected to be returned for
  636. the data block.
  637. InstanceLengthArray is a pointer to an array of ULONG that returns the
  638. lengths of each instance of the data block. If this is NULL then
  639. there was not enough space in the output buffer to fufill the request
  640. so the irp should be completed with the buffer needed.
  641. BufferAvail on entry has the maximum size available to write the data
  642. blocks.
  643. Buffer on return is filled with the returned data blocks. Note that each
  644. instance of the data block must be aligned on a 8 byte boundry.
  645. Return Value:
  646. status
  647. --*/
  648. {
  649. NTSTATUS status;
  650. PAGED_CODE();
  651. CALLTRACE(( "NatpQueryWmiDataBlock\n" ));
  652. status = WmiCompleteRequest(
  653. DeviceObject,
  654. Irp,
  655. STATUS_WMI_GUID_NOT_FOUND,
  656. 0,
  657. IO_NO_INCREMENT
  658. );
  659. return status;
  660. } // NatpQueryWmiDataBlock
  661. NTSTATUS
  662. NatpQueryWmiRegInfo(
  663. IN PDEVICE_OBJECT DeviceObject,
  664. OUT ULONG *RegFlags,
  665. OUT PUNICODE_STRING InstanceName,
  666. OUT PUNICODE_STRING *RegistryPath,
  667. OUT PUNICODE_STRING MofResourceName,
  668. OUT PDEVICE_OBJECT *Pdo
  669. )
  670. /*++
  671. Routine Description:
  672. This routine is a callback into the driver to retrieve the list of
  673. guids or data blocks that the driver wants to register with WMI. This
  674. routine may not pend or block. Driver should NOT call
  675. WmiCompleteRequest.
  676. Arguments:
  677. DeviceObject is the device whose registration info is being queried
  678. *RegFlags returns with a set of flags that describe the guids being
  679. registered for this device. If the device wants enable and disable
  680. collection callbacks before receiving queries for the registered
  681. guids then it should return the WMIREG_FLAG_EXPENSIVE flag. Also the
  682. returned flags may specify WMIREG_FLAG_INSTANCE_PDO in which case
  683. the instance name is determined from the PDO associated with the
  684. device object. Note that the PDO must have an associated devnode. If
  685. WMIREG_FLAG_INSTANCE_PDO is not set then Name must return a unique
  686. name for the device.
  687. InstanceName returns with the instance name for the guids if
  688. WMIREG_FLAG_INSTANCE_PDO is not set in the returned *RegFlags. The
  689. caller will call ExFreePool with the buffer returned.
  690. *RegistryPath returns with the registry path of the driver. The caller
  691. does NOT free this buffer.
  692. *MofResourceName returns with the name of the MOF resource attached to
  693. the binary file. If the driver does not have a mof resource attached
  694. then this can be returned as NULL. The caller does NOT free this
  695. buffer.
  696. *Pdo returns with the device object for the PDO associated with this
  697. device if the WMIREG_FLAG_INSTANCE_PDO flag is retured in
  698. *RegFlags.
  699. Return Value:
  700. status
  701. --*/
  702. {
  703. PAGED_CODE();
  704. CALLTRACE(( "NatpQueryWmiRegInfo\n" ));
  705. //
  706. // Return the registry path for this driver. This is required so WMI
  707. // can find your driver image and can attribute any eventlog messages to
  708. // your driver.
  709. //
  710. *RegistryPath = &NatRegistryPath;
  711. //
  712. // Return the name specified in the .rc file of the resource which
  713. // contains the bianry mof data. By default WMI will look for this
  714. // resource in the driver image (.sys) file, however if the value
  715. // MofImagePath is specified in the driver's registry key
  716. // then WMI will look for the resource in the file specified there.
  717. //
  718. RtlInitUnicodeString(MofResourceName, IPNATMofResource);
  719. //
  720. // Tell WMI to generate instance names off of a static base name
  721. //
  722. *RegFlags = WMIREG_FLAG_INSTANCE_BASENAME;
  723. //
  724. // Set our base instance name. WmiLib will call ExFreePool on the buffer
  725. // of the string, so we need to allocate it from paged pool.
  726. //
  727. InstanceName->Length = wcslen( BaseInstanceName ) * sizeof( WCHAR );
  728. InstanceName->MaximumLength = InstanceName->Length + sizeof( UNICODE_NULL );
  729. InstanceName->Buffer = ExAllocatePoolWithTag(
  730. PagedPool,
  731. InstanceName->MaximumLength,
  732. NAT_TAG_WMI
  733. );
  734. if( NULL != InstanceName->Buffer )
  735. {
  736. RtlCopyMemory(
  737. InstanceName->Buffer,
  738. BaseInstanceName,
  739. InstanceName->Length
  740. );
  741. }
  742. else
  743. {
  744. ERROR(( "NAT: NatpQueryWmiRegInfo unable to allocate memory\n" ));
  745. return STATUS_NO_MEMORY;
  746. }
  747. return STATUS_SUCCESS;
  748. } // NatpQueryWmiRegInfo
  749. NTSTATUS
  750. NatpSetWmiDataBlock(
  751. IN PDEVICE_OBJECT DeviceObject,
  752. IN PIRP Irp,
  753. IN ULONG GuidIndex,
  754. IN ULONG InstanceIndex,
  755. IN ULONG BufferSize,
  756. IN PUCHAR Buffer
  757. )
  758. /*++
  759. Routine Description:
  760. This routine is a callback into the driver to change the contents of
  761. a data block. If the driver can change the data block within
  762. the callback it should call WmiCompleteRequest to complete the irp before
  763. returning to the caller. Or the driver can return STATUS_PENDING if the
  764. irp cannot be completed immediately and must then call WmiCompleteRequest
  765. once the data is changed.
  766. Arguments:
  767. DeviceObject is the device whose data block is being queried
  768. Irp is the Irp that makes this request
  769. GuidIndex is the index into the list of guids provided when the
  770. device registered
  771. BufferSize has the size of the data block passed
  772. Buffer has the new values for the data block
  773. Return Value:
  774. status
  775. --*/
  776. {
  777. NTSTATUS status;
  778. PAGED_CODE();
  779. CALLTRACE(( "NatpSetWmiDataBlock\n" ));
  780. status = WmiCompleteRequest(
  781. DeviceObject,
  782. Irp,
  783. STATUS_WMI_GUID_NOT_FOUND,
  784. 0,
  785. IO_NO_INCREMENT
  786. );
  787. return status;
  788. } // NatpSetWmiDataBlock
  789. NTSTATUS
  790. NatpSetWmiDataItem(
  791. IN PDEVICE_OBJECT DeviceObject,
  792. IN PIRP Irp,
  793. IN ULONG GuidIndex,
  794. IN ULONG InstanceIndex,
  795. IN ULONG DataItemId,
  796. IN ULONG BufferSize,
  797. IN PUCHAR Buffer
  798. )
  799. /*++
  800. Routine Description:
  801. This routine is a callback into the driver to change the contents of
  802. a data block. If the driver can change the data block within
  803. the callback it should call WmiCompleteRequest to complete the irp before
  804. returning to the caller. Or the driver can return STATUS_PENDING if the
  805. irp cannot be completed immediately and must then call WmiCompleteRequest
  806. once the data is changed.
  807. Arguments:
  808. DeviceObject is the device whose data block is being changed
  809. Irp is the Irp that makes this request
  810. GuidIndex is the index into the list of guids provided when the
  811. device registered
  812. DataItemId has the id of the data item being set
  813. BufferSize has the size of the data item passed
  814. Buffer has the new values for the data item
  815. Return Value:
  816. status
  817. --*/
  818. {
  819. NTSTATUS status;
  820. PAGED_CODE();
  821. CALLTRACE(( "NatpSetWmiDataItem\n" ));
  822. status = WmiCompleteRequest(
  823. DeviceObject,
  824. Irp,
  825. STATUS_WMI_GUID_NOT_FOUND,
  826. 0,
  827. IO_NO_INCREMENT
  828. );
  829. return status;
  830. } // NatpSetWmiDataItem
  831. NTSTATUS
  832. NatpWmiFunctionControl(
  833. IN PDEVICE_OBJECT DeviceObject,
  834. IN PIRP Irp,
  835. IN ULONG GuidIndex,
  836. IN WMIENABLEDISABLECONTROL Function,
  837. IN BOOLEAN Enable
  838. )
  839. /*++
  840. Routine Description:
  841. This routine is a callback into the driver to enabled or disable event
  842. generation or data block collection. A device should only expect a
  843. single enable when the first event or data consumer enables events or
  844. data collection and a single disable when the last event or data
  845. consumer disables events or data collection. Data blocks will only
  846. receive collection enable/disable if they were registered as requiring
  847. it. If the driver can complete enabling/disabling within the callback it
  848. should call WmiCompleteRequest to complete the irp before returning to
  849. the caller. Or the driver can return STATUS_PENDING if the irp cannot be
  850. completed immediately and must then call WmiCompleteRequest once the
  851. data is changed.
  852. Arguments:
  853. DeviceObject is the device object
  854. GuidIndex is the index into the list of guids provided when the
  855. device registered
  856. Function specifies which functionality is being enabled or disabled
  857. Enable is TRUE then the function is being enabled else disabled
  858. Return Value:
  859. status
  860. --*/
  861. {
  862. NTSTATUS status = STATUS_SUCCESS;
  863. PIO_STACK_LOCATION IrpSp;
  864. PUINT64 Loggerp;
  865. UINT64 Logger;
  866. KIRQL Irql;
  867. PAGED_CODE();
  868. CALLTRACE(( "NatpWmiFunctionControl\n" ));
  869. if( WmiEventControl == Function )
  870. {
  871. if( GuidIndex < NatWmiGuidCount )
  872. {
  873. if( Enable )
  874. {
  875. //
  876. // Get the logger handle from the Irp
  877. //
  878. IrpSp = IoGetCurrentIrpStackLocation( Irp );
  879. //
  880. // The logging handle is in the first UINT64 following the
  881. // WNODE header.
  882. //
  883. if( ((PWNODE_HEADER)IrpSp->Parameters.WMI.Buffer)->BufferSize
  884. >= sizeof(WNODE_HEADER) + sizeof(UINT64) )
  885. {
  886. Loggerp = (PUINT64) ((PUCHAR)IrpSp->Parameters.WMI.Buffer + sizeof(WNODE_HEADER));
  887. Logger = *Loggerp;
  888. }
  889. else
  890. {
  891. TRACE(WMI, ("NatpWmiFunctionControl: Wnode too small for logger handle\n"));
  892. Logger = 0;
  893. Enable = FALSE;
  894. }
  895. }
  896. else
  897. {
  898. Logger = 0;
  899. }
  900. KeAcquireSpinLock( &NatWmiLock, &Irql );
  901. NatWmiLogHandles[ GuidIndex ] = Logger;
  902. NatWmiEnabledEvents[ GuidIndex ] = (Enable ? 1 : 0);
  903. if( NAT_WMI_CONNECTION_CREATION_EVENT == GuidIndex )
  904. {
  905. //
  906. // NAT_WMI_CONNECTION_CREATION_EVENT is the control guid for
  907. // NAT_WMI_CONNECTION_DELETION_EVENT, so we also need to update
  908. // that latter's entry
  909. //
  910. NatWmiLogHandles[ NAT_WMI_CONNECTION_DELETION_EVENT ] = Logger;
  911. NatWmiEnabledEvents[ NAT_WMI_CONNECTION_DELETION_EVENT ] =
  912. (Enable ? 1 : 0);
  913. }
  914. KeReleaseSpinLock( &NatWmiLock, Irql );
  915. TRACE(
  916. WMI,
  917. ("NatpWmiFunctionControl: %s event %i; Logger = 0x%016x\n",
  918. (Enable ? "Enabled" : "Disabled"), GuidIndex, Logger ));
  919. }
  920. else
  921. {
  922. //
  923. // Invalid guid index.
  924. //
  925. status = STATUS_WMI_GUID_NOT_FOUND;
  926. TRACE( WMI, ( "NatpWmiFunctionControl: Invalid WMI guid %i",
  927. GuidIndex ));
  928. }
  929. }
  930. else
  931. {
  932. //
  933. // We currently don't have any (expensive) data blocks
  934. //
  935. status = STATUS_INVALID_DEVICE_REQUEST;
  936. }
  937. status = WmiCompleteRequest(
  938. DeviceObject,
  939. Irp,
  940. status,
  941. 0,
  942. IO_NO_INCREMENT
  943. );
  944. return status;
  945. } // NatpWmiFunctionControl
  946. VOID
  947. NatShutdownWMI(
  948. VOID
  949. )
  950. /*++
  951. Routine Description:
  952. This routine is called to shutdown WMI.
  953. Arguments:
  954. none.
  955. Return Value:
  956. none.
  957. --*/
  958. {
  959. NTSTATUS status;
  960. CALLTRACE(( "NatShutdownWMI\n" ));
  961. //
  962. // Deregister w/ WMI
  963. //
  964. status = IoWMIRegistrationControl(
  965. NatDeviceObject,
  966. WMIREG_ACTION_DEREGISTER
  967. );
  968. if( !NT_SUCCESS( status ))
  969. {
  970. ERROR(( "Nat: Error shutting down WMI (%08x)\n", status ));
  971. }
  972. } // NatShutdownWMI
  973. #endif