1 /*++
2
3 Copyright (c) Microsoft Corporation
4
5 Module Name:
6
7 FxIoTargetRemote.cpp
8
9 Abstract:
10
11 Author:
12
13 Environment:
14
15 Both kernel and user mode
16
17 Revision History:
18
19 --*/
20
21 #include "../fxtargetsshared.hpp"
22
23 extern "C" {
24 // #include "FxIoTargetRemote.tmh"
25 }
26
27 #include <initguid.h>
28 #include "wdmguid.h"
29
30
FxIoTargetRemote(__in PFX_DRIVER_GLOBALS FxDriverGlobals)31 FxIoTargetRemote::FxIoTargetRemote(
32 __in PFX_DRIVER_GLOBALS FxDriverGlobals
33 ) :
34 FxIoTarget(FxDriverGlobals, sizeof(FxIoTargetRemote)),
35 m_EvtQueryRemove(FxDriverGlobals),
36 m_EvtRemoveCanceled(FxDriverGlobals),
37 m_EvtRemoveComplete(FxDriverGlobals)
38 {
39
40 //
41 // No automatic state changes based on the pnp state changes of our own
42 // device stack. The one exception is remove where we need to shut
43 // everything down.
44 //
45 m_InStack = FALSE;
46
47 m_ClearedPointers = NULL;
48 m_OpenState = FxIoTargetRemoteOpenStateClosed;
49
50 m_TargetHandle = NULL;
51
52 m_EvtQueryRemove.m_Method = NULL;
53 m_EvtRemoveCanceled.m_Method = NULL;
54 m_EvtRemoveComplete.m_Method = NULL;
55
56 #if (FX_CORE_MODE == FX_CORE_KERNEL_MODE)
57 m_TargetNotifyHandle = NULL;
58 #elif (FX_CORE_MODE == FX_CORE_USER_MODE)
59 m_TargetNotifyHandle = WUDF_TARGET_CONTEXT_INVALID;
60
61 m_pIoDispatcher = NULL;
62 m_pRemoteDispatcher = NULL;
63 m_NotificationCallback = NULL;
64 #endif
65 }
66
~FxIoTargetRemote()67 FxIoTargetRemote::~FxIoTargetRemote()
68 {
69 }
70
71 _Must_inspect_result_
72 NTSTATUS
_Create(__in PFX_DRIVER_GLOBALS FxDriverGlobals,__in PWDF_OBJECT_ATTRIBUTES Attributes,__in CfxDeviceBase * Device,__out FxIoTargetRemote ** Target)73 FxIoTargetRemote::_Create(
74 __in PFX_DRIVER_GLOBALS FxDriverGlobals,
75 __in PWDF_OBJECT_ATTRIBUTES Attributes,
76 __in CfxDeviceBase* Device,
77 __out FxIoTargetRemote** Target
78 )
79 {
80 FxIoTargetRemote* pTarget;
81 FxObject* pParent;
82 WDFOBJECT hTarget;
83 NTSTATUS status;
84
85 *Target = NULL;
86
87 if (Attributes == NULL || Attributes->ParentObject == NULL) {
88 pParent = Device;
89 }
90 else {
91 CfxDeviceBase* pSearchDevice;
92
93 FxObjectHandleGetPtr(FxDriverGlobals,
94 Attributes->ParentObject,
95 FX_TYPE_OBJECT,
96 (PVOID*) &pParent);
97
98 pSearchDevice = FxDeviceBase::_SearchForDevice(pParent, NULL);
99
100 if (pSearchDevice == NULL) {
101 status = STATUS_INVALID_DEVICE_REQUEST;
102
103 DoTraceLevelMessage(
104 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
105 "Attributes->ParentObject 0x%p must have WDFDEVICE as an "
106 "eventual ancestor, %!STATUS!",
107 Attributes->ParentObject, status);
108
109 return status;
110 }
111 else if (pSearchDevice != Device) {
112 status = STATUS_INVALID_DEVICE_REQUEST;
113
114 DoTraceLevelMessage(
115 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
116 "Attributes->ParentObject 0x%p ancestor is WDFDEVICE %p, but "
117 "not the same WDFDEVICE 0x%p passed to WdfIoTargetCreate, "
118 "%!STATUS!",
119 Attributes->ParentObject, pSearchDevice->GetHandle(),
120 Device->GetHandle(), status);
121
122 return status;
123 }
124 }
125
126 pTarget = new (FxDriverGlobals, Attributes)
127 FxIoTargetRemote(FxDriverGlobals);
128
129 if (pTarget == NULL) {
130 status = STATUS_INSUFFICIENT_RESOURCES;
131 DoTraceLevelMessage(
132 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
133 "Could not allocate memory for target, %!STATUS!", status);
134 return status;
135 }
136
137 //
138 // initialize the new target
139 //
140 status = pTarget->InitRemote(Device);
141 if (!NT_SUCCESS(status)) {
142 return status;
143 }
144
145 //
146 // Commit and apply the attributes
147 //
148 status = pTarget->Commit(Attributes, &hTarget, pParent);
149
150 if (NT_SUCCESS(status)) {
151 *Target = pTarget;
152 }
153 else {
154 //
155 // This will properly clean up the target's state and free it
156 //
157 DoTraceLevelMessage(
158 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
159 "Commit failed for target, %!STATUS!", status);
160 pTarget->DeleteFromFailedCreate();
161 }
162
163 return status;
164 }
165
166 NTSTATUS
InitRemote(__in FxDeviceBase * Device)167 FxIoTargetRemote::InitRemote(
168 __in FxDeviceBase* Device
169 )
170 {
171 NTSTATUS status;
172
173 //
174 // do the base class mode-specific initialization
175 //
176 status = FxIoTarget::InitModeSpecific(Device); // __super call
177 if (!NT_SUCCESS(status)) {
178 return status;
179 }
180
181 //
182 // Do mode-specific initilialization
183 //
184 status = InitRemoteModeSpecific(Device);
185 if (!NT_SUCCESS(status)) {
186 return status;
187 }
188
189 m_Driver = Device->GetDriver();
190
191 SetDeviceBase(Device);
192 m_InStackDevice = Device->GetDeviceObject();
193
194 (void) Device->AddIoTarget(this);
195
196 return STATUS_SUCCESS;
197 }
198
199 _Must_inspect_result_
200 NTSTATUS
Open(__in PWDF_IO_TARGET_OPEN_PARAMS OpenParams)201 FxIoTargetRemote::Open(
202 __in PWDF_IO_TARGET_OPEN_PARAMS OpenParams
203 )
204 {
205 FxIoTargetRemoveOpenParams params, *pParams;
206 UNICODE_STRING name;
207 LIST_ENTRY pended;
208 WDF_IO_TARGET_OPEN_TYPE type;
209 NTSTATUS status;
210 BOOLEAN close, reopen;
211 PVOID pEa;
212 ULONG eaLength;
213 KIRQL irql;
214
215 RtlZeroMemory(&name, sizeof(name));
216 close = FALSE;
217 reopen = OpenParams->Type == WdfIoTargetOpenReopen ? TRUE : FALSE;
218
219 pEa = NULL;
220 eaLength = 0;
221
222 //
223 // We only support reopening using stored settings when we open by name
224 //
225 if (reopen && m_OpenParams.OpenType != WdfIoTargetOpenByName) {
226 status = STATUS_INVALID_DEVICE_REQUEST;
227 DoTraceLevelMessage(
228 GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
229 "Reopen only supported if the open type is WdfIoTargetOpenByName WDFIOTARGET %p %!STATUS!",
230 GetObjectHandle(), status);
231 return status;
232 }
233
234 //
235 // Must preallocate all settings now
236 //
237 if (reopen) {
238 //
239 // convert the type into the type used for the previous open
240 //
241 type = m_OpenParams.OpenType;
242 pParams = &m_OpenParams;
243 }
244 else {
245 type = OpenParams->Type;
246 pParams = ¶ms;
247
248 if (OpenParams->Type == WdfIoTargetOpenByName) {
249
250 status = FxDuplicateUnicodeString(GetDriverGlobals(),
251 &OpenParams->TargetDeviceName,
252 &name);
253 if (!NT_SUCCESS(status)) {
254 DoTraceLevelMessage(
255 GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
256 "Could not allocate memory for target name for WDFIOTARGET %p",
257 GetObjectHandle());
258 goto Done;
259 }
260 if (OpenParams->EaBuffer != NULL && OpenParams->EaBufferLength > 0) {
261
262 pEa = FxPoolAllocate(GetDriverGlobals(),
263 PagedPool,
264 OpenParams->EaBufferLength);
265
266 if (pEa == NULL) {
267 DoTraceLevelMessage(
268 GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
269 "Could not allocate memory for target name "
270 "for WDFIOTARGET %p", GetObjectHandle());
271 status = STATUS_INSUFFICIENT_RESOURCES;
272 goto Done;
273 }
274 else {
275 eaLength = OpenParams->EaBufferLength;
276 RtlCopyMemory(pEa, OpenParams->EaBuffer, eaLength);
277 }
278 }
279 }
280 }
281
282 Lock(&irql);
283
284 if (m_State == WdfIoTargetDeleted) {
285 DoTraceLevelMessage(
286 GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
287 "Opening WDFIOTARGET %p which is removed, state %d",
288 GetObjectHandle(), m_State);
289 status = STATUS_INVALID_DEVICE_STATE;
290 }
291 else if (m_OpenState != FxIoTargetRemoteOpenStateClosed) {
292 //
293 // We are either open or are opening
294 //
295 DoTraceLevelMessage(
296 GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
297 "Opening an already open WDFIOTARGET %p, open state %d",
298 GetObjectHandle(), m_OpenState);
299 status = STATUS_INVALID_DEVICE_STATE;
300 }
301 else {
302 DoTraceLevelMessage(
303 GetDriverGlobals(), TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
304 "Opening WDFIOTARGET %p", GetObjectHandle());
305
306 //
307 // Clear the event so that if something is waiting on the state
308 // transition, they will block until we are done.
309 //
310 m_OpenedEvent.Clear();
311
312 m_OpenState = FxIoTargetRemoteOpenStateOpening;
313 status = STATUS_SUCCESS;
314 }
315 Unlock(irql);
316
317 if (!NT_SUCCESS(status)) {
318 goto Done;
319 }
320
321 ASSERT(m_TargetFileObject == NULL);
322 ASSERT(m_TargetDevice == NULL);
323 ASSERT(m_TargetPdo == NULL);
324 ASSERT(m_TargetHandle == NULL);
325
326 //
327 // m_TargetNotifyHandle can be a valid value if the caller has previously
328 // opened the target, received a query remove, then a cancel remove, and
329 // is now reopening the target.
330 //
331 UnregisterForPnpNotification(m_TargetNotifyHandle);
332 ResetTargetNotifyHandle();
333
334 //
335 // Only clear the open parameters if we are not attempting a reopen.
336 //
337 if (reopen == FALSE) {
338 m_OpenParams.Clear();
339 }
340
341 switch (type) {
342 case WdfIoTargetOpenUseExistingDevice:
343 KMDF_ONLY_CODE_PATH_ASSERT();
344
345 //
346 // OpenParams must be non NULL b/c we can't reopen a target with a
347 // previous device object.
348 //
349 ASSERT(OpenParams->Type == WdfIoTargetOpenUseExistingDevice);
350
351 m_TargetDevice = (MdDeviceObject) OpenParams->TargetDeviceObject;
352 m_TargetFileObject = (MdFileObject) OpenParams->TargetFileObject;
353 m_TargetHandle = NULL;
354
355 //
356 // By taking a manual reference here, we simplify the code in
357 // FxIoTargetRemote::Close where we can assume there is an outstanding
358 // reference on the PFILE_OBJECT at all times as long as we have a non
359 // NULL pointer.
360 //
361 if (m_TargetFileObject != NULL) {
362 Mx::MxReferenceObject(m_TargetFileObject);
363 }
364
365 status = STATUS_SUCCESS;
366
367 break;
368
369 case WdfIoTargetOpenLocalTargetByFile:
370 UMDF_ONLY_CODE_PATH_ASSERT();
371
372 status = OpenLocalTargetByFile(OpenParams);
373 break;
374
375 case WdfIoTargetOpenByName:
376 //
377 // Only capture the open parameters if we are not reopening.
378 //
379 if (reopen == FALSE) {
380 pParams->Set(OpenParams, &name, pEa, eaLength);
381 }
382
383 status = OpenTargetHandle(OpenParams, pParams);
384 if (NT_SUCCESS(status)) {
385 if (reopen == FALSE) {
386 m_OpenParams.Set(OpenParams, &name, pEa, eaLength);
387
388 //
389 // Setting pEa to NULL stops it from being freed later.
390 // Zeroing out name stops it from being freed later.
391 //
392 pEa = NULL;
393 RtlZeroMemory(&name, sizeof(name));
394 }
395 }
396 else {
397 close = TRUE;
398 }
399 break;
400 }
401
402 InitializeListHead(&pended);
403
404 //
405 // Get Target file object for KMDF. Noop for UMDF.
406 //
407 if (NT_SUCCESS(status)) {
408 status = GetTargetDeviceRelations(&close);
409 }
410
411 if (NT_SUCCESS(status) && CanRegisterForPnpNotification()) {
412 if (reopen == FALSE) {
413 //
414 // Set the values before the register so that if a notification
415 // comes in before the register returns, we have a function to call.
416 //
417 m_EvtQueryRemove.m_Method = OpenParams->EvtIoTargetQueryRemove;
418 m_EvtRemoveCanceled.m_Method = OpenParams->EvtIoTargetRemoveCanceled;
419 m_EvtRemoveComplete.m_Method = OpenParams->EvtIoTargetRemoveComplete;
420 }
421
422 status = RegisterForPnpNotification();
423
424 //
425 // Even if we can't register, we still are successful in opening
426 // up the device and we will proceed from there.
427 //
428 if (!NT_SUCCESS(status)) {
429 DoTraceLevelMessage(
430 GetDriverGlobals(), TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
431 "WDFIOTARGET %p, could not register pnp notification, %!STATUS! not "
432 "treated as an error", GetObjectHandle(), status);
433
434 m_EvtQueryRemove.m_Method = NULL;
435 m_EvtRemoveCanceled.m_Method = NULL;
436 m_EvtRemoveComplete.m_Method = NULL;
437
438 status = STATUS_SUCCESS;
439 }
440 }
441
442 //
443 // UMDF only. Bind handle to remote dispatcher.
444 //
445 #if (FX_CORE_MODE == FX_CORE_USER_MODE)
446 if (NT_SUCCESS(status) && type != WdfIoTargetOpenLocalTargetByFile) {
447 status = BindToHandle();
448 if (!NT_SUCCESS(status)) {
449 close = TRUE;
450 }
451 }
452 #endif
453
454 Lock(&irql);
455
456 if (NT_SUCCESS(status)) {
457
458 #if (FX_CORE_MODE == FX_CORE_KERNEL_MODE)
459 m_TargetStackSize = m_TargetDevice->StackSize;
460 m_TargetIoType = GetTargetIoType();
461 #endif
462
463 m_OpenState = FxIoTargetRemoteOpenStateOpen;
464
465 //
466 // Set our state to started. This will also resend any pended requests
467 // due to a query remove.
468 //
469 status = GotoStartState(&pended, FALSE);
470
471 //
472 // We could not successfully start, close back down
473 //
474 if (!NT_SUCCESS(status)) {
475 DoTraceLevelMessage(
476 GetDriverGlobals(), TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
477 "WDFIOTARGET %p could not transition to started state, %!STATUS!",
478 GetObjectHandle(), status);
479
480 close = TRUE;
481 }
482 }
483 else {
484 m_OpenState = FxIoTargetRemoteOpenStateClosed;
485 }
486
487 //
488 // No matter what, indicate to any waiters that our state change has
489 // completed.
490 //
491 m_OpenedEvent.Set();
492
493 Unlock(irql);
494
495 Done:
496 //
497 // Resubmit any reads that were pended until now.
498 //
499 if (NT_SUCCESS(status)) {
500 SubmitPendedRequests(&pended);
501 }
502 else if (close) {
503 Close(FxIoTargetRemoteCloseReasonPlainClose);
504 }
505
506 if (name.Buffer != NULL) {
507 FxPoolFree(name.Buffer);
508 }
509
510 if (pEa != NULL) {
511 FxPoolFree(pEa);
512 }
513
514 return status;
515 }
516
517
518 VOID
Close(__in FxIoTargetRemoteCloseReason Reason)519 FxIoTargetRemote::Close(
520 __in FxIoTargetRemoteCloseReason Reason
521 )
522 {
523 FxIoTargetClearedPointers pointers;
524 MdTargetNotifyHandle pNotifyHandle;
525 SINGLE_LIST_ENTRY sent;
526 LIST_ENTRY pended;
527 WDF_IO_TARGET_STATE removeState;
528 KIRQL irql;
529 BOOLEAN wait;
530 PFX_DRIVER_GLOBALS pFxDriverGlobals;
531
532 pFxDriverGlobals = GetDriverGlobals();
533 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
534 "enter: WDFIOTARGET %p, reason %d", GetObjectHandle(), Reason);
535
536 RtlZeroMemory(&pointers, sizeof(pointers));
537 pNotifyHandle = NULL;
538
539 sent.Next = NULL;
540 InitializeListHead(&pended);
541
542 wait = FALSE;
543
544 //
545 // Pick a value that is not used anywhere in the function and make sure that
546 // we have changed it, before we go to the Remove state
547 //
548 #pragma prefast(suppress: __WARNING_UNUSED_SCALAR_ASSIGNMENT, "PFD is warning that the following assignement is unused. Suppress it to prevent changing any logic.")
549 removeState = WdfIoTargetStarted;
550
551 CheckState:
552 Lock(&irql);
553
554 //
555 // If we are in the process of opening the target, wait for that to finish.
556 //
557 if (m_OpenState == FxIoTargetRemoteOpenStateOpening) {
558 Unlock(irql);
559
560 DoTraceLevelMessage(
561 pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
562 "Closing WDFIOTARGET %p which is opening, waiting on event %p",
563 GetObjectHandle(), m_OpenedEvent.GetEvent());
564
565 m_OpenedEvent.EnterCRAndWaitAndLeave();
566
567 //
568 // Jump back to the top and recheck
569 //
570 goto CheckState;
571 }
572
573 if (Reason == FxIoTargetRemoteCloseReasonDelete) {
574 DoTraceLevelMessage(
575 pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
576 "Closing WDFIOTARGET %p, reason: delete", GetObjectHandle());
577
578 removeState = WdfIoTargetDeleted;
579 }
580 else if (m_OpenState == FxIoTargetRemoteOpenStateOpen) {
581 if (Reason == FxIoTargetRemoteCloseReasonQueryRemove) {
582 DoTraceLevelMessage(
583 pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
584 "Closing WDFIOTARGET %p, reason: query remove",
585 GetObjectHandle());
586 //
587 // Not really being removed, but that is what the API name is...
588 //
589 removeState = WdfIoTargetClosedForQueryRemove;
590 }
591 else {
592
593 DoTraceLevelMessage(
594 pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
595 "Closing WDFIOTARGET %p, reason: close", GetObjectHandle());
596
597 if (pFxDriverGlobals->IsVersionGreaterThanOrEqualTo(1,9)) {
598 removeState = WdfIoTargetClosed;
599 }
600 else {
601 removeState = WdfIoTargetClosedForQueryRemove;
602 }
603 }
604
605 //
606 // Either way, we are no longer open for business
607 //
608 m_OpenState = FxIoTargetRemoteOpenStateClosed;
609 }
610 else {
611 DoTraceLevelMessage(
612 pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
613 "Closing WDFIOTARGET %p which is not open", GetObjectHandle());
614
615 //
616 // We are not opened, so treat this as a cleanup
617 //
618 removeState = WdfIoTargetClosed;
619 }
620
621 DoTraceLevelMessage(
622 pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
623 "WDFIOTARGET %p: fileobj %p, devobj %p, handle %p, notify handle %I64d",
624 GetObjectHandle(), m_TargetFileObject,
625 m_TargetDevice, m_TargetHandle, (UINT64)m_TargetNotifyHandle);
626
627 if (Reason != FxIoTargetRemoteCloseReasonQueryRemove) {
628 //
629 // If we are closing for a query remove, we want to keep the handle
630 // around so that we can be notified of the final close or if the close
631 // was canceled.
632 //
633 pNotifyHandle = m_TargetNotifyHandle;
634 ResetTargetNotifyHandle();
635 }
636
637 ASSERT(removeState != WdfIoTargetStarted);
638 m_ClearedPointers = &pointers;
639 GotoRemoveState(removeState, &pended, &sent, FALSE, &wait);
640
641 Unlock(irql);
642
643 UnregisterForPnpNotification(pNotifyHandle);
644
645 //
646 // Complete any requests we might have pulled off of our lists
647 //
648 CompletePendedRequestList(&pended);
649 _CancelSentRequests(&sent);
650
651 //
652 // We were just removed, wait for any I/O to complete back if necessary.
653 //
654 if (wait) {
655 DoTraceLevelMessage(
656 pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
657 "WDFIOTARGET %p, waiting for stop to complete", GetObjectHandle());
658
659 WaitForSentIoToComplete();
660 }
661
662 switch (Reason) {
663 case FxIoTargetRemoteCloseReasonQueryRemove:
664 //
665 // m_OpenParams is needed for reopen on canceled query remove
666 //
667 DO_NOTHING();
668 break;
669
670 case FxIoTargetRemoteCloseReasonDelete:
671 m_OpenParams.Clear();
672 break;
673
674 default:
675 //
676 // If this object is not about to be deleted, we need to revert some
677 // of the state that just changed.
678 //
679 m_SentIoEvent.Clear();
680 break;
681 }
682
683 if (removeState == WdfIoTargetDeleted) {
684 WaitForDisposeEvent();
685 }
686
687 //
688 // Finally, close down our handle and pointers
689 //
690 if (pointers.TargetPdo != NULL) {
691 DoTraceLevelMessage(
692 pFxDriverGlobals, TRACE_LEVEL_INFORMATION, TRACINGIOTARGET,
693 "WDFIOTARGET %p derefing PDO %p on close",
694 GetObjectHandle(), pointers.TargetPdo);
695
696 Mx::MxDereferenceObject(pointers.TargetPdo);
697 }
698
699 if (pointers.TargetFileObject != NULL) {
700 DoTraceLevelMessage(
701 pFxDriverGlobals, TRACE_LEVEL_INFORMATION, TRACINGIOTARGET,
702 "WDFIOTARGET %p derefing FileObj %p on close",
703 GetObjectHandle(), pointers.TargetFileObject);
704 Mx::MxDereferenceObject(pointers.TargetFileObject);
705
706 #if (FX_CORE_MODE == FX_CORE_USER_MODE)
707 CloseWdfFileObject(pointers.TargetFileObject);
708 #endif
709 }
710
711 #if (FX_CORE_MODE == FX_CORE_USER_MODE)
712 UnbindHandle(&pointers);
713 #endif
714
715 if (pointers.TargetHandle != NULL) {
716 DoTraceLevelMessage(
717 pFxDriverGlobals, TRACE_LEVEL_INFORMATION, TRACINGIOTARGET,
718 "WDFIOTARGET %p closing handle %p on close",
719 GetObjectHandle(), pointers.TargetHandle);
720 Mx::MxClose(pointers.TargetHandle);
721 }
722 }
723
724 VOID
ClearTargetPointers(VOID)725 FxIoTargetRemote::ClearTargetPointers(
726 VOID
727 )
728 {
729 DoTraceLevelMessage(
730 GetDriverGlobals(), TRACE_LEVEL_INFORMATION, TRACINGIOTARGET,
731 "WDFIOTARGET %p cleared pointers %p state %!WDF_IO_TARGET_STATE!,"
732 " open state %d, pdo %p, fileobj %p, handle %p",
733 GetObjectHandle(), m_ClearedPointers, m_State, m_OpenState, m_TargetPdo,
734 m_TargetFileObject, m_TargetHandle);
735
736 //
737 // Check to see if the caller who is changing state wants these pointer
738 // values before they being cleared out.
739 //
740 if (m_ClearedPointers != NULL) {
741 m_ClearedPointers->TargetPdo = m_TargetPdo;
742 m_ClearedPointers->TargetFileObject = m_TargetFileObject;
743 m_ClearedPointers->TargetHandle = m_TargetHandle;
744 m_ClearedPointers = NULL;
745 }
746
747 //
748 // m_TargetHandle is only an FxIoTargetRemote field, clear it now
749 //
750 m_TargetHandle = NULL;
751
752 //
753 // m_TargetPdo and m_TargetFileObject will be cleared in the following call.
754 //
755 // m_TargetNotifyHandle is not cleared in the following call and is left
756 // valid because we want to receive the notification about query remove being
757 // canceled or completing. When we receive either of those notifications,
758 // m_TargetNotifyHandle will be freed then.
759 //
760 FxIoTarget::ClearTargetPointers(); // __super call
761 }
762
763 VOID
Remove(VOID)764 FxIoTargetRemote::Remove(
765 VOID
766 )
767 {
768 //
769 // Close is the same as remove in this object
770 //
771 Close(FxIoTargetRemoteCloseReasonDelete);
772
773 //
774 // Do mode-specific work
775 //
776 RemoveModeSpecific();
777
778 return ;
779 }
780
781 VOID
Clear(VOID)782 FxIoTargetRemoveOpenParams::Clear(
783 VOID
784 )
785 {
786 if (EaBuffer != NULL) {
787 FxPoolFree(EaBuffer);
788 }
789
790 if (TargetDeviceName.Buffer != NULL) {
791 FxPoolFree(TargetDeviceName.Buffer);
792 }
793
794 RtlZeroMemory(this, sizeof(FxIoTargetRemoveOpenParams));
795 }
796
797 VOID
Set(__in PWDF_IO_TARGET_OPEN_PARAMS OpenParams,__in PUNICODE_STRING Name,__in PVOID Ea,__in ULONG EaLength)798 FxIoTargetRemoveOpenParams::Set(
799 __in PWDF_IO_TARGET_OPEN_PARAMS OpenParams,
800 __in PUNICODE_STRING Name,
801 __in PVOID Ea,
802 __in ULONG EaLength
803 )
804 {
805 OpenType = WdfIoTargetOpenByName;
806
807 EaBuffer = Ea;
808 EaBufferLength = EaLength;
809
810 RtlCopyMemory(&TargetDeviceName, Name, sizeof(UNICODE_STRING));
811
812 DesiredAccess = OpenParams->DesiredAccess;
813 FileAttributes = OpenParams->FileAttributes;
814 ShareAccess = OpenParams->ShareAccess;
815 CreateDisposition = OpenParams->CreateDisposition;
816 CreateOptions = OpenParams->CreateOptions;
817
818 if (OpenParams->AllocationSize != NULL) {
819 AllocationSize.QuadPart = *(OpenParams->AllocationSize);
820 AllocationSizePointer = &AllocationSize;
821 }
822 else {
823 AllocationSizePointer = NULL;
824 }
825 }
826