1 /*++
2 
3 Copyright (c) Microsoft Corporation
4 
5 Module Name:
6 
7     FxDeviceInterfaceUM.cpp
8 
9 Abstract:
10 
11     This module implements the device interface object.
12 
13 Author:
14 
15 
16 
17 Environment:
18 
19     User mode only
20 
21 Revision History:
22 
23 --*/
24 
25 #include "FxSupportPch.hpp"
26 
27 extern "C" {
28 #include "FxDeviceInterfaceUM.tmh"
29 }
30 
31 FxDeviceInterface::FxDeviceInterface(
32     )
33 /*++
34 
35 Routine Description:
36     Constructor for the object.  Initializes all fields
37 
38 Arguments:
39     None
40 
41 Return Value:
42     None
43 
44   --*/
45 {
46     RtlZeroMemory(&m_InterfaceClassGUID, sizeof(m_InterfaceClassGUID));
47 
48     RtlZeroMemory(&m_SymbolicLinkName, sizeof(m_SymbolicLinkName));
49     RtlZeroMemory(&m_ReferenceString, sizeof(m_ReferenceString));
50 
51     m_Entry.Next = NULL;
52 
53     m_State = FALSE;
54 }
55 
56 FxDeviceInterface::~FxDeviceInterface()
57 /*++
58 
59 Routine Description:
60     Destructor for FxDeviceInterface.  Cleans up any allocations previously
61     allocated.
62 
63 Arguments:
64     None
65 
66 Return Value:
67     None
68 
69   --*/
70 {
71     // the device interface should be off now
72     ASSERT(m_State == FALSE);
73 
74     // should no longer be in any list
75     ASSERT(m_Entry.Next == NULL);
76 
77     if (m_ReferenceString.Buffer != NULL) {
78         FxPoolFree(m_ReferenceString.Buffer);
79         RtlZeroMemory(&m_ReferenceString, sizeof(m_ReferenceString));
80     }
81 
82     if (m_SymbolicLinkName.Buffer != NULL) {
83         MxMemory::MxFreePool(m_SymbolicLinkName.Buffer);
84     }
85 }
86 
87 _Must_inspect_result_
88 NTSTATUS
89 FxDeviceInterface::Initialize(
90     __in PFX_DRIVER_GLOBALS FxDriverGlobals,
91     __in CONST GUID* InterfaceGUID,
92     __in_opt PCUNICODE_STRING ReferenceString
93     )
94 /*++
95 
96 Routine Description:
97     Initializes the object with the interface GUID and optional reference string
98 
99 Arguments:
100     InterfaceGUID - GUID describing the interface
101 
102     ReferenceString - string used to differentiate between 2 interfaces on the
103         same PDO
104 
105 Return Value:
106     STATUS_SUCCESS or STATUS_INSUFFICIENT_RESOURCES
107 
108   --*/
109 {
110     RtlCopyMemory(&m_InterfaceClassGUID, InterfaceGUID, sizeof(GUID));
111 
112     if (ReferenceString != NULL) {
113         return FxDuplicateUnicodeString(FxDriverGlobals,
114                                         ReferenceString,
115                                         &m_ReferenceString);
116     }
117     else {
118         return STATUS_SUCCESS;
119     }
120 }
121 
122 
123 VOID
124 FxDeviceInterface::SetState(
125     __in BOOLEAN State
126     )
127 /*++
128 
129 Routine Description:
130     Sets the state of the device interface
131 
132 Arguments:
133     State - the state to set
134 
135 
136 Return Value:
137     None.
138 
139   --*/
140 {
141     HRESULT hr;
142     NTSTATUS status;
143     IWudfDeviceStack *pDeviceStack;
144 
145 
146 
147 
148     //
149     // Get the IWudfDeviceStack interface
150     //
151     pDeviceStack = m_Device->GetDeviceStackInterface();
152 
153     //
154     // Enable the interface
155     //
156     hr = pDeviceStack->SetDeviceInterfaceState(&this->m_InterfaceClassGUID,
157                                                this->m_ReferenceString.Buffer,
158                                                State);
159 
160     if (SUCCEEDED(hr)) {
161         m_State = State;
162     }
163     else {
164         status = FxDevice::NtStatusFromHr(pDeviceStack, hr);
165         DoTraceLevelMessage(
166             FxDevice::GetFxDevice(m_Device)->GetDriverGlobals(),
167             TRACE_LEVEL_WARNING, TRACINGPNP,
168             "Failed to %s device interface %!STATUS!",
169             (State ? "enable" : "disable"), status);
170 
171 
172 
173 
174 
175     }
176 }
177 
178 _Must_inspect_result_
179 NTSTATUS
180 FxDeviceInterface::Register(
181     __in MdDeviceObject DeviceObject
182     )
183 /*++
184 
185 Routine Description:
186     Registers the device interface for a given PDO
187 
188 Arguments:
189     DeviceObject - FDO for the device stack in case of UM, and PDO for
190                    in case of KM.
191 
192 Return Value:
193     returned by IWudfDeviceStack::CreateDeviceInterface
194 
195   --*/
196 {
197     HRESULT hr;
198     NTSTATUS status;
199     IWudfDeviceStack *pDeviceStack;
200 
201     m_Device = DeviceObject;
202 
203     //
204     // Get the IWudfDeviceStack interface
205     //
206     pDeviceStack = m_Device->GetDeviceStackInterface();
207 
208     hr = pDeviceStack->CreateDeviceInterface(&m_InterfaceClassGUID,
209                                              m_ReferenceString.Buffer);
210 
211     if (SUCCEEDED(hr)) {
212         status = STATUS_SUCCESS;
213     }
214     else {
215         status = FxDevice::NtStatusFromHr(pDeviceStack, hr);
216     }
217 
218     return status;
219 }
220 
221 _Must_inspect_result_
222 NTSTATUS
223 FxDeviceInterface::Register(
224     _In_ FxDevice* Device
225     )
226 {
227     NTSTATUS status;
228 
229     //
230     // For UMDF, PDO is already known so no reason to defer registration.
231     // Also, note that Register takes fdo as parameter for UMDF.
232     //
233     status = Register(Device->GetDeviceObject());
234 
235     return status;
236 }
237 
238 NTSTATUS
239 FxDeviceInterface::GetSymbolicLinkName(
240     _In_ FxString* LinkString
241     )
242 {
243     NTSTATUS status;
244     PCWSTR symLink = NULL;
245 
246     if (m_SymbolicLinkName.Buffer == NULL) {
247         IWudfDeviceStack *pDeviceStack;
248         IWudfDeviceStack2 *pDeviceStack2;
249 
250         //
251         // Get the IWudfDeviceStack interface
252         //
253         pDeviceStack = m_Device->GetDeviceStackInterface();
254         HRESULT hrQI;
255         HRESULT hr;
256 
257         hrQI = pDeviceStack->QueryInterface(IID_IWudfDeviceStack2,
258                                             (PVOID*)&pDeviceStack2);
259         FX_VERIFY(INTERNAL, CHECK_QI(hrQI, pDeviceStack2));
260         pDeviceStack->Release();
261 
262         //
263         // Get the symbolic link
264         //
265         hr = pDeviceStack2->GetInterfaceSymbolicLink(&m_InterfaceClassGUID,
266                                                      m_ReferenceString.Buffer,
267                                                      &symLink);
268         if (FAILED(hr)) {
269             status = FxDevice::GetFxDevice(m_Device)->NtStatusFromHr(hr);
270         }
271         else {
272             RtlInitUnicodeString(&m_SymbolicLinkName, symLink);
273             status = STATUS_SUCCESS;
274         }
275     }
276     else {
277         status = STATUS_SUCCESS;
278     }
279 
280     if (NT_SUCCESS(status)) {
281         //
282         // Attempt a copy
283         //
284         status = LinkString->Assign(&m_SymbolicLinkName);
285     }
286 
287     return status;
288 }
289 
290