ReactOS  0.4.15-dev-4603-gb922b6d
fxiotargetremoteum.cpp
Go to the documentation of this file.
1 /*++
2 
3 Copyright (c) Microsoft Corporation
4 
5 Module Name:
6 
7  FxIoTargetRemoteUm.cpp
8 
9 Abstract:
10 
11 Author:
12 
13 Environment:
14 
15  user mode only
16 
17 Revision History:
18 
19 --*/
20 
21 #include "..\..\FxTargetsShared.hpp"
22 
23 extern "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)) {
65  status = FxDevice::NtStatusFromHr(devStack, hr);
68  "Failed to Create RemoteDispatcher, %!STATUS!", status);
69  return status;
70  }
71 
72  return status;
73 }
74 
75 VOID
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 
150 HANDLE
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",
164  GetObjectHandle());
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  //
181  if (handle == INVALID_HANDLE_VALUE) {
182  handle = NULL;
183  }
184 
185  return handle;
186 }
187 
188 NTSTATUS
189 FxIoTargetRemote::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 
213 void
214 FxIoTargetRemote::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 
241 NTSTATUS
244  )
245 {
247 
248  //
249  // Not needed for UMDF
250  //
251  DO_NOTHING();
252 
253  return STATUS_SUCCESS;
254 }
255 
256 NTSTATUS
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 
321 VOID
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 
341 NTSTATUS
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 
392 NTSTATUS
393 FxIoTargetRemote::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 
424 VOID
425 FxIoTargetRemote::CloseWdfFileObject(
427  )
428 {
429  m_Device->GetDeviceStack()->CloseFile(FileObject);
431 }
432 
433 BOOL
434 __stdcall
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) {
487  status = pThis->m_EvtQueryRemove.Invoke(
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 
506 exit:
507 
508  pThis->RELEASE(m_RemoteTarget);
509 
510  return bStatus;
511 }
512 
513 VOID
514 __stdcall
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 
564 exit:
565 
566  pThis->RELEASE(m_RemoteTarget);
567 }
568 
569 VOID
570 __stdcall
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 
630 exit:
631 
632  pThis->RELEASE(m_RemoteTarget);
633 }
634 
635 VOID
636 __stdcall
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 
CfxDevice * m_Device
Definition: fxobject.hpp:329
CHECK_RETURN_IF_USER_MODE NTSTATUS Initialize(__in BOOLEAN InitialState=FALSE)
Definition: fxwaitlock.hpp:51
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
VOID __stdcall OnCustomEvent(_In_ WUDF_TARGET_CONTEXT RegistrationID, _In_ REFGUID Event, _In_reads_bytes_(DataSize) BYTE *Data, _In_ DWORD DataSize, _In_ DWORD NameBufferOffset)
#define HRESULT_FROM_WIN32(x)
Definition: winerror.h:92
VOID UnregisterForPnpNotification(_In_ MdTargetNotifyHandle Handle)
#define _In_opt_
Definition: ms_sal.h:309
#define _Inout_
Definition: ms_sal.h:378
MdDeviceObject __inline GetDeviceObject(VOID)
Definition: fxdevice.hpp:174
HRESULT hr
Definition: shlfolder.c:183
Definition: scsiwmi.h:51
#define _Out_
Definition: ms_sal.h:345
#define TRUE
Definition: types.h:120
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
VOID Invoke(__in WDFIOTARGET Target)
LONG NTSTATUS
Definition: precomp.h:26
#define INVALID_HANDLE_VALUE
Definition: compat.h:590
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1040
PFN_WDF_IO_TARGET_QUERY_REMOVE m_Method
PFILE_OBJECT MdFileObject
Definition: mxgeneralkm.h:32
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
FX_VERIFY_WITH_NAME(DRIVER(BadArgument, TODO), CHECK(ERROR_STRING_HW_ACCESS_NOT_ALLOWED,(pDevice->IsDirectHardwareAccessAllowed()==TRUE)), DriverGlobals->DriverName)
_Must_inspect_result_ NTSTATUS OpenLocalTargetByFile(_In_ PWDF_IO_TARGET_OPEN_PARAMS OpenParams)
FxIoTargetRemoveComplete m_EvtRemoveComplete
FxIoTargetQueryRemove m_EvtQueryRemove
namespace GUID const ADDRINFOEXW ADDRINFOEXW struct timeval OVERLAPPED LPLOOKUPSERVICE_COMPLETION_ROUTINE HANDLE * handle
Definition: sock.c:82
#define TODO
Definition: SAX2.c:49
#define FALSE
Definition: types.h:117
GLenum const GLfloat * params
Definition: glext.h:5645
#define TRACE_LEVEL_VERBOSE
Definition: storswtr.h:30
unsigned int BOOL
Definition: ntddk_ex.h:94
if SUCCEEDED(hr)
static __inline VOID MxReferenceObject(__in PVOID Object)
Definition: mxgeneralkm.h:238
VOID __stdcall OnRemoveComplete(_In_ WUDF_TARGET_CONTEXT RegistrationID)
PVOID __inline GetObjectHandle(VOID)
Definition: fxobject.hpp:603
unsigned char BOOLEAN
static NTSTATUS NtStatusFromHr(_In_ IWudfDeviceStack *DevStack, _In_ HRESULT Hr)
Definition: fxdeviceum.cpp:826
MdDeviceObject __inline GetAttachedDevice(VOID)
Definition: fxdevice.hpp:210
MdFileObject m_TargetFileObject
Definition: fxiotarget.hpp:923
#define _In_
Definition: ms_sal.h:308
#define SAFE_RELEASE(p)
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:547
NTSTATUS GetTargetDeviceRelations(_Out_ BOOLEAN *Close)
IWudfDeviceStack * pDevStack
IWudfDeviceStack * GetDeviceStack(VOID)
Definition: fxdeviceum.hpp:435
PFX_DRIVER_GLOBALS pFxDriverGlobals
VOID RemoveModeSpecific(VOID)
FX_VERIFY(INTERNAL, CHECK_NOT_NULL(LoaderInterface->pIWudfHost))
#define ASSERT(a)
Definition: mode.c:44
HANDLE GetTargetHandle(VOID)
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
LONG HRESULT
Definition: typedefs.h:79
#define VERIFY(e)
Definition: ph.h:34
unsigned long DWORD
Definition: ntddk_ex.h:95
#define __stdcall
Definition: typedefs.h:25
FORCEINLINE VOID WDF_IO_TARGET_OPEN_PARAMS_INIT_REOPEN(_Out_ PWDF_IO_TARGET_OPEN_PARAMS Params)
Definition: wdfiotarget.h:340
_Must_inspect_result_ NTSTATUS Invoke(__in WDFIOTARGET IoTarget)
VOID Close(__in FxIoTargetRemoteCloseReason Reason)
_Must_inspect_result_ _In_ WDFIOTARGET _In_ PWDF_IO_TARGET_OPEN_PARAMS OpenParams
Definition: wdfiotarget.h:398
MdFileObject pFile
_Must_inspect_result_ _In_ WDFDEVICE Device
Definition: wdfchildlist.h:474
unsigned char BYTE
Definition: xxhash.c:193
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
#define TRACE_LEVEL_WARNING
Definition: storswtr.h:28
FxIoTargetRemoveOpenParams m_OpenParams
BOOL __stdcall OnQueryRemove(_In_ WUDF_TARGET_CONTEXT RegistrationID)
#define S_OK
Definition: intsafe.h:52
__inline PFX_DRIVER_GLOBALS GetDriverGlobals(VOID)
Definition: fxobject.hpp:734
MdTargetNotifyHandle m_TargetNotifyHandle
PFN_WDF_IO_TARGET_REMOVE_CANCELED m_Method
VOID __stdcall OnRemoveCanceled(_In_ WUDF_TARGET_CONTEXT RegistrationID)
IN OUT PVCB OUT PDIRENT OUT PBCB IN BOOLEAN CreateFile
Definition: fatprocs.h:913
Definition: sacdrv.h:268
FxIoTargetRemoveCanceled m_EvtRemoveCanceled
WUDF_TARGET_CONTEXT GetRegistrationId(VOID)
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGPNP, "Enter, WDFDEVICE %p", Device)
_Must_inspect_result_ NTSTATUS Open(__in PWDF_IO_TARGET_OPEN_PARAMS OpenParams)
#define NULL
Definition: types.h:112
VOID Invoke(__in WDFIOTARGET Target)
unsigned int ULONG
Definition: retypes.h:1
NTSTATUS RegisterForPnpNotification(VOID)
#define STATUS_SUCCESS
Definition: shellext.h:65
static IPrintDialogCallback callback
Definition: printdlg.c:326
NTSTATUS InitRemoteModeSpecific(__in FxDeviceBase *Device)
void exit(int exitcode)
Definition: _exit.c:33
#define FILE_FLAG_OVERLAPPED
Definition: disk.h:46
WDF_IO_TARGET_OPEN_TYPE OpenType
#define __in
Definition: dbghelp.h:35
static SERVICE_STATUS status
Definition: service.c:31
__inline WDFIOTARGET GetHandle(VOID)
#define TRACINGIOTARGET
Definition: dbgtrace.h:72
_In_ NDIS_STATUS _In_ ULONG _In_ USHORT _In_opt_ PVOID _In_ ULONG DataSize
Definition: ndis.h:4751
NTSTATUS OpenTargetHandle(_In_ PWDF_IO_TARGET_OPEN_PARAMS OpenParams, _Inout_ FxIoTargetRemoveOpenParams *pParams)
PFN_WDF_IO_TARGET_REMOVE_COMPLETE m_Method
#define _In_reads_bytes_(size)
Definition: ms_sal.h:321
#define DO_NOTHING()
Definition: mxgeneral.h:32
Definition: ps.c:97