1 /*++
2
3 Copyright (c) Microsoft Corporation
4
5 Module Name:
6
7 FxDeviceInterfaceAPI.cpp
8
9 Abstract:
10
11 This module implements the device interface object external APIs
12
13 Author:
14
15
16
17
18 Environment:
19
20 kernel and user mode
21
22 Revision History:
23
24 --*/
25
26 #include "fxsupportpch.hpp"
27
28 extern "C" {
29 // #include "FxDeviceInterfaceAPI.tmh"
30 }
31
32 //
33 // extern "C" the entire file
34 //
35 extern "C" {
36
37 _Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)38 __drv_maxIRQL(PASSIVE_LEVEL)
39 NTSTATUS
40 STDCALL
41 WDFEXPORT(WdfDeviceCreateDeviceInterface)(
42 __in
43 PWDF_DRIVER_GLOBALS DriverGlobals,
44 __in
45 WDFDEVICE Device,
46 __in
47 CONST GUID *InterfaceClassGUID,
48 __in_opt
49 PCUNICODE_STRING ReferenceString
50 )
51 /*++
52
53 Routine Description:
54 Creates a device interface associated with the passed in device object
55
56 Arguments:
57 Device - Handle which represents the device exposing the interface
58
59 InterfaceGUID - GUID describing the interface being exposed
60
61 ReferenceString - OPTIONAL string which allows the driver writer to
62 distinguish between different exposed interfaces
63
64 Return Value:
65 STATUS_SUCCESS or appropriate NTSTATUS code
66
67 --*/
68 {
69 DDI_ENTRY();
70
71 SINGLE_LIST_ENTRY **ppPrev, *pCur;
72 PFX_DRIVER_GLOBALS pFxDriverGlobals;
73 FxDeviceInterface *pDeviceInterface;
74 FxDevice *pDevice;
75 FxPkgPnp* pPkgPnp;
76 NTSTATUS status;
77
78 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
79 Device,
80 FX_TYPE_DEVICE,
81 (PVOID*) &pDevice,
82 &pFxDriverGlobals);
83
84 FxPointerNotNull(pFxDriverGlobals, InterfaceClassGUID);
85
86 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
87 if (!NT_SUCCESS(status)) {
88 return status;
89 }
90
91 if (ReferenceString != NULL) {
92 status = FxValidateUnicodeString(pFxDriverGlobals, ReferenceString);
93 if (!NT_SUCCESS(status)) {
94 return status;
95 }
96 }
97
98 if (pDevice->IsLegacy()) {
99 status = STATUS_INVALID_DEVICE_REQUEST;
100
101 DoTraceLevelMessage(
102 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
103 "WDFDEVICE %p is not a PNP device, device interface creation not "
104 "allowed %!STATUS!", Device, status);
105
106 return status;
107 }
108
109 pDeviceInterface = new(pFxDriverGlobals, PagedPool) FxDeviceInterface();
110
111 if (pDeviceInterface == NULL) {
112 status = STATUS_INSUFFICIENT_RESOURCES;
113
114 DoTraceLevelMessage(
115 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
116 "WDFDEVICE %p DeviceInterface object creation failed, %!STATUS!",
117 Device, status);
118
119 return status;
120 }
121
122 status = pDeviceInterface->Initialize(pFxDriverGlobals,
123 InterfaceClassGUID,
124 ReferenceString);
125
126 if (!NT_SUCCESS(status)) {
127 DoTraceLevelMessage(
128 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
129 "WDFDEVICE %p, DeviceInterface object initialization failed, %!STATUS!",
130 Device, status );
131
132 goto Done;
133 }
134
135 pPkgPnp = pDevice->m_PkgPnp;
136
137 pPkgPnp->m_DeviceInterfaceLock.AcquireLock(pFxDriverGlobals);
138
139 status = pDeviceInterface->Register(pDevice);
140
141 if (NT_SUCCESS(status)) {
142 //
143 // Insert into the end of the list
144 //
145 ppPrev = &pPkgPnp->m_DeviceInterfaceHead.Next;
146 pCur = pPkgPnp->m_DeviceInterfaceHead.Next;
147 while (pCur != NULL) {
148 ppPrev = &pCur->Next;
149 pCur = pCur->Next;
150 }
151
152 *ppPrev = &pDeviceInterface->m_Entry;
153 }
154
155 pPkgPnp->m_DeviceInterfaceLock.ReleaseLock(pFxDriverGlobals);
156
157 Done:
158 if (!NT_SUCCESS(status)) {
159 delete pDeviceInterface;
160 pDeviceInterface = NULL;
161 }
162
163 return status;
164 }
165
__drv_maxIRQL(PASSIVE_LEVEL)166 __drv_maxIRQL(PASSIVE_LEVEL)
167 VOID
168 STDCALL
169 WDFEXPORT(WdfDeviceSetDeviceInterfaceState)(
170 __in
171 PWDF_DRIVER_GLOBALS DriverGlobals,
172 __in
173 WDFDEVICE Device,
174 __in
175 CONST GUID *InterfaceClassGUID,
176 __in_opt
177 PCUNICODE_STRING RefString,
178 __in
179 BOOLEAN State
180 )
181 {
182 DDI_ENTRY();
183
184 PSINGLE_LIST_ENTRY ple;
185 PFX_DRIVER_GLOBALS pFxDriverGlobals;
186 NTSTATUS status;
187 FxDevice* pDevice;
188 FxPkgPnp* pPkgPnp;
189
190 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
191 Device,
192 FX_TYPE_DEVICE,
193 (PVOID*) &pDevice,
194 &pFxDriverGlobals);
195
196 FxPointerNotNull(pFxDriverGlobals, InterfaceClassGUID);
197
198 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
199 if (!NT_SUCCESS(status)) {
200 FxVerifierDbgBreakPoint(pFxDriverGlobals);
201 return;
202 }
203
204 if (RefString != NULL) {
205 status = FxValidateUnicodeString(pFxDriverGlobals, RefString);
206 if (!NT_SUCCESS(status)) {
207 FxVerifierDbgBreakPoint(pFxDriverGlobals);
208 return;
209 }
210 }
211
212 if (pDevice->IsLegacy()) {
213 DoTraceLevelMessage(
214 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
215 "WDFDEVICE %p is not a PNP device, device interfaces not allowed",
216 Device);
217 FxVerifierDbgBreakPoint(pFxDriverGlobals);
218 return;
219 }
220
221 pPkgPnp = pDevice->m_PkgPnp;
222
223 pPkgPnp->m_DeviceInterfaceLock.AcquireLock(pFxDriverGlobals);
224
225 //
226 // Iterate over the interfaces and see if we have a match
227 //
228 for (ple = pPkgPnp->m_DeviceInterfaceHead.Next; ple != NULL; ple = ple->Next) {
229 FxDeviceInterface *pDI;
230
231 pDI = FxDeviceInterface::_FromEntry(ple);
232
233 if (FxIsEqualGuid(&pDI->m_InterfaceClassGUID, InterfaceClassGUID)) {
234 if (RefString != NULL) {
235 if ((RefString->Length == pDI->m_ReferenceString.Length)
236 &&
237 (RtlCompareMemory(RefString->Buffer,
238 pDI->m_ReferenceString.Buffer,
239 RefString->Length) == RefString->Length)) {
240 //
241 // They match, carry on
242 //
243 DO_NOTHING();
244 }
245 else {
246 //
247 // The ref strings do not match, continue on in the search
248 // of the collection.
249 //
250 continue;
251 }
252 }
253 else if (pDI->m_ReferenceString.Length > 0) {
254 //
255 // Caller didn't specify a ref string but this interface has
256 // one, continue on in the search through the collection.
257 //
258 continue;
259 }
260
261 //
262 // Set the state and break out of the loop because we found our
263 // interface.
264 //
265 pDI->SetState(State);
266 break;
267 }
268 }
269
270 pPkgPnp->m_DeviceInterfaceLock.ReleaseLock(pFxDriverGlobals);
271 }
272
273 _Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)274 __drv_maxIRQL(PASSIVE_LEVEL)
275 NTSTATUS
276 STDCALL
277 WDFEXPORT(WdfDeviceRetrieveDeviceInterfaceString)(
278 __in
279 PWDF_DRIVER_GLOBALS DriverGlobals,
280 __in
281 WDFDEVICE Device,
282 __in
283 CONST GUID* InterfaceClassGUID,
284 __in_opt
285 PCUNICODE_STRING RefString,
286 __in
287 WDFSTRING String
288 )
289 /*++
290
291 Routine Description:
292 Returns the symbolic link value of the registered device interface.
293
294 Arguments:
295
296
297 Return Value:
298
299
300 --*/
301
302 {
303 DDI_ENTRY();
304
305 PSINGLE_LIST_ENTRY ple;
306 PFX_DRIVER_GLOBALS pFxDriverGlobals;
307 FxDevice* pDevice;
308 FxPkgPnp* pPkgPnp;
309 FxString* pString;
310 NTSTATUS status;
311
312 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
313 Device,
314 FX_TYPE_DEVICE,
315 (PVOID*) &pDevice,
316 &pFxDriverGlobals );
317
318 FxPointerNotNull(pFxDriverGlobals, InterfaceClassGUID);
319
320 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
321 if (!NT_SUCCESS(status)) {
322 return status;
323 }
324
325 if (RefString != NULL) {
326 status = FxValidateUnicodeString(pFxDriverGlobals, RefString);
327 if (!NT_SUCCESS(status)) {
328 return status;
329 }
330 }
331
332 if (pDevice->IsLegacy()) {
333 status = STATUS_INVALID_DEVICE_REQUEST;
334
335 DoTraceLevelMessage(
336 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
337 "WDFDEVICE %p is not a PNP device, device interface creation not "
338 "allowed %!STATUS!", Device, status);
339
340 return status;
341 }
342
343 FxObjectHandleGetPtr(pFxDriverGlobals,
344 String,
345 FX_TYPE_STRING,
346 (PVOID*) &pString);
347
348 pPkgPnp = pDevice->m_PkgPnp;
349
350 status = STATUS_OBJECT_NAME_NOT_FOUND;
351
352 pPkgPnp->m_DeviceInterfaceLock.AcquireLock(pFxDriverGlobals);
353
354 //
355 // Iterate over the interfaces and see if we have a match
356 //
357 for (ple = pPkgPnp->m_DeviceInterfaceHead.Next;
358 ple != NULL;
359 ple = ple->Next) {
360 FxDeviceInterface *pDI;
361
362 pDI = FxDeviceInterface::_FromEntry(ple);
363
364 if (FxIsEqualGuid(&pDI->m_InterfaceClassGUID, InterfaceClassGUID)) {
365 if (RefString != NULL) {
366 if ((RefString->Length == pDI->m_ReferenceString.Length)
367 &&
368 (RtlCompareMemory(RefString->Buffer,
369 pDI->m_ReferenceString.Buffer,
370 RefString->Length) == RefString->Length)) {
371 //
372 // They match, carry on
373 //
374 DO_NOTHING();
375 }
376 else {
377 //
378 // The ref strings do not match, continue on in the search
379 // of the collection.
380 //
381 continue;
382 }
383 }
384 else if (pDI->m_ReferenceString.Length > 0) {
385 //
386 // Caller didn't specify a ref string but this interface has
387 // one, continue on in the search through the collection.
388 //
389 continue;
390 }
391
392 status = pDI->GetSymbolicLinkName(pString);
393
394 break;
395 }
396 }
397
398 pPkgPnp->m_DeviceInterfaceLock.ReleaseLock(pFxDriverGlobals);
399
400 return status;
401 }
402
403 } // extern "C"
404