1c2c66affSColin Finck /*
2c2c66affSColin Finck * COPYRIGHT: See COPYRIGHT.TXT
3c2c66affSColin Finck * PROJECT: Ext2 File System Driver for WinNT/2K/XP
4c2c66affSColin Finck * FILE: write.c
5c2c66affSColin Finck * PROGRAMMER: Matt Wu <mattwu@163.com>
6c2c66affSColin Finck * HOMEPAGE: http://www.ext2fsd.com
7c2c66affSColin Finck * UPDATE HISTORY:
8c2c66affSColin Finck */
9c2c66affSColin Finck
10c2c66affSColin Finck /* INCLUDES *****************************************************************/
11c2c66affSColin Finck
12c2c66affSColin Finck #include "ext2fs.h"
13c2c66affSColin Finck
14c2c66affSColin Finck /* GLOBALS ***************************************************************/
15c2c66affSColin Finck
16c2c66affSColin Finck extern PEXT2_GLOBAL Ext2Global;
17c2c66affSColin Finck
18c2c66affSColin Finck #define DL_FLP DL_DBG
19c2c66affSColin Finck
20c2c66affSColin Finck /* DEFINITIONS *************************************************************/
21c2c66affSColin Finck
22c2c66affSColin Finck #define EXT2_FLPFLUSH_MAGIC 'FF2E'
23c2c66affSColin Finck
24c2c66affSColin Finck typedef struct _EXT2_FLPFLUSH_CONTEXT {
25c2c66affSColin Finck
26c2c66affSColin Finck PEXT2_VCB Vcb;
27c2c66affSColin Finck PEXT2_FCB Fcb;
28c2c66affSColin Finck PFILE_OBJECT FileObject;
29c2c66affSColin Finck
30c2c66affSColin Finck KDPC Dpc;
31c2c66affSColin Finck KTIMER Timer;
32c2c66affSColin Finck WORK_QUEUE_ITEM Item;
33c2c66affSColin Finck
34c2c66affSColin Finck } EXT2_FLPFLUSH_CONTEXT, *PEXT2_FLPFLUSH_CONTEXT;
35c2c66affSColin Finck
36*aaeb131bSVincent Franchomme #ifdef __REACTOS__
37c2c66affSColin Finck VOID NTAPI
38*aaeb131bSVincent Franchomme #else
39*aaeb131bSVincent Franchomme VOID
40*aaeb131bSVincent Franchomme #endif
41c2c66affSColin Finck Ext2FloppyFlush(IN PVOID Parameter);
42c2c66affSColin Finck
43*aaeb131bSVincent Franchomme #ifdef __REACTOS__
44c2c66affSColin Finck VOID NTAPI
45*aaeb131bSVincent Franchomme #else
46*aaeb131bSVincent Franchomme VOID
47*aaeb131bSVincent Franchomme #endif
48c2c66affSColin Finck Ext2FloppyFlushDpc (
49c2c66affSColin Finck IN PKDPC Dpc,
50c2c66affSColin Finck IN PVOID DeferredContext,
51c2c66affSColin Finck IN PVOID SystemArgument1,
52c2c66affSColin Finck IN PVOID SystemArgument2);
53c2c66affSColin Finck
54c2c66affSColin Finck
55c2c66affSColin Finck NTSTATUS
56c2c66affSColin Finck Ext2WriteComplete (IN PEXT2_IRP_CONTEXT IrpContext);
57c2c66affSColin Finck
58c2c66affSColin Finck NTSTATUS
59c2c66affSColin Finck Ext2WriteFile (IN PEXT2_IRP_CONTEXT IrpContext);
60c2c66affSColin Finck
61c2c66affSColin Finck NTSTATUS
62c2c66affSColin Finck Ext2WriteVolume (IN PEXT2_IRP_CONTEXT IrpContext);
63c2c66affSColin Finck
64c2c66affSColin Finck VOID
65c2c66affSColin Finck Ext2DeferWrite(IN PEXT2_IRP_CONTEXT, PIRP Irp);
66c2c66affSColin Finck
67c2c66affSColin Finck
68c2c66affSColin Finck /* FUNCTIONS *************************************************************/
69c2c66affSColin Finck
70*aaeb131bSVincent Franchomme #ifdef __REACTOS__
71c2c66affSColin Finck VOID NTAPI
72*aaeb131bSVincent Franchomme #else
73*aaeb131bSVincent Franchomme VOID
74*aaeb131bSVincent Franchomme #endif
Ext2FloppyFlush(IN PVOID Parameter)75c2c66affSColin Finck Ext2FloppyFlush(IN PVOID Parameter)
76c2c66affSColin Finck {
77c2c66affSColin Finck PEXT2_FLPFLUSH_CONTEXT Context;
78c2c66affSColin Finck PFILE_OBJECT FileObject;
79c2c66affSColin Finck PEXT2_FCB Fcb;
80c2c66affSColin Finck PEXT2_VCB Vcb;
81c2c66affSColin Finck
82c2c66affSColin Finck Context = (PEXT2_FLPFLUSH_CONTEXT) Parameter;
83c2c66affSColin Finck FileObject = Context->FileObject;
84c2c66affSColin Finck Fcb = Context->Fcb;
85c2c66affSColin Finck Vcb = Context->Vcb;
86c2c66affSColin Finck
87c2c66affSColin Finck DEBUG(DL_FLP, ("Ext2FloppyFlushing ...\n"));
88c2c66affSColin Finck
89c2c66affSColin Finck IoSetTopLevelIrp((PIRP)FSRTL_FSP_TOP_LEVEL_IRP);
90c2c66affSColin Finck
91c2c66affSColin Finck if (FileObject) {
92c2c66affSColin Finck ASSERT(Fcb == (PEXT2_FCB)FileObject->FsContext);
93a1d7e993SPierre Schweitzer ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE);
94c2c66affSColin Finck ExAcquireSharedStarveExclusive(&Fcb->PagingIoResource, TRUE);
95c2c66affSColin Finck ExReleaseResourceLite(&Fcb->PagingIoResource);
96c2c66affSColin Finck
97c2c66affSColin Finck CcFlushCache(&(Fcb->SectionObject), NULL, 0, NULL);
98a1d7e993SPierre Schweitzer ExReleaseResourceLite(&Fcb->MainResource);
99c2c66affSColin Finck
100c2c66affSColin Finck ObDereferenceObject(FileObject);
101c2c66affSColin Finck }
102c2c66affSColin Finck
103c2c66affSColin Finck if (Vcb) {
104a1d7e993SPierre Schweitzer ExAcquireResourceExclusiveLite(&Vcb->MainResource, TRUE);
105a1d7e993SPierre Schweitzer
106c2c66affSColin Finck ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
107c2c66affSColin Finck ExReleaseResourceLite(&Vcb->PagingIoResource);
108c2c66affSColin Finck
109a1d7e993SPierre Schweitzer Ext2FlushVcb(Vcb);
110a1d7e993SPierre Schweitzer ExReleaseResourceLite(&Vcb->MainResource);
111c2c66affSColin Finck }
112c2c66affSColin Finck
113c2c66affSColin Finck IoSetTopLevelIrp(NULL);
114c2c66affSColin Finck Ext2FreePool(Parameter, EXT2_FLPFLUSH_MAGIC);
115c2c66affSColin Finck }
116c2c66affSColin Finck
117*aaeb131bSVincent Franchomme #ifdef __REACTOS__
118c2c66affSColin Finck VOID NTAPI
119*aaeb131bSVincent Franchomme #else
120*aaeb131bSVincent Franchomme VOID
121*aaeb131bSVincent Franchomme #endif
Ext2FloppyFlushDpc(IN PKDPC Dpc,IN PVOID DeferredContext,IN PVOID SystemArgument1,IN PVOID SystemArgument2)122c2c66affSColin Finck Ext2FloppyFlushDpc (
123c2c66affSColin Finck IN PKDPC Dpc,
124c2c66affSColin Finck IN PVOID DeferredContext,
125c2c66affSColin Finck IN PVOID SystemArgument1,
126c2c66affSColin Finck IN PVOID SystemArgument2
127c2c66affSColin Finck )
128c2c66affSColin Finck {
129c2c66affSColin Finck PEXT2_FLPFLUSH_CONTEXT Context;
130c2c66affSColin Finck
131c2c66affSColin Finck Context = (PEXT2_FLPFLUSH_CONTEXT) DeferredContext;
132c2c66affSColin Finck
133c2c66affSColin Finck DEBUG(DL_FLP, ("Ext2FloppyFlushDpc is to be started...\n"));
134c2c66affSColin Finck
135c2c66affSColin Finck ExQueueWorkItem(&Context->Item, CriticalWorkQueue);
136c2c66affSColin Finck }
137c2c66affSColin Finck
138c2c66affSColin Finck VOID
Ext2StartFloppyFlushDpc(PEXT2_VCB Vcb,PEXT2_FCB Fcb,PFILE_OBJECT FileObject)139c2c66affSColin Finck Ext2StartFloppyFlushDpc (
140c2c66affSColin Finck PEXT2_VCB Vcb,
141c2c66affSColin Finck PEXT2_FCB Fcb,
142c2c66affSColin Finck PFILE_OBJECT FileObject )
143c2c66affSColin Finck {
144c2c66affSColin Finck LARGE_INTEGER OneSecond;
145c2c66affSColin Finck PEXT2_FLPFLUSH_CONTEXT Context;
146c2c66affSColin Finck
147c2c66affSColin Finck ASSERT(IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK));
148c2c66affSColin Finck
149c2c66affSColin Finck Context = Ext2AllocatePool(
150c2c66affSColin Finck NonPagedPool,
151c2c66affSColin Finck sizeof(EXT2_FLPFLUSH_CONTEXT),
152c2c66affSColin Finck EXT2_FLPFLUSH_MAGIC
153c2c66affSColin Finck );
154c2c66affSColin Finck
155c2c66affSColin Finck if (!Context) {
156c2c66affSColin Finck DEBUG(DL_ERR, ( "Ex2StartFloppy...: failed to allocate Context\n"));
157c2c66affSColin Finck DbgBreak();
158c2c66affSColin Finck return;
159c2c66affSColin Finck }
160c2c66affSColin Finck
161c2c66affSColin Finck KeInitializeTimer(&Context->Timer);
162c2c66affSColin Finck
163c2c66affSColin Finck KeInitializeDpc( &Context->Dpc,
164c2c66affSColin Finck Ext2FloppyFlushDpc,
165c2c66affSColin Finck Context );
166c2c66affSColin Finck
167c2c66affSColin Finck ExInitializeWorkItem( &Context->Item,
168c2c66affSColin Finck Ext2FloppyFlush,
169c2c66affSColin Finck Context );
170c2c66affSColin Finck
171c2c66affSColin Finck Context->Vcb = Vcb;
172c2c66affSColin Finck Context->Fcb = Fcb;
173c2c66affSColin Finck Context->FileObject = FileObject;
174c2c66affSColin Finck
175c2c66affSColin Finck if (FileObject) {
176c2c66affSColin Finck ObReferenceObject(FileObject);
177c2c66affSColin Finck }
178c2c66affSColin Finck
179c2c66affSColin Finck OneSecond.QuadPart = (LONGLONG)-1*1000*1000*10;
180c2c66affSColin Finck KeSetTimer( &Context->Timer,
181c2c66affSColin Finck OneSecond,
182c2c66affSColin Finck &Context->Dpc );
183c2c66affSColin Finck }
184c2c66affSColin Finck
185c2c66affSColin Finck BOOLEAN
Ext2ZeroData(IN PEXT2_IRP_CONTEXT IrpContext,IN PEXT2_VCB Vcb,IN PFILE_OBJECT FileObject,IN PLARGE_INTEGER Start,IN PLARGE_INTEGER End)186c2c66affSColin Finck Ext2ZeroData (
187c2c66affSColin Finck IN PEXT2_IRP_CONTEXT IrpContext,
188c2c66affSColin Finck IN PEXT2_VCB Vcb,
189c2c66affSColin Finck IN PFILE_OBJECT FileObject,
190c2c66affSColin Finck IN PLARGE_INTEGER Start,
191c2c66affSColin Finck IN PLARGE_INTEGER End
192c2c66affSColin Finck )
193c2c66affSColin Finck {
194c2c66affSColin Finck PEXT2_FCB Fcb;
195c2c66affSColin Finck PBCB Bcb;
196c2c66affSColin Finck PVOID Ptr;
197c2c66affSColin Finck ULONG Size;
198c2c66affSColin Finck BOOLEAN rc = TRUE;
199c2c66affSColin Finck
200c2c66affSColin Finck ASSERT (End && Start && End->QuadPart > Start->QuadPart);
201c2c66affSColin Finck Fcb = (PEXT2_FCB) FileObject->FsContext;
202c2c66affSColin Finck
203c2c66affSColin Finck /* skip data zero if we've already tracked unwritten part */
204c2c66affSColin Finck if (0 == ( End->LowPart & (BLOCK_SIZE -1)) &&
205c2c66affSColin Finck 0 == (Start->LowPart & (BLOCK_SIZE -1))) {
206c2c66affSColin Finck
207c2c66affSColin Finck if (INODE_HAS_EXTENT(Fcb->Inode)) {
208c2c66affSColin Finck return TRUE;
209c2c66affSColin Finck } else {
210c2c66affSColin Finck #if !EXT2_PRE_ALLOCATION_SUPPORT
211c2c66affSColin Finck return TRUE;
212c2c66affSColin Finck #endif
213c2c66affSColin Finck }
214c2c66affSColin Finck }
215c2c66affSColin Finck
216c2c66affSColin Finck /* clear data in range [Start, End) */
217c2c66affSColin Finck _SEH2_TRY {
218c2c66affSColin Finck rc = CcZeroData(FileObject, Start, End, Ext2CanIWait());
219c2c66affSColin Finck } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
220c2c66affSColin Finck DbgBreak();
221c2c66affSColin Finck } _SEH2_END;
222c2c66affSColin Finck
223c2c66affSColin Finck return rc;
224c2c66affSColin Finck }
225c2c66affSColin Finck
226c2c66affSColin Finck VOID
Ext2DeferWrite(IN PEXT2_IRP_CONTEXT IrpContext,PIRP Irp)227c2c66affSColin Finck Ext2DeferWrite(IN PEXT2_IRP_CONTEXT IrpContext, PIRP Irp)
228c2c66affSColin Finck {
229c2c66affSColin Finck ASSERT(IrpContext->Irp == Irp);
230c2c66affSColin Finck
231c2c66affSColin Finck Ext2QueueRequest(IrpContext);
232c2c66affSColin Finck }
233c2c66affSColin Finck
234c2c66affSColin Finck
235c2c66affSColin Finck NTSTATUS
Ext2WriteVolume(IN PEXT2_IRP_CONTEXT IrpContext)236c2c66affSColin Finck Ext2WriteVolume (IN PEXT2_IRP_CONTEXT IrpContext)
237c2c66affSColin Finck {
238c2c66affSColin Finck NTSTATUS Status = STATUS_UNSUCCESSFUL;
239c2c66affSColin Finck
240c2c66affSColin Finck PEXT2_VCB Vcb = NULL;
241c2c66affSColin Finck PEXT2_CCB Ccb = NULL;
242c2c66affSColin Finck PEXT2_FCBVCB FcbOrVcb = NULL;
243c2c66affSColin Finck PFILE_OBJECT FileObject = NULL;
244c2c66affSColin Finck
245c2c66affSColin Finck PDEVICE_OBJECT DeviceObject = NULL;
246c2c66affSColin Finck
247c2c66affSColin Finck PIRP Irp = NULL;
248c2c66affSColin Finck PIO_STACK_LOCATION IoStackLocation = NULL;
249c2c66affSColin Finck
250c2c66affSColin Finck ULONG Length;
251c2c66affSColin Finck LARGE_INTEGER ByteOffset;
252c2c66affSColin Finck
253c2c66affSColin Finck BOOLEAN PagingIo = FALSE;
254c2c66affSColin Finck BOOLEAN Nocache = FALSE;
255c2c66affSColin Finck BOOLEAN SynchronousIo = FALSE;
256c2c66affSColin Finck BOOLEAN MainResourceAcquired = FALSE;
257c2c66affSColin Finck
258c2c66affSColin Finck BOOLEAN bDeferred = FALSE;
259c2c66affSColin Finck
260c2c66affSColin Finck PUCHAR Buffer = NULL;
261c2c66affSColin Finck PEXT2_EXTENT Chain = NULL;
262c2c66affSColin Finck EXT2_EXTENT BlockArray;
263c2c66affSColin Finck
264c2c66affSColin Finck _SEH2_TRY {
265c2c66affSColin Finck
266c2c66affSColin Finck ASSERT(IrpContext);
267c2c66affSColin Finck ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
268c2c66affSColin Finck (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
269c2c66affSColin Finck
270c2c66affSColin Finck DeviceObject = IrpContext->DeviceObject;
271c2c66affSColin Finck Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
272c2c66affSColin Finck ASSERT(Vcb != NULL);
273c2c66affSColin Finck ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
274c2c66affSColin Finck (Vcb->Identifier.Size == sizeof(EXT2_VCB)));
275c2c66affSColin Finck
276c2c66affSColin Finck FileObject = IrpContext->FileObject;
277c2c66affSColin Finck FcbOrVcb = (PEXT2_FCBVCB) FileObject->FsContext;
278c2c66affSColin Finck ASSERT(FcbOrVcb);
279c2c66affSColin Finck
280c2c66affSColin Finck if (!(FcbOrVcb->Identifier.Type == EXT2VCB && (PVOID)FcbOrVcb == (PVOID)Vcb)) {
281c2c66affSColin Finck Status = STATUS_INVALID_DEVICE_REQUEST;
282c2c66affSColin Finck _SEH2_LEAVE;
283c2c66affSColin Finck }
284c2c66affSColin Finck
285c2c66affSColin Finck Ccb = (PEXT2_CCB) FileObject->FsContext2;
286c2c66affSColin Finck Irp = IrpContext->Irp;
287c2c66affSColin Finck IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
288c2c66affSColin Finck
289c2c66affSColin Finck Length = IoStackLocation->Parameters.Write.Length;
290c2c66affSColin Finck ByteOffset = IoStackLocation->Parameters.Write.ByteOffset;
291c2c66affSColin Finck
292c2c66affSColin Finck PagingIo = IsFlagOn(Irp->Flags, IRP_PAGING_IO);
293c2c66affSColin Finck Nocache = IsFlagOn(Irp->Flags, IRP_NOCACHE) || (Ccb != NULL);
294c2c66affSColin Finck SynchronousIo = IsFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO);
295c2c66affSColin Finck
296c2c66affSColin Finck if (PagingIo) {
297c2c66affSColin Finck ASSERT(Nocache);
298c2c66affSColin Finck }
299c2c66affSColin Finck
300c2c66affSColin Finck DEBUG(DL_INF, ("Ext2WriteVolume: Off=%I64xh Len=%xh Paging=%xh Nocache=%xh\n",
301c2c66affSColin Finck ByteOffset.QuadPart, Length, PagingIo, Nocache));
302c2c66affSColin Finck
303c2c66affSColin Finck if (Length == 0) {
304c2c66affSColin Finck Irp->IoStatus.Information = 0;
305c2c66affSColin Finck Status = STATUS_SUCCESS;
306c2c66affSColin Finck _SEH2_LEAVE;
307c2c66affSColin Finck }
308c2c66affSColin Finck
309c2c66affSColin Finck if (Nocache &&
310c2c66affSColin Finck (ByteOffset.LowPart & (SECTOR_SIZE - 1) ||
311c2c66affSColin Finck Length & (SECTOR_SIZE - 1))) {
312c2c66affSColin Finck Status = STATUS_INVALID_PARAMETER;
313c2c66affSColin Finck _SEH2_LEAVE;
314c2c66affSColin Finck }
315c2c66affSColin Finck
316c2c66affSColin Finck if (FlagOn(IrpContext->MinorFunction, IRP_MN_DPC)) {
317c2c66affSColin Finck ClearFlag(IrpContext->MinorFunction, IRP_MN_DPC);
318c2c66affSColin Finck Status = STATUS_PENDING;
319c2c66affSColin Finck _SEH2_LEAVE;
320c2c66affSColin Finck }
321c2c66affSColin Finck
322c2c66affSColin Finck if (ByteOffset.QuadPart >=
323c2c66affSColin Finck Vcb->PartitionInformation.PartitionLength.QuadPart ) {
324c2c66affSColin Finck Irp->IoStatus.Information = 0;
325c2c66affSColin Finck Status = STATUS_END_OF_FILE;
326c2c66affSColin Finck _SEH2_LEAVE;
327c2c66affSColin Finck }
328c2c66affSColin Finck
329c2c66affSColin Finck if (!Nocache) {
330c2c66affSColin Finck
331c2c66affSColin Finck BOOLEAN bAgain = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED);
332c2c66affSColin Finck BOOLEAN bWait = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
333c2c66affSColin Finck BOOLEAN bQueue = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED);
334c2c66affSColin Finck
335c2c66affSColin Finck if ( !CcCanIWrite(
336c2c66affSColin Finck FileObject,
337c2c66affSColin Finck Length,
338c2c66affSColin Finck (bWait && bQueue),
339c2c66affSColin Finck bAgain ) ) {
340c2c66affSColin Finck
341c2c66affSColin Finck Status = Ext2LockUserBuffer(
342c2c66affSColin Finck IrpContext->Irp,
343c2c66affSColin Finck Length,
344c2c66affSColin Finck IoReadAccess);
345c2c66affSColin Finck if (NT_SUCCESS(Status)) {
346c2c66affSColin Finck SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED);
347c2c66affSColin Finck CcDeferWrite( FileObject,
348c2c66affSColin Finck (PCC_POST_DEFERRED_WRITE)Ext2DeferWrite,
349c2c66affSColin Finck IrpContext,
350c2c66affSColin Finck Irp,
351c2c66affSColin Finck Length,
352c2c66affSColin Finck bAgain );
353c2c66affSColin Finck
354c2c66affSColin Finck bDeferred = TRUE;
355c2c66affSColin Finck Status = STATUS_PENDING;
356c2c66affSColin Finck
357c2c66affSColin Finck _SEH2_LEAVE;
358c2c66affSColin Finck }
359c2c66affSColin Finck }
360c2c66affSColin Finck }
361c2c66affSColin Finck
362c2c66affSColin Finck /*
363c2c66affSColin Finck * User direct volume access
364c2c66affSColin Finck */
365c2c66affSColin Finck
366c2c66affSColin Finck if (Ccb != NULL && !PagingIo) {
367c2c66affSColin Finck
368c2c66affSColin Finck if (!FlagOn(Ccb->Flags, CCB_VOLUME_DASD_PURGE)) {
369c2c66affSColin Finck
370c2c66affSColin Finck if (!FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED)) {
371c2c66affSColin Finck Status = Ext2PurgeVolume( Vcb, TRUE);
372c2c66affSColin Finck }
373c2c66affSColin Finck
374c2c66affSColin Finck SetFlag(Ccb->Flags, CCB_VOLUME_DASD_PURGE);
375c2c66affSColin Finck }
376c2c66affSColin Finck
377c2c66affSColin Finck if (!IsFlagOn(Ccb->Flags, CCB_ALLOW_EXTENDED_DASD_IO)) {
378c2c66affSColin Finck if (ByteOffset.QuadPart + Length > Vcb->Header.FileSize.QuadPart) {
379c2c66affSColin Finck Length = (ULONG)(Vcb->Header.FileSize.QuadPart - ByteOffset.QuadPart);
380c2c66affSColin Finck }
381c2c66affSColin Finck }
382c2c66affSColin Finck
383c2c66affSColin Finck } else if (Nocache && !PagingIo && (Vcb->SectionObject.DataSectionObject != NULL)) {
384c2c66affSColin Finck
385c2c66affSColin Finck ExAcquireResourceExclusiveLite(&Vcb->MainResource, TRUE);
386c2c66affSColin Finck MainResourceAcquired = TRUE;
387c2c66affSColin Finck
388c2c66affSColin Finck ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
389c2c66affSColin Finck ExReleaseResourceLite(&Vcb->PagingIoResource);
390c2c66affSColin Finck
391c2c66affSColin Finck CcFlushCache( &(Vcb->SectionObject),
392c2c66affSColin Finck &ByteOffset,
393c2c66affSColin Finck Length,
394c2c66affSColin Finck &(Irp->IoStatus));
395c2c66affSColin Finck
396c2c66affSColin Finck if (!NT_SUCCESS(Irp->IoStatus.Status)) {
397c2c66affSColin Finck Status = Irp->IoStatus.Status;
398c2c66affSColin Finck _SEH2_LEAVE;
399c2c66affSColin Finck }
400c2c66affSColin Finck
401c2c66affSColin Finck ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
402c2c66affSColin Finck ExReleaseResourceLite(&Vcb->PagingIoResource);
403c2c66affSColin Finck
404c2c66affSColin Finck CcPurgeCacheSection( &(Vcb->SectionObject),
405c2c66affSColin Finck (PLARGE_INTEGER)&(ByteOffset),
406c2c66affSColin Finck Length,
407c2c66affSColin Finck FALSE );
408c2c66affSColin Finck
409c2c66affSColin Finck ExReleaseResourceLite(&Vcb->MainResource);
410c2c66affSColin Finck MainResourceAcquired = FALSE;
411c2c66affSColin Finck }
412c2c66affSColin Finck
413c2c66affSColin Finck if ( (ByteOffset.QuadPart + Length) > Vcb->Header.FileSize.QuadPart) {
414c2c66affSColin Finck Length = (ULONG)(Vcb->Header.FileSize.QuadPart - ByteOffset.QuadPart);
415c2c66affSColin Finck }
416c2c66affSColin Finck
417c2c66affSColin Finck if (!Nocache) {
418c2c66affSColin Finck
419c2c66affSColin Finck if (FlagOn(IrpContext->MinorFunction, IRP_MN_MDL)) {
420c2c66affSColin Finck
421c2c66affSColin Finck CcPrepareMdlWrite (
422c2c66affSColin Finck Vcb->Volume,
423c2c66affSColin Finck &ByteOffset,
424c2c66affSColin Finck Length,
425c2c66affSColin Finck &Irp->MdlAddress,
426c2c66affSColin Finck &Irp->IoStatus );
427c2c66affSColin Finck
428c2c66affSColin Finck Status = Irp->IoStatus.Status;
429c2c66affSColin Finck
430c2c66affSColin Finck } else {
431c2c66affSColin Finck
432c2c66affSColin Finck Buffer = Ext2GetUserBuffer(Irp);
433c2c66affSColin Finck if (Buffer == NULL) {
434c2c66affSColin Finck DbgBreak();
435c2c66affSColin Finck
436c2c66affSColin Finck Status = STATUS_INVALID_USER_BUFFER;
437c2c66affSColin Finck _SEH2_LEAVE;
438c2c66affSColin Finck }
439c2c66affSColin Finck
440c2c66affSColin Finck if (!CcCopyWrite( Vcb->Volume,
441c2c66affSColin Finck (PLARGE_INTEGER)(&ByteOffset),
442c2c66affSColin Finck Length,
443c2c66affSColin Finck TRUE,
444c2c66affSColin Finck Buffer )) {
445c2c66affSColin Finck Status = STATUS_PENDING;
446c2c66affSColin Finck _SEH2_LEAVE;
447c2c66affSColin Finck }
448c2c66affSColin Finck
449c2c66affSColin Finck Status = Irp->IoStatus.Status;
450c2c66affSColin Finck Ext2AddVcbExtent(Vcb, ByteOffset.QuadPart, (LONGLONG)Length);
451c2c66affSColin Finck }
452c2c66affSColin Finck
453c2c66affSColin Finck if (NT_SUCCESS(Status)) {
454c2c66affSColin Finck Irp->IoStatus.Information = Length;
455c2c66affSColin Finck }
456c2c66affSColin Finck
457c2c66affSColin Finck } else if (PagingIo) {
458c2c66affSColin Finck
459c2c66affSColin Finck LONGLONG DirtyStart;
460c2c66affSColin Finck LONGLONG DirtyLba;
461c2c66affSColin Finck LONGLONG DirtyLength;
462c2c66affSColin Finck LONGLONG RemainLength;
463c2c66affSColin Finck
464c2c66affSColin Finck PEXT2_EXTENT Extent = NULL;
465c2c66affSColin Finck PEXT2_EXTENT List = NULL;
466c2c66affSColin Finck
467c2c66affSColin Finck Length &= ~((ULONG)SECTOR_SIZE - 1);
468c2c66affSColin Finck
469c2c66affSColin Finck Status = Ext2LockUserBuffer(IrpContext->Irp, Length, IoReadAccess);
470c2c66affSColin Finck if (!NT_SUCCESS(Status)) {
471c2c66affSColin Finck _SEH2_LEAVE;
472c2c66affSColin Finck }
473c2c66affSColin Finck
474c2c66affSColin Finck DirtyLba = ByteOffset.QuadPart;
475c2c66affSColin Finck RemainLength = (LONGLONG) Length;
476c2c66affSColin Finck
477c2c66affSColin Finck ASSERT(Length >= SECTOR_SIZE);
478c2c66affSColin Finck
479c2c66affSColin Finck while (RemainLength > 0) {
480c2c66affSColin Finck
481c2c66affSColin Finck DirtyStart = DirtyLba;
482c2c66affSColin Finck ASSERT(DirtyStart >= ByteOffset.QuadPart);
483c2c66affSColin Finck ASSERT(DirtyStart <= ByteOffset.QuadPart + Length);
484c2c66affSColin Finck
485c2c66affSColin Finck if (Ext2LookupVcbExtent(Vcb, DirtyStart, &DirtyLba, &DirtyLength)) {
486c2c66affSColin Finck
487c2c66affSColin Finck if (DirtyLba == -1) {
488c2c66affSColin Finck
489c2c66affSColin Finck DirtyLba = DirtyStart + DirtyLength;
490c2c66affSColin Finck if (ByteOffset.QuadPart + Length > DirtyLba) {
491c2c66affSColin Finck RemainLength = ByteOffset.QuadPart + Length - DirtyLba;
492c2c66affSColin Finck ASSERT(DirtyStart >= ByteOffset.QuadPart);
493c2c66affSColin Finck ASSERT(DirtyStart <= ByteOffset.QuadPart + Length);
494c2c66affSColin Finck } else {
495c2c66affSColin Finck RemainLength = 0;
496c2c66affSColin Finck }
497c2c66affSColin Finck continue;
498c2c66affSColin Finck }
499c2c66affSColin Finck
500c2c66affSColin Finck ASSERT(DirtyLba <= DirtyStart);
501c2c66affSColin Finck Extent = Ext2AllocateExtent();
502c2c66affSColin Finck
503c2c66affSColin Finck if (!Extent) {
504c2c66affSColin Finck DEBUG(DL_ERR, ( "Ex2WriteVolume: failed to allocate Extent\n"));
505c2c66affSColin Finck Status = STATUS_INSUFFICIENT_RESOURCES;
506c2c66affSColin Finck _SEH2_LEAVE;
507c2c66affSColin Finck }
508c2c66affSColin Finck
509c2c66affSColin Finck Extent->Irp = NULL;
510a1d7e993SPierre Schweitzer Extent->Lba = DirtyStart;
511c2c66affSColin Finck Extent->Offset = (ULONG)( DirtyStart + Length -
512c2c66affSColin Finck RemainLength - DirtyLba );
513c2c66affSColin Finck ASSERT(Extent->Offset <= Length);
514c2c66affSColin Finck
515c2c66affSColin Finck if (DirtyLba + DirtyLength >= DirtyStart + RemainLength) {
516c2c66affSColin Finck Extent->Length = (ULONG)( DirtyLba +
517c2c66affSColin Finck RemainLength -
518c2c66affSColin Finck DirtyStart );
519c2c66affSColin Finck ASSERT(Extent->Length <= Length);
520c2c66affSColin Finck RemainLength = 0;
521c2c66affSColin Finck } else {
522c2c66affSColin Finck Extent->Length = (ULONG)(DirtyLength + DirtyLba - DirtyStart);
523a1d7e993SPierre Schweitzer RemainLength = RemainLength - Extent->Length;
524a1d7e993SPierre Schweitzer /*
525c2c66affSColin Finck RemainLength = (DirtyStart + RemainLength) -
526c2c66affSColin Finck (DirtyLba + DirtyLength);
527a1d7e993SPierre Schweitzer */
528c2c66affSColin Finck ASSERT(RemainLength <= (LONGLONG)Length);
529c2c66affSColin Finck ASSERT(Extent->Length <= Length);
530c2c66affSColin Finck }
531c2c66affSColin Finck
532c2c66affSColin Finck ASSERT(Extent->Length >= SECTOR_SIZE);
533a1d7e993SPierre Schweitzer DirtyLba = DirtyStart + Extent->Length;
534c2c66affSColin Finck
535c2c66affSColin Finck if (List) {
536c2c66affSColin Finck List->Next = Extent;
537c2c66affSColin Finck List = Extent;
538c2c66affSColin Finck } else {
539c2c66affSColin Finck Chain = List = Extent;
540c2c66affSColin Finck }
541c2c66affSColin Finck
542c2c66affSColin Finck } else {
543c2c66affSColin Finck
544c2c66affSColin Finck if (RemainLength > SECTOR_SIZE) {
545c2c66affSColin Finck DirtyLba = DirtyStart + SECTOR_SIZE;
546c2c66affSColin Finck RemainLength -= SECTOR_SIZE;
547c2c66affSColin Finck } else {
548c2c66affSColin Finck RemainLength = 0;
549c2c66affSColin Finck }
550c2c66affSColin Finck }
551c2c66affSColin Finck }
552c2c66affSColin Finck
553c2c66affSColin Finck if (Chain) {
554c2c66affSColin Finck Status = Ext2ReadWriteBlocks(IrpContext,
555c2c66affSColin Finck Vcb,
556c2c66affSColin Finck Chain,
557c2c66affSColin Finck Length );
558c2c66affSColin Finck Irp = IrpContext->Irp;
559c2c66affSColin Finck
560c2c66affSColin Finck if (NT_SUCCESS(Status)) {
561c2c66affSColin Finck for (Extent = Chain; Extent != NULL; Extent = Extent->Next) {
562c2c66affSColin Finck Ext2RemoveVcbExtent(Vcb, Extent->Lba, Extent->Length);
563c2c66affSColin Finck }
564c2c66affSColin Finck }
565c2c66affSColin Finck
566c2c66affSColin Finck if (!Irp) {
567c2c66affSColin Finck _SEH2_LEAVE;
568c2c66affSColin Finck }
569c2c66affSColin Finck
570c2c66affSColin Finck } else {
571c2c66affSColin Finck
572c2c66affSColin Finck Irp->IoStatus.Information = Length;
573c2c66affSColin Finck Status = STATUS_SUCCESS;
574c2c66affSColin Finck _SEH2_LEAVE;
575c2c66affSColin Finck }
576c2c66affSColin Finck
577c2c66affSColin Finck } else {
578c2c66affSColin Finck
579c2c66affSColin Finck Length &= ~((ULONG)SECTOR_SIZE - 1);
580c2c66affSColin Finck
581c2c66affSColin Finck Status = Ext2LockUserBuffer(
582c2c66affSColin Finck IrpContext->Irp,
583c2c66affSColin Finck Length,
584c2c66affSColin Finck IoWriteAccess );
585c2c66affSColin Finck
586c2c66affSColin Finck if (!NT_SUCCESS(Status)) {
587c2c66affSColin Finck _SEH2_LEAVE;
588c2c66affSColin Finck }
589c2c66affSColin Finck
590c2c66affSColin Finck BlockArray.Irp = NULL;
591c2c66affSColin Finck BlockArray.Lba = ByteOffset.QuadPart;
592c2c66affSColin Finck BlockArray.Offset = 0;
593c2c66affSColin Finck BlockArray.Length = Length;
594c2c66affSColin Finck BlockArray.Next = NULL;
595c2c66affSColin Finck
596c2c66affSColin Finck Status = Ext2ReadWriteBlocks(IrpContext,
597c2c66affSColin Finck Vcb,
598c2c66affSColin Finck &BlockArray,
599c2c66affSColin Finck Length );
600c2c66affSColin Finck
601c2c66affSColin Finck if (NT_SUCCESS(Status)) {
602c2c66affSColin Finck Irp->IoStatus.Information = Length;
603c2c66affSColin Finck }
604c2c66affSColin Finck
605c2c66affSColin Finck Irp = IrpContext->Irp;
606c2c66affSColin Finck if (!Irp) {
607c2c66affSColin Finck _SEH2_LEAVE;
608c2c66affSColin Finck }
609c2c66affSColin Finck }
610c2c66affSColin Finck
611c2c66affSColin Finck } _SEH2_FINALLY {
612c2c66affSColin Finck
613c2c66affSColin Finck if (MainResourceAcquired) {
614c2c66affSColin Finck ExReleaseResourceLite(&Vcb->MainResource);
615c2c66affSColin Finck }
616c2c66affSColin Finck
617c2c66affSColin Finck if (!IrpContext->ExceptionInProgress) {
618c2c66affSColin Finck
619c2c66affSColin Finck if (Irp) {
620c2c66affSColin Finck
621c2c66affSColin Finck if (Status == STATUS_PENDING) {
622c2c66affSColin Finck
623c2c66affSColin Finck if (!bDeferred) {
624c2c66affSColin Finck Status = Ext2LockUserBuffer(
625c2c66affSColin Finck IrpContext->Irp,
626c2c66affSColin Finck Length,
627c2c66affSColin Finck IoReadAccess );
628c2c66affSColin Finck
629c2c66affSColin Finck if (NT_SUCCESS(Status)) {
630c2c66affSColin Finck Status = Ext2QueueRequest(IrpContext);
631c2c66affSColin Finck } else {
632c2c66affSColin Finck Ext2CompleteIrpContext(IrpContext, Status);
633c2c66affSColin Finck }
634c2c66affSColin Finck }
635c2c66affSColin Finck
636c2c66affSColin Finck } else {
637c2c66affSColin Finck
638c2c66affSColin Finck if (NT_SUCCESS(Status)) {
639c2c66affSColin Finck
640c2c66affSColin Finck if (SynchronousIo && !PagingIo) {
641c2c66affSColin Finck FileObject->CurrentByteOffset.QuadPart =
642c2c66affSColin Finck ByteOffset.QuadPart + Irp->IoStatus.Information;
643c2c66affSColin Finck }
644c2c66affSColin Finck
645c2c66affSColin Finck if (!PagingIo) {
646c2c66affSColin Finck SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
647c2c66affSColin Finck }
648c2c66affSColin Finck }
649c2c66affSColin Finck
650c2c66affSColin Finck Ext2CompleteIrpContext(IrpContext, Status);
651c2c66affSColin Finck }
652c2c66affSColin Finck
653c2c66affSColin Finck } else {
654c2c66affSColin Finck
655c2c66affSColin Finck Ext2FreeIrpContext(IrpContext);
656c2c66affSColin Finck }
657c2c66affSColin Finck }
658c2c66affSColin Finck
659c2c66affSColin Finck if (Chain) {
660c2c66affSColin Finck Ext2DestroyExtentChain(Chain);
661c2c66affSColin Finck }
662c2c66affSColin Finck } _SEH2_END;
663c2c66affSColin Finck
664c2c66affSColin Finck return Status;
665c2c66affSColin Finck }
666c2c66affSColin Finck
667c2c66affSColin Finck NTSTATUS
Ext2WriteInode(IN PEXT2_IRP_CONTEXT IrpContext,IN PEXT2_VCB Vcb,IN PEXT2_MCB Mcb,IN ULONGLONG Offset,IN PVOID Buffer,IN ULONG Size,IN BOOLEAN bDirectIo,OUT PULONG BytesWritten)668c2c66affSColin Finck Ext2WriteInode (
669c2c66affSColin Finck IN PEXT2_IRP_CONTEXT IrpContext,
670c2c66affSColin Finck IN PEXT2_VCB Vcb,
671c2c66affSColin Finck IN PEXT2_MCB Mcb,
672c2c66affSColin Finck IN ULONGLONG Offset,
673c2c66affSColin Finck IN PVOID Buffer,
674c2c66affSColin Finck IN ULONG Size,
675c2c66affSColin Finck IN BOOLEAN bDirectIo,
676c2c66affSColin Finck OUT PULONG BytesWritten
677c2c66affSColin Finck )
678c2c66affSColin Finck {
679c2c66affSColin Finck PEXT2_EXTENT Chain = NULL;
680c2c66affSColin Finck NTSTATUS Status = STATUS_UNSUCCESSFUL;
681c2c66affSColin Finck
682c2c66affSColin Finck _SEH2_TRY {
683c2c66affSColin Finck
684c2c66affSColin Finck if (BytesWritten) {
685c2c66affSColin Finck *BytesWritten = 0;
686c2c66affSColin Finck }
687c2c66affSColin Finck
688c2c66affSColin Finck Status = Ext2BuildExtents (
689c2c66affSColin Finck IrpContext,
690c2c66affSColin Finck Vcb,
691c2c66affSColin Finck Mcb,
692c2c66affSColin Finck Offset,
693c2c66affSColin Finck Size,
694c2c66affSColin Finck S_ISDIR(Mcb->Inode.i_mode) ? FALSE : TRUE,
695c2c66affSColin Finck &Chain
696c2c66affSColin Finck );
697c2c66affSColin Finck
698c2c66affSColin Finck if (!NT_SUCCESS(Status)) {
699c2c66affSColin Finck _SEH2_LEAVE;
700c2c66affSColin Finck }
701c2c66affSColin Finck
702c2c66affSColin Finck if (Chain == NULL) {
703c2c66affSColin Finck Status = STATUS_SUCCESS;
704c2c66affSColin Finck _SEH2_LEAVE;
705c2c66affSColin Finck }
706c2c66affSColin Finck
707c2c66affSColin Finck if (bDirectIo) {
708c2c66affSColin Finck
709c2c66affSColin Finck ASSERT(IrpContext != NULL);
710c2c66affSColin Finck
711c2c66affSColin Finck //
712c2c66affSColin Finck // We assume the offset is aligned.
713c2c66affSColin Finck //
714c2c66affSColin Finck
715c2c66affSColin Finck Status = Ext2ReadWriteBlocks(
716c2c66affSColin Finck IrpContext,
717c2c66affSColin Finck Vcb,
718c2c66affSColin Finck Chain,
719c2c66affSColin Finck Size
720c2c66affSColin Finck );
721c2c66affSColin Finck
722c2c66affSColin Finck } else {
723c2c66affSColin Finck
724c2c66affSColin Finck PEXT2_EXTENT Extent;
725c2c66affSColin Finck for (Extent = Chain; Extent != NULL; Extent = Extent->Next) {
726c2c66affSColin Finck
727c2c66affSColin Finck if ( !Ext2SaveBuffer(
728c2c66affSColin Finck IrpContext,
729c2c66affSColin Finck Vcb,
730c2c66affSColin Finck Extent->Lba,
731c2c66affSColin Finck Extent->Length,
732c2c66affSColin Finck (PVOID)((PUCHAR)Buffer + Extent->Offset)
733c2c66affSColin Finck )) {
734c2c66affSColin Finck _SEH2_LEAVE;
735c2c66affSColin Finck }
736c2c66affSColin Finck }
737c2c66affSColin Finck
738c2c66affSColin Finck if (IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK)) {
739c2c66affSColin Finck
740c2c66affSColin Finck DEBUG(DL_FLP, ("Ext2WriteInode is starting FlushingDpc...\n"));
741c2c66affSColin Finck Ext2StartFloppyFlushDpc(Vcb, NULL, NULL);
742c2c66affSColin Finck }
743c2c66affSColin Finck
744c2c66affSColin Finck Status = STATUS_SUCCESS;
745c2c66affSColin Finck }
746c2c66affSColin Finck
747c2c66affSColin Finck } _SEH2_FINALLY {
748c2c66affSColin Finck
749c2c66affSColin Finck if (Chain) {
750c2c66affSColin Finck Ext2DestroyExtentChain(Chain);
751c2c66affSColin Finck }
752c2c66affSColin Finck
753c2c66affSColin Finck if (NT_SUCCESS(Status) && BytesWritten) {
754c2c66affSColin Finck *BytesWritten = Size;
755c2c66affSColin Finck }
756c2c66affSColin Finck } _SEH2_END;
757c2c66affSColin Finck
758c2c66affSColin Finck return Status;
759c2c66affSColin Finck }
760c2c66affSColin Finck
761c2c66affSColin Finck
762c2c66affSColin Finck NTSTATUS
Ext2WriteFile(IN PEXT2_IRP_CONTEXT IrpContext)763c2c66affSColin Finck Ext2WriteFile(IN PEXT2_IRP_CONTEXT IrpContext)
764c2c66affSColin Finck {
765c2c66affSColin Finck PEXT2_VCB Vcb = NULL;
766c2c66affSColin Finck PEXT2_FCB Fcb = NULL;
767c2c66affSColin Finck PEXT2_CCB Ccb = NULL;
768c2c66affSColin Finck PFILE_OBJECT FileObject = NULL;
769c2c66affSColin Finck
770c2c66affSColin Finck PDEVICE_OBJECT DeviceObject = NULL;
771c2c66affSColin Finck
772c2c66affSColin Finck PIRP Irp = NULL;
773c2c66affSColin Finck PIO_STACK_LOCATION IoStackLocation = NULL;
774c2c66affSColin Finck PUCHAR Buffer = NULL;
775c2c66affSColin Finck
776c2c66affSColin Finck LARGE_INTEGER ByteOffset;
777c2c66affSColin Finck ULONG ReturnedLength = 0;
778c2c66affSColin Finck ULONG Length;
779c2c66affSColin Finck
780c2c66affSColin Finck NTSTATUS Status = STATUS_UNSUCCESSFUL;
781c2c66affSColin Finck
782c2c66affSColin Finck BOOLEAN OpPostIrp = FALSE;
783c2c66affSColin Finck BOOLEAN PagingIo = FALSE;
784c2c66affSColin Finck BOOLEAN Nocache = FALSE;
785c2c66affSColin Finck BOOLEAN SynchronousIo = FALSE;
786c2c66affSColin Finck
787c2c66affSColin Finck BOOLEAN RecursiveWriteThrough = FALSE;
788c2c66affSColin Finck BOOLEAN MainResourceAcquired = FALSE;
789c2c66affSColin Finck BOOLEAN PagingIoResourceAcquired = FALSE;
790c2c66affSColin Finck
791c2c66affSColin Finck BOOLEAN bDeferred = FALSE;
792c2c66affSColin Finck #ifndef __REACTOS__
793c2c66affSColin Finck BOOLEAN UpdateFileValidSize = FALSE;
794c2c66affSColin Finck #endif
795c2c66affSColin Finck BOOLEAN FileSizesChanged = FALSE;
796c2c66affSColin Finck BOOLEAN rc;
797c2c66affSColin Finck
798c2c66affSColin Finck
799c2c66affSColin Finck _SEH2_TRY {
800c2c66affSColin Finck
801c2c66affSColin Finck ASSERT(IrpContext);
802c2c66affSColin Finck ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
803c2c66affSColin Finck (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
804c2c66affSColin Finck
805c2c66affSColin Finck DeviceObject = IrpContext->DeviceObject;
806c2c66affSColin Finck Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
807c2c66affSColin Finck ASSERT(Vcb != NULL);
808c2c66affSColin Finck ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
809c2c66affSColin Finck (Vcb->Identifier.Size == sizeof(EXT2_VCB)));
810c2c66affSColin Finck
811c2c66affSColin Finck FileObject = IrpContext->FileObject;
812c2c66affSColin Finck Fcb = (PEXT2_FCB) FileObject->FsContext;
813c2c66affSColin Finck Ccb = (PEXT2_CCB) FileObject->FsContext2;
814c2c66affSColin Finck ASSERT(Fcb);
815c2c66affSColin Finck ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
816c2c66affSColin Finck (Fcb->Identifier.Size == sizeof(EXT2_FCB)));
817c2c66affSColin Finck
818c2c66affSColin Finck Irp = IrpContext->Irp;
819c2c66affSColin Finck IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
820c2c66affSColin Finck
821c2c66affSColin Finck Length = IoStackLocation->Parameters.Write.Length;
822c2c66affSColin Finck ByteOffset = IoStackLocation->Parameters.Write.ByteOffset;
823c2c66affSColin Finck
824c2c66affSColin Finck PagingIo = IsFlagOn(Irp->Flags, IRP_PAGING_IO);
825c2c66affSColin Finck Nocache = IsFlagOn(Irp->Flags, IRP_NOCACHE);
826c2c66affSColin Finck SynchronousIo = IsFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO);
827c2c66affSColin Finck
828c2c66affSColin Finck if (PagingIo) {
829c2c66affSColin Finck ASSERT(Nocache);
830c2c66affSColin Finck }
831c2c66affSColin Finck
832c2c66affSColin Finck DEBUG(DL_INF, ("Ext2WriteFile: %wZ Offset=%I64xh Length=%xh Paging=%xh Nocache=%xh\n",
833c2c66affSColin Finck &Fcb->Mcb->ShortName, ByteOffset.QuadPart, Length, PagingIo, Nocache));
834c2c66affSColin Finck
835c2c66affSColin Finck if (IsSpecialFile(Fcb) || IsInodeSymLink(Fcb->Inode) ) {
836c2c66affSColin Finck Status = STATUS_INVALID_DEVICE_REQUEST;
837c2c66affSColin Finck _SEH2_LEAVE;
838c2c66affSColin Finck }
839c2c66affSColin Finck
840c2c66affSColin Finck if (IsFileDeleted(Fcb->Mcb) ||
841c2c66affSColin Finck (IsSymLink(Fcb) && IsFileDeleted(Fcb->Mcb->Target)) ) {
842c2c66affSColin Finck Status = STATUS_FILE_DELETED;
843c2c66affSColin Finck _SEH2_LEAVE;
844c2c66affSColin Finck }
845c2c66affSColin Finck
846c2c66affSColin Finck if (Length == 0) {
847c2c66affSColin Finck Irp->IoStatus.Information = 0;
848c2c66affSColin Finck Status = STATUS_SUCCESS;
849c2c66affSColin Finck _SEH2_LEAVE;
850c2c66affSColin Finck }
851c2c66affSColin Finck
852c2c66affSColin Finck if (ByteOffset.LowPart == FILE_USE_FILE_POINTER_POSITION &&
853c2c66affSColin Finck ByteOffset.HighPart == -1) {
854c2c66affSColin Finck ByteOffset = FileObject->CurrentByteOffset;
855c2c66affSColin Finck } else if (IsWritingToEof(ByteOffset)) {
856c2c66affSColin Finck ByteOffset.QuadPart = Fcb->Header.FileSize.QuadPart;
857c2c66affSColin Finck }
858c2c66affSColin Finck
859c2c66affSColin Finck if (Nocache && !PagingIo &&
860c2c66affSColin Finck ( (ByteOffset.LowPart & (SECTOR_SIZE - 1)) ||
861c2c66affSColin Finck (Length & (SECTOR_SIZE - 1))) ) {
862c2c66affSColin Finck Status = STATUS_INVALID_PARAMETER;
863c2c66affSColin Finck _SEH2_LEAVE;
864c2c66affSColin Finck }
865c2c66affSColin Finck
866c2c66affSColin Finck if (FlagOn(IrpContext->MinorFunction, IRP_MN_DPC)) {
867c2c66affSColin Finck ClearFlag(IrpContext->MinorFunction, IRP_MN_DPC);
868c2c66affSColin Finck Status = STATUS_PENDING;
869c2c66affSColin Finck _SEH2_LEAVE;
870c2c66affSColin Finck }
871c2c66affSColin Finck
872c2c66affSColin Finck if (!Nocache) {
873c2c66affSColin Finck
874c2c66affSColin Finck BOOLEAN bAgain = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED);
875c2c66affSColin Finck BOOLEAN bWait = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
876c2c66affSColin Finck BOOLEAN bQueue = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED);
877c2c66affSColin Finck
878c2c66affSColin Finck if ( !CcCanIWrite(
879c2c66affSColin Finck FileObject,
880c2c66affSColin Finck Length,
881c2c66affSColin Finck (bWait && bQueue),
882c2c66affSColin Finck bAgain ) ) {
883c2c66affSColin Finck
884c2c66affSColin Finck Status = Ext2LockUserBuffer(
885c2c66affSColin Finck IrpContext->Irp,
886c2c66affSColin Finck Length,
887c2c66affSColin Finck IoReadAccess);
888c2c66affSColin Finck
889c2c66affSColin Finck if (NT_SUCCESS(Status)) {
890c2c66affSColin Finck SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED);
891c2c66affSColin Finck CcDeferWrite( FileObject,
892c2c66affSColin Finck (PCC_POST_DEFERRED_WRITE)Ext2DeferWrite,
893c2c66affSColin Finck IrpContext,
894c2c66affSColin Finck Irp,
895c2c66affSColin Finck Length,
896c2c66affSColin Finck bAgain );
897c2c66affSColin Finck bDeferred = TRUE;
898c2c66affSColin Finck Status = STATUS_PENDING;
899c2c66affSColin Finck _SEH2_LEAVE;
900c2c66affSColin Finck }
901c2c66affSColin Finck }
902c2c66affSColin Finck }
903c2c66affSColin Finck
904c2c66affSColin Finck if (IsDirectory(Fcb) && !PagingIo) {
905c2c66affSColin Finck Status = STATUS_INVALID_DEVICE_REQUEST;
906c2c66affSColin Finck _SEH2_LEAVE;
907c2c66affSColin Finck }
908c2c66affSColin Finck
909c2c66affSColin Finck if (IsFlagOn(Irp->Flags, IRP_SYNCHRONOUS_PAGING_IO) && !IrpContext->IsTopLevel) {
910c2c66affSColin Finck
911c2c66affSColin Finck PIRP TopIrp;
912c2c66affSColin Finck
913c2c66affSColin Finck TopIrp = IoGetTopLevelIrp();
914c2c66affSColin Finck
915c2c66affSColin Finck if ( (ULONG_PTR)TopIrp > FSRTL_MAX_TOP_LEVEL_IRP_FLAG &&
916c2c66affSColin Finck NodeType(TopIrp) == IO_TYPE_IRP) {
917c2c66affSColin Finck
918c2c66affSColin Finck PIO_STACK_LOCATION IrpStack;
919c2c66affSColin Finck
920c2c66affSColin Finck IrpStack = IoGetCurrentIrpStackLocation(TopIrp);
921c2c66affSColin Finck
922c2c66affSColin Finck if ((IrpStack->MajorFunction == IRP_MJ_WRITE) &&
923c2c66affSColin Finck (IrpStack->FileObject->FsContext == FileObject->FsContext) &&
924c2c66affSColin Finck !FlagOn(TopIrp->Flags, IRP_NOCACHE) ) {
925c2c66affSColin Finck
926c2c66affSColin Finck SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WRITE_THROUGH);
927c2c66affSColin Finck RecursiveWriteThrough = TRUE;
928c2c66affSColin Finck }
929c2c66affSColin Finck }
930c2c66affSColin Finck }
931c2c66affSColin Finck
932c2c66affSColin Finck if (PagingIo) {
933c2c66affSColin Finck
934c2c66affSColin Finck if (!ExAcquireResourceSharedLite(&Fcb->PagingIoResource, TRUE)) {
935c2c66affSColin Finck Status = STATUS_PENDING;
936c2c66affSColin Finck _SEH2_LEAVE;
937c2c66affSColin Finck }
938c2c66affSColin Finck PagingIoResourceAcquired = TRUE;
939c2c66affSColin Finck
940c2c66affSColin Finck if ( (ByteOffset.QuadPart + Length) > Fcb->Header.FileSize.QuadPart) {
941c2c66affSColin Finck
942c2c66affSColin Finck if (ByteOffset.QuadPart >= Fcb->Header.AllocationSize.QuadPart) {
943c2c66affSColin Finck
944c2c66affSColin Finck Status = STATUS_SUCCESS;
945c2c66affSColin Finck Irp->IoStatus.Information = 0;
946c2c66affSColin Finck _SEH2_LEAVE;
947c2c66affSColin Finck
948c2c66affSColin Finck } else {
949c2c66affSColin Finck
950c2c66affSColin Finck ReturnedLength = (ULONG)(Fcb->Header.FileSize.QuadPart - ByteOffset.QuadPart);
951c2c66affSColin Finck if (ByteOffset.QuadPart + Length > Fcb->Header.AllocationSize.QuadPart)
952c2c66affSColin Finck Length = (ULONG)(Fcb->Header.AllocationSize.QuadPart - ByteOffset.QuadPart);
953c2c66affSColin Finck }
954c2c66affSColin Finck
955c2c66affSColin Finck } else {
956c2c66affSColin Finck
957c2c66affSColin Finck ReturnedLength = Length;
958c2c66affSColin Finck }
959c2c66affSColin Finck
960c2c66affSColin Finck } else {
961c2c66affSColin Finck
962c2c66affSColin Finck if (!Ext2CheckFileAccess(Vcb, Fcb->Mcb, Ext2FileCanWrite)) {
963c2c66affSColin Finck Status = STATUS_ACCESS_DENIED;
964c2c66affSColin Finck _SEH2_LEAVE;
965c2c66affSColin Finck }
966c2c66affSColin Finck
967c2c66affSColin Finck if (IsDirectory(Fcb)) {
968c2c66affSColin Finck _SEH2_LEAVE;
969c2c66affSColin Finck }
970c2c66affSColin Finck
971c2c66affSColin Finck if (!ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE)) {
972c2c66affSColin Finck Status = STATUS_PENDING;
973c2c66affSColin Finck _SEH2_LEAVE;
974c2c66affSColin Finck }
975c2c66affSColin Finck MainResourceAcquired = TRUE;
976c2c66affSColin Finck
977c2c66affSColin Finck //
978c2c66affSColin Finck // Do flushing for such cases
979c2c66affSColin Finck //
980c2c66affSColin Finck if (Nocache && Ccb != NULL && Fcb->SectionObject.DataSectionObject != NULL) {
981c2c66affSColin Finck
982c2c66affSColin Finck ExAcquireSharedStarveExclusive( &Fcb->PagingIoResource, TRUE);
983c2c66affSColin Finck ExReleaseResourceLite(&Fcb->PagingIoResource);
984c2c66affSColin Finck
985c2c66affSColin Finck CcFlushCache( &(Fcb->SectionObject),
986c2c66affSColin Finck &ByteOffset,
987c2c66affSColin Finck CEILING_ALIGNED(ULONG, Length, BLOCK_SIZE),
988c2c66affSColin Finck &(Irp->IoStatus));
989c2c66affSColin Finck ClearLongFlag(Fcb->Flags, FCB_FILE_MODIFIED);
990c2c66affSColin Finck
991c2c66affSColin Finck if (!NT_SUCCESS(Irp->IoStatus.Status)) {
992c2c66affSColin Finck Status = Irp->IoStatus.Status;
993c2c66affSColin Finck _SEH2_LEAVE;
994c2c66affSColin Finck }
995c2c66affSColin Finck
996c2c66affSColin Finck ExAcquireSharedStarveExclusive( &Fcb->PagingIoResource, TRUE);
997c2c66affSColin Finck ExReleaseResourceLite(&Fcb->PagingIoResource);
998c2c66affSColin Finck
999c2c66affSColin Finck CcPurgeCacheSection( &(Fcb->SectionObject),
1000c2c66affSColin Finck &(ByteOffset),
1001c2c66affSColin Finck CEILING_ALIGNED(ULONG, Length, BLOCK_SIZE),
1002c2c66affSColin Finck FALSE );
1003c2c66affSColin Finck }
1004c2c66affSColin Finck
1005c2c66affSColin Finck if (!FsRtlCheckLockForWriteAccess(&Fcb->FileLockAnchor, Irp)) {
1006c2c66affSColin Finck Status = STATUS_FILE_LOCK_CONFLICT;
1007c2c66affSColin Finck _SEH2_LEAVE;
1008c2c66affSColin Finck }
1009c2c66affSColin Finck
1010c2c66affSColin Finck if (Ccb != NULL) {
1011c2c66affSColin Finck Status = FsRtlCheckOplock( &Fcb->Oplock,
1012c2c66affSColin Finck Irp,
1013c2c66affSColin Finck IrpContext,
1014c2c66affSColin Finck Ext2OplockComplete,
1015c2c66affSColin Finck Ext2LockIrp );
1016c2c66affSColin Finck
1017c2c66affSColin Finck if (Status != STATUS_SUCCESS) {
1018c2c66affSColin Finck OpPostIrp = TRUE;
1019c2c66affSColin Finck _SEH2_LEAVE;
1020c2c66affSColin Finck }
1021c2c66affSColin Finck
1022c2c66affSColin Finck //
1023c2c66affSColin Finck // Set the flag indicating if Fast I/O is possible
1024c2c66affSColin Finck //
1025c2c66affSColin Finck
1026c2c66affSColin Finck Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb);
1027c2c66affSColin Finck }
1028c2c66affSColin Finck
1029c2c66affSColin Finck //
1030c2c66affSColin Finck // Extend the inode size when the i/o is beyond the file end ?
1031c2c66affSColin Finck //
1032c2c66affSColin Finck
1033c2c66affSColin Finck if ((ByteOffset.QuadPart + Length) > Fcb->Header.FileSize.QuadPart) {
1034c2c66affSColin Finck
1035c2c66affSColin Finck LARGE_INTEGER AllocationSize, Last;
1036c2c66affSColin Finck
1037c2c66affSColin Finck if (!ExAcquireResourceExclusiveLite(&Fcb->PagingIoResource, TRUE)) {
1038c2c66affSColin Finck Status = STATUS_PENDING;
1039c2c66affSColin Finck _SEH2_LEAVE;
1040c2c66affSColin Finck }
1041c2c66affSColin Finck PagingIoResourceAcquired = TRUE;
1042c2c66affSColin Finck
1043c2c66affSColin Finck /* let this irp wait, since it has to be synchronous */
1044c2c66affSColin Finck SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
1045c2c66affSColin Finck
1046c2c66affSColin Finck Last.QuadPart = Fcb->Header.AllocationSize.QuadPart;
1047c2c66affSColin Finck AllocationSize.QuadPart = (LONGLONG)(ByteOffset.QuadPart + Length);
1048c2c66affSColin Finck AllocationSize.QuadPart = CEILING_ALIGNED(ULONGLONG,
1049c2c66affSColin Finck (ULONGLONG)AllocationSize.QuadPart,
1050c2c66affSColin Finck (ULONGLONG)BLOCK_SIZE);
1051c2c66affSColin Finck
1052c2c66affSColin Finck /* tell Ext2ExpandFile to allocate unwritten extent or NULL blocks
1053c2c66affSColin Finck for indirect files, otherwise we might get gabage data in holes */
1054c2c66affSColin Finck IrpContext->MajorFunction += IRP_MJ_MAXIMUM_FUNCTION;
1055c2c66affSColin Finck Status = Ext2ExpandFile(IrpContext, Vcb, Fcb->Mcb, &AllocationSize);
1056c2c66affSColin Finck IrpContext->MajorFunction -= IRP_MJ_MAXIMUM_FUNCTION;
1057c2c66affSColin Finck if (AllocationSize.QuadPart > Last.QuadPart) {
1058c2c66affSColin Finck Fcb->Header.AllocationSize.QuadPart = AllocationSize.QuadPart;
1059c2c66affSColin Finck SetLongFlag(Fcb->Flags, FCB_ALLOC_IN_WRITE);
1060c2c66affSColin Finck }
1061c2c66affSColin Finck ExReleaseResourceLite(&Fcb->PagingIoResource);
1062c2c66affSColin Finck PagingIoResourceAcquired = FALSE;
1063c2c66affSColin Finck
1064c2c66affSColin Finck if (ByteOffset.QuadPart >= Fcb->Header.AllocationSize.QuadPart) {
1065c2c66affSColin Finck if (NT_SUCCESS(Status)) {
1066c2c66affSColin Finck DbgBreak();
1067c2c66affSColin Finck Status = STATUS_UNSUCCESSFUL;
1068c2c66affSColin Finck }
1069c2c66affSColin Finck _SEH2_LEAVE;
1070c2c66affSColin Finck }
1071c2c66affSColin Finck
1072c2c66affSColin Finck if (ByteOffset.QuadPart + Length > Fcb->Header.AllocationSize.QuadPart) {
1073c2c66affSColin Finck Length = (ULONG)(Fcb->Header.AllocationSize.QuadPart - ByteOffset.QuadPart);
1074c2c66affSColin Finck }
1075c2c66affSColin Finck
1076c2c66affSColin Finck Fcb->Header.FileSize.QuadPart = Fcb->Inode->i_size = ByteOffset.QuadPart + Length;
1077c2c66affSColin Finck Ext2SaveInode(IrpContext, Vcb, Fcb->Inode);
1078c2c66affSColin Finck
1079c2c66affSColin Finck if (CcIsFileCached(FileObject)) {
1080c2c66affSColin Finck CcSetFileSizes(FileObject, (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
1081c2c66affSColin Finck }
1082c2c66affSColin Finck
1083c2c66affSColin Finck FileObject->Flags |= FO_FILE_SIZE_CHANGED | FO_FILE_MODIFIED;
1084c2c66affSColin Finck FileSizesChanged = TRUE;
1085c2c66affSColin Finck
1086c2c66affSColin Finck if (Fcb->Header.FileSize.QuadPart >= 0x80000000 &&
1087c2c66affSColin Finck !IsFlagOn(SUPER_BLOCK->s_feature_ro_compat, EXT2_FEATURE_RO_COMPAT_LARGE_FILE)) {
1088c2c66affSColin Finck SetFlag(SUPER_BLOCK->s_feature_ro_compat, EXT2_FEATURE_RO_COMPAT_LARGE_FILE);
1089c2c66affSColin Finck Ext2SaveSuper(IrpContext, Vcb);
1090c2c66affSColin Finck }
1091c2c66affSColin Finck
1092c2c66affSColin Finck DEBUG(DL_IO, ("Ext2WriteFile: expanding %wZ to FS: %I64xh FA: %I64xh\n",
1093c2c66affSColin Finck &Fcb->Mcb->ShortName, Fcb->Header.FileSize.QuadPart,
1094c2c66affSColin Finck Fcb->Header.AllocationSize.QuadPart));
1095c2c66affSColin Finck }
1096c2c66affSColin Finck
1097c2c66affSColin Finck ReturnedLength = Length;
1098c2c66affSColin Finck }
1099c2c66affSColin Finck
1100c2c66affSColin Finck if (!Nocache) {
1101c2c66affSColin Finck
1102c2c66affSColin Finck if (FileObject->PrivateCacheMap == NULL) {
1103c2c66affSColin Finck CcInitializeCacheMap(
1104c2c66affSColin Finck FileObject,
1105c2c66affSColin Finck (PCC_FILE_SIZES)(&Fcb->Header.AllocationSize),
1106c2c66affSColin Finck FALSE,
1107c2c66affSColin Finck &Ext2Global->CacheManagerCallbacks,
1108c2c66affSColin Finck Fcb );
1109c2c66affSColin Finck
1110c2c66affSColin Finck CcSetReadAheadGranularity(
1111c2c66affSColin Finck FileObject,
1112c2c66affSColin Finck READ_AHEAD_GRANULARITY );
1113c2c66affSColin Finck }
1114c2c66affSColin Finck
1115c2c66affSColin Finck if (FlagOn(IrpContext->MinorFunction, IRP_MN_MDL)) {
1116c2c66affSColin Finck
1117c2c66affSColin Finck CcPrepareMdlWrite(
1118c2c66affSColin Finck FileObject,
1119c2c66affSColin Finck &ByteOffset,
1120c2c66affSColin Finck Length,
1121c2c66affSColin Finck &Irp->MdlAddress,
1122c2c66affSColin Finck &Irp->IoStatus );
1123c2c66affSColin Finck
1124c2c66affSColin Finck Status = Irp->IoStatus.Status;
1125c2c66affSColin Finck
1126c2c66affSColin Finck } else {
1127c2c66affSColin Finck
1128c2c66affSColin Finck Buffer = Ext2GetUserBuffer(Irp);
1129c2c66affSColin Finck if (Buffer == NULL) {
1130c2c66affSColin Finck DbgBreak();
1131c2c66affSColin Finck Status = STATUS_INVALID_USER_BUFFER;
1132c2c66affSColin Finck _SEH2_LEAVE;
1133c2c66affSColin Finck }
1134c2c66affSColin Finck
1135c2c66affSColin Finck if (ByteOffset.QuadPart > Fcb->Header.ValidDataLength.QuadPart) {
1136c2c66affSColin Finck
1137c2c66affSColin Finck /* let this irp wait, since it has to be synchronous */
1138c2c66affSColin Finck SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
1139c2c66affSColin Finck
1140c2c66affSColin Finck rc = Ext2ZeroData(IrpContext, Vcb, FileObject,
1141c2c66affSColin Finck &Fcb->Header.ValidDataLength, &ByteOffset);
1142c2c66affSColin Finck if (!rc) {
1143c2c66affSColin Finck Status = STATUS_PENDING;
1144c2c66affSColin Finck DbgBreak();
1145c2c66affSColin Finck _SEH2_LEAVE;
1146c2c66affSColin Finck }
1147c2c66affSColin Finck }
1148c2c66affSColin Finck
1149c2c66affSColin Finck if (!CcCopyWrite(FileObject, &ByteOffset, Length, Ext2CanIWait(), Buffer)) {
1150c2c66affSColin Finck if (Ext2CanIWait() ||
1151c2c66affSColin Finck !CcCopyWrite(FileObject, &ByteOffset, Length, TRUE, Buffer)) {
1152c2c66affSColin Finck Status = STATUS_PENDING;
1153c2c66affSColin Finck DbgBreak();
1154c2c66affSColin Finck _SEH2_LEAVE;
1155c2c66affSColin Finck }
1156c2c66affSColin Finck }
1157c2c66affSColin Finck
1158c2c66affSColin Finck if (ByteOffset.QuadPart + Length > Fcb->Header.ValidDataLength.QuadPart ) {
1159c2c66affSColin Finck
1160c2c66affSColin Finck if (Fcb->Header.FileSize.QuadPart < ByteOffset.QuadPart + Length) {
1161c2c66affSColin Finck Fcb->Header.ValidDataLength.QuadPart = Fcb->Header.FileSize.QuadPart;
1162c2c66affSColin Finck } else {
1163c2c66affSColin Finck if (Fcb->Header.ValidDataLength.QuadPart < ByteOffset.QuadPart + Length)
1164c2c66affSColin Finck Fcb->Header.ValidDataLength.QuadPart = ByteOffset.QuadPart + Length;
1165c2c66affSColin Finck }
1166c2c66affSColin Finck
1167c2c66affSColin Finck CcSetFileSizes(FileObject, (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
1168c2c66affSColin Finck FileSizesChanged = TRUE;
1169c2c66affSColin Finck }
1170c2c66affSColin Finck
1171c2c66affSColin Finck Status = STATUS_SUCCESS;
1172c2c66affSColin Finck }
1173c2c66affSColin Finck
1174c2c66affSColin Finck if (NT_SUCCESS(Status)) {
1175c2c66affSColin Finck Irp->IoStatus.Information = Length;
1176c2c66affSColin Finck if (IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK)) {
1177c2c66affSColin Finck DEBUG(DL_FLP, ("Ext2WriteFile is starting FlushingDpc...\n"));
1178c2c66affSColin Finck Ext2StartFloppyFlushDpc(Vcb, Fcb, FileObject);
1179c2c66affSColin Finck }
1180c2c66affSColin Finck }
1181c2c66affSColin Finck
1182c2c66affSColin Finck } else {
1183c2c66affSColin Finck
1184c2c66affSColin Finck if (!PagingIo && !RecursiveWriteThrough && !IsLazyWriter(Fcb)) {
1185c2c66affSColin Finck if (ByteOffset.QuadPart > Fcb->Header.ValidDataLength.QuadPart) {
1186c2c66affSColin Finck
1187c2c66affSColin Finck /* let this irp wait, since it has to be synchronous */
1188c2c66affSColin Finck SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
1189c2c66affSColin Finck rc = Ext2ZeroData(IrpContext, Vcb, FileObject,
1190c2c66affSColin Finck &Fcb->Header.ValidDataLength,
1191c2c66affSColin Finck &ByteOffset);
1192c2c66affSColin Finck if (!rc) {
1193c2c66affSColin Finck Status = STATUS_PENDING;
1194c2c66affSColin Finck DbgBreak();
1195c2c66affSColin Finck _SEH2_LEAVE;
1196c2c66affSColin Finck }
1197c2c66affSColin Finck }
1198c2c66affSColin Finck }
1199c2c66affSColin Finck
1200c2c66affSColin Finck Status = Ext2LockUserBuffer(
1201c2c66affSColin Finck IrpContext->Irp,
1202c2c66affSColin Finck Length,
1203c2c66affSColin Finck IoReadAccess );
1204c2c66affSColin Finck
1205c2c66affSColin Finck if (!NT_SUCCESS(Status)) {
1206c2c66affSColin Finck _SEH2_LEAVE;
1207c2c66affSColin Finck }
1208c2c66affSColin Finck
1209c2c66affSColin Finck Irp->IoStatus.Status = STATUS_SUCCESS;
1210c2c66affSColin Finck Irp->IoStatus.Information = ReturnedLength;
1211c2c66affSColin Finck
1212c2c66affSColin Finck Status = Ext2WriteInode(
1213c2c66affSColin Finck IrpContext,
1214c2c66affSColin Finck Vcb,
1215c2c66affSColin Finck Fcb->Mcb,
1216c2c66affSColin Finck (ULONGLONG)(ByteOffset.QuadPart),
1217c2c66affSColin Finck NULL,
1218c2c66affSColin Finck ReturnedLength,
1219c2c66affSColin Finck TRUE,
1220c2c66affSColin Finck &Length
1221c2c66affSColin Finck );
1222c2c66affSColin Finck
1223c2c66affSColin Finck Irp = IrpContext->Irp;
1224c2c66affSColin Finck
1225c2c66affSColin Finck if (NT_SUCCESS(Status) && !RecursiveWriteThrough && !IsLazyWriter(Fcb)) {
1226c2c66affSColin Finck
1227c2c66affSColin Finck if (ByteOffset.QuadPart + Length > Fcb->Header.ValidDataLength.QuadPart ) {
1228c2c66affSColin Finck
1229c2c66affSColin Finck FileSizesChanged = TRUE;
1230c2c66affSColin Finck
1231c2c66affSColin Finck if (Fcb->Header.FileSize.QuadPart < ByteOffset.QuadPart + Length) {
1232c2c66affSColin Finck if (!PagingIo)
1233c2c66affSColin Finck Fcb->Header.FileSize.QuadPart = ByteOffset.QuadPart + Length;
1234c2c66affSColin Finck Fcb->Header.ValidDataLength.QuadPart = Fcb->Header.FileSize.QuadPart;
1235c2c66affSColin Finck } else {
1236c2c66affSColin Finck if (Fcb->Header.ValidDataLength.QuadPart < ByteOffset.QuadPart + Length)
1237c2c66affSColin Finck Fcb->Header.ValidDataLength.QuadPart = ByteOffset.QuadPart + Length;
1238c2c66affSColin Finck }
1239c2c66affSColin Finck
1240c2c66affSColin Finck if (!PagingIo && CcIsFileCached(FileObject)) {
1241c2c66affSColin Finck CcSetFileSizes(FileObject, (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
1242c2c66affSColin Finck }
1243c2c66affSColin Finck
1244c2c66affSColin Finck DEBUG(DL_IO, ("Ext2WriteFile: %wZ written FS: %I64xh FA: %I64xh BO: %I64xh LEN: %u\n",
1245c2c66affSColin Finck &Fcb->Mcb->ShortName, Fcb->Header.FileSize.QuadPart,
1246c2c66affSColin Finck Fcb->Header.AllocationSize.QuadPart, ByteOffset.QuadPart, Length));
1247c2c66affSColin Finck }
1248c2c66affSColin Finck }
1249c2c66affSColin Finck }
1250c2c66affSColin Finck
1251c2c66affSColin Finck if (FileSizesChanged) {
1252c2c66affSColin Finck FileObject->Flags |= FO_FILE_SIZE_CHANGED | FO_FILE_MODIFIED;
1253c2c66affSColin Finck Ext2NotifyReportChange( IrpContext, Vcb, Fcb->Mcb,
1254c2c66affSColin Finck FILE_NOTIFY_CHANGE_SIZE,
1255c2c66affSColin Finck FILE_ACTION_MODIFIED );
1256c2c66affSColin Finck }
1257c2c66affSColin Finck
1258c2c66affSColin Finck } _SEH2_FINALLY {
1259c2c66affSColin Finck
1260c2c66affSColin Finck /*
1261c2c66affSColin Finck * in case we got excpetions, we need revert MajorFunction
1262c2c66affSColin Finck * back to IRP_MJ_WRITE. The reason we do this, is to tell
1263c2c66affSColin Finck * Ext2ExpandFile to allocate unwritten extent or don't add
1264c2c66affSColin Finck * new blocks for indirect files.
1265c2c66affSColin Finck */
1266c2c66affSColin Finck if (IrpContext->MajorFunction > IRP_MJ_MAXIMUM_FUNCTION)
1267c2c66affSColin Finck IrpContext->MajorFunction -= IRP_MJ_MAXIMUM_FUNCTION;
1268c2c66affSColin Finck
1269c2c66affSColin Finck if (Irp) {
1270c2c66affSColin Finck if (PagingIoResourceAcquired) {
1271c2c66affSColin Finck ExReleaseResourceLite(&Fcb->PagingIoResource);
1272c2c66affSColin Finck }
1273c2c66affSColin Finck
1274c2c66affSColin Finck if (MainResourceAcquired) {
1275c2c66affSColin Finck ExReleaseResourceLite(&Fcb->MainResource);
1276c2c66affSColin Finck }
1277c2c66affSColin Finck }
1278c2c66affSColin Finck
1279c2c66affSColin Finck if (!OpPostIrp && !IrpContext->ExceptionInProgress) {
1280c2c66affSColin Finck
1281c2c66affSColin Finck if (Irp) {
1282c2c66affSColin Finck
1283c2c66affSColin Finck if (Status == STATUS_PENDING ||
1284c2c66affSColin Finck Status == STATUS_CANT_WAIT ) {
1285c2c66affSColin Finck
1286c2c66affSColin Finck if (!bDeferred) {
1287c2c66affSColin Finck Status = Ext2QueueRequest(IrpContext);
1288c2c66affSColin Finck }
1289c2c66affSColin Finck
1290c2c66affSColin Finck } else {
1291c2c66affSColin Finck
1292c2c66affSColin Finck if (NT_SUCCESS(Status) && !PagingIo) {
1293c2c66affSColin Finck
1294c2c66affSColin Finck if (SynchronousIo) {
1295c2c66affSColin Finck FileObject->CurrentByteOffset.QuadPart =
1296c2c66affSColin Finck ByteOffset.QuadPart + Irp->IoStatus.Information;
1297c2c66affSColin Finck }
1298c2c66affSColin Finck
1299c2c66affSColin Finck SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
1300c2c66affSColin Finck SetLongFlag(Fcb->Flags, FCB_FILE_MODIFIED);
1301c2c66affSColin Finck }
1302c2c66affSColin Finck
1303c2c66affSColin Finck Ext2CompleteIrpContext(IrpContext, Status);
1304c2c66affSColin Finck }
1305c2c66affSColin Finck } else {
1306c2c66affSColin Finck Ext2FreeIrpContext(IrpContext);
1307c2c66affSColin Finck }
1308c2c66affSColin Finck }
1309c2c66affSColin Finck } _SEH2_END;
1310c2c66affSColin Finck
1311c2c66affSColin Finck DEBUG(DL_IO, ("Ext2WriteFile: %wZ written at Offset=%I64xh Length=%xh PagingIo=%d Nocache=%d "
1312c2c66affSColin Finck "RetLen=%xh VDL=%I64xh FileSize=%I64xh i_size=%I64xh Status=%xh\n",
1313c2c66affSColin Finck &Fcb->Mcb->ShortName, ByteOffset, Length, PagingIo, Nocache, ReturnedLength,
1314c2c66affSColin Finck Fcb->Header.ValidDataLength.QuadPart,Fcb->Header.FileSize.QuadPart,
1315c2c66affSColin Finck Fcb->Inode->i_size, Status));
1316c2c66affSColin Finck
1317c2c66affSColin Finck return Status;
1318c2c66affSColin Finck }
1319c2c66affSColin Finck
1320c2c66affSColin Finck NTSTATUS
Ext2WriteComplete(IN PEXT2_IRP_CONTEXT IrpContext)1321c2c66affSColin Finck Ext2WriteComplete (IN PEXT2_IRP_CONTEXT IrpContext)
1322c2c66affSColin Finck {
1323c2c66affSColin Finck NTSTATUS Status = STATUS_UNSUCCESSFUL;
1324c2c66affSColin Finck PFILE_OBJECT FileObject;
1325c2c66affSColin Finck PIRP Irp;
1326c2c66affSColin Finck PIO_STACK_LOCATION IrpSp;
1327c2c66affSColin Finck
1328c2c66affSColin Finck _SEH2_TRY {
1329c2c66affSColin Finck
1330c2c66affSColin Finck ASSERT(IrpContext);
1331c2c66affSColin Finck ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
1332c2c66affSColin Finck (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
1333c2c66affSColin Finck
1334c2c66affSColin Finck FileObject = IrpContext->FileObject;
1335c2c66affSColin Finck
1336c2c66affSColin Finck Irp = IrpContext->Irp;
1337c2c66affSColin Finck IrpSp = IoGetCurrentIrpStackLocation(Irp);
1338c2c66affSColin Finck
1339c2c66affSColin Finck CcMdlWriteComplete(FileObject, &(IrpSp->Parameters.Write.ByteOffset), Irp->MdlAddress);
1340c2c66affSColin Finck Irp->MdlAddress = NULL;
1341c2c66affSColin Finck Status = STATUS_SUCCESS;
1342c2c66affSColin Finck
1343c2c66affSColin Finck } _SEH2_FINALLY {
1344c2c66affSColin Finck
1345c2c66affSColin Finck if (!IrpContext->ExceptionInProgress) {
1346c2c66affSColin Finck Ext2CompleteIrpContext(IrpContext, Status);
1347c2c66affSColin Finck }
1348c2c66affSColin Finck } _SEH2_END;
1349c2c66affSColin Finck
1350c2c66affSColin Finck return Status;
1351c2c66affSColin Finck }
1352c2c66affSColin Finck
1353c2c66affSColin Finck
1354c2c66affSColin Finck NTSTATUS
Ext2Write(IN PEXT2_IRP_CONTEXT IrpContext)1355c2c66affSColin Finck Ext2Write (IN PEXT2_IRP_CONTEXT IrpContext)
1356c2c66affSColin Finck {
1357c2c66affSColin Finck NTSTATUS Status;
1358c2c66affSColin Finck PEXT2_FCBVCB FcbOrVcb;
1359c2c66affSColin Finck PDEVICE_OBJECT DeviceObject;
1360c2c66affSColin Finck PFILE_OBJECT FileObject;
1361c2c66affSColin Finck PEXT2_VCB Vcb;
1362c2c66affSColin Finck BOOLEAN bCompleteRequest = TRUE;
1363c2c66affSColin Finck
1364c2c66affSColin Finck ASSERT(IrpContext);
1365c2c66affSColin Finck
1366c2c66affSColin Finck ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
1367c2c66affSColin Finck (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
1368c2c66affSColin Finck
1369c2c66affSColin Finck _SEH2_TRY {
1370c2c66affSColin Finck
1371c2c66affSColin Finck if (IsFlagOn(IrpContext->MinorFunction, IRP_MN_COMPLETE)) {
1372c2c66affSColin Finck
1373c2c66affSColin Finck Status = Ext2WriteComplete(IrpContext);
1374c2c66affSColin Finck bCompleteRequest = FALSE;
1375c2c66affSColin Finck
1376c2c66affSColin Finck } else {
1377c2c66affSColin Finck
1378c2c66affSColin Finck DeviceObject = IrpContext->DeviceObject;
1379c2c66affSColin Finck if (IsExt2FsDevice(DeviceObject)) {
1380c2c66affSColin Finck Status = STATUS_INVALID_DEVICE_REQUEST;
1381c2c66affSColin Finck _SEH2_LEAVE;
1382c2c66affSColin Finck }
1383c2c66affSColin Finck FileObject = IrpContext->FileObject;
1384c2c66affSColin Finck
1385c2c66affSColin Finck Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
1386c2c66affSColin Finck
1387c2c66affSColin Finck if (Vcb->Identifier.Type != EXT2VCB ||
1388c2c66affSColin Finck Vcb->Identifier.Size != sizeof(EXT2_VCB) ) {
1389c2c66affSColin Finck Status = STATUS_INVALID_PARAMETER;
1390c2c66affSColin Finck _SEH2_LEAVE;
1391c2c66affSColin Finck }
1392c2c66affSColin Finck
1393c2c66affSColin Finck if (IsVcbReadOnly(Vcb)) {
1394c2c66affSColin Finck Status = STATUS_MEDIA_WRITE_PROTECTED;
1395c2c66affSColin Finck _SEH2_LEAVE;
1396c2c66affSColin Finck }
1397c2c66affSColin Finck
1398c2c66affSColin Finck if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED) &&
1399c2c66affSColin Finck Vcb->LockFile != FileObject ) {
1400c2c66affSColin Finck Status = STATUS_ACCESS_DENIED;
1401c2c66affSColin Finck _SEH2_LEAVE;
1402c2c66affSColin Finck }
1403c2c66affSColin Finck
1404c2c66affSColin Finck FcbOrVcb = (PEXT2_FCBVCB) FileObject->FsContext;
1405c2c66affSColin Finck
1406c2c66affSColin Finck if (FcbOrVcb->Identifier.Type == EXT2VCB) {
1407c2c66affSColin Finck
1408c2c66affSColin Finck Status = Ext2WriteVolume(IrpContext);
1409c2c66affSColin Finck if (!NT_SUCCESS(Status)) {
1410c2c66affSColin Finck DbgBreak();
1411c2c66affSColin Finck }
1412c2c66affSColin Finck bCompleteRequest = FALSE;
1413c2c66affSColin Finck
1414c2c66affSColin Finck } else if (FcbOrVcb->Identifier.Type == EXT2FCB) {
1415c2c66affSColin Finck
1416c2c66affSColin Finck if (IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING)) {
1417c2c66affSColin Finck Status = STATUS_TOO_LATE;
1418c2c66affSColin Finck _SEH2_LEAVE;
1419c2c66affSColin Finck }
1420c2c66affSColin Finck
1421c2c66affSColin Finck Status = Ext2WriteFile(IrpContext);
1422c2c66affSColin Finck if (!NT_SUCCESS(Status)) {
1423c2c66affSColin Finck DbgBreak();
1424c2c66affSColin Finck }
1425c2c66affSColin Finck
1426c2c66affSColin Finck bCompleteRequest = FALSE;
1427c2c66affSColin Finck } else {
1428c2c66affSColin Finck Status = STATUS_INVALID_PARAMETER;
1429c2c66affSColin Finck }
1430c2c66affSColin Finck }
1431c2c66affSColin Finck
1432c2c66affSColin Finck } _SEH2_FINALLY {
1433c2c66affSColin Finck
1434c2c66affSColin Finck if (bCompleteRequest) {
1435c2c66affSColin Finck Ext2CompleteIrpContext(IrpContext, Status);
1436c2c66affSColin Finck }
1437c2c66affSColin Finck } _SEH2_END;
1438c2c66affSColin Finck
1439c2c66affSColin Finck return Status;
1440c2c66affSColin Finck }
1441