ReactOS  0.4.14-dev-49-gfb4591c
pnp.c File Reference
#include "cdprocs.h"
Include dependency graph for pnp.c:

Go to the source code of this file.

Macros

#define BugCheckFileId   (CDFS_BUG_CHECK_PNP)
 

Functions

 _Requires_lock_held_ (_Requires_lock_held_() _Releases_nonreentrant_lock_(CdData.DataResource) NTSTATUSCdPnpRemove(_Inout_ PIRP_CONTEXT IrpContext _Global_critical_region_)
 
 _Requires_lock_held_ (_Global_critical_region_)
 
NTSTATUS NTAPI CdPnpCompletionRoutine (_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _In_reads_opt_(_Inexpressible_("varies")) PVOID Contxt)
 

Macro Definition Documentation

◆ BugCheckFileId

#define BugCheckFileId   (CDFS_BUG_CHECK_PNP)

Definition at line 23 of file pnp.c.

Function Documentation

◆ _Requires_lock_held_() [1/2]

_Requires_lock_held_ ( _Requires_lock_held_()_Releases_nonreentrant_lock_(CdData.DataResource)NTSTATUSCdPnpRemove ( _Inout_ PIRP_CONTEXT IrpContext  _Global_critical_region_)

Definition at line 25 of file pnp.c.

104 {
106  BOOLEAN PassThrough = FALSE;
107 
109 
110  PVOLUME_DEVICE_OBJECT OurDeviceObject;
111  PVCB Vcb;
112 
113  PAGED_CODE();
114 
115  // Global lock object is acquired based on internal book-keeping
117 
118  //
119  // Get the current Irp stack location.
120  //
121 
123 
124  //
125  // Find our Vcb. This is tricky since we have no file object in the Irp.
126  //
127 
128  OurDeviceObject = (PVOLUME_DEVICE_OBJECT) IrpSp->DeviceObject;
129 
130  //
131  // IO holds a handle reference on our VDO and holds the device lock, which
132  // syncs us against mounts/verifies. However we hold no reference on the
133  // volume, which may already have been torn down (and the Vpb freed), for
134  // example by a force dismount. Check for this condition. We must hold this
135  // lock until the pnp worker functions take additional locks/refs on the Vcb.
136  //
137 
138  CdAcquireCdData( IrpContext);
139 
140  //
141  // Make sure this device object really is big enough to be a volume device
142  // object. If it isn't, we need to get out before we try to reference some
143  // field that takes us past the end of an ordinary device object.
144  //
145 
146 #ifdef _MSC_VER
147 #pragma prefast(suppress: 28175, "this is a filesystem driver, touching the size member is allowed")
148 #endif
149  if (OurDeviceObject->DeviceObject.Size != sizeof(VOLUME_DEVICE_OBJECT) ||
150  NodeType( &OurDeviceObject->Vcb ) != CDFS_NTC_VCB) {
151 
152  //
153  // We were called with something we don't understand.
154  //
155 
157  CdReleaseCdData( IrpContext);
158  CdCompleteRequest( IrpContext, Irp, Status );
159  return Status;
160  }
161 
162  //
163  // Force all PnP operations to be synchronous.
164  //
165 
166  SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT );
167 
168  Vcb = &OurDeviceObject->Vcb;
169 
170  //
171  // Check that the Vcb hasn't already been deleted. If so, just pass the
172  // request through to the driver below, we don't need to do anything.
173  //
174 
175  if (NULL == Vcb->Vpb) {
176 
177  PassThrough = TRUE;
178  }
179  else {
180 
181  //
182  // Case on the minor code.
183  //
184 
185  switch ( IrpSp->MinorFunction ) {
186 
188 
189  Status = CdPnpQueryRemove( IrpContext, Irp, Vcb );
190  break;
191 
193 
194  Status = CdPnpSurpriseRemove( IrpContext, Irp, Vcb );
195  break;
196 
198 
199  Status = CdPnpRemove( IrpContext, Irp, Vcb );
200  break;
201 
203 
204  Status = CdPnpCancelRemove( IrpContext, Irp, Vcb );
205  break;
206 
207  default:
208 
209  PassThrough = TRUE;
210  break;
211  }
212  }
213 
214  if (PassThrough) {
215 
216  CdReleaseCdData( IrpContext);
217 
218  //
219  // Just pass the IRP on. As we do not need to be in the
220  // way on return, ellide ourselves out of the stack.
221  //
222 
224 
225  Status = IoCallDriver(Vcb->TargetDeviceObject, Irp);
226 
227  //
228  // Cleanup our Irp Context. The driver has completed the Irp.
229  //
230 
231  CdCompleteRequest( IrpContext, NULL, STATUS_SUCCESS );
232  }
233 
234  return Status;
235 }
#define IRP_MN_CANCEL_REMOVE_DEVICE
#define _Analysis_suppress_lock_checking_(lock)
Definition: no_sal2.h:685
#define TRUE
Definition: types.h:120
#define IRP_CONTEXT_FLAG_WAIT
Definition: cdstruc.h:1221
#define IRP_MN_REMOVE_DEVICE
_In_ PIRP Irp
Definition: csq.h:116
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
LONG NTSTATUS
Definition: precomp.h:26
Definition: cdstruc.h:504
VOLUME_DEVICE_OBJECT * PVOLUME_DEVICE_OBJECT
Definition: cdstruc.h:775
#define PAGED_CODE()
Definition: video.h:57
#define IRP_MN_QUERY_REMOVE_DEVICE
VOID CdCompleteRequest(_Inout_opt_ PIRP_CONTEXT IrpContext, _Inout_opt_ PIRP Irp, _In_ NTSTATUS Status)
Definition: cddata.c:914
ERESOURCE DataResource
Definition: cdstruc.h:408
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
NodeType
Definition: Node.h:5
DEVICE_OBJECT DeviceObject
Definition: cdstruc.h:735
#define IRP_MN_SURPRISE_REMOVAL
Definition: ntifs_ex.h:408
CD_DATA CdData
Definition: cddata.c:42
#define Vcb
Definition: cdprocs.h:1425
#define CDFS_NTC_VCB
Definition: nodetype.h:28
PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:2867
#define CdAcquireCdData(IC)
Definition: cdprocs.h:978
Status
Definition: gdiplustypes.h:24
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2745
#define SetFlag(_F, _SF)
Definition: ext2fs.h:187
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4157
#define CdReleaseCdData(IC)
Definition: cdprocs.h:981
NTSTATUS NTAPI IoCallDriver(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: irp.c:1218
#define IoSkipCurrentIrpStackLocation(Irp)
Definition: ntifs_ex.h:421
return STATUS_SUCCESS
Definition: btrfs.c:2966

◆ _Requires_lock_held_() [2/2]

_Requires_lock_held_ ( _Global_critical_region_  )

Definition at line 237 of file pnp.c.

269 {
271  KEVENT Event;
272  BOOLEAN VcbPresent = TRUE;
273 
274  PAGED_CODE();
275 
277 
278  //
279  // Having said yes to a QUERY, any communication with the
280  // underlying storage stack is undefined (and may block)
281  // until the bounding CANCEL or REMOVE is sent.
282  //
283  // Acquire the global resource so that we can try to vaporize the volume,
284  // and the vcb resource itself.
285  //
286 
287  CdAcquireVcbExclusive( IrpContext, Vcb, FALSE );
288 
289  //
290  // Drop a reference on the Vcb to keep it around after we drop the locks.
291  //
292 
293  CdLockVcb( IrpContext, Vcb);
294  Vcb->VcbReference += 1;
295  CdUnlockVcb( IrpContext, Vcb);
296 
297  CdReleaseCdData( IrpContext);
298 
299  Status = CdLockVolumeInternal( IrpContext, Vcb, NULL );
300 
301  //
302  // Reacquire the global lock, which means dropping the Vcb resource.
303  //
304 
305  CdReleaseVcb( IrpContext, Vcb );
306 
307  CdAcquireCdData( IrpContext );
308  CdAcquireVcbExclusive( IrpContext, Vcb, FALSE );
309 
310  //
311  // Remove our extra reference.
312  //
313 
314  CdLockVcb( IrpContext, Vcb);
315  Vcb->VcbReference -= 1;
316  CdUnlockVcb( IrpContext, Vcb);
317 
318  if (NT_SUCCESS( Status )) {
319 
320  //
321  // We need to pass this down before starting the dismount, which
322  // could disconnect us immediately from the stack.
323  //
324 
325  //
326  // Get the next stack location, and copy over the stack location
327  //
328 
330 
331  //
332  // Set up the completion routine
333  //
334 
338  &Event,
339  TRUE,
340  TRUE,
341  TRUE );
342 
343  //
344  // Send the request and wait.
345  //
346 
347  Status = IoCallDriver(Vcb->TargetDeviceObject, Irp);
348 
349  if (Status == STATUS_PENDING) {
350 
352  Executive,
353  KernelMode,
354  FALSE,
355  NULL );
356 
357  Status = Irp->IoStatus.Status;
358  }
359 
360  //
361  // Now if no one below us failed already, initiate the dismount
362  // on this volume, make it go away. PnP needs to see our internal
363  // streams close and drop their references to the target device.
364  //
365  // Since we were able to lock the volume, we are guaranteed to
366  // move this volume into dismount state and disconnect it from
367  // the underlying storage stack. The force on our part is actually
368  // unnecesary, though complete.
369  //
370  // What is not strictly guaranteed, though, is that the closes
371  // for the metadata streams take effect synchronously underneath
372  // of this call. This would leave references on the target device
373  // even though we are disconnected!
374  //
375 
376  if (NT_SUCCESS( Status )) {
377 
378  VcbPresent = CdCheckForDismount( IrpContext, Vcb, TRUE );
379 
380  NT_ASSERT( !VcbPresent || Vcb->VcbCondition == VcbDismountInProgress );
381  }
382 
383  //
384  // Note: Normally everything will complete and the internal streams will
385  // vaporise. However there is some code in the system which drops additional
386  // references on fileobjects, including our internal stream file objects,
387  // for (WMI) tracing purposes. If that happens to run concurrently with our
388  // teardown, our internal streams will not vaporise until those references
389  // are removed. So it's possible that the volume still remains at this
390  // point. The pnp query remove will fail due to our references on the device.
391  // To be cleaner we will return an error here. We could pend the pnp
392  // IRP until the volume goes away, but since we don't know when that will
393  // be, and this is a very rare case, we'll just fail the query.
394  //
395  // The reason this is the case is that handles/fileobjects place a reference
396  // on the device objects they overly. In the filesystem case, these references
397  // are on our target devices. PnP correcly thinks that if references remain
398  // on the device objects in the stack that someone has a handle, and that this
399  // counts as a reason to not succeed the query - even though every interrogated
400  // driver thinks that it is OK.
401  //
402 
403  if (NT_SUCCESS( Status) && VcbPresent && (Vcb->VcbReference != 0)) {
404 
406  }
407  }
408 
409  //
410  // Release the Vcb if it could still remain.
411  //
412 
413  if (VcbPresent) {
414 
415  CdReleaseVcb( IrpContext, Vcb );
416  }
417  else {
418  _Analysis_assume_lock_not_held_(Vcb->VcbResource);
419  }
420 
421  CdReleaseCdData( IrpContext );
422 
423  //
424  // Cleanup our IrpContext and complete the IRP if neccesary.
425  //
426 
427  CdCompleteRequest( IrpContext, Irp, Status );
428 
429  return Status;
430 }
#define ASSERT_EXCLUSIVE_CDDATA
Definition: cddata.h:258
#define TRUE
Definition: types.h:120
_In_ PIRP Irp
Definition: csq.h:116
LONG NTSTATUS
Definition: precomp.h:26
NTSTATUS NTAPI KeWaitForSingleObject(IN PVOID Object, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: wait.c:416
#define PAGED_CODE()
Definition: video.h:57
#define IoSetCompletionRoutine(_Irp, _CompletionRoutine, _Context, _InvokeOnSuccess, _InvokeOnError, _InvokeOnCancel)
Definition: irp.cpp:515
FORCEINLINE VOID IoCopyCurrentIrpStackLocationToNext(_Inout_ PIRP Irp)
Definition: iofuncs.h:2820
VOID CdCompleteRequest(_Inout_opt_ PIRP_CONTEXT IrpContext, _Inout_opt_ PIRP Irp, _In_ NTSTATUS Status)
Definition: cddata.c:914
_In_ PVOID _In_ ULONG Event
Definition: iotypes.h:435
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
#define CdAcquireVcbExclusive(IC, V, I)
Definition: cdprocs.h:984
#define CdReleaseVcb(IC, V)
Definition: cdprocs.h:990
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
#define CdUnlockVcb(IC, V)
Definition: cdprocs.h:1033
#define Vcb
Definition: cdprocs.h:1425
NTSTATUS NTAPI CdPnpCompletionRoutine(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _In_reads_opt_(_Inexpressible_("varies")) PVOID Contxt)
Definition: pnp.c:819
#define CdLockVcb(IC, V)
Definition: cdprocs.h:1028
#define VOID
Definition: acefi.h:82
#define CdAcquireCdData(IC)
Definition: cdprocs.h:978
Status
Definition: gdiplustypes.h:24
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define STATUS_DEVICE_BUSY
Definition: udferr_usr.h:129
#define CdReleaseCdData(IC)
Definition: cdprocs.h:981
NTSTATUS NTAPI IoCallDriver(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: irp.c:1218
#define _Analysis_assume_lock_not_held_(lock)
Definition: no_sal2.h:683
#define NT_ASSERT
Definition: rtlfuncs.h:3312

◆ CdPnpCompletionRoutine()

NTSTATUS NTAPI CdPnpCompletionRoutine ( _In_ PDEVICE_OBJECT  DeviceObject,
_In_ PIRP  Irp,
_In_reads_opt_(_Inexpressible_("varies")) PVOID  Contxt 
)

Definition at line 819 of file pnp.c.

824 {
825  PKEVENT Event = (PKEVENT) Contxt;
826  _Analysis_assume_(Contxt != NULL);
827 
828  KeSetEvent( Event, 0, FALSE );
829 
831 
834  UNREFERENCED_PARAMETER( Contxt );
835 }
struct _KEVENT * PKEVENT
#define STATUS_MORE_PROCESSING_REQUIRED
Definition: shellext.h:63
_In_ PIRP Irp
Definition: csq.h:116
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:323
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
smooth NULL
Definition: ftsmooth.c:416
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1560
#define _Analysis_assume_(expr)
Definition: no_sal2.h:10

Referenced by _Requires_lock_held_().