Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1319 lines
32 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. //
  519. // Compute packet size. We need to walk our buffer chain to do
  520. // this...
  521. //
  522. EventDatap->PacketSize = 0;
  523. PacketBuffer = Contextp->RecvBuffer;
  524. do
  525. {
  526. EventDatap->PacketSize += PacketBuffer->ipr_size;
  527. PacketBuffer = PacketBuffer->ipr_next;
  528. } while( NULL != PacketBuffer );
  529. if( NAT_PROTOCOL_TCP == Protocol || NAT_PROTOCOL_UDP == Protocol )
  530. {
  531. EventDatap->SourceIdentifier =
  532. ((PUSHORT)Contextp->ProtocolHeader)[0];
  533. EventDatap->DestinationIdentifier =
  534. ((PUSHORT)Contextp->ProtocolHeader)[1];
  535. if( NAT_PROTOCOL_TCP == Protocol )
  536. {
  537. EventDatap->ProtocolData1 =
  538. ((PTCP_HEADER)Contextp->ProtocolHeader)->SequenceNumber;
  539. EventDatap->ProtocolData2 =
  540. ((PTCP_HEADER)Contextp->ProtocolHeader)->AckNumber;
  541. EventDatap->ProtocolData3 =
  542. ((PTCP_HEADER)Contextp->ProtocolHeader)->WindowSize;
  543. EventDatap->ProtocolData4 =
  544. TCP_ALL_FLAGS( (PTCP_HEADER)Contextp->ProtocolHeader );
  545. }
  546. }
  547. else if( NAT_PROTOCOL_ICMP == Protocol )
  548. {
  549. EventDatap->ProtocolData1 =
  550. ((PICMP_HEADER)Contextp->ProtocolHeader)->Type;
  551. EventDatap->ProtocolData2 =
  552. ((PICMP_HEADER)Contextp->ProtocolHeader)->Code;
  553. }
  554. //
  555. // Fire the event. Since this is a trace event and not a standard
  556. // WMI event, IoWMIWriteEvent will not attempt to free the buffer
  557. // passed into it.
  558. //
  559. Status = IoWMIWriteEvent( Buffer );
  560. if( !NT_SUCCESS( Status ))
  561. {
  562. TRACE(
  563. WMI,
  564. ("NatLogDroppedPacket: IoWMIWriteEvent returned %08x\n", Status )
  565. );
  566. }
  567. Contextp->Flags |= NAT_XLATE_FLAG_LOGGED;
  568. }
  569. else
  570. {
  571. TRACE(WMI, ("NatLogDroppedPacket: No logging handle\n"));
  572. }
  573. } // NatLogDroppedPacket
  574. NTSTATUS
  575. NatpExecuteWmiMethod(
  576. IN PDEVICE_OBJECT DeviceObject,
  577. IN PIRP Irp,
  578. IN ULONG GuidIndex,
  579. IN ULONG InstanceIndex,
  580. IN ULONG MethodId,
  581. IN ULONG InBufferSize,
  582. IN ULONG OutBufferSize,
  583. IN PUCHAR Buffer
  584. )
  585. /*++
  586. Routine Description:
  587. This routine is a callback into the driver to execute a method. If
  588. the driver can complete the method within the callback it should
  589. call WmiCompleteRequest to complete the irp before returning to the
  590. caller. Or the driver can return STATUS_PENDING if the irp cannot be
  591. completed immediately and must then call WmiCompleteRequest once the
  592. data is changed.
  593. Arguments:
  594. DeviceObject is the device whose method is being executed
  595. Irp is the Irp that makes this request
  596. GuidIndex is the index into the list of guids provided when the
  597. device registered
  598. MethodId has the id of the method being called
  599. InBufferSize has the size of the data block passed in as the input to
  600. the method.
  601. OutBufferSize on entry has the maximum size available to write the
  602. returned data block.
  603. Buffer is filled with the input buffer on entry and returns with
  604. the output data block
  605. Return Value:
  606. status
  607. --*/
  608. {
  609. NTSTATUS status;
  610. PAGED_CODE();
  611. CALLTRACE(( "NatpExecuteWmiMethod\n" ));
  612. status = WmiCompleteRequest(
  613. DeviceObject,
  614. Irp,
  615. STATUS_WMI_GUID_NOT_FOUND,
  616. 0,
  617. IO_NO_INCREMENT
  618. );
  619. return status;
  620. } // NatpExecuteWmiMethod
  621. NTSTATUS
  622. NatpQueryWmiDataBlock(
  623. IN PDEVICE_OBJECT DeviceObject,
  624. IN PIRP Irp,
  625. IN ULONG GuidIndex,
  626. IN ULONG InstanceIndex,
  627. IN ULONG InstanceCount,
  628. IN OUT PULONG InstanceLengthArray,
  629. IN ULONG BufferAvail,
  630. OUT PUCHAR Buffer
  631. )
  632. /*++
  633. Routine Description:
  634. This routine is a callback into the driver to query for the contents of
  635. all instances of a data block. If the driver can satisfy the query within
  636. the callback it should call WmiCompleteRequest to complete the irp before
  637. returning to the caller. Or the driver can return STATUS_PENDING if the
  638. irp cannot be completed immediately and must then call WmiCompleteRequest
  639. once the query is satisfied.
  640. Arguments:
  641. DeviceObject is the device whose data block is being queried
  642. Irp is the Irp that makes this request
  643. GuidIndex is the index into the list of guids provided when the
  644. device registered
  645. InstanceCount is the number of instances expected to be returned for
  646. the data block.
  647. InstanceLengthArray is a pointer to an array of ULONG that returns the
  648. lengths of each instance of the data block. If this is NULL then
  649. there was not enough space in the output buffer to fufill the request
  650. so the irp should be completed with the buffer needed.
  651. BufferAvail on entry has the maximum size available to write the data
  652. blocks.
  653. Buffer on return is filled with the returned data blocks. Note that each
  654. instance of the data block must be aligned on a 8 byte boundry.
  655. Return Value:
  656. status
  657. --*/
  658. {
  659. NTSTATUS status;
  660. PAGED_CODE();
  661. CALLTRACE(( "NatpQueryWmiDataBlock\n" ));
  662. status = WmiCompleteRequest(
  663. DeviceObject,
  664. Irp,
  665. STATUS_WMI_GUID_NOT_FOUND,
  666. 0,
  667. IO_NO_INCREMENT
  668. );
  669. return status;
  670. } // NatpQueryWmiDataBlock
  671. NTSTATUS
  672. NatpQueryWmiRegInfo(
  673. IN PDEVICE_OBJECT DeviceObject,
  674. OUT ULONG *RegFlags,
  675. OUT PUNICODE_STRING InstanceName,
  676. OUT PUNICODE_STRING *RegistryPath,
  677. OUT PUNICODE_STRING MofResourceName,
  678. OUT PDEVICE_OBJECT *Pdo
  679. )
  680. /*++
  681. Routine Description:
  682. This routine is a callback into the driver to retrieve the list of
  683. guids or data blocks that the driver wants to register with WMI. This
  684. routine may not pend or block. Driver should NOT call
  685. WmiCompleteRequest.
  686. Arguments:
  687. DeviceObject is the device whose registration info is being queried
  688. *RegFlags returns with a set of flags that describe the guids being
  689. registered for this device. If the device wants enable and disable
  690. collection callbacks before receiving queries for the registered
  691. guids then it should return the WMIREG_FLAG_EXPENSIVE flag. Also the
  692. returned flags may specify WMIREG_FLAG_INSTANCE_PDO in which case
  693. the instance name is determined from the PDO associated with the
  694. device object. Note that the PDO must have an associated devnode. If
  695. WMIREG_FLAG_INSTANCE_PDO is not set then Name must return a unique
  696. name for the device.
  697. InstanceName returns with the instance name for the guids if
  698. WMIREG_FLAG_INSTANCE_PDO is not set in the returned *RegFlags. The
  699. caller will call ExFreePool with the buffer returned.
  700. *RegistryPath returns with the registry path of the driver. The caller
  701. does NOT free this buffer.
  702. *MofResourceName returns with the name of the MOF resource attached to
  703. the binary file. If the driver does not have a mof resource attached
  704. then this can be returned as NULL. The caller does NOT free this
  705. buffer.
  706. *Pdo returns with the device object for the PDO associated with this
  707. device if the WMIREG_FLAG_INSTANCE_PDO flag is retured in
  708. *RegFlags.
  709. Return Value:
  710. status
  711. --*/
  712. {
  713. PAGED_CODE();
  714. CALLTRACE(( "NatpQueryWmiRegInfo\n" ));
  715. //
  716. // Return the registry path for this driver. This is required so WMI
  717. // can find your driver image and can attribute any eventlog messages to
  718. // your driver.
  719. //
  720. *RegistryPath = &NatRegistryPath;
  721. //
  722. // Return the name specified in the .rc file of the resource which
  723. // contains the bianry mof data. By default WMI will look for this
  724. // resource in the driver image (.sys) file, however if the value
  725. // MofImagePath is specified in the driver's registry key
  726. // then WMI will look for the resource in the file specified there.
  727. //
  728. RtlInitUnicodeString(MofResourceName, IPNATMofResource);
  729. //
  730. // Tell WMI to generate instance names off of a static base name
  731. //
  732. *RegFlags = WMIREG_FLAG_INSTANCE_BASENAME;
  733. //
  734. // Set our base instance name. WmiLib will call ExFreePool on the buffer
  735. // of the string, so we need to allocate it from paged pool.
  736. //
  737. InstanceName->Length = wcslen( BaseInstanceName ) * sizeof( WCHAR );
  738. InstanceName->MaximumLength = InstanceName->Length + sizeof( UNICODE_NULL );
  739. InstanceName->Buffer = ExAllocatePoolWithTag(
  740. PagedPool,
  741. InstanceName->MaximumLength,
  742. NAT_TAG_WMI
  743. );
  744. if( NULL != InstanceName->Buffer )
  745. {
  746. RtlCopyMemory(
  747. InstanceName->Buffer,
  748. BaseInstanceName,
  749. InstanceName->Length
  750. );
  751. }
  752. else
  753. {
  754. ERROR(( "NAT: NatpQueryWmiRegInfo unable to allocate memory\n" ));
  755. return STATUS_NO_MEMORY;
  756. }
  757. return STATUS_SUCCESS;
  758. } // NatpQueryWmiRegInfo
  759. NTSTATUS
  760. NatpSetWmiDataBlock(
  761. IN PDEVICE_OBJECT DeviceObject,
  762. IN PIRP Irp,
  763. IN ULONG GuidIndex,
  764. IN ULONG InstanceIndex,
  765. IN ULONG BufferSize,
  766. IN PUCHAR Buffer
  767. )
  768. /*++
  769. Routine Description:
  770. This routine is a callback into the driver to change the contents of
  771. a data block. If the driver can change the data block within
  772. the callback it should call WmiCompleteRequest to complete the irp before
  773. returning to the caller. Or the driver can return STATUS_PENDING if the
  774. irp cannot be completed immediately and must then call WmiCompleteRequest
  775. once the data is changed.
  776. Arguments:
  777. DeviceObject is the device whose data block is being queried
  778. Irp is the Irp that makes this request
  779. GuidIndex is the index into the list of guids provided when the
  780. device registered
  781. BufferSize has the size of the data block passed
  782. Buffer has the new values for the data block
  783. Return Value:
  784. status
  785. --*/
  786. {
  787. NTSTATUS status;
  788. PAGED_CODE();
  789. CALLTRACE(( "NatpSetWmiDataBlock\n" ));
  790. status = WmiCompleteRequest(
  791. DeviceObject,
  792. Irp,
  793. STATUS_WMI_GUID_NOT_FOUND,
  794. 0,
  795. IO_NO_INCREMENT
  796. );
  797. return status;
  798. } // NatpSetWmiDataBlock
  799. NTSTATUS
  800. NatpSetWmiDataItem(
  801. IN PDEVICE_OBJECT DeviceObject,
  802. IN PIRP Irp,
  803. IN ULONG GuidIndex,
  804. IN ULONG InstanceIndex,
  805. IN ULONG DataItemId,
  806. IN ULONG BufferSize,
  807. IN PUCHAR Buffer
  808. )
  809. /*++
  810. Routine Description:
  811. This routine is a callback into the driver to change the contents of
  812. a data block. If the driver can change the data block within
  813. the callback it should call WmiCompleteRequest to complete the irp before
  814. returning to the caller. Or the driver can return STATUS_PENDING if the
  815. irp cannot be completed immediately and must then call WmiCompleteRequest
  816. once the data is changed.
  817. Arguments:
  818. DeviceObject is the device whose data block is being changed
  819. Irp is the Irp that makes this request
  820. GuidIndex is the index into the list of guids provided when the
  821. device registered
  822. DataItemId has the id of the data item being set
  823. BufferSize has the size of the data item passed
  824. Buffer has the new values for the data item
  825. Return Value:
  826. status
  827. --*/
  828. {
  829. NTSTATUS status;
  830. PAGED_CODE();
  831. CALLTRACE(( "NatpSetWmiDataItem\n" ));
  832. status = WmiCompleteRequest(
  833. DeviceObject,
  834. Irp,
  835. STATUS_WMI_GUID_NOT_FOUND,
  836. 0,
  837. IO_NO_INCREMENT
  838. );
  839. return status;
  840. } // NatpSetWmiDataItem
  841. NTSTATUS
  842. NatpWmiFunctionControl(
  843. IN PDEVICE_OBJECT DeviceObject,
  844. IN PIRP Irp,
  845. IN ULONG GuidIndex,
  846. IN WMIENABLEDISABLECONTROL Function,
  847. IN BOOLEAN Enable
  848. )
  849. /*++
  850. Routine Description:
  851. This routine is a callback into the driver to enabled or disable event
  852. generation or data block collection. A device should only expect a
  853. single enable when the first event or data consumer enables events or
  854. data collection and a single disable when the last event or data
  855. consumer disables events or data collection. Data blocks will only
  856. receive collection enable/disable if they were registered as requiring
  857. it. If the driver can complete enabling/disabling within the callback it
  858. should call WmiCompleteRequest to complete the irp before returning to
  859. the caller. Or the driver can return STATUS_PENDING if the irp cannot be
  860. completed immediately and must then call WmiCompleteRequest once the
  861. data is changed.
  862. Arguments:
  863. DeviceObject is the device object
  864. GuidIndex is the index into the list of guids provided when the
  865. device registered
  866. Function specifies which functionality is being enabled or disabled
  867. Enable is TRUE then the function is being enabled else disabled
  868. Return Value:
  869. status
  870. --*/
  871. {
  872. NTSTATUS status = STATUS_SUCCESS;
  873. PIO_STACK_LOCATION IrpSp;
  874. PUINT64 Loggerp;
  875. UINT64 Logger;
  876. KIRQL Irql;
  877. PAGED_CODE();
  878. CALLTRACE(( "NatpWmiFunctionControl\n" ));
  879. if( WmiEventControl == Function )
  880. {
  881. if( GuidIndex < NatWmiGuidCount )
  882. {
  883. if( Enable )
  884. {
  885. //
  886. // Get the logger handle from the Irp
  887. //
  888. IrpSp = IoGetCurrentIrpStackLocation( Irp );
  889. //
  890. // The logging handle is in the first UINT64 following the
  891. // WNODE header.
  892. //
  893. if( ((PWNODE_HEADER)IrpSp->Parameters.WMI.Buffer)->BufferSize
  894. >= sizeof(WNODE_HEADER) + sizeof(UINT64) )
  895. {
  896. Loggerp = (PUINT64) ((PUCHAR)IrpSp->Parameters.WMI.Buffer + sizeof(WNODE_HEADER));
  897. Logger = *Loggerp;
  898. }
  899. else
  900. {
  901. TRACE(WMI, ("NatpWmiFunctionControl: Wnode too small for logger handle\n"));
  902. Logger = 0;
  903. Enable = FALSE;
  904. }
  905. }
  906. else
  907. {
  908. Logger = 0;
  909. }
  910. KeAcquireSpinLock( &NatWmiLock, &Irql );
  911. NatWmiLogHandles[ GuidIndex ] = Logger;
  912. NatWmiEnabledEvents[ GuidIndex ] = (Enable ? 1 : 0);
  913. if( NAT_WMI_CONNECTION_CREATION_EVENT == GuidIndex )
  914. {
  915. //
  916. // NAT_WMI_CONNECTION_CREATION_EVENT is the control guid for
  917. // NAT_WMI_CONNECTION_DELETION_EVENT, so we also need to update
  918. // that latter's entry
  919. //
  920. NatWmiLogHandles[ NAT_WMI_CONNECTION_DELETION_EVENT ] = Logger;
  921. NatWmiEnabledEvents[ NAT_WMI_CONNECTION_DELETION_EVENT ] =
  922. (Enable ? 1 : 0);
  923. }
  924. KeReleaseSpinLock( &NatWmiLock, Irql );
  925. TRACE(
  926. WMI,
  927. ("NatpWmiFunctionControl: %s event %i; Logger = 0x%016x\n",
  928. (Enable ? "Enabled" : "Disabled"), GuidIndex, Logger ));
  929. }
  930. else
  931. {
  932. //
  933. // Invalid guid index.
  934. //
  935. status = STATUS_WMI_GUID_NOT_FOUND;
  936. TRACE( WMI, ( "NatpWmiFunctionControl: Invalid WMI guid %i",
  937. GuidIndex ));
  938. }
  939. }
  940. else
  941. {
  942. //
  943. // We currently don't have any (expensive) data blocks
  944. //
  945. status = STATUS_INVALID_DEVICE_REQUEST;
  946. }
  947. status = WmiCompleteRequest(
  948. DeviceObject,
  949. Irp,
  950. status,
  951. 0,
  952. IO_NO_INCREMENT
  953. );
  954. return status;
  955. } // NatpWmiFunctionControl
  956. VOID
  957. NatShutdownWMI(
  958. VOID
  959. )
  960. /*++
  961. Routine Description:
  962. This routine is called to shutdown WMI.
  963. Arguments:
  964. none.
  965. Return Value:
  966. none.
  967. --*/
  968. {
  969. NTSTATUS status;
  970. CALLTRACE(( "NatShutdownWMI\n" ));
  971. //
  972. // Deregister w/ WMI
  973. //
  974. status = IoWMIRegistrationControl(
  975. NatDeviceObject,
  976. WMIREG_ACTION_DEREGISTER
  977. );
  978. if( !NT_SUCCESS( status ))
  979. {
  980. ERROR(( "Nat: Error shutting down WMI (%08x)\n", status ));
  981. }
  982. } // NatShutdownWMI
  983. #endif