1 /*++
2 
3 Copyright (c) Microsoft Corporation
4 
5 Module Name:
6 
7     FxQueryInterface.cpp
8 
9 Abstract:
10 
11     This module implements the device interface object.
12 
13 Author:
14 
15 
16 
17 Environment:
18 
19     Kernel mode only
20 
21 Revision History:
22 
23 --*/
24 
25 #include "fxsupportpch.hpp"
26 
27 extern "C" {
28 // #include "FxQueryInterface.tmh"
29 }
30 
31 FxQueryInterface::FxQueryInterface(
32     __in FxDevice* Device,
33     __in PWDF_QUERY_INTERFACE_CONFIG Config
34     ) :
35     m_Device(Device),
36     m_Interface(NULL)
37 {
38     m_Entry.Next = NULL;
39 
40     m_EmbeddedInterface = FALSE;
41 
42     if (Config != NULL) {
43         m_SendQueryToParentStack = Config->SendQueryToParentStack;
44         m_ImportInterface = Config->ImportInterface;
45         m_ProcessRequest.m_Method = Config->EvtDeviceProcessQueryInterfaceRequest;
46         RtlCopyMemory(&m_InterfaceType, Config->InterfaceType, sizeof(GUID));
47     }
48 }
49 
50 FxQueryInterface::~FxQueryInterface()
51 {
52     //
53     // Should not in any list
54     //
55     ASSERT(m_Entry.Next == NULL);
56 
57     if (m_Interface != NULL && m_EmbeddedInterface == FALSE) {
58         FxPoolFree(m_Interface);
59     }
60 }
61 
62 VOID
63 FxQueryInterface::_FormatIrp(
64     __in PIRP Irp,
65     __in const GUID* InterfaceGuid,
66     __out PINTERFACE Interface,
67     __in USHORT InterfaceSize,
68     __in USHORT InterfaceVersion,
69     __in_opt PVOID InterfaceSpecificData
70     )
71 {
72     PIO_STACK_LOCATION stack;
73 
74     Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
75 
76     stack = IoGetNextIrpStackLocation(Irp);
77 
78     stack->MajorFunction = IRP_MJ_PNP;
79     stack->MinorFunction = IRP_MN_QUERY_INTERFACE;
80 
81     stack->Parameters.QueryInterface.Interface = Interface;
82     stack->Parameters.QueryInterface.InterfaceSpecificData = InterfaceSpecificData;
83     stack->Parameters.QueryInterface.Size = InterfaceSize;
84     stack->Parameters.QueryInterface.Version = InterfaceVersion;
85     stack->Parameters.QueryInterface.InterfaceType = InterfaceGuid;
86 }
87 
88 _Must_inspect_result_
89 NTSTATUS
90 FxQueryInterface::_QueryForInterface(
91     __in PDEVICE_OBJECT TopOfStack,
92     __in const GUID* InterfaceType,
93     __out PINTERFACE Interface,
94     __in USHORT Size,
95     __in USHORT Version,
96     __in_opt PVOID InterfaceSpecificData
97     )
98 /*++
99 
100 Routine Description:
101     Send an IRP_MJPNP/IRP_MN_QUERY_INTERFACE irp to a device object and its
102     attached stack.
103 
104 Arguments:
105     TargetDevice - device to send the query to.
106 
107     InterfaceType - The type of interface to query for
108 
109     Interface - The interface to fill out
110 
111     Size - Size of Interface in bytes
112 
113     Version - Version of the interface to be queried
114 
115     InterfaceSpecificData - Addtional interface data to be queried
116 
117 
118 Return Value:
119     NTSTATUS as indicated by the handler of the QI with in the device stack,
120     STATUS_NOT_SUPPORTED if the QI is not handled.
121 
122   --*/
123 {
124     PIRP pIrp;
125     NTSTATUS status;
126 
127     pIrp = IoAllocateIrp(TopOfStack->StackSize, FALSE);
128 
129     if (pIrp != NULL) {
130         FxAutoIrp irp(pIrp);
131 
132         _FormatIrp(
133             pIrp,
134             InterfaceType,
135             Interface,
136             Size,
137             Version,
138             InterfaceSpecificData
139             );
140 
141         status = irp.SendIrpSynchronously(TopOfStack);
142     }
143     else {
144         status = STATUS_INSUFFICIENT_RESOURCES;
145     }
146 
147     return status;
148 }
149 
150 VOID
151 FxQueryInterface::SetEmbedded(
152     __in PWDF_QUERY_INTERFACE_CONFIG Config,
153     __in PINTERFACE Interface
154     )
155 /*++
156 
157 Routine Description:
158     Marks the structure as embedded and sets the configuration.  This is used
159     for FxQueryInterface structs which are embedded in other structures because
160     at contruction time the Config is not available yet.
161 
162     By marking as embedded, FxPkgPnp will not free the structure when it deletes
163     the query interface chain.
164 
165 Arguments:
166     Config - how the interface behaves
167 
168     Interface - the interface that is exported
169 
170 Return Value:
171     None
172 
173   --*/
174 {
175     m_EmbeddedInterface = TRUE;
176     m_Interface = Interface;
177 
178     m_SendQueryToParentStack = Config->SendQueryToParentStack;
179     m_ImportInterface = Config->ImportInterface;
180     m_ProcessRequest.m_Method = Config->EvtDeviceProcessQueryInterfaceRequest;
181     RtlCopyMemory(&m_InterfaceType, Config->InterfaceType, sizeof(GUID));
182 }
183