ReactOS  0.4.13-dev-544-gede3fdd
write.c File Reference
#include "cdprocs.h"
Include dependency graph for write.c:

Go to the source code of this file.

Macros

#define BugCheckFileId   (CDFS_BUG_CHECK_WRITE)
 
#define SafeZeroMemory(IC, AT, BYTE_COUNT)
 

Functions

 _Requires_lock_held_ (_Global_critical_region_)
 

Macro Definition Documentation

◆ BugCheckFileId

#define BugCheckFileId   (CDFS_BUG_CHECK_WRITE)

Definition at line 23 of file write.c.

◆ SafeZeroMemory

#define SafeZeroMemory (   IC,
  AT,
  BYTE_COUNT 
)
Value:
{ \
_SEH2_TRY { \
RtlZeroMemory( (AT), (BYTE_COUNT) ); \
__pragma(warning(suppress: 6320)) \
CdRaiseStatus( IC, STATUS_INVALID_USER_BUFFER ); \
} _SEH2_END; \
}
boolean suppress
Definition: jpeglib.h:1005
#define STATUS_INVALID_USER_BUFFER
Definition: udferr_usr.h:166
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
_SEH2_END
Definition: create.c:4424
#define AT
Definition: mbstring.h:34
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
#define warning(s)
Definition: debug.h:71

Definition at line 38 of file write.c.

Function Documentation

◆ _Requires_lock_held_()

_Requires_lock_held_ ( _Global_critical_region_  )

Definition at line 61 of file write.c.

87 {
90 
92  PFCB Fcb;
93  PCCB Ccb;
94 
95  BOOLEAN Wait;
96  ULONG SynchronousIo;
97  PVOID UserBuffer;
98 
100  LONGLONG ByteRange;
102  ULONG WriteByteCount;
103  ULONG OriginalByteCount;
104 
105  BOOLEAN ReleaseFile = TRUE;
106 
107  CD_IO_CONTEXT LocalIoContext;
108 
109  PAGED_CODE();
110 
111  //
112  // If this is a zero length write then return SUCCESS immediately.
113  //
114 
115  if (IrpSp->Parameters.Write.Length == 0) {
116 
117  CdCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
118  return STATUS_SUCCESS;
119  }
120 
121  //
122  // Decode the file object and verify we support write on this. It
123  // must be a volume file.
124  //
125 
126  TypeOfOpen = CdDecodeFileObject( IrpContext, IrpSp->FileObject, &Fcb, &Ccb );
127 
128  // Internal lock object is acquired if return status is STATUS_PENDING
130 
131  if (TypeOfOpen != UserVolumeOpen) {
132 
135  }
136 
137  //
138  // Examine our input parameters to determine if this is noncached and/or
139  // a paging io operation.
140  //
141 
142  Wait = BooleanFlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT );
143  SynchronousIo = FlagOn( IrpSp->FileObject->Flags, FO_SYNCHRONOUS_IO );
144 
145 
146  //
147  // Extract the range of the Io.
148  //
149 
150  StartingOffset = IrpSp->Parameters.Write.ByteOffset.QuadPart;
151  OriginalByteCount = ByteCount = IrpSp->Parameters.Write.Length;
152 
153  ByteRange = StartingOffset + ByteCount;
154 
155  //
156  // Acquire the file shared to perform the write.
157  //
158 
159  CdAcquireFileShared( IrpContext, Fcb );
160 
161  //
162  // Use a try-finally to facilitate cleanup.
163  //
164 
165  _SEH2_TRY {
166 
167  //
168  // Verify the Fcb. Allow writes if this is a DASD handle that is
169  // dismounting the volume.
170  //
171 
173 
174  CdVerifyFcbOperation( IrpContext, Fcb );
175  }
176 
178 
179  //
180  // Complete the request if it begins beyond the end of file.
181  //
182 
183  if (StartingOffset >= Fcb->FileSize.QuadPart) {
184 
186  }
187 
188  //
189  // Truncate the write if it extends beyond the end of the file.
190  //
191 
192  if (ByteRange > Fcb->FileSize.QuadPart) {
193 
194  ByteCount = (ULONG) (Fcb->FileSize.QuadPart - StartingOffset);
195  ByteRange = Fcb->FileSize.QuadPart;
196  }
197  }
198 
199  //
200  // If we have an unaligned transfer then post this request if
201  // we can't wait. Unaligned means that the starting offset
202  // is not on a sector boundary or the write is not integral
203  // sectors.
204  //
205 
206  WriteByteCount = BlockAlign( Fcb->Vcb, ByteCount );
207 
208  if (SectorOffset( StartingOffset ) ||
209  SectorOffset( WriteByteCount ) ||
210  (WriteByteCount > OriginalByteCount)) {
211 
212  if (!Wait) {
213 
214  CdRaiseStatus( IrpContext, STATUS_CANT_WAIT );
215  }
216 
217  //
218  // Make sure we don't overwrite the buffer.
219  //
220 
221  WriteByteCount = ByteCount;
222  }
223 
224  //
225  // Initialize the IoContext for the write.
226  // If there is a context pointer, we need to make sure it was
227  // allocated and not a stale stack pointer.
228  //
229 
230  if (IrpContext->IoContext == NULL ||
231  !FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_ALLOC_IO )) {
232 
233  //
234  // If we can wait, use the context on the stack. Otherwise
235  // we need to allocate one.
236  //
237 
238  if (Wait) {
239 
240  IrpContext->IoContext = &LocalIoContext;
241  ClearFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_ALLOC_IO );
242 
243  } else {
244 
245  IrpContext->IoContext = CdAllocateIoContext();
246  SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_ALLOC_IO );
247  }
248  }
249 
250  RtlZeroMemory( IrpContext->IoContext, sizeof( CD_IO_CONTEXT ) );
251 
252  //
253  // Store whether we allocated this context structure in the structure
254  // itself.
255  //
256 
257  IrpContext->IoContext->AllocatedContext =
258  BooleanFlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_ALLOC_IO );
259 
260  if (Wait) {
261 
262  KeInitializeEvent( &IrpContext->IoContext->SyncEvent,
264  FALSE );
265 
266  } else {
267 
268  IrpContext->IoContext->ResourceThreadId = ExGetCurrentResourceThread();
269  IrpContext->IoContext->Resource = Fcb->Resource;
270  IrpContext->IoContext->RequestedByteCount = ByteCount;
271  }
272 
273  Irp->IoStatus.Information = WriteByteCount;
274 
275  //
276  // Set the FO_MODIFIED flag here to trigger a verify when this
277  // handle is closed. Note that we can err on the conservative
278  // side with no problem, i.e. if we accidently do an extra
279  // verify there is no problem.
280  //
281 
283 
284  //
285  // Dasd access is always non-cached. Call the Dasd write routine to
286  // perform the actual write.
287  //
288 
289  Status = CdVolumeDasdWrite( IrpContext, Fcb, StartingOffset, WriteByteCount );
290 
291  //
292  // Don't complete this request now if STATUS_PENDING was returned.
293  //
294 
295  if (Status == STATUS_PENDING) {
296 
297  Irp = NULL;
298  ReleaseFile = FALSE;
299 
300  //
301  // Test is we should zero part of the buffer or update the
302  // synchronous file position.
303  //
304 
305  } else {
306 
307  //
308  // Convert any unknown error code to IO_ERROR.
309  //
310 
311  if (!NT_SUCCESS( Status )) {
312 
313  //
314  // Set the information field to zero.
315  //
316 
317  Irp->IoStatus.Information = 0;
318 
319  //
320  // Raise if this is a user induced error.
321  //
322 
323  if (IoIsErrorUserInduced( Status )) {
324 
325  CdRaiseStatus( IrpContext, Status );
326  }
327 
329 
330  //
331  // Check if there is any portion of the user's buffer to zero.
332  //
333 
334  } else if (WriteByteCount != ByteCount) {
335 
336  CdMapUserBuffer( IrpContext, &UserBuffer );
337 
338  SafeZeroMemory( IrpContext,
339  Add2Ptr( UserBuffer,
340  ByteCount,
341  PVOID ),
342  WriteByteCount - ByteCount );
343 
344  Irp->IoStatus.Information = ByteCount;
345  }
346 
347  //
348  // Update the file position if this is a synchronous request.
349  //
350 
351  if (SynchronousIo && NT_SUCCESS( Status )) {
352 
353  IrpSp->FileObject->CurrentByteOffset.QuadPart = ByteRange;
354  }
355  }
356 
357  try_exit: NOTHING;
358  } _SEH2_FINALLY {
359 
360  //
361  // Release the Fcb.
362  //
363 
364  if (ReleaseFile) {
365 
366  CdReleaseFile( IrpContext, Fcb );
367  }
368  } _SEH2_END;
369 
370  //
371  // Post the request if we got CANT_WAIT.
372  //
373 
374  if (Status == STATUS_CANT_WAIT) {
375 
376  Status = CdFsdPostRequest( IrpContext, Irp );
377 
378  //
379  // Otherwise complete the request.
380  //
381 
382  } else {
383 
384  CdCompleteRequest( IrpContext, Irp, Status );
385  }
386 
387  return Status;
388 }
return TRUE
Definition: write.c:2909
#define ExGetCurrentResourceThread()
Definition: env_spec_w32.h:633
#define _Analysis_suppress_lock_checking_(lock)
Definition: no_sal2.h:685
#define IRP_CONTEXT_FLAG_WAIT
Definition: cdstruc.h:1221
#define Add2Ptr(PTR, INC)
NTSTATUS Status
Definition: write.c:2825
#define CCB_FLAG_DISMOUNT_ON_CLOSE
Definition: cdstruc.h:1113
_In_ PFCB _In_ LONGLONG StartingOffset
Definition: cdprocs.h:282
#define IRP_CONTEXT_FLAG_ALLOC_IO
Definition: cdstruc.h:1227
#define CdReleaseFile(IC, F)
Definition: cdprocs.h:1008
_In_ PIRP Irp
Definition: csq.h:116
Definition: cdstruc.h:908
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
#define CCB_FLAG_ALLOW_EXTENDED_DASD_IO
Definition: cdstruc.h:1114
Definition: cdstruc.h:1073
#define CdMapUserBuffer(IC, UB)
Definition: cdprocs.h:376
#define IoIsErrorUserInduced(Status)
Definition: iofuncs.h:2769
LONG NTSTATUS
Definition: precomp.h:26
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define CdAcquireFileShared(IC, F)
Definition: cdprocs.h:1002
#define PAGED_CODE()
Definition: video.h:57
_SEH2_TRY
Definition: create.c:4250
#define STATUS_END_OF_FILE
Definition: shellext.h:62
#define FO_SYNCHRONOUS_IO
Definition: iotypes.h:1732
#define FO_FILE_MODIFIED
Definition: iotypes.h:1744
_Inout_ PFILE_OBJECT _In_ TYPE_OF_OPEN TypeOfOpen
Definition: cdprocs.h:593
VOID CdCompleteRequest(_Inout_opt_ PIRP_CONTEXT IrpContext, _Inout_opt_ PIRP Irp, _In_ NTSTATUS Status)
Definition: cddata.c:914
#define SectorOffset(L)
Definition: cdprocs.h:1632
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
#define SafeZeroMemory(IC, AT, BYTE_COUNT)
Definition: write.c:38
#define BlockAlign(V, L)
Definition: cdprocs.h:1648
int64_t LONGLONG
Definition: typedefs.h:66
#define CdAllocateIoContext()
Definition: cdprocs.h:1349
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
#define try_return(S)
Definition: cdprocs.h:2189
ULONG Flags
Definition: ntfs.h:520
enum _TYPE_OF_OPEN TYPE_OF_OPEN
_Inout_ PFILE_OBJECT _In_ TYPE_OF_OPEN PFCB _In_opt_ PCCB Ccb
Definition: cdprocs.h:593
#define NOTHING
Definition: env_spec_w32.h:461
#define FlagOn(_F, _SF)
Definition: ext2fs.h:179
ClearFlag(Dirent->Flags, DIRENT_FLAG_NOT_PERSISTENT)
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS _In_ LARGE_INTEGER ByteCount
Definition: iotypes.h:1060
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
PFILE_OBJECT FileObject
Definition: iotypes.h:2812
_SEH2_END
Definition: create.c:4424
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define CdRaiseStatus(IC, S)
Definition: cdprocs.h:1869
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4157
_SEH2_FINALLY
Definition: create.c:4395
BOOLEAN CdVerifyFcbOperation(_In_opt_ PIRP_CONTEXT IrpContext, _In_ PFCB Fcb)
Definition: verfysup.c:615
#define STATUS_UNEXPECTED_IO_ERROR
Definition: ntstatus.h:455
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
PVCB Vcb
Definition: cdstruc.h:939
NTSTATUS NTAPI FsRtlNormalizeNtstatus(IN NTSTATUS NtStatusToNormalize, IN NTSTATUS NormalizedNtStatus)
Definition: filter.c:90
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:2771
_In_ PFCB Fcb
Definition: cdprocs.h:151
return STATUS_SUCCESS
Definition: btrfs.c:2777
#define STATUS_CANT_WAIT
Definition: ntstatus.h:438
IN BOOLEAN Wait
Definition: fatprocs.h:1529