1 /*++
2
3 Copyright (c) Microsoft Corporation
4
5 Module Name:
6
7 FxIoTargetAPI.cpp
8
9 Abstract:
10
11 This module implements the IO Target APIs
12
13 Author:
14
15 Environment:
16
17 kernel mode only
18
19 Revision History:
20
21 --*/
22
23 #include "../fxtargetsshared.hpp"
24
25 extern "C" {
26 // #include "FxIoTargetAPI.tmh"
27 }
28
29 //
30 // Extern the entire file
31 //
32 extern "C" {
33
34 _Must_inspect_result_
__drv_maxIRQL(DISPATCH_LEVEL)35 __drv_maxIRQL(DISPATCH_LEVEL)
36 NTSTATUS
37 STDCALL
38 WDFEXPORT(WdfIoTargetStart)(
39 __in
40 PWDF_DRIVER_GLOBALS DriverGlobals,
41 __in
42 WDFIOTARGET IoTarget
43 )
44 /*++
45
46 Routine Description:
47 Changes the target's state to started. In the started state, the target
48 can send I/O.
49
50 Arguments:
51 IoTarget - the target whose state will change
52
53 Return Value:
54 NTSTATUS
55
56 --*/
57 {
58 DDI_ENTRY();
59
60 FxIoTarget* pTarget;
61
62 FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
63 IoTarget,
64 FX_TYPE_IO_TARGET,
65 (PVOID*) &pTarget);
66
67 return pTarget->Start();
68 }
69
70 __drv_when(Action == 3, __drv_maxIRQL(DISPATCH_LEVEL))
71 __drv_when(Action == 0 || Action == 1 || Action == 2, __drv_maxIRQL(PASSIVE_LEVEL))
72 VOID
73 STDCALL
WDFEXPORT(WdfIoTargetStop)74 WDFEXPORT(WdfIoTargetStop)(
75 __in
76 PWDF_DRIVER_GLOBALS DriverGlobals,
77 __in
78 WDFIOTARGET IoTarget,
79 __in
80 __drv_strictTypeMatch(__drv_typeConst)
81 WDF_IO_TARGET_SENT_IO_ACTION Action
82 )
83 /*++
84
85 Routine Description:
86 This function puts the target into the stopped state. Depending on the value
87 of Action, this function may not return until sent I/O has been canceled and/or
88 completed.
89
90 Arguments:
91 IoTarget - the target whose state is being changed
92
93 Action - what to do with the I/O that is pending in the target already
94
95 Return Value:
96 None
97
98 --*/
99 {
100 DDI_ENTRY();
101
102 PFX_DRIVER_GLOBALS pFxDriverGlobals;
103 FxIoTarget* pTarget;
104 NTSTATUS status;
105
106 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
107 IoTarget,
108 FX_TYPE_IO_TARGET,
109 (PVOID*) &pTarget,
110 &pFxDriverGlobals);
111
112 if (Action == WdfIoTargetSentIoUndefined ||
113 Action > WdfIoTargetLeaveSentIoPending) {
114 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
115 "Action %d undefined or out of range", Action);
116 return;
117 }
118
119 if (Action == WdfIoTargetCancelSentIo ||
120 Action == WdfIoTargetWaitForSentIoToComplete) {
121 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
122 if (!NT_SUCCESS(status)) {
123 return;
124 }
125 }
126
127 pTarget->Stop(Action);
128 }
129
130 __drv_when(Action == 2, __drv_maxIRQL(DISPATCH_LEVEL))
131 __drv_when(Action == 0 || Action == 1, __drv_maxIRQL(PASSIVE_LEVEL))
132 VOID
133 STDCALL
WDFEXPORT(WdfIoTargetPurge)134 WDFEXPORT(WdfIoTargetPurge)(
135 __in
136 PWDF_DRIVER_GLOBALS DriverGlobals,
137 __in
138 WDFIOTARGET IoTarget,
139 __in
140 __drv_strictTypeMatch(__drv_typeConst)
141 WDF_IO_TARGET_PURGE_IO_ACTION Action
142 )
143 /*++
144
145 Routine Description:
146 This function puts the target into the purged state. Depending on the value
147 of Action, this function may not return until pending and sent I/O has been
148 canceled and completed.
149
150 Arguments:
151 IoTarget - the target whose state is being changed
152
153 Action - purge action: wait or not for I/O to complete after doing the purge.
154
155 Return Value:
156 None
157
158 --*/
159 {
160 DDI_ENTRY();
161
162 PFX_DRIVER_GLOBALS pFxDriverGlobals;
163 FxIoTarget* pTarget;
164 NTSTATUS status;
165
166 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
167 IoTarget,
168 FX_TYPE_IO_TARGET,
169 (PVOID*) &pTarget,
170 &pFxDriverGlobals);
171
172 if (Action == WdfIoTargetPurgeIoUndefined ||
173 Action > WdfIoTargetPurgeIo) {
174 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
175 "Action %d undefined or out of range", Action);
176 return;
177 }
178
179 if (Action == WdfIoTargetPurgeIoAndWait) {
180 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
181 if (!NT_SUCCESS(status)) {
182 return;
183 }
184 }
185
186 pTarget->Purge(Action);
187 }
188
__drv_maxIRQL(DISPATCH_LEVEL)189 __drv_maxIRQL(DISPATCH_LEVEL)
190 WDF_IO_TARGET_STATE
191 STDCALL
192 WDFEXPORT(WdfIoTargetGetState)(
193 __in
194 PWDF_DRIVER_GLOBALS DriverGlobals,
195 __in
196 WDFIOTARGET IoTarget
197 )
198 /*++
199
200 Routine Description:
201 Returns the current state of the target
202
203 Arguments:
204 IoTarget - target whose state is being returned
205
206 Return Value:
207 current target state
208
209 --*/
210 {
211 DDI_ENTRY();
212
213 FxIoTarget* pTarget;
214
215 FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
216 IoTarget,
217 FX_TYPE_IO_TARGET,
218 (PVOID*) &pTarget);
219
220 return pTarget->GetState();
221 }
222
223 _Must_inspect_result_
224 NTSTATUS
FxIoTargetValidateOpenParams(__in PFX_DRIVER_GLOBALS FxDriverGlobals,__in PWDF_IO_TARGET_OPEN_PARAMS OpenParams)225 FxIoTargetValidateOpenParams(
226 __in PFX_DRIVER_GLOBALS FxDriverGlobals,
227 __in PWDF_IO_TARGET_OPEN_PARAMS OpenParams
228 )
229 /*++
230
231 Routine Description:
232 Validates the target open parameters structure.
233
234 Arguments:
235 FxDriverGlobals - driver globals
236
237 OpenParams - the structure to validate
238
239 Return Value:
240 NTSTATUS
241
242 --*/
243
244 {
245 NTSTATUS status;
246
247 //
248 // Check specific fields based on Type
249 //
250 switch (OpenParams->Type) {
251 case WdfIoTargetOpenUseExistingDevice:
252 if (OpenParams->TargetDeviceObject == NULL) {
253 status = STATUS_INVALID_PARAMETER;
254 DoTraceLevelMessage(
255 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
256 "Expected non NULL TargetDeviceObject in OpenParams, %!STATUS!",
257 status);
258 return status;
259 }
260
261 //
262 // This type is supported only in KMDF.
263 //
264 if (FxDriverGlobals->IsUserModeDriver) {
265 status = STATUS_INVALID_PARAMETER;
266 DoTraceLevelMessage(
267 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
268 "The open type WdfIoTargetOpenUseExistingDevice is not "
269 "supported in UMDF drivers. It is supported in KMDF "
270 "drivers only, %!STATUS!",
271 status);
272 return status;
273 }
274
275 if (OpenParams->TargetFileObject == NULL &&
276 (OpenParams->EvtIoTargetQueryRemove != NULL ||
277 OpenParams->EvtIoTargetRemoveCanceled != NULL ||
278 OpenParams->EvtIoTargetRemoveComplete != NULL)) {
279 status = STATUS_INVALID_PARAMETER;
280
281 DoTraceLevelMessage(
282 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
283 "OpenParams %p TargetFileObject is NULL but a state callback "
284 "(query remove %p, remove canceled %p, remove complete %p)"
285 " was specified, %!STATUS!",
286 OpenParams, OpenParams->EvtIoTargetQueryRemove,
287 OpenParams->EvtIoTargetRemoveCanceled,
288 OpenParams->EvtIoTargetRemoveComplete, status);
289
290 return status;
291 }
292 break;
293
294 case WdfIoTargetOpenByName:
295 if (OpenParams->TargetDeviceName.Buffer == NULL ||
296 OpenParams->TargetDeviceName.Length == 0 ||
297 OpenParams->TargetDeviceName.MaximumLength == 0) {
298 status = STATUS_INVALID_PARAMETER;
299 DoTraceLevelMessage(
300 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
301 "Expected valid OpenParams TargetDeviceName string, %!STATUS!",
302 status);
303 return status;
304 }
305 break;
306
307 case WdfIoTargetOpenLocalTargetByFile:
308 //
309 // This type is supported only in UMDF.
310 //
311 if (FxDriverGlobals->IsUserModeDriver == FALSE) {
312 status = STATUS_INVALID_PARAMETER;
313 DoTraceLevelMessage(
314 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
315 "The open type WdfIoTargetOpenLocalTargetByFile is not "
316 "supported in KMDF drivers. It is supported in UMDF "
317 "drivers only, %!STATUS!",
318 status);
319 return status;
320 }
321
322 if ((OpenParams->EvtIoTargetQueryRemove != NULL ||
323 OpenParams->EvtIoTargetRemoveCanceled != NULL ||
324 OpenParams->EvtIoTargetRemoveComplete != NULL)) {
325 status = STATUS_INVALID_PARAMETER;
326
327 DoTraceLevelMessage(
328 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
329 "The open type is WdfIoTargetOpenLocalTargetByFile but a state"
330 " callback (query remove %p, remove canceled %p, remove"
331 " complete %p) was specified, %!STATUS!",
332 OpenParams->EvtIoTargetQueryRemove,
333 OpenParams->EvtIoTargetRemoveCanceled,
334 OpenParams->EvtIoTargetRemoveComplete, status);
335
336 return status;
337 }
338
339 if (OpenParams->FileName.Buffer != NULL ||
340 OpenParams->FileName.Length != 0 ||
341 OpenParams->FileName.MaximumLength != 0) {
342 status = FxValidateUnicodeString(FxDriverGlobals,
343 &OpenParams->FileName);
344 if (!NT_SUCCESS(status)) {
345 return status;
346 }
347 }
348
349
350 break;
351
352 case WdfIoTargetOpenReopen:
353 break;
354
355 default:
356 status = STATUS_INVALID_PARAMETER;
357 DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
358 "OpenParams Type (%d) incorrect, %!STATUS!",
359 OpenParams->Type, status);
360
361 return status;
362 }
363
364 return STATUS_SUCCESS;
365 }
366
367
368 _Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)369 __drv_maxIRQL(PASSIVE_LEVEL)
370 NTSTATUS
371 STDCALL
372 WDFEXPORT(WdfIoTargetCreate)(
373 __in
374 PWDF_DRIVER_GLOBALS DriverGlobals,
375 __in
376 WDFDEVICE Device,
377 __in_opt
378 PWDF_OBJECT_ATTRIBUTES IoTargetAttributes,
379 __out
380 WDFIOTARGET* IoTarget
381 )
382 /*++
383
384 Routine Description:
385 Creates a WDFIOTARGET which can be opened upon success.
386
387 Arguments:
388 Device - the device which will own the target. The target will be parented
389 by the owning device
390
391 IoTargetAttributes - optional attributes to apply to the target
392
393 IoTarget - pointer which will receive the created target handle
394
395 Return Value:
396 NTSTATUS
397
398 --*/
399 {
400 DDI_ENTRY();
401
402 PFX_DRIVER_GLOBALS pFxDriverGlobals;
403 FxIoTargetRemote* pTarget;
404 FxDeviceBase* pDevice;
405 NTSTATUS status;
406
407 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
408 Device,
409 FX_TYPE_DEVICE_BASE,
410 (PWDFOBJECT) &pDevice,
411 &pFxDriverGlobals);
412
413 FxPointerNotNull(pFxDriverGlobals, IoTarget);
414
415 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
416 "WDFDEVICE 0x%p", Device);
417
418 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
419 if (!NT_SUCCESS(status)) {
420 return status;
421 }
422
423 //
424 // Since the target is auto parented to the Device, we don't allow the client
425 // to specify a parent.
426 //
427 status = FxValidateObjectAttributes(pFxDriverGlobals, IoTargetAttributes);
428 if (!NT_SUCCESS(status)) {
429 return status;
430 }
431
432 status = FxIoTargetRemote::_Create(
433 pFxDriverGlobals, IoTargetAttributes, pDevice, &pTarget);
434
435 if (NT_SUCCESS(status)) {
436 *IoTarget = pTarget->GetHandle();
437 }
438
439 return status;
440 }
441
442 _Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)443 __drv_maxIRQL(PASSIVE_LEVEL)
444 NTSTATUS
445 STDCALL
446 WDFEXPORT(WdfIoTargetOpen)(
447 __in
448 PWDF_DRIVER_GLOBALS DriverGlobals,
449 __in
450 WDFIOTARGET IoTarget,
451 __in
452 PWDF_IO_TARGET_OPEN_PARAMS OpenParams
453 )
454 /*++
455
456 Routine Description:
457 Opens a target. The target must be in the closed state for an open to
458 succeed. Open is either wrapping an existing PDEVICE_OBJECT + PFILE_OBJECT
459 that the client provides or opening a PDEVICE_OBJECT by name.
460
461 Arguments:
462 IoTarget - Target to be opened
463
464 OpenParams - structure which describes how to open the target
465
466 Return Value:
467 NTSTATUS
468
469 --*/
470 {
471 //
472 // UMDF only, noop for KMDF.
473 // It's ok to be impersonated here, because it can be required in order for
474 // the CreateFile() call to succeed.
475 //
476 DDI_ENTRY_IMPERSONATION_OK();
477
478 PFX_DRIVER_GLOBALS pFxDriverGlobals;
479 FxIoTargetRemote* pTarget;
480 NTSTATUS status;
481 ULONG expectedConfigSize;
482 WDF_IO_TARGET_OPEN_PARAMS openParams;
483
484 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
485 IoTarget,
486 FX_TYPE_IO_TARGET_REMOTE,
487 (PVOID*) &pTarget,
488 &pFxDriverGlobals);
489
490 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
491 "enter WDFIOTARGET 0x%p", IoTarget);
492
493 FxPointerNotNull(pFxDriverGlobals, OpenParams);
494
495 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
496 if (!NT_SUCCESS(status)) {
497 return status;
498 }
499
500 expectedConfigSize = pFxDriverGlobals->IsVersionGreaterThanOrEqualTo(1,13) ?
501 sizeof(WDF_IO_TARGET_OPEN_PARAMS) :
502 sizeof(WDF_IO_TARGET_OPEN_PARAMS_V1_11);
503
504 //
505 // Check Size
506 //
507 if (OpenParams->Size != sizeof(WDF_IO_TARGET_OPEN_PARAMS) &&
508 OpenParams->Size != sizeof(WDF_IO_TARGET_OPEN_PARAMS_V1_11)) {
509 status = STATUS_INFO_LENGTH_MISMATCH;
510 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
511 "OpenParams size (%d) incorrect, expected %d, %!STATUS!",
512 OpenParams->Size, expectedConfigSize, status);
513 return status;
514 }
515
516 //
517 // Normalize WDF_IO_TARGET_OPEN_PARAMS structure.
518 //
519 if (OpenParams->Size < sizeof(WDF_IO_TARGET_OPEN_PARAMS)) {
520 RtlZeroMemory(&openParams, sizeof(WDF_IO_TARGET_OPEN_PARAMS));
521
522 //
523 // Copy over existing fields and readjust the struct size.
524 //
525 RtlCopyMemory(&openParams, OpenParams, OpenParams->Size);
526 openParams.Size = sizeof(openParams);
527
528 //
529 // Use new open params structure from now on.
530 //
531 OpenParams = &openParams;
532 }
533
534 status = FxIoTargetValidateOpenParams(pFxDriverGlobals, OpenParams);
535 if (!NT_SUCCESS(status)) {
536 //
537 // FxIoTargetValidateCreateParams traces the error
538 //
539 return status;
540 }
541
542 status = pTarget->Open(OpenParams);
543
544 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
545 "exit WDFIOTARGET 0x%p, %!STATUS!", IoTarget, status);
546
547 return status;
548 }
549
__drv_maxIRQL(PASSIVE_LEVEL)550 __drv_maxIRQL(PASSIVE_LEVEL)
551 VOID
552 STDCALL
553 WDFEXPORT(WdfIoTargetCloseForQueryRemove)(
554 __in
555 PWDF_DRIVER_GLOBALS DriverGlobals,
556 __in
557 WDFIOTARGET IoTarget
558 )
559 /*++
560
561 Routine Description:
562 Closes a target in response to a query remove notification callback. This
563 will pend all i/o sent after the call returns.
564
565 Arguments:
566 IoTarget - Target to be closed
567
568 Return Value:
569 None
570
571 --*/
572 {
573 DDI_ENTRY();
574
575 PFX_DRIVER_GLOBALS pFxDriverGlobals;
576 FxIoTargetRemote* pTarget;
577 NTSTATUS status;
578
579 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
580 IoTarget,
581 FX_TYPE_IO_TARGET_REMOTE,
582 (PVOID*) &pTarget,
583 &pFxDriverGlobals);
584
585 pFxDriverGlobals = GetFxDriverGlobals(DriverGlobals);
586
587 DoTraceLevelMessage(
588 pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
589 "enter WDFIOTARGET 0x%p", IoTarget);
590
591 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
592 if (!NT_SUCCESS(status)) {
593 return;
594 }
595
596 pTarget->Close(FxIoTargetRemoteCloseReasonQueryRemove);
597 }
598
__drv_maxIRQL(PASSIVE_LEVEL)599 __drv_maxIRQL(PASSIVE_LEVEL)
600 VOID
601 STDCALL
602 WDFEXPORT(WdfIoTargetClose)(
603 __in
604 PWDF_DRIVER_GLOBALS DriverGlobals,
605 __in
606 WDFIOTARGET IoTarget
607 )
608 /*++
609
610 Routine Description:
611 Closes the target for good. The target can be in either a query removed or
612 opened state.
613
614 Arguments:
615 IoTarget - target to close
616
617 Return Value:
618 None
619
620 --*/
621 {
622 DDI_ENTRY();
623
624 PFX_DRIVER_GLOBALS pFxDriverGlobals;
625 FxIoTargetRemote* pTarget;
626 NTSTATUS status;
627
628 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
629 IoTarget,
630 FX_TYPE_IO_TARGET_REMOTE,
631 (PVOID*) &pTarget,
632 &pFxDriverGlobals);
633
634 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
635 "enter WDFIOTARGET 0x%p", IoTarget);
636
637 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
638 if (!NT_SUCCESS(status)) {
639 return;
640 }
641
642 pTarget->Close(FxIoTargetRemoteCloseReasonPlainClose);
643 }
644
__drv_maxIRQL(DISPATCH_LEVEL)645 __drv_maxIRQL(DISPATCH_LEVEL)
646 WDFDEVICE
647 STDCALL
648 WDFEXPORT(WdfIoTargetGetDevice)(
649 __in
650 PWDF_DRIVER_GLOBALS DriverGlobals,
651 __in
652 WDFIOTARGET IoTarget
653 )
654 /*++
655
656 Routine Description:
657 Returns the owning WDFDEVICE for the WDFIOTARGET, this is not necessarily
658 the PDEVICE_OBJECT of the target itself.
659
660 Arguments:
661 IoTarget - the target being retrieved
662
663 Return Value:
664 a valid WDFDEVICE handle , NULL if there are any problems
665
666 --*/
667
668 {
669 DDI_ENTRY();
670
671 PFX_DRIVER_GLOBALS pFxDriverGlobals;
672 FxIoTarget* pTarget;
673 WDFDEVICE device;
674
675 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
676 IoTarget,
677 FX_TYPE_IO_TARGET,
678 (PVOID*) &pTarget,
679 &pFxDriverGlobals);
680
681 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
682 "enter WDFIOTARGET 0x%p", IoTarget);
683
684 device = pTarget->GetDeviceHandle();
685
686 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
687 "exit WDFIOTARGET 0x%p, WDFDEVICE 0x%p", IoTarget, device);
688
689 return device;
690 }
691
692 static
693 _Must_inspect_result_
694 NTSTATUS
FxIoTargetSendIo(__in PFX_DRIVER_GLOBALS FxDriverGlobals,__in WDFIOTARGET IoTarget,__inout_opt WDFREQUEST Request,__in UCHAR MajorCode,__inout_opt PWDF_MEMORY_DESCRIPTOR IoBuffer,__in_opt PLONGLONG DeviceOffset,__in_opt PWDF_REQUEST_SEND_OPTIONS RequestOptions,__out_opt PULONG_PTR BytesReturned)695 FxIoTargetSendIo(
696 __in
697 PFX_DRIVER_GLOBALS FxDriverGlobals,
698 __in
699 WDFIOTARGET IoTarget,
700 __inout_opt
701 WDFREQUEST Request,
702 __in
703 UCHAR MajorCode,
704 __inout_opt
705 PWDF_MEMORY_DESCRIPTOR IoBuffer,
706 __in_opt
707 PLONGLONG DeviceOffset,
708 __in_opt
709 PWDF_REQUEST_SEND_OPTIONS RequestOptions,
710 __out_opt
711 PULONG_PTR BytesReturned
712 )
713 /*++
714
715 Routine Description:
716 This routine sends a read or write synchronously to the target. If Request
717 is not NULL, the PIRP it contains will be used to send the IO.
718
719 Arguments:
720 IoTarget - target to where the IO is going to be sent
721
722 Request - optional. If specified, the PIRP it contains will be used
723 to send the I/O
724
725 MajorCode - read or write major code
726
727 IoBuffer - Buffer which will be used in the I/O. The buffer can be a PMDL,
728 buffer, or WDFMEMORY
729
730 DeviceOffset - offset into the target (and not the memory) in which the I/O
731 will start
732
733 RequestOptions - optional. If specified, the timeout value is used to cancel
734 the sent i/o if the timeout is exceeded
735
736 BytesReturned - upon success, the number of bytes transferred in the I/O
737 request
738
739 Return Value:
740 NTSTATUS
741
742 --*/
743
744 {
745 FxIoTarget* pTarget;
746 FxRequestBuffer ioBuf;
747 NTSTATUS status;
748
749 FxObjectHandleGetPtrAndGlobals(FxDriverGlobals,
750 IoTarget,
751 FX_TYPE_IO_TARGET,
752 (PVOID*) &pTarget,
753 &FxDriverGlobals);
754
755 //
756 // Minimize the points of failure by using the stack instead of allocating
757 // out of pool. For UMDF, request initialization can fail so we still need
758 // to call initialize for FxSyncRequest. Initialization always succeeds for
759 // KM.
760 //
761 FxIoContext context;
762 FxSyncRequest request(FxDriverGlobals, &context, Request);
763
764 status = request.Initialize();
765 if (!NT_SUCCESS(status)) {
766 DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
767 "Failed to initialize FxSyncRequest for WDFIOTARGET "
768 "0x%p", IoTarget);
769 return status;
770 }
771
772 DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
773 "enter: WDFIOTARGET 0x%p, WDFREQUEST 0x%p, MJ code 0x%x",
774 IoTarget, Request, MajorCode);
775
776 //
777 // Since we are synchronously waiting, we must be at passive level
778 //
779 status = FxVerifierCheckIrqlLevel(FxDriverGlobals, PASSIVE_LEVEL);
780 if (!NT_SUCCESS(status)) {
781 return status;
782 }
783
784 status = FxValidateRequestOptions(FxDriverGlobals, RequestOptions);
785 if (!NT_SUCCESS(status)) {
786 DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
787 "invalid options, %!STATUS!", status);
788 return status;
789 }
790
791 if (IoBuffer != NULL) {
792 //
793 // This transcribes the client union into a local structure which we
794 // can change w/out altering the client's buffer.
795 //
796 status = ioBuf.ValidateMemoryDescriptor(FxDriverGlobals, IoBuffer);
797 if (!NT_SUCCESS(status)) {
798 DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
799 "invalid input buffer descriptor 0x%p, %!STATUS!",
800 IoBuffer, status);
801 return status;
802 }
803 }
804
805 //
806 // Format the next stack location in the PIRP
807 //
808 status = pTarget->FormatIoRequest(
809 request.m_TrueRequest, MajorCode, &ioBuf, DeviceOffset, NULL);
810
811 if (NT_SUCCESS(status)) {
812 //
813 // And send it
814 //
815 DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
816 "WDFIOTARGET 0x%p, WDFREQUEST 0x%p being submitted",
817 IoTarget, request.m_TrueRequest->GetTraceObjectHandle());
818
819 status = pTarget->SubmitSync(request.m_TrueRequest, RequestOptions);
820
821 if (BytesReturned != NULL) {
822 *BytesReturned = request.m_TrueRequest->GetSubmitFxIrp()->GetInformation();
823
824 }
825 }
826 else {
827 DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
828 "could not format MJ 0x%x request, %!STATUS!",
829 MajorCode, status);
830 }
831
832 return status;
833 }
834
835 static
836 _Must_inspect_result_
837 NTSTATUS
FxIoTargetFormatIo(__in PFX_DRIVER_GLOBALS FxDriverGlobals,__in WDFIOTARGET IoTarget,__inout WDFREQUEST Request,__in UCHAR MajorCode,__inout_opt WDFMEMORY IoBuffer,__in_opt PWDFMEMORY_OFFSET IoBufferOffsets,__in_opt PLONGLONG DeviceOffset)838 FxIoTargetFormatIo(
839 __in
840 PFX_DRIVER_GLOBALS FxDriverGlobals,
841 __in
842 WDFIOTARGET IoTarget,
843 __inout
844 WDFREQUEST Request,
845 __in
846 UCHAR MajorCode,
847 __inout_opt
848 WDFMEMORY IoBuffer,
849 __in_opt
850 PWDFMEMORY_OFFSET IoBufferOffsets,
851 __in_opt
852 PLONGLONG DeviceOffset
853 )
854 /*++
855
856 Routine Description:
857 Formats a Request for a read or write. The request can later be sent to the
858 target using WdfRequestSend. Upon success, this will take a reference on the
859 Iobuffer handle if it is not NULL. This reference will be released when
860 one of the following occurs:
861 1) the request is completed through WdfRequestComplete
862 2) the request is reused through WdfRequestReuse
863 3) the request is reformatted through any target format DDI
864
865 Arguments:
866 IoTarget - the request that the read or write will later be sent to
867
868 Request - the request that will be formatted
869
870 MajorCode - read or write major code
871
872 IoBuffer - optional reference counted memory handle
873
874 IoBufferOffset - optional offset into the IoBuffer. This can specify the
875 starting offset and/or length of the transfer
876
877 DeviceOffset - offset into the target in which the i/o will start
878
879 Return Value:
880 NTSTATUS
881
882 --*/
883 {
884 FxIoTarget *pTarget;
885 FxRequest *pRequest;
886 IFxMemory* pIoMemory;
887 FxRequestBuffer ioBuf;
888 NTSTATUS status;
889
890 FxObjectHandleGetPtrAndGlobals(FxDriverGlobals,
891 IoTarget,
892 FX_TYPE_IO_TARGET,
893 (PVOID*) &pTarget,
894 &FxDriverGlobals);
895
896 DoTraceLevelMessage(FxDriverGlobals,
897 TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
898 "enter: WDFIOTARGET 0x%p, WDFREQUEST 0x%p, MJ code 0x%x, WDFMEMORY 0x%p",
899 IoTarget, Request, MajorCode, IoBuffer);
900
901 FxObjectHandleGetPtr(FxDriverGlobals,
902 Request,
903 FX_TYPE_REQUEST,
904 (PVOID*) &pRequest);
905
906 if (IoBuffer != NULL) {
907 FxObjectHandleGetPtr(FxDriverGlobals,
908 IoBuffer,
909 IFX_TYPE_MEMORY,
910 (PVOID*) &pIoMemory);
911
912 status = pIoMemory->ValidateMemoryOffsets(IoBufferOffsets);
913 if (!NT_SUCCESS(status)) {
914 DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
915 "invalid memory offsets, %!STATUS!",
916 status);
917 return status;
918 }
919
920 //
921 // This transcribes the client union into a local structure which we
922 // can change w/out altering the client's buffer.
923 //
924 ioBuf.SetMemory(pIoMemory, IoBufferOffsets);
925 }
926 else {
927 pIoMemory = NULL;
928 }
929
930 //
931 // Format the next stack locaiton in the PIRP
932 //
933 status = pTarget->FormatIoRequest(
934 pRequest, MajorCode, &ioBuf, DeviceOffset, NULL);
935
936 if (NT_SUCCESS(status)) {
937 if (MajorCode == IRP_MJ_WRITE) {
938 pRequest->GetContext()->FormatWriteParams(pIoMemory, IoBufferOffsets);
939 }
940 else if (MajorCode == IRP_MJ_READ) {
941 pRequest->GetContext()->FormatReadParams(pIoMemory, IoBufferOffsets);
942 }
943 }
944
945 DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
946 "exit WDFIOTARGET 0x%p, WDFREQUEST 0x%p, %!STATUS!",
947 IoTarget, Request, status);
948
949 return status;
950 }
951
952 _Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)953 __drv_maxIRQL(PASSIVE_LEVEL)
954 NTSTATUS
955 STDCALL
956 WDFEXPORT(WdfIoTargetSendReadSynchronously)(
957 __in
958 PWDF_DRIVER_GLOBALS DriverGlobals,
959 __in
960 WDFIOTARGET IoTarget,
961 __in_opt
962 WDFREQUEST Request,
963 __in_opt
964 PWDF_MEMORY_DESCRIPTOR OutputBuffer,
965 __in_opt
966 PLONGLONG DeviceOffset,
967 __in_opt
968 PWDF_REQUEST_SEND_OPTIONS RequestOptions,
969 __out_opt
970 PULONG_PTR BytesRead
971 )
972 {
973 DDI_ENTRY();
974
975 return FxIoTargetSendIo(GetFxDriverGlobals(DriverGlobals),
976 IoTarget,
977 Request,
978 IRP_MJ_READ,
979 OutputBuffer,
980 DeviceOffset,
981 RequestOptions,
982 BytesRead);
983 }
984
985 _Must_inspect_result_
__drv_maxIRQL(DISPATCH_LEVEL)986 __drv_maxIRQL(DISPATCH_LEVEL)
987 NTSTATUS
988 STDCALL
989 WDFEXPORT(WdfIoTargetFormatRequestForRead)(
990 __in
991 PWDF_DRIVER_GLOBALS DriverGlobals,
992 __in
993 WDFIOTARGET IoTarget,
994 __in
995 WDFREQUEST Request,
996 __in_opt
997 WDFMEMORY OutputBuffer,
998 __in_opt
999 PWDFMEMORY_OFFSET OutputBufferOffsets,
1000 __in_opt
1001 PLONGLONG DeviceOffset
1002 )
1003 {
1004 DDI_ENTRY();
1005
1006 return FxIoTargetFormatIo(GetFxDriverGlobals(DriverGlobals),
1007 IoTarget,
1008 Request,
1009 IRP_MJ_READ,
1010 OutputBuffer,
1011 OutputBufferOffsets,
1012 DeviceOffset);
1013 }
1014
1015
1016 _Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)1017 __drv_maxIRQL(PASSIVE_LEVEL)
1018 NTSTATUS
1019 STDCALL
1020 WDFEXPORT(WdfIoTargetSendWriteSynchronously)(
1021 __in
1022 PWDF_DRIVER_GLOBALS DriverGlobals,
1023 __in
1024 WDFIOTARGET IoTarget,
1025 __in_opt
1026 WDFREQUEST Request,
1027 __in_opt
1028 PWDF_MEMORY_DESCRIPTOR InputBuffer,
1029 __in_opt
1030 PLONGLONG DeviceOffset,
1031 __in_opt
1032 PWDF_REQUEST_SEND_OPTIONS RequestOptions,
1033 __out_opt
1034 PULONG_PTR BytesWritten
1035 )
1036 {
1037 DDI_ENTRY();
1038
1039 return FxIoTargetSendIo(GetFxDriverGlobals(DriverGlobals),
1040 IoTarget,
1041 Request,
1042 IRP_MJ_WRITE,
1043 InputBuffer,
1044 DeviceOffset,
1045 RequestOptions,
1046 BytesWritten);
1047 }
1048
1049 _Must_inspect_result_
__drv_maxIRQL(DISPATCH_LEVEL)1050 __drv_maxIRQL(DISPATCH_LEVEL)
1051 NTSTATUS
1052 STDCALL
1053 WDFEXPORT(WdfIoTargetFormatRequestForWrite)(
1054 __in
1055 PWDF_DRIVER_GLOBALS DriverGlobals,
1056 __in
1057 WDFIOTARGET IoTarget,
1058 __in
1059 WDFREQUEST Request,
1060 __in_opt
1061 WDFMEMORY InputBuffer,
1062 __in_opt
1063 PWDFMEMORY_OFFSET InputBufferOffsets,
1064 __in_opt
1065 PLONGLONG DeviceOffset
1066 )
1067 {
1068 DDI_ENTRY();
1069
1070 return FxIoTargetFormatIo(GetFxDriverGlobals(DriverGlobals),
1071 IoTarget,
1072 Request,
1073 IRP_MJ_WRITE,
1074 InputBuffer,
1075 InputBufferOffsets,
1076 DeviceOffset);
1077 }
1078
1079 _Must_inspect_result_
1080 NTSTATUS
FxIoTargetSendIoctl(__in PFX_DRIVER_GLOBALS FxDriverGlobals,__in WDFIOTARGET IoTarget,__in_opt WDFREQUEST Request,__in ULONG Ioctl,__in BOOLEAN Internal,__in_opt PWDF_MEMORY_DESCRIPTOR InputBuffer,__in_opt PWDF_MEMORY_DESCRIPTOR OutputBuffer,__in_opt PWDF_REQUEST_SEND_OPTIONS RequestOptions,__out_opt PULONG_PTR BytesReturned)1081 FxIoTargetSendIoctl(
1082 __in
1083 PFX_DRIVER_GLOBALS FxDriverGlobals,
1084 __in
1085 WDFIOTARGET IoTarget,
1086 __in_opt
1087 WDFREQUEST Request,
1088 __in
1089 ULONG Ioctl,
1090 __in
1091 BOOLEAN Internal,
1092 __in_opt
1093 PWDF_MEMORY_DESCRIPTOR InputBuffer,
1094 __in_opt
1095 PWDF_MEMORY_DESCRIPTOR OutputBuffer,
1096 __in_opt
1097 PWDF_REQUEST_SEND_OPTIONS RequestOptions,
1098 __out_opt
1099 PULONG_PTR BytesReturned
1100 )
1101 /*++
1102
1103 Routine Description:
1104 Sends an external or internal IOCTL to the target. If the optional request
1105 is specified, this function will use it's PIRP to send the request to the
1106 target. Both buffers are optional.
1107
1108 Arguments:
1109 IoTarget - the target to which the IOCTL is being sent
1110
1111 IOCTL - the device io control value
1112
1113 Internal - if TRUE, an internal IOCTL, if FALSE, a normal IOCTL
1114
1115 InputBuffer - optional. Can be one of the following: PMDL, PVOID, or WDFMEMORY
1116
1117 OutputBuffer - optional. Can be one of the following: PMDL, PVOID, or WDFMEMORY
1118
1119 RequestOptions - optional. Specifies a timeout to be used if the sent IO
1120 does not return within the time specified.
1121
1122 BytesReturned - number of bytes transfered
1123
1124 Return Value:
1125 NTSTATUS
1126
1127 --*/
1128 {
1129 FxIoTarget* pTarget;
1130 FxRequestBuffer inputBuf, outputBuf;
1131 NTSTATUS status;
1132
1133 FxObjectHandleGetPtrAndGlobals(FxDriverGlobals,
1134 IoTarget,
1135 FX_TYPE_IO_TARGET,
1136 (PVOID*) &pTarget,
1137 &FxDriverGlobals);
1138
1139 //
1140 // Minimize the points of failure by using the stack instead of allocating
1141 // out of pool. For UMDF, request initialization can fail so we still need
1142 // to call initialize for FxSyncRequest. Initialization always succeeds for
1143 // KM.
1144 //
1145 FxIoContext context;
1146 FxSyncRequest request(FxDriverGlobals, &context, Request);
1147
1148 status = request.Initialize();
1149 if (!NT_SUCCESS(status)) {
1150 DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
1151 "Failed to initialize FxSyncRequest for WDFIOTARGET "
1152 "0x%p", IoTarget);
1153 return status;
1154 }
1155
1156 DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
1157 "enter: WDFIOTARGET 0x%p, WDFREQUEST 0x%p, IOCTL 0x%x, "
1158 "internal %d", IoTarget, Request, Ioctl, Internal);
1159
1160 //
1161 // Since we are synchronously waiting, we must be at passive
1162 //
1163 status = FxVerifierCheckIrqlLevel(FxDriverGlobals, PASSIVE_LEVEL);
1164 if (!NT_SUCCESS(status)) {
1165 return status;
1166 }
1167
1168 status = FxValidateRequestOptions(FxDriverGlobals, RequestOptions);
1169 if (!NT_SUCCESS(status)) {
1170 DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
1171 "invalid options, %!STATUS!", status);
1172 return status;
1173 }
1174
1175 if (InputBuffer != NULL) {
1176 //
1177 // This transcribes the client union into a local structure which we
1178 // can change w/out altering the client's buffer.
1179 //
1180 status = inputBuf.ValidateMemoryDescriptor(FxDriverGlobals, InputBuffer);
1181 if (!NT_SUCCESS(status)) {
1182 DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
1183 "invalid input buffer descriptor 0x%p, %!STATUS!",
1184 InputBuffer, status);
1185 return status;
1186 }
1187 }
1188
1189 if (OutputBuffer != NULL) {
1190 //
1191 // This transcribes the client union into a local structure which we
1192 // can change w/out altering the client's buffer.
1193 //
1194 status = outputBuf.ValidateMemoryDescriptor(FxDriverGlobals, OutputBuffer);
1195 if (!NT_SUCCESS(status)) {
1196 DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
1197 "invalid output buffer descriptor 0x%p, %!STATUS!",
1198 OutputBuffer, status);
1199 return status;
1200 }
1201 }
1202
1203 //
1204 // Format the next stack location
1205 //
1206 status = pTarget->FormatIoctlRequest(
1207 request.m_TrueRequest, Ioctl, Internal, &inputBuf, &outputBuf, NULL);
1208
1209 if (NT_SUCCESS(status)) {
1210 DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
1211 "WDFIOTARGET 0x%p, WDFREQUEST 0x%p being submitted",
1212 IoTarget,
1213 request.m_TrueRequest->GetTraceObjectHandle());
1214
1215 status = pTarget->SubmitSync(request.m_TrueRequest, RequestOptions);
1216
1217 if (BytesReturned != NULL) {
1218 *BytesReturned = request.m_TrueRequest->GetSubmitFxIrp()->GetInformation();
1219 }
1220 }
1221 else {
1222 DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
1223 "could not format IOCTL 0x%x request, %!STATUS!",
1224 Ioctl, status);
1225 }
1226
1227 return status;
1228 }
1229
1230 static
1231 _Must_inspect_result_
1232 NTSTATUS
FxIoTargetFormatIoctl(__in PFX_DRIVER_GLOBALS FxDriverGlobals,__in WDFIOTARGET IoTarget,__in WDFREQUEST Request,__in ULONG Ioctl,__in BOOLEAN Internal,__in_opt WDFMEMORY InputBuffer,__in_opt PWDFMEMORY_OFFSET InputBufferOffsets,__in_opt WDFMEMORY OutputBuffer,__in_opt PWDFMEMORY_OFFSET OutputBufferOffsets)1233 FxIoTargetFormatIoctl(
1234 __in
1235 PFX_DRIVER_GLOBALS FxDriverGlobals,
1236 __in
1237 WDFIOTARGET IoTarget,
1238 __in
1239 WDFREQUEST Request,
1240 __in
1241 ULONG Ioctl,
1242 __in
1243 BOOLEAN Internal,
1244 __in_opt
1245 WDFMEMORY InputBuffer,
1246 __in_opt
1247 PWDFMEMORY_OFFSET InputBufferOffsets,
1248 __in_opt
1249 WDFMEMORY OutputBuffer,
1250 __in_opt
1251 PWDFMEMORY_OFFSET OutputBufferOffsets
1252 )
1253 /*++
1254
1255 Routine Description:
1256 Formats a request as an IOCTL to be sent to the specified target. Upon
1257 success, this will take a reference on each of the WDFMEMORY handles that
1258 are passed in. This reference will be released when one of the following
1259 occurs:
1260 1) the request is completed through WdfRequestComplete
1261 2) the request is reused through WdfRequestReuse
1262 3) the request is reformatted through any target format DDI
1263
1264 Arguments:
1265 IoTarget - the target to which the IOCTL will be formatted for
1266
1267 Request - the request which will be formatted
1268
1269 IOCTL - the device IO control itself to be used
1270
1271 Internal - if TRUE, an internal IOCTL, if FALSE, a normal IOCTL
1272
1273 InputBuffer - optional. If specified, a reference counted memory handle to
1274 be placed in the next stack location.
1275
1276 InputBufferOffsets - optional. If specified, it can override the starting
1277 offset of the buffer and the length of the buffer used
1278
1279 OutputBuffer - optional. If specified, a reference counted memory handle to
1280 be placed in the next stack location.
1281
1282 OutputBufferOffsets - optional. If specified, it can override the starting
1283 offset of the buffer and the length of the buffer used
1284
1285 Return Value:
1286 NTSTATUS
1287
1288 --*/
1289 {
1290 FxIoTarget *pTarget;
1291 FxRequest *pRequest;
1292 IFxMemory *pInputMemory, *pOutputMemory;
1293 FxRequestBuffer inputBuf, outputBuf;
1294 NTSTATUS status;
1295
1296 FxObjectHandleGetPtrAndGlobals(FxDriverGlobals,
1297 IoTarget,
1298 FX_TYPE_IO_TARGET,
1299 (PVOID*) &pTarget,
1300 &FxDriverGlobals);
1301
1302 DoTraceLevelMessage(
1303 FxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
1304 "enter: WDFIOTARGET 0x%p, WDFREQUEST 0x%p, IOCTL 0x%x, internal %d, input "
1305 "WDFMEMORY 0x%p, output WDFMEMORY 0x%p",
1306 IoTarget, Request, Ioctl, Internal, InputBuffer, OutputBuffer);
1307
1308 FxObjectHandleGetPtr(FxDriverGlobals,
1309 Request,
1310 FX_TYPE_REQUEST,
1311 (PVOID*) &pRequest);
1312
1313 if (InputBuffer != NULL) {
1314 FxObjectHandleGetPtr(FxDriverGlobals,
1315 InputBuffer,
1316 IFX_TYPE_MEMORY,
1317 (PVOID*) &pInputMemory);
1318
1319 status = pInputMemory->ValidateMemoryOffsets(InputBufferOffsets);
1320 if (!NT_SUCCESS(status)) {
1321 DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
1322 "Invalid input memory offsets, %!STATUS!",
1323 status);
1324 return status;
1325 }
1326
1327 //
1328 // This transcribes the client union into a local structure which we
1329 // can change w/out altering the client's buffer.
1330 //
1331 inputBuf.SetMemory(pInputMemory, InputBufferOffsets);
1332 }
1333
1334 if (OutputBuffer != NULL) {
1335 FxObjectHandleGetPtr(FxDriverGlobals,
1336 OutputBuffer,
1337 IFX_TYPE_MEMORY,
1338 (PVOID*) &pOutputMemory);
1339
1340 status = pOutputMemory->ValidateMemoryOffsets(OutputBufferOffsets);
1341 if (!NT_SUCCESS(status)) {
1342 DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
1343 "Invalid output memory offsets, %!STATUS!",
1344 status);
1345 return status;
1346 }
1347
1348 //
1349 // This transcribes the client union into a local structure which we
1350 // can change w/out altering the client's buffer.
1351 //
1352 outputBuf.SetMemory(pOutputMemory, OutputBufferOffsets);
1353 }
1354
1355 //
1356 // format the next stack location
1357 //
1358 status = pTarget->FormatIoctlRequest(
1359 pRequest, Ioctl, Internal, &inputBuf, &outputBuf, NULL);
1360
1361 if (NT_SUCCESS(status)) {
1362 FxRequestContext* pContext;
1363
1364 //
1365 // Upon a successful format, a FxRequestContext will have been
1366 // associated with the FxRequest
1367 //
1368 pContext = pRequest->GetContext();
1369
1370 pContext->m_CompletionParams.Parameters.Ioctl.IoControlCode = Ioctl;
1371
1372 if (Internal) {
1373 pContext->m_CompletionParams.Type = WdfRequestTypeDeviceControlInternal;
1374 }
1375 else {
1376 pContext->m_CompletionParams.Type = WdfRequestTypeDeviceControl;
1377 }
1378
1379 pContext->m_CompletionParams.Parameters.Ioctl.Input.Buffer = InputBuffer;
1380 if (InputBufferOffsets != NULL) {
1381 pContext->m_CompletionParams.Parameters.Ioctl.Input.Offset =
1382 InputBufferOffsets->BufferOffset;
1383 }
1384
1385 pContext->m_CompletionParams.Parameters.Ioctl.Output.Buffer = OutputBuffer;
1386 if (OutputBufferOffsets != NULL) {
1387 pContext->m_CompletionParams.Parameters.Ioctl.Output.Offset =
1388 OutputBufferOffsets->BufferOffset;
1389 }
1390 }
1391
1392 DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
1393 "Exit WDFIOTARGET 0x%p, WDFREQUEST 0x%p, %!STATUS!",
1394 IoTarget, Request, status);
1395
1396 return status;
1397 }
1398
1399 _Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)1400 __drv_maxIRQL(PASSIVE_LEVEL)
1401 NTSTATUS
1402 STDCALL
1403 WDFEXPORT(WdfIoTargetSendIoctlSynchronously)(
1404 __in
1405 PWDF_DRIVER_GLOBALS DriverGlobals,
1406 __in
1407 WDFIOTARGET IoTarget,
1408 __in_opt
1409 WDFREQUEST Request,
1410 __in
1411 ULONG Ioctl,
1412 __in_opt
1413 PWDF_MEMORY_DESCRIPTOR InputBuffer,
1414 __in_opt
1415 PWDF_MEMORY_DESCRIPTOR OutputBuffer,
1416 __in_opt
1417 PWDF_REQUEST_SEND_OPTIONS RequestOptions,
1418 __out_opt
1419 PULONG_PTR BytesReturned
1420 )
1421 {
1422 DDI_ENTRY();
1423
1424 return FxIoTargetSendIoctl(
1425 GetFxDriverGlobals(DriverGlobals),
1426 IoTarget,
1427 Request,
1428 Ioctl,
1429 FALSE,
1430 InputBuffer,
1431 OutputBuffer,
1432 RequestOptions,
1433 BytesReturned
1434 );
1435 }
1436
1437 _Must_inspect_result_
__drv_maxIRQL(DISPATCH_LEVEL)1438 __drv_maxIRQL(DISPATCH_LEVEL)
1439 NTSTATUS
1440 STDCALL
1441 WDFEXPORT(WdfIoTargetFormatRequestForIoctl)(
1442 __in
1443 PWDF_DRIVER_GLOBALS DriverGlobals,
1444 __in
1445 WDFIOTARGET IoTarget,
1446 __in
1447 WDFREQUEST Request,
1448 __in
1449 ULONG Ioctl,
1450 __in_opt
1451 WDFMEMORY InputBuffer,
1452 __in_opt
1453 PWDFMEMORY_OFFSET InputBufferOffsets,
1454 __in_opt
1455 WDFMEMORY OutputBuffer,
1456 __in_opt
1457 PWDFMEMORY_OFFSET OutputBufferOffsets
1458 )
1459 {
1460 DDI_ENTRY();
1461
1462 return FxIoTargetFormatIoctl(GetFxDriverGlobals(DriverGlobals),
1463 IoTarget,
1464 Request,
1465 Ioctl,
1466 FALSE,
1467 InputBuffer,
1468 InputBufferOffsets,
1469 OutputBuffer,
1470 OutputBufferOffsets);
1471 }
1472
1473 _Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)1474 __drv_maxIRQL(PASSIVE_LEVEL)
1475 NTSTATUS
1476 STDCALL
1477 WDFEXPORT(WdfIoTargetSendInternalIoctlSynchronously)(
1478 __in
1479 PWDF_DRIVER_GLOBALS DriverGlobals,
1480 __in
1481 WDFIOTARGET IoTarget,
1482 __in_opt
1483 WDFREQUEST Request,
1484 __in
1485 ULONG Ioctl,
1486 __in_opt
1487 PWDF_MEMORY_DESCRIPTOR InputBuffer,
1488 __in_opt
1489 PWDF_MEMORY_DESCRIPTOR OutputBuffer,
1490 __in_opt
1491 PWDF_REQUEST_SEND_OPTIONS RequestOptions,
1492 __out_opt
1493 PULONG_PTR BytesReturned
1494 )
1495 {
1496 DDI_ENTRY();
1497
1498 return FxIoTargetSendIoctl(
1499 GetFxDriverGlobals(DriverGlobals),
1500 IoTarget,
1501 Request,
1502 Ioctl,
1503 TRUE,
1504 InputBuffer,
1505 OutputBuffer,
1506 RequestOptions,
1507 BytesReturned
1508 );
1509 }
1510
1511 _Must_inspect_result_
__drv_maxIRQL(DISPATCH_LEVEL)1512 __drv_maxIRQL(DISPATCH_LEVEL)
1513 NTSTATUS
1514 STDCALL
1515 WDFEXPORT(WdfIoTargetFormatRequestForInternalIoctl)(
1516 __in
1517 PWDF_DRIVER_GLOBALS DriverGlobals,
1518 __in
1519 WDFIOTARGET IoTarget,
1520 __in
1521 WDFREQUEST Request,
1522 __in
1523 ULONG Ioctl,
1524 __in_opt
1525 WDFMEMORY InputBuffer,
1526 __in_opt
1527 PWDFMEMORY_OFFSET InputBufferOffsets,
1528 __in_opt
1529 WDFMEMORY OutputBuffer,
1530 __in_opt
1531 PWDFMEMORY_OFFSET OutputBufferOffsets
1532 )
1533 {
1534 DDI_ENTRY();
1535
1536 return FxIoTargetFormatIoctl(GetFxDriverGlobals(DriverGlobals),
1537 IoTarget,
1538 Request,
1539 Ioctl,
1540 TRUE,
1541 InputBuffer,
1542 InputBufferOffsets,
1543 OutputBuffer,
1544 OutputBufferOffsets);
1545 }
1546
1547 _Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)1548 __drv_maxIRQL(PASSIVE_LEVEL)
1549 NTSTATUS
1550 STDCALL
1551 WDFEXPORT(WdfIoTargetSendInternalIoctlOthersSynchronously)(
1552 __in
1553 PWDF_DRIVER_GLOBALS DriverGlobals,
1554 __in
1555 WDFIOTARGET IoTarget,
1556 __in_opt
1557 WDFREQUEST Request,
1558 __in
1559 ULONG Ioctl,
1560 __in_opt
1561 PWDF_MEMORY_DESCRIPTOR OtherArg1,
1562 __in_opt
1563 PWDF_MEMORY_DESCRIPTOR OtherArg2,
1564 __in_opt
1565 PWDF_MEMORY_DESCRIPTOR OtherArg4,
1566 __in_opt
1567 PWDF_REQUEST_SEND_OPTIONS RequestOptions,
1568 __out_opt
1569 PULONG_PTR BytesReturned
1570 )
1571 /*++
1572
1573 Routine Description:
1574 Sends an internal IOCTL to the target synchronously. Since all 3 buffers can
1575 be used, we cannot overload WdfIoTargetSendInternalIoctlSynchronously since
1576 it can only take 2 buffers.
1577
1578 Arguments:
1579 IoTarget - the target to which the request will be sent
1580
1581 Request - optional. If specified, the request's PIRP will be used to send
1582 the i/o to the target.
1583
1584 Ioctl - internal ioctl value to send
1585
1586 OtherArg1
1587 OtherArg2
1588 OtherArg4 - arguments to use in the stack locations's Others field. There
1589 is no OtherArg3 because 3 is where the IOCTL value is written.
1590 All buffers are optional.
1591
1592 RequestOptions - optional. If specified, the timeout indicated will be used
1593 if the request exceeds the timeout.
1594
1595 BytesReturned - the number of bytes returned by the target
1596
1597 Return Value:
1598 NTSTATUS
1599
1600 --*/
1601 {
1602 DDI_ENTRY();
1603
1604 PFX_DRIVER_GLOBALS pFxDriverGlobals;
1605 FxIoTarget* pTarget;
1606 FxRequestBuffer args[FX_REQUEST_NUM_OTHER_PARAMS];
1607 NTSTATUS status;
1608
1609 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
1610 IoTarget,
1611 FX_TYPE_IO_TARGET,
1612 (PVOID*) &pTarget,
1613 &pFxDriverGlobals);
1614
1615 //
1616 // Minimize the points of failure by using the stack instead of allocating
1617 // out of pool. For UMDF, request initialization can fail so we still need
1618 // to call initialize for FxSyncRequest. Initialization always succeeds for
1619 // KM.
1620 //
1621 FxInternalIoctlOthersContext context;
1622 FxSyncRequest request(pFxDriverGlobals, &context, Request);
1623
1624 status = request.Initialize();
1625 if (!NT_SUCCESS(status)) {
1626 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
1627 "Failed to initialize FxSyncRequest for WDFIOTARGET "
1628 "0x%p", IoTarget);
1629 return status;
1630 }
1631
1632 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
1633 "enter: WDFIOTARGET 0x%p, WDFREQUEST 0x%p, IOCTL 0x%x, Args %p %p %p",
1634 IoTarget, Request, Ioctl, OtherArg1, OtherArg2, OtherArg4);
1635
1636 //
1637 // Since we are waiting synchronously, we must be at pasisve
1638 //
1639 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
1640 if (!NT_SUCCESS(status)) {
1641 return status;
1642 }
1643
1644 status = FxValidateRequestOptions(pFxDriverGlobals, RequestOptions);
1645 if (!NT_SUCCESS(status)) {
1646 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
1647 "Invalid options, %!STATUS!", status);
1648 return status;
1649 }
1650
1651 ULONG i;
1652
1653 i = 0;
1654 if (OtherArg1 != NULL) {
1655 //
1656 // This transcribes the client union into a local structure which we
1657 // can change w/out altering the client's buffer.
1658 //
1659 status = args[i].ValidateMemoryDescriptor(pFxDriverGlobals, OtherArg1);
1660 if (!NT_SUCCESS(status)) {
1661 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
1662 "invalid OtherArg1 buffer descriptor 0x%p, %!STATUS!",
1663 OtherArg1, status);
1664 return status;
1665 }
1666 }
1667
1668 i++;
1669 if (OtherArg2 != NULL) {
1670 //
1671 // This transcribes the client union into a local structure which we
1672 // can change w/out altering the client's buffer.
1673 //
1674 status = args[i].ValidateMemoryDescriptor(pFxDriverGlobals, OtherArg2);
1675 if (!NT_SUCCESS(status)) {
1676 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
1677 "invalid OtherArg2 buffer descriptor 0x%p, %!STATUS!",
1678 OtherArg2, status);
1679 return status;
1680 }
1681 }
1682
1683 i++;
1684 if (OtherArg4 != NULL) {
1685 //
1686 // This transcribes the client union into a local structure which we
1687 // can change w/out altering the client's buffer.
1688 //
1689 status = args[i].ValidateMemoryDescriptor(pFxDriverGlobals, OtherArg4);
1690 if (!NT_SUCCESS(status)) {
1691 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
1692 "invalid OtherArg4 buffer descriptor 0x%p, %!STATUS!",
1693 OtherArg4, status);
1694 return status;
1695 }
1696 }
1697
1698 //
1699 // Format the next stack location
1700 //
1701 status = pTarget->FormatInternalIoctlOthersRequest(request.m_TrueRequest,
1702 Ioctl,
1703 args);
1704
1705 if (NT_SUCCESS(status)) {
1706 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
1707 "WDFIOTARGET 0x%p, WDFREQUEST 0x%p being submitted",
1708 IoTarget,
1709 request.m_TrueRequest->GetTraceObjectHandle());
1710
1711 status = pTarget->SubmitSync(request.m_TrueRequest, RequestOptions);
1712
1713 if (BytesReturned != NULL) {
1714 *BytesReturned = request.m_TrueRequest->GetSubmitFxIrp()->GetInformation();
1715 }
1716 }
1717 else {
1718 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
1719 "Could not format IOCTL 0x%x request, %!STATUS!",
1720 Ioctl, status);
1721 }
1722
1723 return status;
1724 }
1725
1726 _Must_inspect_result_
__drv_maxIRQL(DISPATCH_LEVEL)1727 __drv_maxIRQL(DISPATCH_LEVEL)
1728 NTSTATUS
1729 STDCALL
1730 WDFEXPORT(WdfIoTargetFormatRequestForInternalIoctlOthers)(
1731 __in
1732 PWDF_DRIVER_GLOBALS DriverGlobals,
1733 __in
1734 WDFIOTARGET IoTarget,
1735 __in
1736 WDFREQUEST Request,
1737 __in
1738 ULONG Ioctl,
1739 __in_opt
1740 WDFMEMORY OtherArg1,
1741 __in_opt
1742 PWDFMEMORY_OFFSET OtherArg1Offsets,
1743 __in_opt
1744 WDFMEMORY OtherArg2,
1745 __in_opt
1746 PWDFMEMORY_OFFSET OtherArg2Offsets,
1747 __in_opt
1748 WDFMEMORY OtherArg4,
1749 __in_opt
1750 PWDFMEMORY_OFFSET OtherArg4Offsets
1751 )
1752 /*++
1753
1754 Routine Description:
1755 Formats an internal IOCTL so that it can sent to the target. Since all 3
1756 buffers can be used, we cannot overload
1757 WdfIoTargetFormatRequestForInternalIoctlOthers since it can only take 2 buffers.
1758
1759 Upon success, this will take a reference on each of the WDFMEMORY handles that
1760 are passed in. This reference will be released when one of the following
1761 occurs:
1762 1) the request is completed through WdfRequestComplete
1763 2) the request is reused through WdfRequestReuse
1764 3) the request is reformatted through any target format DDI
1765
1766 Arguments:
1767 IoTarget - the target to which the request will be sent
1768
1769 Request - the request to be formatted
1770
1771 Ioctl - internal ioctl value to send
1772
1773 OtherArg1
1774 OtherArg2
1775 OtherArg4 - arguments to use in the stack locations's Others field. There
1776 is no OtherArg3 because 3 is where the IOCTL value is written.
1777 All buffers are optional
1778
1779 OterhArgXOffsets - offset into each buffer which can override the starting
1780 offset of the buffer. Length does not matter since
1781 there is no way of generically describing the length of
1782 each of the 3 buffers in the PIRP
1783
1784 Return Value:
1785 NTSTATUS
1786
1787 --*/
1788 {
1789 DDI_ENTRY();
1790
1791 PFX_DRIVER_GLOBALS pFxDriverGlobals;
1792 FxIoTarget *pTarget;
1793 FxRequest *pRequest;
1794 IFxMemory *pMemory[FX_REQUEST_NUM_OTHER_PARAMS];
1795 FxRequestBuffer args[FX_REQUEST_NUM_OTHER_PARAMS];
1796 WDFMEMORY memoryHandles[FX_REQUEST_NUM_OTHER_PARAMS];
1797 PWDFMEMORY_OFFSET offsets[FX_REQUEST_NUM_OTHER_PARAMS];
1798 NTSTATUS status;
1799 ULONG i;
1800 FxInternalIoctlParams InternalIoctlParams;
1801
1802 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
1803 IoTarget,
1804 FX_TYPE_IO_TARGET,
1805 (PVOID*) &pTarget,
1806 &pFxDriverGlobals);
1807
1808 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
1809 "Enter: WDFIOTARGET 0x%p, WDFREQUEST 0x%p, IOCTL 0x%x, "
1810 "WDFMEMORY 1 0x%p, 2 0x%p, 3 0x%p",
1811 IoTarget, Request, Ioctl, OtherArg1, OtherArg2,
1812 OtherArg4);
1813
1814 FxObjectHandleGetPtr(pFxDriverGlobals,
1815 Request,
1816 FX_TYPE_REQUEST,
1817 (PVOID*) &pRequest);
1818
1819 i = 0;
1820 InternalIoctlParams.Argument1 = memoryHandles[i] = OtherArg1;
1821 offsets[i] = OtherArg1Offsets;
1822
1823 InternalIoctlParams.Argument2 = memoryHandles[++i] = OtherArg2;
1824 offsets[i] = OtherArg2Offsets;
1825
1826 InternalIoctlParams.Argument4 = memoryHandles[++i] = OtherArg4;
1827 offsets[i] = OtherArg4Offsets;
1828
1829 for (i = 0; i < FX_REQUEST_NUM_OTHER_PARAMS; i++) {
1830 if (memoryHandles[i] != NULL) {
1831
1832 FxObjectHandleGetPtr(pFxDriverGlobals,
1833 memoryHandles[i],
1834 IFX_TYPE_MEMORY,
1835 (PVOID*) &pMemory[i]);
1836
1837 status = pMemory[i]->ValidateMemoryOffsets(offsets[i]);
1838 if (!NT_SUCCESS(status)) {
1839 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
1840 "Invalid OtherArg%d memory offsets, %!STATUS!",
1841 i+1, status);
1842 return status;
1843 }
1844
1845 //
1846 // This transcribes the client union into a local structure which we
1847 // can change w/out altering the client's buffer.
1848 //
1849 args[i].SetMemory(pMemory[i], offsets[i]);
1850 }
1851 }
1852
1853 status = pTarget->FormatInternalIoctlOthersRequest(pRequest, Ioctl, args);
1854 if (NT_SUCCESS(status)) {
1855 pRequest->GetContext()->FormatOtherParams(&InternalIoctlParams);
1856 }
1857 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
1858 "Exit: WDFIOTARGET %p, WDFREQUEST %p, IOCTL 0x%x, "
1859 "Arg Handles %p %p %p, status %!STATUS!",
1860 IoTarget, Request, Ioctl, OtherArg1, OtherArg2,
1861 OtherArg4, status);
1862
1863 return status;
1864 }
1865
1866 _Must_inspect_result_
_IRQL_requires_max_(DISPATCH_LEVEL)1867 _IRQL_requires_max_(DISPATCH_LEVEL)
1868 NTSTATUS
1869 STDCALL
1870 WDFEXPORT(WdfIoTargetSelfAssignDefaultIoQueue)(
1871 _In_
1872 PWDF_DRIVER_GLOBALS DriverGlobals,
1873 _In_
1874 WDFIOTARGET IoTarget,
1875 _In_
1876 WDFQUEUE Queue
1877 )
1878
1879 /*++
1880
1881 Routine Description:
1882
1883 Assigns a default queue for the Self IO Target.
1884
1885 By default the IO sent to the Self IO Target is dispatched ot the
1886 client's default / top level queue.
1887
1888 This routine assigns a default queue for the Intenral I/O target.
1889 If a client calls this API, all the I/O directed to the Self IO target
1890 is dispatched to the queue specified.
1891
1892 Arguments:
1893
1894 IoTarget - Handle to the Self Io Target.
1895
1896 Queue - Handle to a queue that is being assigned as the default queue for
1897 the Self io target.
1898
1899 Returns:
1900
1901 NTSTATUS
1902
1903 --*/
1904
1905 {
1906 DDI_ENTRY();
1907
1908 PFX_DRIVER_GLOBALS pGlobals;
1909 NTSTATUS status;
1910 FxIoTargetSelf* pTargetSelf;
1911 FxDevice* pDevice;
1912 FxIoQueue* pFxIoQueue;
1913
1914 pDevice = NULL;
1915 pFxIoQueue = NULL;
1916
1917 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
1918 IoTarget,
1919 FX_TYPE_IO_TARGET_SELF,
1920 (PVOID *) &pTargetSelf,
1921 &pGlobals);
1922
1923 pDevice = pTargetSelf->GetDevice();
1924
1925 //
1926 // Validate the Queue handle
1927 //
1928 FxObjectHandleGetPtr(pGlobals,
1929 Queue,
1930 FX_TYPE_QUEUE,
1931 (PVOID*)&pFxIoQueue);
1932
1933 if (pDevice != pFxIoQueue->GetDevice()) {
1934 status = STATUS_INVALID_DEVICE_REQUEST;
1935
1936 DoTraceLevelMessage(
1937 pGlobals, TRACE_LEVEL_ERROR, TRACINGIO,
1938 "Input WDFQUEUE 0x%p belongs to WDFDEVICE 0x%p, but "
1939 "Self Io Target 0x%p corresponds to the WDFDEVICE 0x%p, %!STATUS!",
1940 Queue, pFxIoQueue->GetDevice()->GetHandle(), IoTarget,
1941 pDevice->GetHandle(), status);
1942
1943 return status;
1944 }
1945
1946 if (pDevice->IsLegacy()) {
1947 //
1948 // This is a controldevice. Make sure the create is called after the device
1949 // is initialized and ready to accept I/O.
1950 //
1951 MxDeviceObject deviceObject(pDevice->GetDeviceObject());
1952 if ((deviceObject.GetFlags() & DO_DEVICE_INITIALIZING) == 0x0) {
1953
1954 status = STATUS_INVALID_DEVICE_STATE;
1955 DoTraceLevelMessage(
1956 pGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
1957 "Queue cannot be configured for automatic dispatching"
1958 " after WdfControlDeviceFinishInitializing"
1959 "is called on the WDFDEVICE %p is called %!STATUS!",
1960 pDevice->GetHandle(),
1961 status);
1962 return status;
1963 }
1964 }
1965 else {
1966 //
1967 // This is either FDO or PDO. Make sure it's not started yet.
1968 //
1969 if (pDevice->GetDevicePnpState() != WdfDevStatePnpInit) {
1970 status = STATUS_INVALID_DEVICE_STATE;
1971 DoTraceLevelMessage(
1972 pGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
1973 "Queue cannot be configured for automatic dispatching"
1974 "after the WDFDEVICE %p is started, %!STATUS!",
1975 pDevice->GetHandle(), status);
1976 return status;
1977 }
1978 }
1979
1980 pTargetSelf->SetDispatchQueue(pFxIoQueue);
1981
1982 return STATUS_SUCCESS;
1983 }
1984
__drv_maxIRQL(DISPATCH_LEVEL)1985 __drv_maxIRQL(DISPATCH_LEVEL)
1986 HANDLE
1987 STDCALL
1988 WDFEXPORT(WdfIoTargetWdmGetTargetFileHandle)(
1989 __in
1990 PWDF_DRIVER_GLOBALS DriverGlobals,
1991 __in
1992 WDFIOTARGET IoTarget
1993 )
1994 /*++
1995
1996 Routine Description:
1997 Returns the file handle that the target represents. For KMDF, the handle is a kernel
1998 handle, so it is not tied to any process context. For UMDF it is a Win32 handle opened
1999 in the host process context. Not all targets have a file handle associated with them,
2000 so NULL is a valid return value that does not indicate error.
2001
2002 Arguments:
2003 IoTarget - target whose file handle is being returned
2004
2005 Return Value:
2006 A valid kernel/win32 handle or NULL
2007
2008 --*/
2009 {
2010 PFX_DRIVER_GLOBALS pFxDriverGlobals;
2011 FxIoTargetRemote* pTarget;
2012 PVOID handle;
2013
2014 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
2015 IoTarget,
2016 FX_TYPE_IO_TARGET_REMOTE,
2017 (PVOID*) &pTarget,
2018 &pFxDriverGlobals);
2019
2020 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
2021 "enter WDFIOTARGET 0x%p", IoTarget);
2022
2023 handle = pTarget->GetTargetHandle();
2024
2025 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
2026 "exit WDFIOTARGET 0x%p, WDM file handle 0x%p",
2027 IoTarget, handle);
2028
2029 return handle;
2030 }
2031
2032
2033 } // extern "C"
2034