ReactOS  0.4.14-dev-1256-g2125fec
devctrl.c
Go to the documentation of this file.
1 /*++
2 
3 Copyright (c) 1989-2000 Microsoft Corporation
4 
5 Module Name:
6 
7  DevCtrl.c
8 
9 Abstract:
10 
11  This module implements the File System Device Control routines for Fat
12  called by the dispatch driver.
13 
14 
15 --*/
16 
17 #include "fatprocs.h"
18 
19 //
20 // The local debug trace level
21 //
22 
23 #define Dbg (DEBUG_TRACE_DEVCTRL)
24 
25 //
26 // Local procedure prototypes
27 //
28 
29 //
30 // Tell prefast this is an IO_COMPLETION_ROUTINE
31 //
32 IO_COMPLETION_ROUTINE FatDeviceControlCompletionRoutine;
33 
35 NTAPI
38  IN PIRP Irp,
39  IN PVOID Contxt
40  );
41 
42 #ifdef ALLOC_PRAGMA
43 #pragma alloc_text(PAGE, FatCommonDeviceControl)
44 #pragma alloc_text(PAGE, FatFsdDeviceControl)
45 #endif
46 
47 
51 NTAPI
52 FatFsdDeviceControl (
53  _In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
55  )
56 
57 /*++
58 
59 Routine Description:
60 
61  This routine implements the FSD part of Device control operations
62 
63 Arguments:
64 
65  VolumeDeviceObject - Supplies the volume device object where the
66  file exists
67 
68  Irp - Supplies the Irp being processed
69 
70 Return Value:
71 
72  NTSTATUS - The FSD status for the IRP
73 
74 --*/
75 
76 {
78  PIRP_CONTEXT IrpContext = NULL;
79 
81 
82  PAGED_CODE();
83 
84  DebugTrace(+1, Dbg, "FatFsdDeviceControl\n", 0);
85 
87 
89 
90  _SEH2_TRY {
91 
92  IrpContext = FatCreateIrpContext( Irp, CanFsdWait( Irp ));
93 
94  Status = FatCommonDeviceControl( IrpContext, Irp );
95 
97 
98  //
99  // We had some trouble trying to perform the requested
100  // operation, so we'll abort the I/O request with
101  // the error status that we get back from the
102  // execption code
103  //
104 
105  Status = FatProcessException( IrpContext, Irp, _SEH2_GetExceptionCode() );
106  } _SEH2_END;
107 
108  if (TopLevel) { IoSetTopLevelIrp( NULL ); }
109 
111 
112  //
113  // And return to our caller
114  //
115 
116  DebugTrace(-1, Dbg, "FatFsdDeviceControl -> %08lx\n", Status);
117 
118  UNREFERENCED_PARAMETER( VolumeDeviceObject );
119 
120  return Status;
121 }
122 
123 
124 _Requires_lock_held_(_Global_critical_region_)
125 NTSTATUS
126 FatCommonDeviceControl (
127  IN PIRP_CONTEXT IrpContext,
128  IN PIRP Irp
129  )
130 
131 /*++
132 
133 Routine Description:
134 
135  This is the common routine for doing Device control operations called
136  by both the fsd and fsp threads
137 
138 Arguments:
139 
140  Irp - Supplies the Irp to process
141 
142  InFsp - Indicates if this is the fsp thread or someother thread
143 
144 Return Value:
145 
146  NTSTATUS - The return status for the operation
147 
148 --*/
149 
150 {
153  KEVENT WaitEvent;
155 
156  PVCB Vcb;
157  PFCB Fcb;
158  PCCB Ccb;
159 
160  PAGED_CODE();
161 
162  //
163  // Get a pointer to the current Irp stack location
164  //
165 
167 
168  DebugTrace(+1, Dbg, "FatCommonDeviceControl\n", 0);
169  DebugTrace( 0, Dbg, "Irp = %p\n", Irp);
170  DebugTrace( 0, Dbg, "MinorFunction = %08lx\n", IrpSp->MinorFunction);
171 
172  //
173  // Decode the file object, the only type of opens we accept are
174  // user volume opens.
175  //
176 
178 
180 
181  DebugTrace(-1, Dbg, "FatCommonDeviceControl -> %08lx\n", STATUS_INVALID_PARAMETER);
183  }
184 
185  //
186  // A few IOCTLs actually require some intervention on our part
187  //
188 
189  switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) {
190 
192 
193  //
194  // This is sent by the Volume Snapshot driver (Lovelace).
195  // We flush the volume, and hold all file resources
196  // to make sure that nothing more gets dirty. Then we wait
197  // for the IRP to complete or cancel.
198  //
199 
200  SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT );
201  FatAcquireExclusiveVolume( IrpContext, Vcb );
202 
203  FatFlushAndCleanVolume( IrpContext,
204  Irp,
205  Vcb,
207 
208  KeInitializeEvent( &WaitEvent, NotificationEvent, FALSE );
209  CompletionContext = &WaitEvent;
210 
211  //
212  // Get the next stack location, and copy over the stack location
213  //
214 
216 
217  //
218  // Set up the completion routine
219  //
220 
224  TRUE,
225  TRUE,
226  TRUE );
227  break;
228 
230 
231  //
232  // We cannot allow this IOCTL to be sent unless the volume is locked,
233  // since this IOCTL allows direct writing of data to the volume.
234  // We do allow kernel callers to force access via a flag. A handle that
235  // issued a dismount can send this IOCTL as well.
236  //
237 
238  if (!FlagOn( Vcb->VcbState, VCB_STATE_FLAG_LOCKED ) &&
241 
242  FatCompleteRequest( IrpContext,
243  Irp,
245 
246  DebugTrace(-1, Dbg, "FatCommonDeviceControl -> %08lx\n", STATUS_ACCESS_DENIED);
247  return STATUS_ACCESS_DENIED;
248  }
249 
250  break;
251 
256 
257  //
258  // If someone is issuing a format unit command underneath us, then make
259  // sure we mark the device as needing verification when they close their
260  // handle.
261  //
262 
263  if ((!FlagOn( IrpSp->FileObject->Flags, FO_FILE_MODIFIED ) ||
265  (Irp->AssociatedIrp.SystemBuffer != NULL)) {
266 
267  PCDB Cdb = NULL;
268 
269  //
270  // If this is a 32 bit application running on 64 bit then thunk the
271  // input structures to grab the Cdb.
272  //
273 
274 #if defined (_WIN64) && defined(BUILD_WOW64_ENABLED)
275  if (IoIs32bitProcess(Irp)) {
276 
277  if ( (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_SCSI_PASS_THROUGH) ||
278  (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_SCSI_PASS_THROUGH_DIRECT )) {
279 
280  if (IrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof( SCSI_PASS_THROUGH32 )) {
281 
282  Cdb = (PCDB)((PSCSI_PASS_THROUGH32)(Irp->AssociatedIrp.SystemBuffer))->Cdb;
283  }
284  } else {
285 
286  if (IrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof( SCSI_PASS_THROUGH32_EX )) {
287 
288  Cdb = (PCDB)((PSCSI_PASS_THROUGH32_EX)(Irp->AssociatedIrp.SystemBuffer))->Cdb;
289  }
290  }
291 
292  } else {
293 #endif
294  if ( (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_SCSI_PASS_THROUGH) ||
295  (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_SCSI_PASS_THROUGH_DIRECT )) {
296 
297  if (IrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof( SCSI_PASS_THROUGH )) {
298 
299  Cdb = (PCDB)((PSCSI_PASS_THROUGH)(Irp->AssociatedIrp.SystemBuffer))->Cdb;
300  }
301  } else {
302 
303  if (IrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof( SCSI_PASS_THROUGH_EX )) {
304 
305  Cdb = (PCDB)((PSCSI_PASS_THROUGH_EX)(Irp->AssociatedIrp.SystemBuffer))->Cdb;
306  }
307  }
308 
309 #if defined (_WIN64) && defined(BUILD_WOW64_ENABLED)
310  }
311 #endif
312 
313  if ((Cdb != NULL) && (Cdb->AsByte[0] == SCSIOP_FORMAT_UNIT)) {
314 
317  }
318  }
319 
320  //
321  // Fall through as we do not need to know the outcome of this operation.
322  //
323 
324  default:
325 
326  //
327  // FAT doesn't need to see this on the way back, so skip ourselves.
328  //
329 
331  break;
332  }
333 
334  //
335  // Send the request.
336  //
337 
338  Status = IoCallDriver(Vcb->TargetDeviceObject, Irp);
339 
341 
342  KeWaitForSingleObject( &WaitEvent,
343  Executive,
344  KernelMode,
345  FALSE,
346  NULL );
347 
348  Status = Irp->IoStatus.Status;
349  }
350 
351  //
352  // If we had a context, the IRP remains for us and we will complete it.
353  // Handle it appropriately.
354  //
355 
356  if (CompletionContext) {
357 
358  //
359  // Release all the resources that we held because of a
360  // VOLSNAP_FLUSH_AND_HOLD.
361  //
362 
363  NT_ASSERT( IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_VOLSNAP_FLUSH_AND_HOLD_WRITES );
364 
365  FatReleaseVolume( IrpContext, Vcb );
366 
367  //
368  // If we had no context, the IRP will complete asynchronously.
369  //
370 
371  } else {
372 
373  Irp = NULL;
374  }
375 
376  FatCompleteRequest( IrpContext, Irp, Status );
377 
378  DebugTrace(-1, Dbg, "FatCommonDeviceControl -> %08lx\n", Status);
379 
380  return Status;
381 }
382 
383 
384 //
385 // Local support routine
386 //
387 
388 NTSTATUS
389 NTAPI
392  _In_ PIRP Irp,
393  _In_reads_opt_(_Inexpressible_("varies")) PVOID Contxt
394  )
395 
396 {
397  PKEVENT Event = (PKEVENT) Contxt;
398 
399  //
400  // If there is an event, this is a synch request. Signal and
401  // let I/O know this isn't done yet.
402  //
403 
404  if (Event) {
405 
406  KeSetEvent( Event, 0, FALSE );
408  }
409 
412 
413  return STATUS_SUCCESS;
414 }
415 
#define Dbg
Definition: devctrl.c:23
#define FatReleaseVolume(IRPCONTEXT, VCB)
Definition: fatprocs.h:1409
#define IN
Definition: typedefs.h:39
#define TRUE
Definition: types.h:120
#define IRP_CONTEXT_FLAG_WAIT
Definition: cdstruc.h:1221
struct _KEVENT * PKEVENT
#define FsRtlEnterFileSystem
BOOLEAN FatIsIrpTopLevel(IN PIRP Irp)
Definition: fatdata.c:817
#define IOCTL_SCSI_PASS_THROUGH_DIRECT_EX
Definition: ntddscsi.h:38
#define FsRtlExitFileSystem
#define FatCompleteRequest(IRPCONTEXT, IRP, STATUS)
Definition: fatprocs.h:2621
#define STATUS_MORE_PROCESSING_REQUIRED
Definition: shellext.h:68
#define CCB_FLAG_SENT_FORMAT_UNIT
Definition: fatstruc.h:1344
_In_ PIRP Irp
Definition: csq.h:116
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:323
Definition: cdstruc.h:908
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
Definition: cdstruc.h:1073
Definition: cdrw_hw.h:28
LONG NTSTATUS
Definition: precomp.h:26
#define DebugTrace(INDENT, LEVEL, X, Y)
Definition: fatdata.h:313
_Requires_lock_held_(_Global_critical_region_)
Definition: devctrl.c:124
Definition: cdstruc.h:504
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
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
_SEH2_TRY
Definition: create.c:4250
IN PFCB IN PCCB IN TYPE_OF_OPEN IN BOOLEAN IN BOOLEAN TopLevel
Definition: fatprocs.h:2401
#define IoSetCompletionRoutine(_Irp, _CompletionRoutine, _Context, _InvokeOnSuccess, _InvokeOnError, _InvokeOnCancel)
Definition: irp.cpp:498
#define IOCTL_SCSI_PASS_THROUGH_EX
Definition: ntddscsi.h:37
FORCEINLINE VOID IoCopyCurrentIrpStackLocationToNext(_Inout_ PIRP Irp)
Definition: iofuncs.h:2820
#define FO_FILE_MODIFIED
Definition: iotypes.h:1745
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define FatAcquireExclusiveVolume(IRPCONTEXT, VCB)
Definition: fatprocs.h:1400
_Unreferenced_parameter_ PVOID * CompletionContext
Definition: cdprocs.h:1130
#define _SEH2_GetExceptionInformation()
Definition: pseh2_64.h:11
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
union _CDB * PCDB
IO_COMPLETION_ROUTINE FatDeviceControlCompletionRoutine
Definition: devctrl.c:32
PIRP_CONTEXT FatCreateIrpContext(IN PIRP Irp, IN BOOLEAN Wait)
Definition: strucsup.c:2300
#define CCB_FLAG_COMPLETE_DISMOUNT
Definition: fatstruc.h:1330
#define VCB_STATE_FLAG_LOCKED
Definition: fatstruc.h:558
#define STATUS_PENDING
Definition: ntstatus.h:82
#define Vcb
Definition: cdprocs.h:1425
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define _Inout_
Definition: no_sal2.h:244
#define CanFsdWait(I)
Definition: cdprocs.h:2011
ULONG Flags
Definition: ntfs.h:532
#define IOCTL_DISK_COPY_DATA
Definition: ntdddisk.h:188
VOID NTAPI IoSetTopLevelIrp(IN PIRP Irp)
Definition: irp.c:2000
#define SCSIOP_FORMAT_UNIT
Definition: cdrw_hw.h:871
_Inout_ PFILE_OBJECT _In_ TYPE_OF_OPEN PFCB _In_opt_ PCCB Ccb
Definition: cdprocs.h:593
#define FlagOn(_F, _SF)
Definition: ext2fs.h:179
DRIVER_DISPATCH(nfs41_FsdDispatch)
_Function_class_(IRP_MJ_DEVICE_CONTROL)
Definition: devctrl.c:48
Status
Definition: gdiplustypes.h:24
#define IOCTL_SCSI_PASS_THROUGH
Definition: scsi_port.h:47
#define _In_
Definition: no_sal2.h:204
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1560
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2745
#define SetFlag(_F, _SF)
Definition: ext2fs.h:187
PFILE_OBJECT FileObject
Definition: iotypes.h:2813
_SEH2_END
Definition: create.c:4424
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define IOCTL_VOLSNAP_FLUSH_AND_HOLD_WRITES
#define IOCTL_SCSI_PASS_THROUGH_DIRECT
Definition: scsi_port.h:51
ULONG FatExceptionFilter(IN PIRP_CONTEXT IrpContext, IN PEXCEPTION_POINTERS ExceptionPointer)
Definition: fatdata.c:204
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4157
NTSTATUS NTAPI IoCallDriver(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: irp.c:1218
#define IoSkipCurrentIrpStackLocation(Irp)
Definition: ntifs_ex.h:421
#define _In_reads_opt_(size)
Definition: no_sal2.h:231
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:2772
_In_ PFCB Fcb
Definition: cdprocs.h:151
return STATUS_SUCCESS
Definition: btrfs.c:2938
#define SL_FORCE_DIRECT_WRITE
Definition: iotypes.h:1783
TYPE_OF_OPEN FatDecodeFileObject(_In_ PFILE_OBJECT FileObject, _Outptr_ PVCB *Vcb, _Outptr_ PFCB *FcbOrDcb, _Outptr_ PCCB *Ccb)
Definition: filobsup.c:176
UCHAR AsByte[16]
Definition: scsi.h:1658
#define IRP_MJ_DEVICE_CONTROL
Definition: rdpdr.c:52
#define NT_ASSERT
Definition: rtlfuncs.h:3312