ReactOS 0.4.16-dev-340-g0540c21
fxiotargetremoteum.cpp
Go to the documentation of this file.
1/*++
2
3Copyright (c) Microsoft Corporation
4
5Module Name:
6
7 FxIoTargetRemoteUm.cpp
8
9Abstract:
10
11Author:
12
13Environment:
14
15 user mode only
16
17Revision History:
18
19--*/
20
21#include "..\..\FxTargetsShared.hpp"
22
23extern "C" {
24#include "FxIoTargetRemoteUm.tmh"
25}
26
27#include <initguid.h>
28#include "wdmguid.h"
29
33 )
34{
36 HRESULT hr;
37 IWudfDeviceStack* devStack;
38
39 devStack = Device->GetDeviceObject()->GetDeviceStackInterface();
40
41 //
42 // Event initialization can fail in UM so initialize it now instead of in
43 // constructor.
44 //
46 if (!NT_SUCCESS(status)) {
49 "Failed to initialize m_OpenedEvent, %!STATUS!", status);
50 return status;
51 }
52
53 //
54 // Create remote dispatcher.
55 // This calls directly into the Host to create.
56 // For most IoTargets the dispatcher is hidden from the Fx, but
57 // for the RemoteTarget, we need to directly dispatch I/O to
58 // a win32 handle, regardless of what dispatch method the device
59 // is set to use in it's INF.
60 //
61 hr = devStack->CreateRemoteDispatcher(&m_pIoDispatcher,
62 &m_pRemoteDispatcher);
63
64 if (FAILED(hr)) {
68 "Failed to Create RemoteDispatcher, %!STATUS!", status);
69 return status;
70 }
71
72 return status;
73}
74
75VOID
77 VOID
78 )
79
80{
81 //
82 // Delete callback object
83 //
84 if (m_NotificationCallback != NULL) {
85 delete m_NotificationCallback;
86 m_NotificationCallback = NULL;
87 }
88
89 SAFE_RELEASE(m_pIoDispatcher);
90 SAFE_RELEASE(m_pRemoteDispatcher);
91}
92
97 )
98{
100 HRESULT hr = S_OK;
101 HANDLE hTarget;
102 ULONG flagsAndAttributes;
103
104 FX_VERIFY_WITH_NAME(INTERNAL,
105 VERIFY(INVALID_HANDLE_VALUE == m_pRemoteDispatcher->GetHandle()),
106 GetDriverGlobals()->Public.DriverName);
107
108 //
109 // UMDF 1.11 allowed following fields to be set by caller.
110 // DWORD dwDesiredAccess
111 // typedef struct _UMDF_IO_TARGET_OPEN_PARAMS
112 // {
113 // DWORD dwShareMode; //
114 // DWORD dwCreationDisposition;
115 // DWORD dwFlagsAndAttributes;
116 // } UMDF_IO_TARGET_OPEN_PARAMS;
117 //
118 //
119 // We always use overlapped I/O
120 //
121 flagsAndAttributes = pParams->FileAttributes | FILE_FLAG_OVERLAPPED;
122
123 hTarget = CreateFile(pParams->TargetDeviceName.Buffer,
124 pParams->DesiredAccess, // dwDesiredAccess
125 pParams->ShareAccess, // dwShareMode
126 NULL, // lpSecurityAttributes
127 pParams->CreateDisposition, // dwCreationDisposition
128 flagsAndAttributes, // dwFlagsAndAttributes
129 NULL);
130
131 if (INVALID_HANDLE_VALUE == hTarget) {
134
137 "CreateFile for WDFIOTARGET %p returned status %!STATUS!",
139
140 FX_VERIFY_WITH_NAME(INTERNAL, VERIFY(FAILED(hr)), GetDriverGlobals()->Public.DriverName);
141 }
142 else {
143 m_TargetHandle = hTarget;
145 }
146
147 return status;
148}
149
150HANDLE
152 VOID
153 )
154{
155 HRESULT hrQi;
156 IWudfFile2* pFile;
158
160 if (m_TargetFileObject == NULL) {
163 "WDFIOTARGET %p has no target file object, could not get handle",
165 }
166 else {
168
169 hrQi = m_TargetFileObject->QueryInterface(IID_IWudfFile2, (PVOID*)&pFile);
170 FX_VERIFY(INTERNAL, CHECK_QI(hrQi, pFile));
171 pFile->Release();
172
173 handle = pFile->GetWeakRefHandle();
174 }
175 }
176
177 //
178 // Normalize the invalid handle value returned by CreateFile in host
179 // to what's expected by the WdfIoTargetWdmGetTargetFileHandle caller.
180 //
182 handle = NULL;
183 }
184
185 return handle;
186}
187
189FxIoTargetRemote::BindToHandle(
190 VOID
191 )
192{
194 HRESULT hr;
195
196 //
197 // Tell the RemoteDispatcher to bind to the new handle.
198 //
199 hr = m_pRemoteDispatcher->BindToHandle(m_TargetHandle);
200 if (FAILED(hr)) {
204 "WDFIOTARGET %p could not bind remote dispatcher to new handle, "
205 "%!STATUS!", GetObjectHandle(), status);
206 return status;
207 }
208
210 return status;
211}
212
213void
214FxIoTargetRemote::UnbindHandle(
215 _In_ FxIoTargetClearedPointers* TargetPointers
216 )
217{
218 if (NULL != m_pRemoteDispatcher) {
219 //
220 // Close the handle we gave to the RemoteDispatcher
221 //
222 // NOTE: IWudfRemoteDispatcher::CloseHandle can be safely called even if
223 // we've not previously given it a handle. In this case, it does
224 // nothing.
225 //
228 "WDFIOTARGET %p Unbinding RemoteDispatcher %p to handle %p on close",
229 GetObjectHandle(), m_pRemoteDispatcher, TargetPointers->TargetHandle);
230
231 m_pRemoteDispatcher->CloseHandle();
232
233 //
234 // Host closes the handle in CloseHandle call above so set the handle
235 // in TargetPointers to NULL.
236 //
237 TargetPointers->TargetHandle = NULL;
238 }
239}
240
244 )
245{
247
248 //
249 // Not needed for UMDF
250 //
251 DO_NOTHING();
252
253 return STATUS_SUCCESS;
254}
255
258 VOID
259 )
260{
262 HRESULT hr;
264
266
267 //
268 // Allocate callback object
269 //
270 if (m_NotificationCallback == NULL) {
271 callback = new (GetDriverGlobals())
273
274 if (callback == NULL) {
278 "WDFIOTARGET %p could not allocate resources for "
279 "notification registration, %!STATUS!",
281 return status;
282 }
283
284 m_NotificationCallback = callback;
285 }
286
287 //
288 // Register for Target Device Change notifications
289 // These notifications will arrive asynchronously.
290 //
291 IWudfDeviceStack * pDevStack = m_Device->GetDeviceStack();
292
293 hr = pDevStack->RegisterTargetDeviceNotification(
294 static_cast<IWudfTargetCallbackDeviceChange *> (m_NotificationCallback),
297
298 if (FAILED(hr)) {
299 if (m_NotificationCallback != NULL) {
300 delete m_NotificationCallback;
301 m_NotificationCallback = NULL;
302 }
303
307 "WDFIOTARGET %p failed to register for Pnp notification, %!STATUS!",
309 return status;
310 }
311
315 "WDFIOTARGET %p registered for Pnp notification, %!STATUS!",
317
318 return status;
319}
320
321VOID
323 _In_ MdTargetNotifyHandle NotifyHandle
324 )
325{
326 //
327 // check if we previously registered
328 //
329 if (NotifyHandle == WUDF_TARGET_CONTEXT_INVALID) {
330 return;
331 }
332
333 //
334 // Unregister.
335 //
336 IWudfDeviceStack * pDevStack = m_Device->GetDeviceStack();
337 pDevStack->UnregisterTargetDeviceNotification(NotifyHandle);
338
339}
340
344 )
345{
347
348 //
349 // OpenParams must be non NULL b/c we can't reopen a target with a
350 // previous device object.
351 //
354
355 //
356 // Create a file object. This is UM-specific feature, where host opens
357 // the reflector control device (optionally supplying the reference string
358 // provided by caller). If there are lower device drivers in the um stack,
359 // host sends them IRP_MJ_CREATE as well. The lower drivers in kernel see
360 // IRP_MJ_CREATE as well as a result of opening the reflector control
361 // object.
362 // Note that m_TargetDevice is already set to next lower device during init.
363 //
364 status = CreateWdfFileObject(&OpenParams->FileName,
366
367 if (!NT_SUCCESS(status)) {
370 "Failed to create WDF File Object, %!STATUS!", status);
371 return status;
372 }
373
374 //
375 // Target handle is not used in this type of open.
376 //
378
379 //
380 // By taking a manual reference here, we simplify the code in
381 // FxIoTargetRemote::Close where we can assume there is an outstanding
382 // reference on the WDM file object at all times as long as we have a non
383 // NULL pointer.
384 //
385 if (m_TargetFileObject != NULL) {
387 }
388
389 return status;
390}
391
393FxIoTargetRemote::CreateWdfFileObject(
396 )
397{
398 HRESULT hr = S_OK;
400 MdFileObject wdmFileObject = NULL;
401
402 FX_VERIFY_WITH_NAME(DRIVER(BadArgument, TODO), CHECK_NOT_NULL(FileObject),
403 GetDriverGlobals()->Public.DriverName);
404
405 *FileObject = NULL;
406
407 hr = m_Device->GetDeviceStack()->CreateWdfFile(
410 FileName->Buffer,
411 &wdmFileObject
412 );
413 if (SUCCEEDED(hr)) {
414 *FileObject = wdmFileObject;
416 }
417 else {
419 }
420
421 return status;
422}
423
424VOID
425FxIoTargetRemote::CloseWdfFileObject(
427 )
428{
429 m_Device->GetDeviceStack()->CloseFile(FileObject);
431}
432
433BOOL
436 _In_ WUDF_TARGET_CONTEXT RegistrationID
437 )
438{
440 FxIoTargetRemote* pThis;
442 BOOLEAN bStatus;
443
444 pThis = m_RemoteTarget;
445
446 //
447 // In one of these callbacks, the driver may decide to delete the target.
448 // If that is the case, we need to be able to return and deref the object until
449 // we are done.
450 //
451 pThis->ADDREF(m_RemoteTarget);
452
454
456 bStatus = TRUE;
457
458 if (GetRegistrationId() != RegistrationID) {
459 //
460 // By design, we can get notification callbacks even after we have
461 // unregistered for notifications. This can happen if there were
462 // callbacks already in flight before we unregistered. In this case, we
463 // simply succeed on query-remove. Since we have already unregistered,
464 // there is no reason for us to fail query-remove.
465 //
468 "QueryRemove callback was for an old registration, ignoring.");
469
470 bStatus = TRUE;
471 goto exit;
472 }
473
476 "WDFIOTARGET %p: query remove notification",
478
479 //
480 // Device is gracefully being removed. PnP is asking us to close down
481 // the target. If there is a driver callback, there is *no* default
482 // behavior. This is because we don't know what the callback is going
483 // to do. For instance, the driver could reopen the target to a
484 // different device in a multi-path scenario.
485 //
486 if (pThis->m_EvtQueryRemove.m_Method != NULL) {
488 pThis->GetHandle());
489 }
490 else {
493 "WDFIOTARGET %p: query remove, default action (close for QR)",
494 pThis->GetObjectHandle());
495
496 //
497 // No callback, close it down conditionally.
498 //
500 }
501
502 if (!NT_SUCCESS(status)) {
503 bStatus = FALSE;
504 }
505
506exit:
507
508 pThis->RELEASE(m_RemoteTarget);
509
510 return bStatus;
511}
512
513VOID
516 _In_ WUDF_TARGET_CONTEXT RegistrationID
517 )
518{
520 FxIoTargetRemote* pThis;
521
522 pThis = m_RemoteTarget;
523
524 //
525 // In one of these callbacks, the driver may decide to delete the target.
526 // If that is the case, we need to be able to return and deref the object until
527 // we are done.
528 //
529 pThis->ADDREF(m_RemoteTarget);
530
532
533 if (GetRegistrationId() != RegistrationID) {
536 "RemoveComplete callback was for an old registration, ignoring.");
537
538 goto exit;
539 }
540
543 "WDFIOTARGET %p: remove complete notification", pThis->GetObjectHandle());
544
545 //
546 // The device was surprise removed, close it for good if the driver has
547 // no override.
548 //
549 if (pThis->m_EvtRemoveComplete.m_Method != NULL) {
550 pThis->m_EvtRemoveComplete.Invoke(pThis->GetHandle());
551 }
552 else {
555 "WDFIOTARGET %p: remove complete, default action (close)",
556 pThis->GetObjectHandle());
557
558 //
559 // The device is now gone for good. Close down the target for good.
560 //
562 }
563
564exit:
565
566 pThis->RELEASE(m_RemoteTarget);
567}
568
569VOID
572 _In_ WUDF_TARGET_CONTEXT RegistrationID
573 )
574{
576 FxIoTargetRemote* pThis;
578
579 pThis = m_RemoteTarget;
580
581 //
582 // In one of these callbacks, the driver may decide to delete the target.
583 // If that is the case, we need to be able to return and deref the object until
584 // we are done.
585 //
586 pThis->ADDREF(m_RemoteTarget);
587
590
591 if (GetRegistrationId() != RegistrationID) {
594 "RemoveCanceled callback was for an old registration, ignoring.");
595
596 goto exit;
597 }
598
601 "WDFIOTARGET %p: remove canceled notification", pThis->GetObjectHandle());
602
603 if (pThis->m_EvtRemoveCanceled.m_Method != NULL) {
604 pThis->m_EvtRemoveCanceled.Invoke(pThis->GetHandle());
605 }
606 else {
608
611 "WDFIOTARGET %p: remove canceled, default action (reopen)",
612 pThis->GetObjectHandle());
613
615
616 //
617 // Attempt to reopen the target with stored settings
618 //
619 status = pThis->Open(&params);
620
621
622
623
624
625
626
628 }
629
630exit:
631
632 pThis->RELEASE(m_RemoteTarget);
633}
634
635VOID
638 _In_ WUDF_TARGET_CONTEXT RegistrationID,
642 _In_ DWORD NameBufferOffset
643 )
644{
645 UNREFERENCED_PARAMETER(RegistrationID);
649 UNREFERENCED_PARAMETER(NameBufferOffset);
650
651 //
652 // UMDF 2.0 doesn't yet support custom event. Ignore the event.
653 //
654 DO_NOTHING();
655
656 return;
657}
658
unsigned char BOOLEAN
#define TODO
Definition: SAX2.c:44
LONG NTSTATUS
Definition: precomp.h:26
MdDeviceObject __inline GetAttachedDevice(VOID)
Definition: fxdevice.hpp:210
MdDeviceObject __inline GetDeviceObject(VOID)
Definition: fxdevice.hpp:174
static NTSTATUS NtStatusFromHr(_In_ IWudfDeviceStack *DevStack, _In_ HRESULT Hr)
Definition: fxdeviceum.cpp:826
IWudfDeviceStack * GetDeviceStack(VOID)
Definition: fxdeviceum.hpp:435
VOID __stdcall OnRemoveComplete(_In_ WUDF_TARGET_CONTEXT RegistrationID)
VOID __stdcall OnCustomEvent(_In_ WUDF_TARGET_CONTEXT RegistrationID, _In_ REFGUID Event, _In_reads_bytes_(DataSize) BYTE *Data, _In_ DWORD DataSize, _In_ DWORD NameBufferOffset)
WUDF_TARGET_CONTEXT GetRegistrationId(VOID)
BOOL __stdcall OnQueryRemove(_In_ WUDF_TARGET_CONTEXT RegistrationID)
VOID __stdcall OnRemoveCanceled(_In_ WUDF_TARGET_CONTEXT RegistrationID)
FxIoTargetRemoveComplete m_EvtRemoveComplete
_Must_inspect_result_ NTSTATUS OpenLocalTargetByFile(_In_ PWDF_IO_TARGET_OPEN_PARAMS OpenParams)
_Must_inspect_result_ NTSTATUS Open(__in PWDF_IO_TARGET_OPEN_PARAMS OpenParams)
HANDLE GetTargetHandle(VOID)
__inline WDFIOTARGET GetHandle(VOID)
FxIoTargetQueryRemove m_EvtQueryRemove
FxIoTargetRemoveOpenParams m_OpenParams
NTSTATUS GetTargetDeviceRelations(_Out_ BOOLEAN *Close)
VOID UnregisterForPnpNotification(_In_ MdTargetNotifyHandle Handle)
MdTargetNotifyHandle m_TargetNotifyHandle
VOID Close(__in FxIoTargetRemoteCloseReason Reason)
NTSTATUS RegisterForPnpNotification(VOID)
NTSTATUS InitRemoteModeSpecific(__in FxDeviceBase *Device)
VOID RemoveModeSpecific(VOID)
FxIoTargetRemoveCanceled m_EvtRemoveCanceled
NTSTATUS OpenTargetHandle(_In_ PWDF_IO_TARGET_OPEN_PARAMS OpenParams, _Inout_ FxIoTargetRemoveOpenParams *pParams)
MdFileObject m_TargetFileObject
Definition: fxiotarget.hpp:923
PVOID __inline GetObjectHandle(VOID)
Definition: fxobject.hpp:603
__inline PFX_DRIVER_GLOBALS GetDriverGlobals(VOID)
Definition: fxobject.hpp:734
CfxDevice * m_Device
Definition: fxobject.hpp:329
static __inline VOID MxReferenceObject(__in PVOID Object)
Definition: mxgeneralkm.h:238
#define __in
Definition: dbghelp.h:35
#define TRACINGIOTARGET
Definition: dbgtrace.h:72
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
FX_VERIFY(INTERNAL, CHECK_NOT_NULL(LoaderInterface->pIWudfHost))
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGPNP, "Enter, WDFDEVICE %p", Device)
PFX_DRIVER_GLOBALS pFxDriverGlobals
return pObject GetObjectHandle()
IWudfDeviceStack * pDevStack
FX_VERIFY_WITH_NAME(DRIVER(BadArgument, TODO), CHECK(ERROR_STRING_HW_ACCESS_NOT_ALLOWED,(pDevice->IsDirectHardwareAccessAllowed()==TRUE)), DriverGlobals->DriverName)
MdFileObject pFile
@ FxIoTargetRemoteCloseReasonPlainClose
@ FxIoTargetRemoteCloseReasonQueryRemove
GLenum const GLfloat * params
Definition: glext.h:5645
#define S_OK
Definition: intsafe.h:52
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define FAILED(hr)
Definition: intsafe.h:51
#define ASSERT(a)
Definition: mode.c:44
#define FILE_FLAG_OVERLAPPED
Definition: disk.h:46
static IPrintDialogCallback callback
Definition: printdlg.c:326
#define DO_NOTHING()
Definition: mxgeneral.h:32
PFILE_OBJECT MdFileObject
Definition: mxgeneralkm.h:32
_In_ NDIS_STATUS _In_ ULONG _In_ USHORT _In_opt_ PVOID _In_ ULONG DataSize
Definition: ndis.h:4755
#define _In_reads_bytes_(s)
Definition: no_sal2.h:170
#define _Inout_
Definition: no_sal2.h:162
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
#define _In_opt_
Definition: no_sal2.h:212
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:325
@ Close
Definition: sacdrv.h:268
#define exit(n)
Definition: config.h:202
#define STATUS_SUCCESS
Definition: shellext.h:65
HRESULT hr
Definition: shlfolder.c:183
#define TRACE_LEVEL_WARNING
Definition: storswtr.h:28
#define TRACE_LEVEL_VERBOSE
Definition: storswtr.h:30
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
CHECK_RETURN_IF_USER_MODE NTSTATUS Initialize(__in BOOLEAN InitialState=FALSE)
Definition: fxwaitlock.hpp:51
PFN_WDF_IO_TARGET_QUERY_REMOVE m_Method
_Must_inspect_result_ NTSTATUS Invoke(__in WDFIOTARGET IoTarget)
VOID Invoke(__in WDFIOTARGET Target)
PFN_WDF_IO_TARGET_REMOVE_CANCELED m_Method
PFN_WDF_IO_TARGET_REMOVE_COMPLETE m_Method
VOID Invoke(__in WDFIOTARGET Target)
WDF_IO_TARGET_OPEN_TYPE OpenType
Definition: scsiwmi.h:51
Definition: ps.c:97
#define VERIFY(e)
Definition: ph.h:34
#define __stdcall
Definition: typedefs.h:25
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_Must_inspect_result_ _In_ WDFDEVICE Device
Definition: wdfchildlist.h:474
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
@ WdfIoTargetOpenLocalTargetByFile
Definition: wdfiotarget.h:66
_Must_inspect_result_ _In_ WDFIOTARGET _In_ PWDF_IO_TARGET_OPEN_PARAMS OpenParams
Definition: wdfiotarget.h:401
FORCEINLINE VOID WDF_IO_TARGET_OPEN_PARAMS_INIT_REOPEN(_Out_ PWDF_IO_TARGET_OPEN_PARAMS Params)
Definition: wdfiotarget.h:340
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define CreateFile
Definition: winbase.h:3774
#define HRESULT_FROM_WIN32(x)
Definition: winerror.h:92
#define SAFE_RELEASE(p)
unsigned char BYTE
Definition: xxhash.c:193