ReactOS 0.4.16-dev-297-gc569aee
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;
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
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)) {
265 } else {
269 }
270 }
271
272 // Get some of the parameters supplied to us
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
305
306 UDFPrint((" UDF_IRP_CONTEXT_FLUSH2_REQUIRED\n"));
307 PtrIrpContext->IrpContextFlags &= ~UDF_IRP_CONTEXT_FLUSH2_REQUIRED;
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) {
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) &&
576
577 // This clause determines if the top level request was
578 // in the FastIo path.
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));
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)) {
722 } else {
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
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
922try_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) {
958 }
959 if(Res2Acq) {
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.
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
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()
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
ULONG WriteLength
Definition: CcPinRead_drv.c:40
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
#define HandleToUlong(h)
Definition: basetsd.h:79
VOID NTAPI CcSetReadAheadGranularity(IN PFILE_OBJECT FileObject, IN ULONG Granularity)
Definition: cachesub.c:36
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 CcIsFileCached(FO)
_In_ PFCB Fcb
Definition: cdprocs.h:159
_Inout_ PFILE_OBJECT _In_ TYPE_OF_OPEN PFCB _In_opt_ PCCB Ccb
Definition: cdprocs.h:592
#define try_return(S)
Definition: cdprocs.h:2179
struct _VCB * PVCB
Definition: fatstruc.h:557
VOID UDFCloseAllDelayed(IN PVCB Vcb)
Definition: close.cpp:754
_In_ PIRP Irp
Definition: csq.h:116
#define STATUS_PENDING
Definition: d3dkmdt.h:43
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4137
BOOLEAN UDFAcquireResourceExclusiveWithCheck(IN PERESOURCE Resource)
Definition: misc.cpp:2529
NTSTATUS UDFPostRequest(IN PtrUDFIrpContext PtrIrpContext, IN PIRP Irp)
Definition: misc.cpp:1128
VOID UDFReleaseIrpContext(PtrUDFIrpContext PtrIrpContext)
Definition: misc.cpp:1086
ULONG UDFIsResourceAcquired(IN PERESOURCE Resource)
Definition: misc.cpp:2518
#define CollectStatistics(VCB, Field)
Definition: env_spec.h:120
__inline VOID UDFNotifyFullReportChange(PVCB V, PUDF_FILE_INFO FI, ULONG E, ULONG A)
Definition: env_spec.h:99
#define CollectStatisticsEx(VCB, Field, a)
Definition: env_spec.h:124
#define CollectStatistics2(VCB, Field)
Definition: env_spec.h:128
#define UDFReleaseResource(Resource)
Definition: env_spec_w32.h:661
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define UDFAcquireResourceShared(Resource, CanWait)
Definition: env_spec_w32.h:658
#define UDFAcquireResourceExclusive(Resource, CanWait)
Definition: env_spec_w32.h:656
#define MmPrint(_x_)
Definition: env_spec_w32.h:289
#define UDFTouch(a)
Definition: env_spec_w32.h:303
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
#define TmPrint(_x_)
Definition: env_spec_w32.h:290
#define PerfPrint(_x_)
Definition: env_spec_w32.h:291
ERESOURCE * PERESOURCE
Definition: env_spec_w32.h:595
#define UDFAcquireSharedStarveExclusive(Resource, CanWait)
Definition: env_spec_w32.h:669
#define BrutePoint()
Definition: env_spec_w32.h:504
#define AdPrint(_x_)
Definition: env_spec_w32.h:292
#define ThPrint(_x_)
Definition: env_spec_w32.h:293
#define FILE_WRITE_TO_END_OF_FILE
Definition: ext2fs.h:278
FAST_IO_POSSIBLE NTAPI UDFIsFastIoPossible(IN PtrUDFFCB Fcb)
Definition: fastio.cpp:118
#define NtReqFcb
IN PDCB IN PCCB IN VBO IN OUT PULONG OUT PDIRENT OUT PBCB OUT PVBO ByteOffset
Definition: fatprocs.h:732
BOOLEAN NTAPI FsRtlCheckLockForWriteAccess(IN PFILE_LOCK FileLock, IN PIRP Irp)
Definition: filelock.c:710
PsGetCurrentThreadId
Definition: CrNtStubs.h:8
ULONG UDFFlushLogicalVolume(IN PtrUDFIrpContext PtrIrpContext, IN PIRP Irp, IN PVCB Vcb, IN ULONG FlushFlags)
Definition: flush.cpp:506
#define FSRTL_FSP_TOP_LEVEL_IRP
Definition: fsrtltypes.h:59
#define FSRTL_CACHE_TOP_LEVEL_IRP
Definition: fsrtltypes.h:60
#define FSRTL_MAX_TOP_LEVEL_IRP_FLAG
Definition: fsrtltypes.h:65
#define FSRTL_MOD_WRITE_TOP_LEVEL_IRP
Definition: fsrtltypes.h:61
#define FSRTL_FAST_IO_TOP_LEVEL_IRP
Definition: fsrtltypes.h:62
VOID NTAPI CcSetFileSizes(IN PFILE_OBJECT FileObject, IN PCC_FILE_SIZES FileSizes)
Definition: fssup.c:356
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:195
BOOLEAN NTAPI CcPurgeCacheSection(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN OPTIONAL PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN UninitializeCacheMaps)
Definition: fssup.c:386
#define NOTHING
Definition: input_list.c:10
#define ASSERT(a)
Definition: mode.c:44
#define min(a, b)
Definition: monoChain.cc:55
#define FILE_USE_FILE_POINTER_POSITION
Definition: nt_native.h:780
BOOLEAN NTAPI CcCopyWrite(IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN Wait, IN PVOID Buffer)
Definition: copysup.c:129
BOOLEAN NTAPI CcCanIWrite(IN PFILE_OBJECT FileObject, IN ULONG BytesToWrite, IN BOOLEAN Wait, IN UCHAR Retrying)
Definition: copysup.c:214
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
#define IoCompleteRequest
Definition: irp.c:1240
PIRP NTAPI IoGetTopLevelIrp(VOID)
Definition: irp.c:1843
#define STATUS_FILE_LOCK_CONFLICT
Definition: ntstatus.h:320
#define STATUS_TOO_LATE
Definition: ntstatus.h:626
long LONG
Definition: pedump.c:60
#define Vcb
Definition: cdprocs.h:1415
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
#define UDFZeroDataEx(NtReqFcb, Offset, Length, CanWait, Vcb, FileObject)
Definition: protos.h:1146
NTSTATUS UDFLockCallersBuffer(PtrUDFIrpContext PtrIrpContext, PIRP Irp, BOOLEAN IsReadOperation, uint32 Length)
Definition: read.cpp:936
VOID UDFMdlComplete(PtrUDFIrpContext PtrIrpContext, PIRP Irp, PIO_STACK_LOCATION IrpSp, BOOLEAN ReadCompletion)
Definition: read.cpp:1117
PVOID UDFGetCallersBuffer(PtrUDFIrpContext PtrIrpContext, PIRP Irp)
Definition: read.cpp:871
NTSTATUS UDFUnlockCallersBuffer(PtrUDFIrpContext PtrIrpContext, PIRP Irp, PVOID SystemBuffer)
Definition: read.cpp:1034
#define UDFCloseAllSystemDelayedInDir(Vcb, FI)
Definition: protos.h:99
#define _SEH2_AbnormalTermination()
Definition: pseh2_64.h:166
#define _SEH2_FINALLY
Definition: pseh2_64.h:114
#define _SEH2_END
Definition: pseh2_64.h:155
#define _SEH2_TRY
Definition: pseh2_64.h:55
#define IRP_MJ_WRITE
Definition: rdpdr.c:47
VOID UDFVVerify(IN PVCB Vcb, IN ULONG Flags)
Definition: remap.cpp:601
#define STATUS_SUCCESS
Definition: shellext.h:65
#define UDF_IRP_CONTEXT_RES1_ACQ
Definition: struct.h:395
#define UDF_IRP_CONTEXT_DEFERRED_WRITE
Definition: struct.h:388
#define UDF_IRP_CONTEXT_NOT_TOP_LEVEL
Definition: struct.h:390
#define UDF_IRP_CONTEXT_FLUSH2_REQUIRED
Definition: struct.h:393
#define UDF_FCB_PAGE_FILE
Definition: struct.h:302
#define UDF_IRP_CONTEXT_CAN_BLOCK
Definition: struct.h:385
#define UDF_FCB_DELETED
Definition: struct.h:314
#define UDF_IRP_CONTEXT_FORCED_POST
Definition: struct.h:397
struct _UDFContextControlBlock * PtrUDFCCB
#define UDF_IRP_CONTEXT_WRITE_THROUGH
Definition: struct.h:386
#define UDF_CCB_MODIFIED
Definition: struct.h:150
#define UDF_NTREQ_FCB_MODIFIED
Definition: struct.h:236
#define UDF_NODE_TYPE_VCB
Definition: struct.h:61
#define UDF_FCB_DIRECTORY
Definition: struct.h:303
#define UDF_IRP_CONTEXT_RES2_ACQ
Definition: struct.h:396
PVCB Vcb
Definition: cdstruc.h:933
struct _FCB::@729::@732 Fcb
PFILE_OBJECT FileObject
Definition: iotypes.h:3169
union _IO_STACK_LOCATION::@1579 Parameters
struct _IO_STACK_LOCATION::@3978::@3983 Write
uint32 IrpContextFlags
Definition: struct.h:364
Definition: cdstruc.h:498
int64_t LONGLONG
Definition: typedefs.h:68
ULONG_PTR SIZE_T
Definition: typedefs.h:80
uint32_t ULONG_PTR
Definition: typedefs.h:65
uint32_t ULONG
Definition: typedefs.h:59
char * PCHAR
Definition: typedefs.h:51
#define UDF_VCB_FLAGS_VOLUME_MOUNTED
Definition: udf_common.h:459
#define UDF_VCB_FLAGS_VOLUME_LOCKED
Definition: udf_common.h:460
#define UDF_VCB_FLAGS_UNSAFE_IOCTL
Definition: udf_common.h:488
#define UDF_VCB_FLAGS_VOLUME_READ_ONLY
Definition: udf_common.h:463
#define UDF_VCB_FLAGS_RAW_DISK
Definition: udf_common.h:476
#define UDF_VCB_FLAGS_MEDIA_READ_ONLY
Definition: udf_common.h:481
#define UDF_VCB_FLAGS_SHUTDOWN
Definition: udf_common.h:462
#define UDF_VCB_SKIP_EJECT_CHECK
Definition: udf_common.h:470
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
void UDFSetFileSizeInDirNdx(IN PVCB Vcb, IN PUDF_FILE_INFO FileInfo, IN int64 *ASize)
Definition: udf_info.cpp:1190
OSSTATUS UDFResizeFile__(IN PVCB Vcb, IN OUT PUDF_FILE_INFO FileInfo, IN int64 NewLength)
Definition: udf_info.cpp:3468
#define UDFIsFileCached__(Vcb, FileInfo, Offset, Length, ForWrite)
Definition: udf_info.h:839
#define UDF_MAX_VERIFY_CACHE
Definition: udf_info.h:1255
#define UFD_VERIFY_FLAG_WAIT
Definition: udf_info.h:1303
#define UDFGetFileAllocationSize(Vcb, FileInfo)
Definition: udf_info.h:797
#define UDF_SYS_CACHE_STOP_THR
Definition: udf_info.h:1258
#define UDFIsAStream(FI)
Definition: udf_info.h:1002
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_INVALID_USER_BUFFER
Definition: udferr_usr.h:166
UDFData UDFGlobalData
Definition: udfinit.cpp:25
#define UDF_CHECK_PAGING_IO_RESOURCE(NTReqFCB)
Definition: udffs.h:260
#define UDFPrint(Args)
Definition: udffs.h:223
OSSTATUS WCacheEODirect__(IN PW_CACHE Cache, IN PVOID Context)
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
VOID NTAPI UDFDeferredWriteCallBack(IN PVOID Context1, IN PVOID Context2)
Definition: write.cpp:1048
#define IRP_MN_COMPLETE
Definition: iotypes.h:4420
#define FILE_ACTION_MODIFIED_STREAM
#define FILE_NOTIFY_CHANGE_SIZE
#define IO_TYPE_IRP
#define FILE_ACTION_MODIFIED
#define IRP_PAGING_IO
#define FILE_NOTIFY_CHANGE_LAST_ACCESS
#define FO_FILE_MODIFIED
Definition: iotypes.h:1788
#define FILE_NOTIFY_CHANGE_STREAM_WRITE
#define FILE_NOTIFY_CHANGE_STREAM_SIZE
* PFILE_OBJECT
Definition: iotypes.h:1998
#define IRP_MN_MDL
Definition: iotypes.h:4419
#define FO_FILE_SIZE_CHANGED
Definition: iotypes.h:1789
#define IRP_MN_DPC
Definition: iotypes.h:4418
#define IO_DISK_INCREMENT
Definition: iotypes.h:600
#define FO_SYNCHRONOUS_IO
Definition: iotypes.h:1776
#define FILE_NOTIFY_CHANGE_LAST_WRITE
#define IRP_SYNCHRONOUS_PAGING_IO
#define IRP_NOCACHE

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()
_In_ PNET_PNP_EVENT _In_ PTDI_PNP_CONTEXT Context1
Definition: tdikrnl.h:1095
_In_ PNET_PNP_EVENT _In_ PTDI_PNP_CONTEXT _In_ PTDI_PNP_CONTEXT Context2
Definition: tdikrnl.h:1096

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
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:66
uint32_t * PULONG
Definition: typedefs.h:59
#define PURGE_BLOCK_SZ

◆ 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()
NTSTATUS UDFExceptionHandler(PtrUDFIrpContext PtrIrpContext, PIRP Irp)
Definition: misc.cpp:358
BOOLEAN __fastcall UDFIsIrpTopLevel(PIRP Irp)
Definition: misc.cpp:228
VOID UDFLogEvent(NTSTATUS UDFEventLogId, NTSTATUS RC)
Definition: misc.cpp:575
PtrUDFIrpContext UDFAllocateIrpContext(PIRP Irp, PDEVICE_OBJECT PtrTargetDeviceObject)
Definition: misc.cpp:985
long UDFExceptionFilter(PtrUDFIrpContext PtrIrpContext, PEXCEPTION_POINTERS PtrExceptionPointers)
Definition: misc.cpp:265
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#define UDF_ERROR_INTERNAL_ERROR
Definition: errmsg.h:71
#define FsRtlEnterFileSystem
#define FsRtlExitFileSystem
VOID NTAPI IoSetTopLevelIrp(IN PIRP Irp)
Definition: irp.c:2000
#define _SEH2_GetExceptionInformation()
Definition: pseh2_64.h:164
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
NTSTATUS UDFCommonWrite(PtrUDFIrpContext PtrIrpContext, PIRP Irp)
Definition: write.cpp:112

Referenced by UDFInitializeFunctionPointers().