ReactOS  0.4.14-dev-317-g96040ec
write.cpp File Reference
#include "udffs.h"
Include dependency graph for write.cpp:

Go to the source code of this file.

Macros

#define UDF_BUG_CHECK_ID   UDF_FILE_WRITE
 
#define USE_CcCopyWrite_TO_ZERO
 
#define PURGE_BLOCK_SZ   0x10000000
 

Functions

NTSTATUS NTAPI UDFWrite (PDEVICE_OBJECT DeviceObject, PIRP Irp)
 
NTSTATUS UDFCommonWrite (PtrUDFIrpContext PtrIrpContext, PIRP Irp)
 
VOID NTAPI UDFDeferredWriteCallBack (IN PVOID Context1, IN PVOID Context2)
 
VOID UDFPurgeCacheEx_ (PtrUDFNTRequiredFCB NtReqFcb, LONGLONG Offset, LONGLONG Length, BOOLEAN CanWait, PVCB Vcb, PFILE_OBJECT FileObject)
 

Macro Definition Documentation

◆ PURGE_BLOCK_SZ

#define PURGE_BLOCK_SZ   0x10000000

◆ UDF_BUG_CHECK_ID

#define UDF_BUG_CHECK_ID   UDF_FILE_WRITE

Definition at line 20 of file write.cpp.

◆ USE_CcCopyWrite_TO_ZERO

#define USE_CcCopyWrite_TO_ZERO

Definition at line 1067 of file write.cpp.

Function Documentation

◆ UDFCommonWrite()

NTSTATUS UDFCommonWrite ( PtrUDFIrpContext  PtrIrpContext,
PIRP  Irp 
)

Definition at line 112 of file write.cpp.

115 {
119  ULONG WriteLength = 0, TruncatedLength = 0;
120  SIZE_T NumberBytesWritten = 0;
122  PtrUDFFCB Fcb = NULL;
123  PtrUDFCCB Ccb = NULL;
124  PVCB Vcb = NULL;
126  PERESOURCE PtrResourceAcquired = NULL;
127  PERESOURCE PtrResourceAcquired2 = NULL;
128  PVOID SystemBuffer = NULL;
129 // PVOID TmpBuffer = NULL;
130 // uint32 KeyValue = 0;
131  PIRP TopIrp;
132 
133  LONGLONG ASize;
134  LONGLONG OldVDL;
135 
136  ULONG Res1Acq = 0;
137  ULONG Res2Acq = 0;
138 
139  BOOLEAN CacheLocked = FALSE;
140 
141  BOOLEAN CanWait = FALSE;
142  BOOLEAN PagingIo = FALSE;
143  BOOLEAN NonBufferedIo = FALSE;
144  BOOLEAN SynchronousIo = FALSE;
145  BOOLEAN IsThisADeferredWrite = FALSE;
146  BOOLEAN WriteToEOF = FALSE;
147  BOOLEAN Resized = FALSE;
148  BOOLEAN RecursiveWriteThrough = FALSE;
149  BOOLEAN WriteFileSizeToDirNdx = FALSE;
150  BOOLEAN ZeroBlock = FALSE;
151  BOOLEAN VcbAcquired = FALSE;
152  BOOLEAN ZeroBlockDone = FALSE;
153 
154  TmPrint(("UDFCommonWrite: irp %x\n", Irp));
155 
156  _SEH2_TRY {
157 
158 
159  TopIrp = IoGetTopLevelIrp();
160 
161  switch((ULONG_PTR)TopIrp) {
163  UDFPrint((" FSRTL_FSP_TOP_LEVEL_IRP\n"));
164  break;
166  UDFPrint((" FSRTL_CACHE_TOP_LEVEL_IRP\n"));
167  break;
169  UDFPrint((" FSRTL_MOD_WRITE_TOP_LEVEL_IRP\n"));
170  break;
172  UDFPrint((" FSRTL_FAST_IO_TOP_LEVEL_IRP\n"));
173  BrutePoint();
174  break;
175  case NULL:
176  UDFPrint((" NULL TOP_LEVEL_IRP\n"));
177  break;
178  default:
179  if(TopIrp == Irp) {
180  UDFPrint((" TOP_LEVEL_IRP\n"));
181  } else {
182  UDFPrint((" RECURSIVE_IRP, TOP = %x\n", TopIrp));
183  }
184  break;
185  }
186 
187  // First, get a pointer to the current I/O stack location
189  ASSERT(IrpSp);
190  MmPrint((" Enter Irp, MDL=%x\n", Irp->MdlAddress));
191  if(Irp->MdlAddress) {
192  UDFTouch(Irp->MdlAddress);
193  }
194 
197 
198  // If this happens to be a MDL write complete request, then
199  // allocated MDL can be freed. This may cause a recursive write
200  // back into the FSD.
202  // Caller wants to tell the Cache Manager that a previously
203  // allocated MDL can be freed.
204  UDFMdlComplete(PtrIrpContext, Irp, IrpSp, FALSE);
205  // The IRP has been completed.
207  }
208 
209  // If this is a request at IRQL DISPATCH_LEVEL, then post the request
210  if (IrpSp->MinorFunction & IRP_MN_DPC) {
212  }
213 
214  // Get the FCB and CCB pointers
215  Ccb = (PtrUDFCCB)(FileObject->FsContext2);
216  ASSERT(Ccb);
217  Fcb = Ccb->Fcb;
218  ASSERT(Fcb);
219  Vcb = Fcb->Vcb;
220 
221  if(Fcb->FCBFlags & UDF_FCB_DELETED) {
222  ASSERT(FALSE);
224  }
225 
226  // is this operation allowed ?
227  if(Vcb->VCBFlags & UDF_VCB_FLAGS_MEDIA_READ_ONLY) {
229  }
230  Vcb->VCBFlags |= UDF_VCB_SKIP_EJECT_CHECK;
231 
232  // Disk based file systems might decide to verify the logical volume
233  // (if required and only if removable media are supported) at this time
234  // As soon as Tray is locked, we needn't call UDFVerifyVcb()
235 
236  ByteOffset = IrpSp->Parameters.Write.ByteOffset;
237 
238  CanWait = (PtrIrpContext->IrpContextFlags & UDF_IRP_CONTEXT_CAN_BLOCK) ? TRUE : FALSE;
239  PagingIo = (Irp->Flags & IRP_PAGING_IO) ? TRUE : FALSE;
240  NonBufferedIo = (Irp->Flags & IRP_NOCACHE) ? TRUE : FALSE;
241  SynchronousIo = (FileObject->Flags & FO_SYNCHRONOUS_IO) ? TRUE : FALSE;
242  UDFPrint((" Flags: %s; %s; %s; %s; Irp(W): %8.8x\n",
243  CanWait ? "Wt" : "nw", PagingIo ? "Pg" : "np",
244  NonBufferedIo ? "NBuf" : "buff", SynchronousIo ? "Snc" : "Asc",
245  Irp->Flags));
246 
247  NtReqFcb = Fcb->NTRequiredFCB;
248 
249  Res1Acq = UDFIsResourceAcquired(&(NtReqFcb->MainResource));
250  if(!Res1Acq) {
251  Res1Acq = PtrIrpContext->IrpContextFlags & UDF_IRP_CONTEXT_RES1_ACQ;
252  }
253  Res2Acq = UDFIsResourceAcquired(&(NtReqFcb->PagingIoResource));
254  if(!Res2Acq) {
255  Res2Acq = PtrIrpContext->IrpContextFlags & UDF_IRP_CONTEXT_RES2_ACQ;
256  }
257 
258  if(!NonBufferedIo &&
259  (Fcb->NodeIdentifier.NodeType != UDF_NODE_TYPE_VCB)) {
260  if((Fcb->NodeIdentifier.NodeType != UDF_NODE_TYPE_VCB) &&
261  UDFIsAStream(Fcb->FileInfo)) {
262  UDFNotifyFullReportChange( Vcb, Fcb->FileInfo,
265  } else {
266  UDFNotifyFullReportChange( Vcb, Fcb->FileInfo,
269  }
270  }
271 
272  // Get some of the parameters supplied to us
273  WriteLength = IrpSp->Parameters.Write.Length;
274  if (WriteLength == 0) {
275  // a 0 byte write can be immediately succeeded
276  if (SynchronousIo && !PagingIo && NT_SUCCESS(RC)) {
277  // NT expects changing CurrentByteOffset to zero in this case
278  FileObject->CurrentByteOffset.QuadPart = 0;
279  }
280  try_return(RC);
281  }
282 
283  // If this is the normal file we have to check for
284  // write access according to the current state of the file locks.
285  if (!PagingIo &&
286  !FsRtlCheckLockForWriteAccess( &(NtReqFcb->FileLock), Irp) ) {
288  }
289 
290  // **********
291  // Is this a write of the volume itself ?
292  // **********
293  if (Fcb->NodeIdentifier.NodeType == UDF_NODE_TYPE_VCB) {
294  // Yup, we need to send this on to the disk driver after
295  // validation of the offset and length.
296  Vcb = (PVCB)(Fcb);
297  if(!CanWait)
299  // I dislike the idea of writing to not locked media
300  if(!(Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_LOCKED)) {
302  }
303 
304  if(PtrIrpContext->IrpContextFlags & UDF_IRP_CONTEXT_FLUSH2_REQUIRED) {
305 
306  UDFPrint((" UDF_IRP_CONTEXT_FLUSH2_REQUIRED\n"));
308 
309  if(!(Vcb->VCBFlags & UDF_VCB_FLAGS_RAW_DISK)) {
310  UDFCloseAllSystemDelayedInDir(Vcb, Vcb->RootDirFCB->FileInfo);
311  }
312 #ifdef UDF_DELAYED_CLOSE
314 #endif //UDF_DELAYED_CLOSE
315 
316  }
317 
318  // Acquire the volume resource exclusive
319  UDFAcquireResourceExclusive(&(Vcb->VCBResource), TRUE);
320  PtrResourceAcquired = &(Vcb->VCBResource);
321 
322  // I dislike the idea of writing to mounted media too, but M$ has another point of view...
323  if(Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_MOUNTED) {
324  // flush system cache
326  }
327 #if defined(_MSC_VER) && !defined(__clang__)
328 /* FIXME */
329  if(PagingIo) {
330  CollectStatistics(Vcb, MetaDataWrites);
331  CollectStatisticsEx(Vcb, MetaDataWriteBytes, NumberBytesWritten);
332  }
333 #endif
334  // Forward the request to the lower level driver
335  // Lock the callers buffer
336  if (!NT_SUCCESS(RC = UDFLockCallersBuffer(PtrIrpContext, Irp, TRUE, WriteLength))) {
337  try_return(RC);
338  }
339  SystemBuffer = UDFGetCallersBuffer(PtrIrpContext, Irp);
340  if(!SystemBuffer)
342  // Indicate, that volume contents can change after this operation
343  // This flag will force VerifyVolume in future
344  UDFPrint((" set UnsafeIoctl\n"));
345  Vcb->VCBFlags |= UDF_VCB_FLAGS_UNSAFE_IOCTL;
346  // Make sure, that volume will never be quick-remounted
347  // It is very important for ChkUdf utility.
348  Vcb->SerialNumber--;
349  // Perform actual Write
350  RC = UDFTWrite(Vcb, SystemBuffer, WriteLength,
351  (ULONG)(ByteOffset.QuadPart >> Vcb->BlockSizeBits),
352  &NumberBytesWritten);
353  UDFUnlockCallersBuffer(PtrIrpContext, Irp, SystemBuffer);
354  try_return(RC);
355  }
356 
357  if(Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_READ_ONLY) {
359  }
360 
361  // back pressure for very smart and fast system cache ;)
362  if(!NonBufferedIo) {
363  // cached IO
364  if(Vcb->VerifyCtx.QueuedCount ||
365  Vcb->VerifyCtx.ItemCount >= UDF_MAX_VERIFY_CACHE) {
367  }
368  } else {
369  if(Vcb->VerifyCtx.ItemCount > UDF_SYS_CACHE_STOP_THR) {
371  }
372  }
373 
374  // The FSD (if it is a "nice" FSD) should check whether it is
375  // convenient to allow the write to proceed by utilizing the
376  // CcCanIWrite() function call. If it is not convenient to perform
377  // the write at this time, we should defer the request for a while.
378  // The check should not however be performed for non-cached write
379  // operations. To determine whether we are retrying the operation
380  // or now, use Flags in the IrpContext structure we have created
381 
382  IsThisADeferredWrite = (PtrIrpContext->IrpContextFlags & UDF_IRP_CONTEXT_DEFERRED_WRITE) ? TRUE : FALSE;
383 
384  if (!NonBufferedIo) {
385  MmPrint((" CcCanIWrite()\n"));
386  if (!CcCanIWrite(FileObject, WriteLength, CanWait, IsThisADeferredWrite)) {
387  // Cache Manager and/or the VMM does not want us to perform
388  // the write at this time. Post the request.
390  UDFPrint(("UDFCommonWrite: Defer write\n"));
391  MmPrint((" CcDeferWrite()\n"));
392  CcDeferWrite(FileObject, UDFDeferredWriteCallBack, PtrIrpContext, Irp, WriteLength, IsThisADeferredWrite);
394  }
395  }
396 
397  // If the write request is directed to a page file,
398  // send the request directly to the disk
399  if (Fcb->FCBFlags & UDF_FCB_PAGE_FILE) {
400  NonBufferedIo = TRUE;
401  }
402 
403  // We can continue. Check whether this write operation is targeted
404  // to a directory object in which case the UDF FSD will disallow
405  // the write request.
406  if (Fcb->FCBFlags & UDF_FCB_DIRECTORY) {
408  try_return(RC);
409  }
410 
411  // Validate start offset and length supplied.
412  // Here is a special check that determines whether the caller wishes to
413  // begin the write at current end-of-file (whatever the value of that
414  // offset might be)
415  if(ByteOffset.HighPart == (LONG)0xFFFFFFFF) {
416  if(ByteOffset.LowPart == FILE_WRITE_TO_END_OF_FILE) {
417  WriteToEOF = TRUE;
418  ByteOffset = NtReqFcb->CommonFCBHeader.FileSize;
419  } else
421  ByteOffset = FileObject->CurrentByteOffset;
422  }
423  }
424 
425  // Check if this volume has already been shut down. If it has, fail
426  // this write request.
427  if (Vcb->VCBFlags & UDF_VCB_FLAGS_SHUTDOWN) {
429  }
430 
431  // Paging I/O write operations are special. If paging i/o write
432  // requests begin beyond end-of-file, the request should be no-oped
433  // If paging i/o
434  // requests extend beyond current end of file, they should be truncated
435  // to current end-of-file.
436  if(PagingIo && (WriteToEOF || ((ByteOffset.QuadPart + WriteLength) > NtReqFcb->CommonFCBHeader.FileSize.QuadPart))) {
437  if (ByteOffset.QuadPart > NtReqFcb->CommonFCBHeader.FileSize.QuadPart) {
438  TruncatedLength = 0;
439  } else {
440  TruncatedLength = (ULONG)(NtReqFcb->CommonFCBHeader.FileSize.QuadPart - ByteOffset.QuadPart);
441  }
442  if(!TruncatedLength) try_return(RC = STATUS_SUCCESS);
443  } else {
444  TruncatedLength = WriteLength;
445  }
446 
447 #if defined(_MSC_VER) && !defined(__clang__)
448 /* FIXME */
449  if(PagingIo) {
450  CollectStatistics(Vcb, UserFileWrites);
451  CollectStatisticsEx(Vcb, UserFileWriteBytes, NumberBytesWritten);
452  }
453 #endif
454 
455  // There are certain complications that arise when the same file stream
456  // has been opened for cached and non-cached access. The FSD is then
457  // responsible for maintaining a consistent view of the data seen by
458  // the caller.
459  // If this happens to be a non-buffered I/O, we should __try to flush the
460  // cached data (if some other file object has already initiated caching
461  // on the file stream). We should also __try to purge the cached
462  // information though the purge will probably fail if the file has been
463  // mapped into some process' virtual address space
464  // WARNING !!! we should not flush data beyond valid data length
465  if ( NonBufferedIo &&
466  !PagingIo &&
467  NtReqFcb->SectionObject.DataSectionObject &&
468  TruncatedLength &&
469  (ByteOffset.QuadPart < NtReqFcb->CommonFCBHeader.FileSize.QuadPart)) {
470 
471  if(!Res1Acq) {
472  // Try to acquire the FCB MainResource exclusively
473  if(!UDFAcquireResourceExclusive(&(NtReqFcb->MainResource), CanWait)) {
475  }
476  PtrResourceAcquired = &(NtReqFcb->MainResource);
477  }
478 
479  if(!Res2Acq) {
480  // We hold PagingIo shared around the flush to fix a
481  // cache coherency problem.
482  UDFAcquireSharedStarveExclusive(&(NtReqFcb->PagingIoResource), TRUE );
483  PtrResourceAcquired2 = &(NtReqFcb->PagingIoResource);
484  }
485 
486  // Flush and then attempt to purge the cache
487  if((ByteOffset.QuadPart + TruncatedLength) > NtReqFcb->CommonFCBHeader.FileSize.QuadPart) {
488  NumberBytesWritten = TruncatedLength;
489  } else {
490  NumberBytesWritten = (ULONG)(NtReqFcb->CommonFCBHeader.FileSize.QuadPart - ByteOffset.QuadPart);
491  }
492 
493  MmPrint((" CcFlushCache()\n"));
494  CcFlushCache(&(NtReqFcb->SectionObject), &ByteOffset, NumberBytesWritten, &(Irp->IoStatus));
495 
496  if(PtrResourceAcquired2) {
497  UDFReleaseResource(&(NtReqFcb->PagingIoResource));
498  PtrResourceAcquired2 = NULL;
499  }
500  // If the flush failed, return error to the caller
501  if (!NT_SUCCESS(RC = Irp->IoStatus.Status)) {
502  NumberBytesWritten = 0;
503  try_return(RC);
504  }
505 
506  if(!Res2Acq) {
507  // Acquiring and immediately dropping the resource serializes
508  // us behind any other writes taking place (either from the
509  // lazy writer or modified page writer).
510  UDFAcquireResourceExclusive(&(NtReqFcb->PagingIoResource), TRUE );
511  UDFReleaseResource(&(NtReqFcb->PagingIoResource));
512  }
513 
514  // Attempt the purge and ignore the return code
515  MmPrint((" CcPurgeCacheSection()\n"));
516  CcPurgeCacheSection(&(NtReqFcb->SectionObject), &ByteOffset,
517  NumberBytesWritten, FALSE);
518  NumberBytesWritten = 0;
519  // We are finished with our flushing and purging
520  if(PtrResourceAcquired) {
521  UDFReleaseResource(PtrResourceAcquired);
522  PtrResourceAcquired = NULL;
523  }
524  }
525 
526  // Determine if we were called by the lazywriter.
527  // We reuse 'IsThisADeferredWrite' here to decrease stack usage
528  IsThisADeferredWrite = (NtReqFcb->LazyWriterThreadID == HandleToUlong(PsGetCurrentThreadId()));
529 
530  // Acquire the appropriate FCB resource
531  if(PagingIo) {
532  // PagingIoResource is already acquired exclusive
533  // on LazyWrite condition (see UDFAcqLazyWrite())
534  ASSERT(NonBufferedIo);
535  if(!IsThisADeferredWrite) {
536  if(!Res2Acq) {
537  // Try to acquire the FCB PagingIoResource exclusive
538  if(!UDFAcquireResourceExclusive(&(NtReqFcb->PagingIoResource), CanWait)) {
540  }
541  // Remember the resource that was acquired
542  PtrResourceAcquired2 = &(NtReqFcb->PagingIoResource);
543  }
544  }
545  } else {
546  // Try to acquire the FCB MainResource shared
547  if(NonBufferedIo) {
548  if(!Res2Acq) {
549  if(!UDFAcquireResourceExclusive(&(NtReqFcb->PagingIoResource), CanWait)) {
550  //if(!UDFAcquireSharedWaitForExclusive(&(NtReqFcb->PagingIoResource), CanWait)) {
552  }
553  PtrResourceAcquired2 = &(NtReqFcb->PagingIoResource);
554  }
555  } else {
556  if(!Res1Acq) {
558  if(!UDFAcquireResourceExclusive(&(NtReqFcb->MainResource), CanWait)) {
559  //if(!UDFAcquireResourceShared(&(NtReqFcb->MainResource), CanWait)) {
561  }
562  PtrResourceAcquired = &(NtReqFcb->MainResource);
563  }
564  }
565  // Remember the resource that was acquired
566  }
567 
568  // Set the flag indicating if Fast I/O is possible
569  NtReqFcb->CommonFCBHeader.IsFastIoPossible = UDFIsFastIoPossible(Fcb);
570 /* if(NtReqFcb->CommonFCBHeader.IsFastIoPossible == FastIoIsPossible) {
571  NtReqFcb->CommonFCBHeader.IsFastIoPossible = FastIoIsQuestionable;
572  }*/
573 
574  if ( (Irp->Flags & IRP_SYNCHRONOUS_PAGING_IO) &&
575  (PtrIrpContext->IrpContextFlags & UDF_IRP_CONTEXT_NOT_TOP_LEVEL)) {
576 
577  // This clause determines if the top level request was
578  // in the FastIo path.
579  if ((ULONG_PTR)TopIrp > FSRTL_MAX_TOP_LEVEL_IRP_FLAG) {
580 
581  PIO_STACK_LOCATION IrpStack;
582  ASSERT( TopIrp->Type == IO_TYPE_IRP );
583  IrpStack = IoGetCurrentIrpStackLocation(TopIrp);
584 
585  // Finally this routine detects if the Top irp was a
586  // write to this file and thus we are the writethrough.
587  if ((IrpStack->MajorFunction == IRP_MJ_WRITE) &&
588  (IrpStack->FileObject->FsContext == FileObject->FsContext)) {
589 
590  RecursiveWriteThrough = TRUE;
592  }
593  }
594  }
595 
596  // Here is the deal with ValidDataLength and FileSize:
597  //
598  // Rule 1: PagingIo is never allowed to extend file size.
599  //
600  // Rule 2: Only the top level requestor may extend Valid
601  // Data Length. This may be paging IO, as when a
602  // a user maps a file, but will never be as a result
603  // of cache lazy writer writes since they are not the
604  // top level request.
605  //
606  // Rule 3: If, using Rules 1 and 2, we decide we must extend
607  // file size or valid data, we take the Fcb exclusive.
608 
609  // Check whether the current request will extend the file size,
610  // or the valid data length (if the FSD supports the concept of a
611  // valid data length associated with the file stream). In either case,
612  // inform the Cache Manager at this time using CcSetFileSizes() about
613  // the new file length. Note that real FSD implementations will have to
614  // first allocate enough on-disk space at this point (before they
615  // inform the Cache Manager about the new size) to ensure that the write
616  // will subsequently not fail due to lack of disk space.
617 
618  OldVDL = NtReqFcb->CommonFCBHeader.ValidDataLength.QuadPart;
619  ZeroBlock = (ByteOffset.QuadPart > OldVDL);
620 
621  if (!PagingIo &&
622  !RecursiveWriteThrough &&
623  !IsThisADeferredWrite) {
624 
625  BOOLEAN ExtendFS;
626 
627  ExtendFS = (ByteOffset.QuadPart + TruncatedLength > NtReqFcb->CommonFCBHeader.FileSize.QuadPart);
628 
629  if( WriteToEOF || ZeroBlock || ExtendFS) {
630  // we are extending the file;
631 
632  if(!CanWait)
634 // CanWait = TRUE;
635  // Release any resources acquired above ...
636  if (PtrResourceAcquired2) {
637  UDFReleaseResource(PtrResourceAcquired2);
638  PtrResourceAcquired2 = NULL;
639  }
640  if (PtrResourceAcquired) {
641  UDFReleaseResource(PtrResourceAcquired);
642  PtrResourceAcquired = NULL;
643  }
644  if(!UDFAcquireResourceShared(&(Vcb->VCBResource), CanWait)) {
646  }
647  VcbAcquired = TRUE;
648  if(!Res1Acq) {
649  // Try to acquire the FCB MainResource exclusively
651  if(!UDFAcquireResourceExclusive(&(NtReqFcb->MainResource), CanWait)) {
653  }
654  // Remember the resource that was acquired
655  PtrResourceAcquired = &(NtReqFcb->MainResource);
656  }
657 
658  if(!Res2Acq) {
659  // allocate space...
660  AdPrint((" Try to acquire PagingIoRes\n"));
661  UDFAcquireResourceExclusive(&(NtReqFcb->PagingIoResource), TRUE );
662  PtrResourceAcquired2 = &(NtReqFcb->PagingIoResource);
663  }
664  AdPrint((" PagingIoRes Ok, Resizing...\n"));
665 
666  if(ExtendFS) {
667  RC = UDFResizeFile__(Vcb, Fcb->FileInfo, ByteOffset.QuadPart + TruncatedLength);
668 
669  if(!NT_SUCCESS(RC)) {
670  if(PtrResourceAcquired2) {
671  UDFReleaseResource(&(NtReqFcb->PagingIoResource));
672  PtrResourceAcquired2 = NULL;
673  }
674  try_return(RC);
675  }
676  Resized = TRUE;
677  // ... and inform the Cache Manager about it
678  NtReqFcb->CommonFCBHeader.FileSize.QuadPart = ByteOffset.QuadPart + TruncatedLength;
679  NtReqFcb->CommonFCBHeader.AllocationSize.QuadPart = UDFGetFileAllocationSize(Vcb, Fcb->FileInfo);
680  if(!Vcb->LowFreeSpace) {
681  NtReqFcb->CommonFCBHeader.AllocationSize.QuadPart += (PAGE_SIZE*9-1);
682  } else {
683  NtReqFcb->CommonFCBHeader.AllocationSize.QuadPart += (PAGE_SIZE-1);
684  }
685  NtReqFcb->CommonFCBHeader.AllocationSize.LowPart &= ~(PAGE_SIZE-1);
686  }
687 
688  UDFPrint(("UDFCommonWrite: Set size %x (alloc size %x)\n", ByteOffset.LowPart + TruncatedLength, NtReqFcb->CommonFCBHeader.AllocationSize.LowPart));
689  if (CcIsFileCached(FileObject)) {
690  if(ExtendFS) {
691  MmPrint((" CcSetFileSizes()\n"));
692  CcSetFileSizes(FileObject, (PCC_FILE_SIZES)&(NtReqFcb->CommonFCBHeader.AllocationSize));
693  NtReqFcb->NtReqFCBFlags |= UDF_NTREQ_FCB_MODIFIED;
694  }
695  // Attempt to Zero newly added fragment
696  // and ignore the return code
697  // This should be done to inform cache manager
698  // that given extent has no cached data
699  // (Otherwise, CM sometimes thinks that it has)
700  if(ZeroBlock) {
701  NtReqFcb->NtReqFCBFlags |= UDF_NTREQ_FCB_MODIFIED;
702  ThPrint((" UDFZeroDataEx(1)\n"));
704  OldVDL,
705  /*ByteOffset.QuadPart*/ NtReqFcb->CommonFCBHeader.FileSize.QuadPart - OldVDL,
706  CanWait, Vcb, FileObject);
707 #ifdef UDF_DBG
708  ZeroBlockDone = TRUE;
709 #endif //UDF_DBG
710  }
711  }
712  if (PtrResourceAcquired2) {
713  UDFReleaseResource(PtrResourceAcquired2);
714  PtrResourceAcquired2 = NULL;
715  }
716 
717  // Inform any pending IRPs (notify change directory).
718  if(UDFIsAStream(Fcb->FileInfo)) {
719  UDFNotifyFullReportChange( Vcb, Fcb->FileInfo,
722  } else {
723  UDFNotifyFullReportChange( Vcb, Fcb->FileInfo,
726  }
727  }
728 
729  }
730 
731 #ifdef UDF_DISABLE_SYSTEM_CACHE_MANAGER
732  NonBufferedIo = TRUE;
733 #endif
734  if(Fcb && Fcb->FileInfo && Fcb->FileInfo->Dloc) {
735  AdPrint(("UDFCommonWrite: DataLoc %x, Mapping %x\n", Fcb->FileInfo->Dloc->DataLoc, Fcb->FileInfo->Dloc->DataLoc.Mapping));
736  }
737 
738  // Branch here for cached vs non-cached I/O
739  if (!NonBufferedIo) {
740 
741  // The caller wishes to perform cached I/O. Initiate caching if
742  // this is the first cached I/O operation using this file object
743  if (!FileObject->PrivateCacheMap) {
744  // This is the first cached I/O operation. You must ensure
745  // that the FCB Common FCB Header contains valid sizes at this time
746  UDFPrint(("UDFCommonWrite: Init system cache\n"));
747  MmPrint((" CcInitializeCacheMap()\n"));
748  CcInitializeCacheMap(FileObject, (PCC_FILE_SIZES)(&(NtReqFcb->CommonFCBHeader.AllocationSize)),
749  FALSE, // We will not utilize pin access for this file
750  &(UDFGlobalData.CacheMgrCallBacks), // callbacks
751  NtReqFcb); // The context used in callbacks
752  MmPrint((" CcSetReadAheadGranularity()\n"));
753  CcSetReadAheadGranularity(FileObject, Vcb->SystemCacheGran);
754 
755  }
756 
757  if(ZeroBlock && !ZeroBlockDone) {
758  ThPrint((" UDFZeroDataEx(2)\n"));
760  OldVDL,
761  /*ByteOffset.QuadPart*/ ByteOffset.QuadPart + TruncatedLength - OldVDL,
762  CanWait, Vcb, FileObject);
763  if(ByteOffset.LowPart & (PAGE_SIZE-1)) {
764  }
765  }
766 
767  WriteFileSizeToDirNdx = (PtrIrpContext->IrpContextFlags & UDF_IRP_CONTEXT_WRITE_THROUGH) ?
768  TRUE : FALSE;
769  // Check and see if this request requires a MDL returned to the caller
770  if (IrpSp->MinorFunction & IRP_MN_MDL) {
771  // Caller does want a MDL returned. Note that this mode
772  // implies that the caller is prepared to block
773  MmPrint((" CcPrepareMdlWrite()\n"));
774 // CcPrepareMdlWrite(FileObject, &ByteOffset, TruncatedLength, &(Irp->MdlAddress), &(Irp->IoStatus));
775 // NumberBytesWritten = Irp->IoStatus.Information;
776 // RC = Irp->IoStatus.Status;
777 
778  NumberBytesWritten = 0;
780 
781  try_return(RC);
782  }
783 
784  if(NtReqFcb->SectionObject.DataSectionObject &&
785  TruncatedLength >= 0x10000 &&
786  ByteOffset.LowPart &&
787  !(ByteOffset.LowPart & 0x00ffffff)) {
788 
789  //if(WinVer_Id() < WinVer_2k) {
790  //LARGE_INTEGER flush_offs;
791  //flush_offs.QuadPart = ByteOffset.QuadPart - 0x100*0x10000;
792  MmPrint((" CcFlushCache() 16Mb\n"));
793  //CcFlushCache(&(NtReqFcb->SectionObject), &ByteOffset, 0x100*0x10000, &(Irp->IoStatus));
794 
795  // there was a nice idea: flush just previous part. But it doesn't work
796  CcFlushCache(&(NtReqFcb->SectionObject), NULL, 0, &(Irp->IoStatus));
797  //}
798  }
799 
800  // This is a regular run-of-the-mill cached I/O request. Let the
801  // Cache Manager worry about it!
802  // First though, we need a buffer pointer (address) that is valid
803 
804  // We needn't call CcZeroData 'cause udf_info.cpp will care about it
805  SystemBuffer = UDFGetCallersBuffer(PtrIrpContext, Irp);
806  if(!SystemBuffer)
808  ASSERT(SystemBuffer);
809  NtReqFcb->NtReqFCBFlags |= UDF_NTREQ_FCB_MODIFIED;
810  PerfPrint(("UDFCommonWrite: CcCopyWrite %x bytes at %x\n", TruncatedLength, ByteOffset.LowPart));
811  MmPrint((" CcCopyWrite()\n"));
812  if(!CcCopyWrite(FileObject, &(ByteOffset), TruncatedLength, CanWait, SystemBuffer)) {
813  // The caller was not prepared to block and data is not immediately
814  // available in the system cache
815  // Mark Irp Pending ...
817  }
818 
819  UDFUnlockCallersBuffer(PtrIrpContext, Irp, SystemBuffer);
820  // We have the data
821  RC = STATUS_SUCCESS;
822  NumberBytesWritten = TruncatedLength;
823 
824  try_return(RC);
825 
826  } else {
827 
828  MmPrint((" Write NonBufferedIo\n"));
829 
830  // We needn't call CcZeroData here (like in Fat driver)
831  // 'cause we've already done it above
832  // (see call to UDFZeroDataEx() )
833  if (!RecursiveWriteThrough &&
834  !IsThisADeferredWrite &&
835  (OldVDL < ByteOffset.QuadPart)) {
836 #ifdef UDF_DBG
837  ASSERT(!ZeroBlockDone);
838 #endif //UDF_DBG
840  OldVDL,
841  /*ByteOffset.QuadPart*/ ByteOffset.QuadPart - OldVDL,
842  CanWait, Vcb, FileObject);
843  }
844  if(OldVDL < (ByteOffset.QuadPart + TruncatedLength)) {
845  NtReqFcb->CommonFCBHeader.ValidDataLength.QuadPart = ByteOffset.QuadPart + TruncatedLength;
846  }
847 
848 #if 1
850  UDFPrint(("FSRTL_MOD_WRITE_TOP_LEVEL_IRP => CanWait\n"));
851  CanWait = TRUE;
852  } else
853  if((ULONG_PTR)TopIrp == FSRTL_CACHE_TOP_LEVEL_IRP) {
854  UDFPrint(("FSRTL_CACHE_TOP_LEVEL_IRP => CanWait\n"));
855  CanWait = TRUE;
856  }
857 
858  if(NtReqFcb->AcqSectionCount || NtReqFcb->AcqFlushCount) {
859  MmPrint((" AcqCount (%d/%d)=> CanWait ?\n", NtReqFcb->AcqSectionCount, NtReqFcb->AcqFlushCount));
860  CanWait = TRUE;
861  } else
862  {}
863 /* if((TopIrp != Irp)) {
864  UDFPrint(("(TopIrp != Irp) => CanWait\n"));
865  CanWait = TRUE;
866  } else*/
867 #endif
869  MmPrint((" !PASSIVE_LEVEL\n"));
870  CanWait = FALSE;
872  }
873  // Successful check will cause WCache lock
874  if(!CanWait && UDFIsFileCached__(Vcb, Fcb->FileInfo, ByteOffset.QuadPart, TruncatedLength, TRUE)) {
875  UDFPrint(("UDFCommonWrite: Cached => CanWait\n"));
876  CacheLocked = TRUE;
877  CanWait = TRUE;
878  }
879  // Send the request to lower level drivers
880  if(!CanWait) {
881  UDFPrint(("UDFCommonWrite: Post physical write %x bytes at %x\n", TruncatedLength, ByteOffset.LowPart));
882 
884  }
885 
886  if(!Res2Acq) {
887  if(UDFAcquireResourceExclusiveWithCheck(&(NtReqFcb->PagingIoResource))) {
888  PtrResourceAcquired2 = &(NtReqFcb->PagingIoResource);
889  }
890  }
891 
892  PerfPrint(("UDFCommonWrite: Physical write %x bytes at %x\n", TruncatedLength, ByteOffset.LowPart));
893 
894  // Lock the callers buffer
895  if (!NT_SUCCESS(RC = UDFLockCallersBuffer(PtrIrpContext, Irp, TRUE, TruncatedLength))) {
896  try_return(RC);
897  }
898 
899  SystemBuffer = UDFGetCallersBuffer(PtrIrpContext, Irp);
900  if(!SystemBuffer) {
902  }
903  NtReqFcb->NtReqFCBFlags |= UDF_NTREQ_FCB_MODIFIED;
904  RC = UDFWriteFile__(Vcb, Fcb->FileInfo, ByteOffset.QuadPart, TruncatedLength,
905  CacheLocked, (PCHAR)SystemBuffer, &NumberBytesWritten);
906 
907  UDFUnlockCallersBuffer(PtrIrpContext, Irp, SystemBuffer);
908 
909 #if defined(_MSC_VER) && !defined(__clang__)
910 /* FIXME */
911  if(PagingIo) {
912  CollectStatistics(Vcb, UserDiskWrites);
913  } else {
914  CollectStatistics2(Vcb, NonCachedDiskWrites);
915  }
916 #endif
917  WriteFileSizeToDirNdx = TRUE;
918 
919  try_return(RC);
920  }
921 
922 try_exit: NOTHING;
923 
924  } _SEH2_FINALLY {
925 
926  if(CacheLocked) {
927  WCacheEODirect__(&(Vcb->FastCache), Vcb);
928  }
929 
930  // Release any resources acquired here ...
931  if(PtrResourceAcquired2) {
932  UDFReleaseResource(PtrResourceAcquired2);
933  }
934  if(PtrResourceAcquired) {
935  if(NtReqFcb &&
936  (PtrResourceAcquired ==
937  &(NtReqFcb->MainResource))) {
939  }
940  UDFReleaseResource(PtrResourceAcquired);
941  }
942  if(VcbAcquired) {
943  UDFReleaseResource(&(Vcb->VCBResource));
944  }
945 
946  // Post IRP if required
947  if(RC == STATUS_PENDING) {
948 
949  // Lock the callers buffer here. Then invoke a common routine to
950  // perform the post operation.
951  if (!(IrpSp->MinorFunction & IRP_MN_MDL)) {
952  RC = UDFLockCallersBuffer(PtrIrpContext, Irp, FALSE, WriteLength);
953  ASSERT(NT_SUCCESS(RC));
954  }
955  if(PagingIo) {
956  if(Res1Acq) {
957  PtrIrpContext->IrpContextFlags |= UDF_IRP_CONTEXT_RES1_ACQ;
958  }
959  if(Res2Acq) {
960  PtrIrpContext->IrpContextFlags |= UDF_IRP_CONTEXT_RES2_ACQ;
961  }
962  }
963 
964  // Perform the post operation which will mark the IRP pending
965  // and will return STATUS_PENDING back to us
966  RC = UDFPostRequest(PtrIrpContext, Irp);
967 
968  } else {
969  // For synchronous I/O, the FSD must maintain the current byte offset
970  // Do not do this however, if I/O is marked as paging-io
971  if (SynchronousIo && !PagingIo && NT_SUCCESS(RC)) {
972  FileObject->CurrentByteOffset.QuadPart = ByteOffset.QuadPart + NumberBytesWritten;
973  }
974  // If the write completed successfully and this was not a paging-io
975  // operation, set a flag in the CCB that indicates that a write was
976  // performed and that the file time should be updated at cleanup
977  if (NT_SUCCESS(RC) && !PagingIo) {
978  Ccb->CCBFlags |= UDF_CCB_MODIFIED;
979  // If the file size was changed, set a flag in the FCB indicating that
980  // this occurred.
981  FileObject->Flags |= FO_FILE_MODIFIED;
982  if(Resized) {
983  if(!WriteFileSizeToDirNdx) {
985  } else {
986  ASize = UDFGetFileAllocationSize(Vcb, Fcb->FileInfo);
987  UDFSetFileSizeInDirNdx(Vcb, Fcb->FileInfo, &ASize);
988  }
989  }
990  // Update ValidDataLength
991  if(!IsThisADeferredWrite &&
992  NtReqFcb) {
993  if(NtReqFcb->CommonFCBHeader.ValidDataLength.QuadPart < (ByteOffset.QuadPart + NumberBytesWritten)) {
994 
995  NtReqFcb->CommonFCBHeader.ValidDataLength.QuadPart =
996  min(NtReqFcb->CommonFCBHeader.FileSize.QuadPart,
997  ByteOffset.QuadPart + NumberBytesWritten);
998  }
999  }
1000  }
1001 
1002  // If the request failed, and we had done some nasty stuff like
1003  // extending the file size (including informing the Cache Manager
1004  // about the new file size), and allocating on-disk space etc., undo
1005  // it at this time.
1006 
1007  // Can complete the IRP here if no exception was encountered
1008  if(!_SEH2_AbnormalTermination() &&
1009  Irp) {
1010  Irp->IoStatus.Status = RC;
1011  Irp->IoStatus.Information = NumberBytesWritten;
1012  // complete the IRP
1013  MmPrint((" Complete Irp, MDL=%x\n", Irp->MdlAddress));
1014  if(Irp->MdlAddress) {
1015  UDFTouch(Irp->MdlAddress);
1016  }
1018  }
1019  // Free up the Irp Context
1020  UDFReleaseIrpContext(PtrIrpContext);
1021 
1022  } // can we complete the IRP ?
1023  } _SEH2_END; // end of "__finally" processing
1024 
1025  UDFPrint(("\n"));
1026  return(RC);
1027 } // end UDFCommonWrite()
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
#define UDFAcquireResourceExclusive(Resource, CanWait)
Definition: env_spec_w32.h:656
signed char * PCHAR
Definition: retypes.h:7
#define UDF_VCB_FLAGS_MEDIA_READ_ONLY
Definition: udf_common.h:481
VOID UDFReleaseIrpContext(PtrUDFIrpContext PtrIrpContext)
Definition: misc.cpp:1086
BOOLEAN NTAPI CcPurgeCacheSection(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN OPTIONAL PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN UninitializeCacheMaps)
Definition: fssup.c:384
#define UDFPrint(Args)
Definition: udffs.h:225
#define TRUE
Definition: types.h:120
VOID NTAPI UDFDeferredWriteCallBack(IN PVOID Context1, IN PVOID Context2)
Definition: write.cpp:1048
struct _UDFContextControlBlock * PtrUDFCCB
#define UDFCloseAllSystemDelayedInDir(Vcb, FI)
Definition: protos.h:99
#define FSRTL_MOD_WRITE_TOP_LEVEL_IRP
Definition: fsrtltypes.h:61
#define AdPrint(_x_)
Definition: env_spec_w32.h:292
struct _FCB::@710::@713 Fcb
#define UDFGetFileAllocationSize(Vcb, FileInfo)
Definition: udf_info.h:797
#define UDF_IRP_CONTEXT_NOT_TOP_LEVEL
Definition: struct.h:390
VOID NTAPI CcFlushCache(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN OPTIONAL PLARGE_INTEGER FileOffset, IN ULONG Length, OUT OPTIONAL PIO_STATUS_BLOCK IoStatus)
Definition: cachesub.c:222
#define UDF_IRP_CONTEXT_WRITE_THROUGH
Definition: struct.h:386
_In_ PIRP Irp
Definition: csq.h:116
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define UDF_NODE_TYPE_VCB
Definition: struct.h:61
#define CollectStatistics2(VCB, Field)
Definition: env_spec.h:128
BOOLEAN NTAPI FsRtlCheckLockForWriteAccess(IN PFILE_LOCK FileLock, IN PIRP Irp)
Definition: filelock.c:714
#define UDFReleaseResource(Resource)
Definition: env_spec_w32.h:661
LONG NTSTATUS
Definition: precomp.h:26
#define HandleToUlong(h)
Definition: basetsd.h:79
#define IRP_NOCACHE
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
Definition: cdstruc.h:504
#define FILE_NOTIFY_CHANGE_SIZE
#define FILE_NOTIFY_CHANGE_LAST_WRITE
#define FILE_USE_FILE_POINTER_POSITION
Definition: ffsdrv.h:155
void UDFSetFileSizeInDirNdx(IN PVCB Vcb, IN PUDF_FILE_INFO FileInfo, IN int64 *ASize)
Definition: udf_info.cpp:1190
#define UDF_IRP_CONTEXT_CAN_BLOCK
Definition: struct.h:385
#define FILE_NOTIFY_CHANGE_STREAM_SIZE
_SEH2_TRY
Definition: create.c:4250
#define UDF_CCB_MODIFIED
Definition: struct.h:150
uint32_t ULONG_PTR
Definition: typedefs.h:63
#define UDF_VCB_FLAGS_RAW_DISK
Definition: udf_common.h:476
#define FO_SYNCHRONOUS_IO
Definition: iotypes.h:1733
#define IRP_MN_COMPLETE
Definition: iotypes.h:4064
#define FO_FILE_SIZE_CHANGED
Definition: iotypes.h:1746
#define UDF_IRP_CONTEXT_FLUSH2_REQUIRED
Definition: struct.h:393
#define UDF_VCB_FLAGS_VOLUME_READ_ONLY
Definition: udf_common.h:463
#define FO_FILE_MODIFIED
Definition: iotypes.h:1745
ERESOURCE * PERESOURCE
Definition: env_spec_w32.h:595
#define IO_DISK_INCREMENT
Definition: iotypes.h:568
#define UDF_VCB_FLAGS_UNSAFE_IOCTL
Definition: udf_common.h:488
long LONG
Definition: pedump.c:60
#define CcIsFileCached(FO)
#define FILE_ACTION_MODIFIED
#define STATUS_INVALID_USER_BUFFER
Definition: udferr_usr.h:166
#define FILE_ACTION_MODIFIED_STREAM
unsigned char BOOLEAN
#define TmPrint(_x_)
Definition: env_spec_w32.h:290
smooth NULL
Definition: ftsmooth.c:416
#define _SEH2_AbnormalTermination()
Definition: pseh2_64.h:13
#define UDF_VCB_FLAGS_SHUTDOWN
Definition: udf_common.h:462
#define IoCompleteRequest
Definition: irp.c:1240
PsGetCurrentThreadId
Definition: CrNtStubs.h:7
uint32 IrpContextFlags
Definition: struct.h:364
OSSTATUS UDFTWrite(IN void *_Vcb, IN void *Buffer, IN SIZE_T Length, IN uint32 LBA, OUT PSIZE_T WrittenBytes, IN uint32 Flags)
Definition: phys_lib.cpp:453
_Inout_ PFILE_OBJECT FileObject
Definition: cdprocs.h:593
__inline VOID UDFNotifyFullReportChange(PVCB V, PUDF_FILE_INFO FI, ULONG E, ULONG A)
Definition: env_spec.h:99
#define UDF_MAX_VERIFY_CACHE
Definition: udf_info.h:1255
#define FILE_WRITE_TO_END_OF_FILE
Definition: ext2fs.h:273
int64_t LONGLONG
Definition: typedefs.h:66
#define UDFTouch(a)
Definition: env_spec_w32.h:303
#define UDF_VCB_SKIP_EJECT_CHECK
Definition: udf_common.h:470
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
BOOLEAN NTAPI CcCanIWrite(IN PFILE_OBJECT FileObject, IN ULONG BytesToWrite, IN BOOLEAN Wait, IN UCHAR Retrying)
Definition: copysup.c:214
VOID NTAPI CcInitializeCacheMap(IN PFILE_OBJECT FileObject, IN PCC_FILE_SIZES FileSizes, IN BOOLEAN PinAccess, IN PCACHE_MANAGER_CALLBACKS Callbacks, IN PVOID LazyWriteContext)
Definition: fssup.c:193
#define try_return(S)
Definition: cdprocs.h:2189
#define Vcb
Definition: cdprocs.h:1425
#define ThPrint(_x_)
Definition: env_spec_w32.h:293
#define UDF_FCB_DIRECTORY
Definition: struct.h:303
#define BrutePoint()
Definition: env_spec_w32.h:504
#define PerfPrint(_x_)
Definition: env_spec_w32.h:291
PIRP NTAPI IoGetTopLevelIrp(VOID)
Definition: irp.c:1843
#define MmPrint(_x_)
Definition: env_spec_w32.h:289
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define FSRTL_MAX_TOP_LEVEL_IRP_FLAG
Definition: fsrtltypes.h:65
#define FILE_NOTIFY_CHANGE_STREAM_WRITE
#define FSRTL_FSP_TOP_LEVEL_IRP
Definition: fsrtltypes.h:59
* PFILE_OBJECT
Definition: iotypes.h:1955
#define UDF_IRP_CONTEXT_FORCED_POST
Definition: struct.h:397
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define NtReqFcb
#define CollectStatisticsEx(VCB, Field, a)
Definition: env_spec.h:124
#define UDF_VCB_FLAGS_VOLUME_MOUNTED
Definition: udf_common.h:459
#define UDF_FCB_DELETED
Definition: struct.h:314
#define IO_TYPE_IRP
UDFData UDFGlobalData
Definition: udfinit.cpp:25
OSSTATUS UDFWriteFile__(IN PVCB Vcb, IN PUDF_FILE_INFO FileInfo, IN int64 Offset, IN SIZE_T Length, IN BOOLEAN Direct, IN int8 *Buffer, OUT PSIZE_T WrittenBytes)
Definition: udf_info.cpp:1605
#define UDFIsFileCached__(Vcb, FileInfo, Offset, Length, ForWrite)
Definition: udf_info.h:839
#define IRP_MN_MDL
Definition: iotypes.h:4063
_Inout_ PFILE_OBJECT _In_ TYPE_OF_OPEN PFCB _In_opt_ PCCB Ccb
Definition: cdprocs.h:593
OSSTATUS WCacheEODirect__(IN PW_CACHE Cache, IN PVOID Context)
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define NOTHING
Definition: env_spec_w32.h:461
struct _VCB * PVCB
Definition: fatstruc.h:556
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
#define UDFZeroDataEx(NtReqFcb, Offset, Length, CanWait, Vcb, FileObject)
Definition: protos.h:1146
#define UDFAcquireResourceShared(Resource, CanWait)
Definition: env_spec_w32.h:658
#define UDF_FCB_PAGE_FILE
Definition: struct.h:302
#define UFD_VERIFY_FLAG_WAIT
Definition: udf_info.h:1303
#define IRP_MN_DPC
Definition: iotypes.h:4062
#define FSRTL_FAST_IO_TOP_LEVEL_IRP
Definition: fsrtltypes.h:62
BOOLEAN NTAPI CcCopyWrite(IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN Wait, IN PVOID Buffer)
Definition: copysup.c:129
FAST_IO_POSSIBLE NTAPI UDFIsFastIoPossible(IN PtrUDFFCB Fcb)
Definition: fastio.cpp:118
PVOID UDFGetCallersBuffer(PtrUDFIrpContext PtrIrpContext, PIRP Irp)
Definition: read.cpp:871
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2745
ULONG_PTR SIZE_T
Definition: typedefs.h:78
NTSTATUS UDFPostRequest(IN PtrUDFIrpContext PtrIrpContext, IN PIRP Irp)
Definition: misc.cpp:1128
PFILE_OBJECT FileObject
Definition: iotypes.h:2813
_SEH2_END
Definition: create.c:4424
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4157
VOID NTAPI CcSetFileSizes(IN PFILE_OBJECT FileObject, IN PCC_FILE_SIZES FileSizes)
Definition: fssup.c:354
#define UDF_CHECK_PAGING_IO_RESOURCE(NTReqFCB)
Definition: udffs.h:262
OSSTATUS UDFResizeFile__(IN PVCB Vcb, IN OUT PUDF_FILE_INFO FileInfo, IN int64 NewLength)
Definition: udf_info.cpp:3468
_SEH2_FINALLY
Definition: create.c:4395
#define min(a, b)
Definition: monoChain.cc:55
VOID UDFMdlComplete(PtrUDFIrpContext PtrIrpContext, PIRP Irp, PIO_STACK_LOCATION IrpSp, BOOLEAN ReadCompletion)
Definition: read.cpp:1117
#define IRP_PAGING_IO
#define UDFAcquireSharedStarveExclusive(Resource, CanWait)
Definition: env_spec_w32.h:669
#define CollectStatistics(VCB, Field)
Definition: env_spec.h:120
ULONG UDFFlushLogicalVolume(IN PtrUDFIrpContext PtrIrpContext, IN PIRP Irp, IN PVCB Vcb, IN ULONG FlushFlags)
Definition: flush.cpp:506
#define STATUS_FILE_LOCK_CONFLICT
Definition: ntstatus.h:306
VOID UDFCloseAllDelayed(IN PVCB Vcb)
Definition: close.cpp:754
#define UDF_IRP_CONTEXT_RES1_ACQ
Definition: struct.h:395
unsigned int ULONG
Definition: retypes.h:1
NTSTATUS UDFUnlockCallersBuffer(PtrUDFIrpContext PtrIrpContext, PIRP Irp, PVOID SystemBuffer)
Definition: read.cpp:1034
PVCB Vcb
Definition: cdstruc.h:939
BOOLEAN UDFAcquireResourceExclusiveWithCheck(IN PERESOURCE Resource)
Definition: misc.cpp:2529
#define IRP_MJ_WRITE
Definition: rdpdr.c:47
#define UDF_IRP_CONTEXT_DEFERRED_WRITE
Definition: struct.h:388
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:2772
_In_ PFCB Fcb
Definition: cdprocs.h:151
#define FSRTL_CACHE_TOP_LEVEL_IRP
Definition: fsrtltypes.h:60
return STATUS_SUCCESS
Definition: btrfs.c:2938
#define UDFIsAStream(FI)
Definition: udf_info.h:1002
#define FILE_NOTIFY_CHANGE_LAST_ACCESS
VOID UDFVVerify(IN PVCB Vcb, IN ULONG Flags)
Definition: remap.cpp:601
#define UDF_IRP_CONTEXT_RES2_ACQ
Definition: struct.h:396
#define STATUS_TOO_LATE
Definition: ntstatus.h:612
#define UDF_SYS_CACHE_STOP_THR
Definition: udf_info.h:1258
VOID NTAPI CcDeferWrite(IN PFILE_OBJECT FileObject, IN PCC_POST_DEFERRED_WRITE PostRoutine, IN PVOID Context1, IN PVOID Context2, IN ULONG BytesToWrite, IN BOOLEAN Retrying)
Definition: copysup.c:225
NTSTATUS UDFLockCallersBuffer(PtrUDFIrpContext PtrIrpContext, PIRP Irp, BOOLEAN IsReadOperation, uint32 Length)
Definition: read.cpp:936
#define IRP_SYNCHRONOUS_PAGING_IO
IN PDCB IN PCCB IN VBO IN OUT PULONG OUT PDIRENT OUT PBCB OUT PVBO ByteOffset
Definition: fatprocs.h:716
#define UDF_NTREQ_FCB_MODIFIED
Definition: struct.h:236
#define UDF_VCB_FLAGS_VOLUME_LOCKED
Definition: udf_common.h:460
ULONG UDFIsResourceAcquired(IN PERESOURCE Resource)
Definition: misc.cpp:2518
VOID NTAPI CcSetReadAheadGranularity(IN PFILE_OBJECT FileObject, IN ULONG Granularity)
Definition: cachesub.c:36

Referenced by UDFCommonDispatch(), and UDFWrite().

◆ UDFDeferredWriteCallBack()

VOID NTAPI UDFDeferredWriteCallBack ( IN PVOID  Context1,
IN PVOID  Context2 
)

Definition at line 1048 of file write.cpp.

1052 {
1053  UDFPrint(("UDFDeferredWriteCallBack\n"));
1054  // We should typically simply post the request to our internal
1055  // queue of posted requests (just as we would if the original write
1056  // could not be completed because the caller could not block).
1057  // Once we post the request, return from this routine. The write
1058  // will then be retried in the context of a system worker thread
1060 
1061 } // end UDFDeferredWriteCallBack()
#define UDFPrint(Args)
Definition: udffs.h:225
_In_ PNET_PNP_EVENT _In_ PTDI_PNP_CONTEXT _In_ PTDI_PNP_CONTEXT Context2
Definition: tdikrnl.h:1094
NTSTATUS UDFPostRequest(IN PtrUDFIrpContext PtrIrpContext, IN PIRP Irp)
Definition: misc.cpp:1128
_In_ PNET_PNP_EVENT _In_ PTDI_PNP_CONTEXT Context1
Definition: tdikrnl.h:1094

Referenced by UDFCommonWrite().

◆ UDFPurgeCacheEx_()

VOID UDFPurgeCacheEx_ ( PtrUDFNTRequiredFCB  NtReqFcb,
LONGLONG  Offset,
LONGLONG  Length,
BOOLEAN  CanWait,
PVCB  Vcb,
PFILE_OBJECT  FileObject 
)

Definition at line 1070 of file write.cpp.

1080 {
1081  ULONG Off_l;
1082 #ifdef USE_CcCopyWrite_TO_ZERO
1083  ULONG PgLen;
1084 #endif //USE_CcCopyWrite_TO_ZERO
1085 
1086  // We'll just purge cache section here,
1087  // without call to CcZeroData()
1088  // 'cause udf_info.cpp will care about it
1089 
1090 #define PURGE_BLOCK_SZ 0x10000000
1091 
1092  // NOTE: if FS engine doesn't suport
1093  // sparse/unrecorded areas, CcZeroData must be called
1094  // In this case we'll see some recursive WRITE requests
1095 
1096  _SEH2_TRY {
1097  MmPrint((" UDFPurgeCacheEx_(): Offs: %I64x, ", Offset));
1098  MmPrint((" Len: %lx\n", Length));
1099  SECTION_OBJECT_POINTERS* SectionObject = &(NtReqFcb->SectionObject);
1100  if(Length) {
1101  LONGLONG Offset0, OffsetX, VDL;
1102 
1103  Offset0 = Offset;
1104  if((Off_l = ((ULONG)Offset0 & (PAGE_SIZE-1)))) {
1105  // Offset, Offset0
1106  // v
1107  // ...|dddddddddddd00000|....
1108  // |<- Off_l ->|
1109 #ifndef USE_CcCopyWrite_TO_ZERO
1110  *((PULONG)&Offset0) &= ~(PAGE_SIZE-1);
1111  MmPrint((" CcFlushCache(s) Offs %I64x, Len %x\n", Offset0, Off_l));
1112  CcFlushCache( SectionObject, (PLARGE_INTEGER)&Offset0, Off_l, NULL );
1113 #else //USE_CcCopyWrite_TO_ZERO
1114  // ...|ddddd000000000000|....
1115  // |<- PgLen ->|
1116  PgLen = PAGE_SIZE - Off_l; /*(*((PULONG)&Offset) & (PAGE_SIZE-1))*/
1117  //
1118  if(PgLen > Length)
1119  PgLen = (ULONG)Length;
1120 
1121  MmPrint((" ZeroCache (CcWrite) Offs %I64x, Len %x\n", Offset, PgLen));
1122 #ifdef DBG
1123  if(FileObject && Vcb) {
1124 
1125  ASSERT(CanWait);
1126 #endif //DBG
1127  if (PgLen) {
1128  if (SectionObject->SharedCacheMap) {
1129  CcCopyWrite(FileObject, (PLARGE_INTEGER)&Offset, PgLen, TRUE || CanWait, Vcb->ZBuffer);
1130  }
1131  Offset += PgLen;
1132  Length -= PgLen;
1133  }
1134 #ifdef DBG
1135  } else {
1136  MmPrint((" Can't use CcWrite to zero cache\n"));
1137  }
1138 #endif //DBG
1139 #endif //USE_CcCopyWrite_TO_ZERO
1140  }
1141  VDL = NtReqFcb->CommonFCBHeader.ValidDataLength.QuadPart;
1142  OffsetX = Offset+Length;
1143  if((Off_l = ((ULONG)OffsetX & (PAGE_SIZE-1)))) {
1144 
1145  if(OffsetX < VDL) {
1146 #ifndef USE_CcCopyWrite_TO_ZERO
1147  Off_l = ( (ULONG)(VDL-OffsetX) > PAGE_SIZE ) ?
1148  (PAGE_SIZE - Off_l) :
1149  ((ULONG)(VDL-OffsetX));
1150  *((PULONG)&OffsetX) &= ~(PAGE_SIZE-1);
1151  MmPrint((" CcFlushCache(e) Offs %I64x, Len %x\n", OffsetX, Off_l));
1152  CcFlushCache( SectionObject, (PLARGE_INTEGER)&OffsetX, Off_l, NULL );
1153 #else //USE_CcCopyWrite_TO_ZERO
1154  if(VDL - OffsetX > PAGE_SIZE) {
1155  PgLen = (ULONG)OffsetX & ~(PAGE_SIZE-1);
1156  } else {
1157  PgLen = (ULONG)(VDL - OffsetX) & ~(PAGE_SIZE-1);
1158  }
1159  // ...|000000000000ddddd|....
1160  // |<- PgLen ->|
1161  MmPrint((" ZeroCache (CcWrite - 2) Offs %I64x, Len %x\n", OffsetX, PgLen));
1162 #ifdef DBG
1163  if(FileObject && Vcb) {
1164  ASSERT(CanWait);
1165 #endif //DBG
1166  if (SectionObject->SharedCacheMap) {
1167  CcCopyWrite(FileObject, (PLARGE_INTEGER)&OffsetX, PgLen, TRUE || CanWait, Vcb->ZBuffer);
1168  }
1169  Length -= PgLen;
1170 #ifdef DBG
1171  } else {
1172  MmPrint((" Can't use CcWrite to zero cache (2)\n"));
1173  }
1174 #endif //DBG
1175 #endif //USE_CcCopyWrite_TO_ZERO
1176  }
1177  }
1178 #ifndef USE_CcCopyWrite_TO_ZERO
1179  do
1180 #else //USE_CcCopyWrite_TO_ZERO
1181  while(Length)
1182 #endif //USE_CcCopyWrite_TO_ZERO
1183  {
1184  MmPrint((" CcPurgeCacheSection()\n"));
1185  if(PURGE_BLOCK_SZ > Length) {
1187  (ULONG)Length, FALSE);
1188  /*
1189  NtReqFcb->CommonFCBHeader.ValidDataLength.QuadPart += Length;
1190  ASSERT(NtReqFcb->CommonFCBHeader.ValidDataLength.QuadPart <=
1191  NtReqFcb->CommonFCBHeader.FileSize.QuadPart);
1192  MmPrint((" CcFlushCache()\n"));
1193  CcFlushCache( SectionObject, (PLARGE_INTEGER)&Offset, (ULONG)Length, NULL );
1194  */
1195 #ifndef ALLOW_SPARSE
1196  // UDFZeroFile__(
1197 #endif //ALLOW_SPARSE
1198  break;
1199  } else {
1202  /*
1203  NtReqFcb->CommonFCBHeader.ValidDataLength.QuadPart += PURGE_BLOCK_SZ;
1204  ASSERT(NtReqFcb->CommonFCBHeader.ValidDataLength.QuadPart <=
1205  NtReqFcb->CommonFCBHeader.FileSize.QuadPart);
1206  MmPrint((" CcFlushCache()\n"));
1207  CcFlushCache( SectionObject, (PLARGE_INTEGER)&Offset, (ULONG)Length, NULL );
1208  */
1209 #ifndef ALLOW_SPARSE
1210  // UDFZeroFile__(
1211 #endif //ALLOW_SPARSE
1214  }
1215  }
1216 #ifndef USE_CcCopyWrite_TO_ZERO
1217  while(Length);
1218 #endif //USE_CcCopyWrite_TO_ZERO
1219  if(VDL < Offset)
1220  NtReqFcb->CommonFCBHeader.ValidDataLength.QuadPart = Offset;
1221  }
1223  BrutePoint();
1224  } _SEH2_END;
1225 } // end UDFPurgeCacheEx_()
_Must_inspect_result_ _Outptr_ PVOID * SectionObject
Definition: fsrtlfuncs.h:860
BOOLEAN NTAPI CcPurgeCacheSection(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN OPTIONAL PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN UninitializeCacheMaps)
Definition: fssup.c:384
#define TRUE
Definition: types.h:120
VOID NTAPI CcFlushCache(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN OPTIONAL PLARGE_INTEGER FileOffset, IN ULONG Length, OUT OPTIONAL PIO_STATUS_BLOCK IoStatus)
Definition: cachesub.c:222
#define PURGE_BLOCK_SZ
_SEH2_TRY
Definition: create.c:4250
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
smooth NULL
Definition: ftsmooth.c:416
_Inout_ PFILE_OBJECT FileObject
Definition: cdprocs.h:593
int64_t LONGLONG
Definition: typedefs.h:66
#define Vcb
Definition: cdprocs.h:1425
#define BrutePoint()
Definition: env_spec_w32.h:504
#define MmPrint(_x_)
Definition: env_spec_w32.h:289
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define NtReqFcb
#define PAGE_SIZE
Definition: env_spec_w32.h:49
BOOLEAN NTAPI CcCopyWrite(IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN Wait, IN PVOID Buffer)
Definition: copysup.c:129
_SEH2_END
Definition: create.c:4424
unsigned int * PULONG
Definition: retypes.h:1
unsigned int ULONG
Definition: retypes.h:1
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6

◆ UDFWrite()

NTSTATUS NTAPI UDFWrite ( PDEVICE_OBJECT  DeviceObject,
PIRP  Irp 
)

Definition at line 42 of file write.cpp.

46 {
48  PtrUDFIrpContext PtrIrpContext = NULL;
49  BOOLEAN AreWeTopLevel = FALSE;
50 
51  TmPrint(("UDFWrite: , thrd:%8.8x\n",PsGetCurrentThread()));
52 
55  ASSERT(Irp);
56 
57  // set the top level context
58  AreWeTopLevel = UDFIsIrpTopLevel(Irp);
59  ASSERT(!UDFIsFSDevObj(DeviceObject));
60 
61  _SEH2_TRY {
62 
63  // get an IRP context structure and issue the request
64  PtrIrpContext = UDFAllocateIrpContext(Irp, DeviceObject);
65  if(PtrIrpContext) {
66 
67  RC = UDFCommonWrite(PtrIrpContext, Irp);
68 
69  } else {
71  Irp->IoStatus.Status = RC;
72  Irp->IoStatus.Information = 0;
73  // complete the IRP
75  }
76 
78 
79  RC = UDFExceptionHandler(PtrIrpContext, Irp);
80 
82  } _SEH2_END;
83 
84  if (AreWeTopLevel) {
86  }
87 
89 
90  return(RC);
91 } // end UDFWrite()
PtrUDFIrpContext UDFAllocateIrpContext(PIRP Irp, PDEVICE_OBJECT PtrTargetDeviceObject)
Definition: misc.cpp:985
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define FsRtlEnterFileSystem
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#define FsRtlExitFileSystem
VOID UDFLogEvent(NTSTATUS UDFEventLogId, NTSTATUS RC)
Definition: misc.cpp:575
_In_ PIRP Irp
Definition: csq.h:116
LONG NTSTATUS
Definition: precomp.h:26
_SEH2_TRY
Definition: create.c:4250
#define IO_DISK_INCREMENT
Definition: iotypes.h:568
#define _SEH2_GetExceptionInformation()
Definition: pseh2_64.h:11
unsigned char BOOLEAN
#define TmPrint(_x_)
Definition: env_spec_w32.h:290
smooth NULL
Definition: ftsmooth.c:416
#define IoCompleteRequest
Definition: irp.c:1240
NTSTATUS UDFExceptionHandler(PtrUDFIrpContext PtrIrpContext, PIRP Irp)
Definition: misc.cpp:358
BOOLEAN __fastcall UDFIsIrpTopLevel(PIRP Irp)
Definition: misc.cpp:228
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
VOID NTAPI IoSetTopLevelIrp(IN PIRP Irp)
Definition: irp.c:2000
long UDFExceptionFilter(PtrUDFIrpContext PtrIrpContext, PEXCEPTION_POINTERS PtrExceptionPointers)
Definition: misc.cpp:265
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1560
#define UDF_ERROR_INTERNAL_ERROR
Definition: errmsg.h:71
_SEH2_END
Definition: create.c:4424
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
return STATUS_SUCCESS
Definition: btrfs.c:2938
NTSTATUS UDFCommonWrite(PtrUDFIrpContext PtrIrpContext, PIRP Irp)
Definition: write.cpp:112

Referenced by UDFInitializeFunctionPointers().