ReactOS 0.4.16-dev-297-gc569aee
write.c
Go to the documentation of this file.
1/*++
2
3Copyright (c) 1989-2000 Microsoft Corporation
4
5Module Name:
6
7 Write.c
8
9Abstract:
10
11 This module implements the File Write routine for Write called by the
12 Fsd/Fsp dispatch drivers.
13
14
15--*/
16
17#include "cdprocs.h"
18
19//
20// The Bug check file id for this module
21//
22
23#define BugCheckFileId (CDFS_BUG_CHECK_WRITE)
24
25//
26// VOID
27// SafeZeroMemory (
28// _Out_ PUCHAR At,
29// _In_ ULONG ByteCount
30// );
31//
32
33//
34// This macro just puts a nice little try-except around RtlZeroMemory
35//
36
37#ifndef __REACTOS__
38#define SafeZeroMemory(IC,AT,BYTE_COUNT) { \
39 _SEH2_TRY { \
40 RtlZeroMemory( (AT), (BYTE_COUNT) ); \
41__pragma(warning(suppress: 6320)) \
42 } _SEH2_EXCEPT( EXCEPTION_EXECUTE_HANDLER ) { \
43 CdRaiseStatus( IC, STATUS_INVALID_USER_BUFFER ); \
44 } _SEH2_END; \
45}
46#else
47#define SafeZeroMemory(IC,AT,BYTE_COUNT) { \
48 _SEH2_TRY { \
49 RtlZeroMemory( (AT), (BYTE_COUNT) ); \
50 } _SEH2_EXCEPT( EXCEPTION_EXECUTE_HANDLER ) { \
51 CdRaiseStatus( IC, STATUS_INVALID_USER_BUFFER ); \
52 } _SEH2_END; \
53}
54#endif
55
56#ifdef ALLOC_PRAGMA
57#pragma alloc_text(PAGE, CdCommonWrite)
58#endif
59
60
61_Requires_lock_held_(_Global_critical_region_)
63CdCommonWrite (
64 _Inout_ PIRP_CONTEXT IrpContext,
66 )
67
68/*++
69
70Routine Description:
71
72 This is the common entry point for NtWriteFile calls. For synchronous requests,
73 CommonWrite will complete the request in the current thread. If not
74 synchronous the request will be passed to the Fsp if there is a need to
75 block.
76
77Arguments:
78
79 Irp - Supplies the Irp to process
80
81Return Value:
82
83 NTSTATUS - The result of this operation.
84
85--*/
86
87{
90
92 PFCB Fcb;
93 PCCB Ccb;
94
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
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
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}
389
390
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
#define PAGED_CODE()
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
VOID CdCompleteRequest(_Inout_opt_ PIRP_CONTEXT IrpContext, _Inout_opt_ PIRP Irp, _In_ NTSTATUS Status)
Definition: cddata.c:914
#define CdMapUserBuffer(IC, UB)
Definition: cdprocs.h:383
_Inout_ PFILE_OBJECT _In_ TYPE_OF_OPEN TypeOfOpen
Definition: cdprocs.h:589
#define CdReleaseFile(IC, F)
Definition: cdprocs.h:1003
#define BlockAlign(V, L)
Definition: cdprocs.h:1638
@ UserVolumeOpen
Definition: cdprocs.h:575
_In_ PFCB _In_ LONGLONG StartingOffset
Definition: cdprocs.h:291
_In_ PFCB Fcb
Definition: cdprocs.h:159
_Inout_ PFILE_OBJECT _In_ TYPE_OF_OPEN PFCB _In_opt_ PCCB Ccb
Definition: cdprocs.h:592
#define CdAllocateIoContext()
Definition: cdprocs.h:1344
BOOLEAN CdVerifyFcbOperation(_In_opt_ PIRP_CONTEXT IrpContext, _In_ PFCB Fcb)
Definition: verfysup.c:615
#define SectorOffset(L)
Definition: cdprocs.h:1622
#define CdAcquireFileShared(IC, F)
Definition: cdprocs.h:997
enum _TYPE_OF_OPEN TYPE_OF_OPEN
#define try_return(S)
Definition: cdprocs.h:2179
#define CdRaiseStatus(IC, S)
Definition: cdprocs.h:1859
#define CCB_FLAG_ALLOW_EXTENDED_DASD_IO
Definition: cdstruc.h:1108
#define CCB_FLAG_DISMOUNT_ON_CLOSE
Definition: cdstruc.h:1107
#define IRP_CONTEXT_FLAG_WAIT
Definition: cdstruc.h:1215
#define IRP_CONTEXT_FLAG_ALLOC_IO
Definition: cdstruc.h:1221
#define _Requires_lock_held_(lock)
#define _Analysis_suppress_lock_checking_(lock)
_In_ PIRP Irp
Definition: csq.h:116
#define STATUS_PENDING
Definition: d3dkmdt.h:43
#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 SafeZeroMemory(IC, AT, BYTE_COUNT)
Definition: write.c:38
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4137
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define ExGetCurrentResourceThread()
Definition: env_spec_w32.h:633
#define ClearFlag(_F, _SF)
Definition: ext2fs.h:191
#define SetFlag(_F, _SF)
Definition: ext2fs.h:187
#define FlagOn(_F, _SF)
Definition: ext2fs.h:179
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
Status
Definition: gdiplustypes.h:25
#define NOTHING
Definition: input_list.c:10
#define Add2Ptr(PTR, INC)
#define _Inout_
Definition: no_sal2.h:162
@ NotificationEvent
NTSTATUS NTAPI FsRtlNormalizeNtstatus(IN NTSTATUS NtStatusToNormalize, IN NTSTATUS NormalizedNtStatus)
Definition: filter.c:90
#define STATUS_CANT_WAIT
Definition: ntstatus.h:452
#define STATUS_UNEXPECTED_IO_ERROR
Definition: ntstatus.h:469
#define _SEH2_FINALLY
Definition: pseh2_64.h:114
#define _SEH2_END
Definition: pseh2_64.h:155
#define _SEH2_TRY
Definition: pseh2_64.h:55
#define STATUS_END_OF_FILE
Definition: shellext.h:67
#define STATUS_SUCCESS
Definition: shellext.h:65
Definition: cdstruc.h:1067
Definition: cdstruc.h:902
ULONG Flags
Definition: ntfs.h:536
PVCB Vcb
Definition: cdstruc.h:933
PFILE_OBJECT FileObject
Definition: iotypes.h:3169
union _IO_STACK_LOCATION::@1579 Parameters
struct _IO_STACK_LOCATION::@3978::@3983 Write
int64_t LONGLONG
Definition: typedefs.h:68
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
_In_ WDFDPC _In_ BOOLEAN Wait
Definition: wdfdpc.h:170
#define IoIsErrorUserInduced(Status)
Definition: iofuncs.h:2817
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS _In_ LARGE_INTEGER ByteCount
Definition: iotypes.h:1099
#define FO_FILE_MODIFIED
Definition: iotypes.h:1788
#define FO_SYNCHRONOUS_IO
Definition: iotypes.h:1776