3 * Copyright (C) 2002, 2014 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
19 * COPYRIGHT: See COPYING in the top level directory
20 * PROJECT: ReactOS kernel
21 * FILE: drivers/filesystem/ntfs/rw.c
22 * PURPOSE: NTFS filesystem driver
23 * PROGRAMMERS: Art Yerkes
24 * Pierre Schweitzer (pierre@reactos.org)
28 /* INCLUDES *****************************************************************/
36 /* FUNCTIONS ****************************************************************/
39 * FUNCTION: Reads data from a file
43 NtfsReadFile(PDEVICE_EXTENSION DeviceExt
,
44 PFILE_OBJECT FileObject
,
51 NTSTATUS Status
= STATUS_SUCCESS
;
53 PFILE_RECORD_HEADER FileRecord
;
54 PNTFS_ATTR_CONTEXT DataContext
;
59 BOOLEAN AllocatedBuffer
= FALSE
;
60 PCHAR ReadBuffer
= (PCHAR
)Buffer
;
63 DPRINT1("NtfsReadFile(%p, %p, %p, %u, %u, %x, %p)\n", DeviceExt
, FileObject
, Buffer
, Length
, ReadOffset
, IrpFlags
, LengthRead
);
69 DPRINT1("Null read!\n");
70 return STATUS_SUCCESS
;
73 Fcb
= (PNTFS_FCB
)FileObject
->FsContext
;
75 if (NtfsFCBIsCompressed(Fcb
))
77 DPRINT1("Compressed file!\n");
79 return STATUS_NOT_IMPLEMENTED
;
82 FileRecord
= ExAllocatePoolWithTag(NonPagedPool
, DeviceExt
->NtfsInfo
.BytesPerFileRecord
, TAG_NTFS
);
83 if (FileRecord
== NULL
)
85 DPRINT1("Not enough memory!\n");
86 return STATUS_INSUFFICIENT_RESOURCES
;
89 Status
= ReadFileRecord(DeviceExt
, Fcb
->MFTIndex
, FileRecord
);
90 if (!NT_SUCCESS(Status
))
92 DPRINT1("Can't find record!\n");
93 ExFreePoolWithTag(FileRecord
, TAG_NTFS
);
98 Status
= FindAttribute(DeviceExt
, FileRecord
, AttributeData
, Fcb
->Stream
, wcslen(Fcb
->Stream
), &DataContext
, NULL
);
99 if (!NT_SUCCESS(Status
))
101 NTSTATUS BrowseStatus
;
102 FIND_ATTR_CONTXT Context
;
103 PNTFS_ATTR_RECORD Attribute
;
105 DPRINT1("No '%S' data stream associated with file!\n", Fcb
->Stream
);
107 BrowseStatus
= FindFirstAttribute(&Context
, DeviceExt
, FileRecord
, FALSE
, &Attribute
);
108 while (NT_SUCCESS(BrowseStatus
))
110 if (Attribute
->Type
== AttributeData
)
114 Name
.Length
= Attribute
->NameLength
* sizeof(WCHAR
);
115 Name
.MaximumLength
= Name
.Length
;
116 Name
.Buffer
= (PWCHAR
)((ULONG_PTR
)Attribute
+ Attribute
->NameOffset
);
117 DPRINT1("Data stream: '%wZ' available\n", &Name
);
120 BrowseStatus
= FindNextAttribute(&Context
, &Attribute
);
122 FindCloseAttribute(&Context
);
124 ReleaseAttributeContext(DataContext
);
125 ExFreePoolWithTag(FileRecord
, TAG_NTFS
);
129 StreamSize
= AttributeDataLength(&DataContext
->Record
);
130 if (ReadOffset
>= StreamSize
)
132 DPRINT1("Reading beyond stream end!\n");
133 ReleaseAttributeContext(DataContext
);
134 ExFreePoolWithTag(FileRecord
, TAG_NTFS
);
135 return STATUS_END_OF_FILE
;
139 if (ReadOffset
+ Length
> StreamSize
)
140 ToRead
= StreamSize
- ReadOffset
;
142 RealReadOffset
= ReadOffset
;
145 if ((ReadOffset
% DeviceExt
->NtfsInfo
.BytesPerSector
) != 0 || (ToRead
% DeviceExt
->NtfsInfo
.BytesPerSector
) != 0)
147 RealReadOffset
= ROUND_DOWN(ReadOffset
, DeviceExt
->NtfsInfo
.BytesPerSector
);
148 RealLength
= ROUND_UP(ToRead
, DeviceExt
->NtfsInfo
.BytesPerSector
);
149 /* do we need to extend RealLength by one sector? */
150 if (RealLength
+ RealReadOffset
< ReadOffset
+ Length
)
152 if (RealReadOffset
+ RealLength
+ DeviceExt
->NtfsInfo
.BytesPerSector
<= AttributeAllocatedLength(&DataContext
->Record
))
153 RealLength
+= DeviceExt
->NtfsInfo
.BytesPerSector
;
157 ReadBuffer
= ExAllocatePoolWithTag(NonPagedPool
, RealLength
, TAG_NTFS
);
158 if (ReadBuffer
== NULL
)
160 DPRINT1("Not enough memory!\n");
161 ReleaseAttributeContext(DataContext
);
162 ExFreePoolWithTag(FileRecord
, TAG_NTFS
);
163 return STATUS_INSUFFICIENT_RESOURCES
;
165 AllocatedBuffer
= TRUE
;
168 DPRINT1("Effective read: %lu at %lu for stream '%S'\n", RealLength
, RealReadOffset
, Fcb
->Stream
);
169 RealLengthRead
= ReadAttribute(DeviceExt
, DataContext
, RealReadOffset
, (PCHAR
)ReadBuffer
, RealLength
);
170 if (RealLengthRead
== 0)
172 DPRINT1("Read failure!\n");
173 ReleaseAttributeContext(DataContext
);
174 ExFreePoolWithTag(FileRecord
, TAG_NTFS
);
177 ExFreePoolWithTag(ReadBuffer
, TAG_NTFS
);
182 ReleaseAttributeContext(DataContext
);
183 ExFreePoolWithTag(FileRecord
, TAG_NTFS
);
185 *LengthRead
= ToRead
;
187 DPRINT1("%lu got read\n", *LengthRead
);
191 RtlCopyMemory(Buffer
, ReadBuffer
+ (ReadOffset
- RealReadOffset
), ToRead
);
194 if (ToRead
!= Length
)
196 RtlZeroMemory(Buffer
+ ToRead
, Length
- ToRead
);
201 ExFreePoolWithTag(ReadBuffer
, TAG_NTFS
);
204 return STATUS_SUCCESS
;
209 NtfsRead(PNTFS_IRP_CONTEXT IrpContext
)
211 PDEVICE_EXTENSION DeviceExt
;
212 PIO_STACK_LOCATION Stack
;
213 PFILE_OBJECT FileObject
;
216 LARGE_INTEGER ReadOffset
;
217 ULONG ReturnedReadLength
= 0;
218 NTSTATUS Status
= STATUS_SUCCESS
;
220 PDEVICE_OBJECT DeviceObject
;
222 DPRINT("NtfsRead(IrpContext %p)\n", IrpContext
);
224 DeviceObject
= IrpContext
->DeviceObject
;
225 Irp
= IrpContext
->Irp
;
226 Stack
= IrpContext
->Stack
;
227 FileObject
= IrpContext
->FileObject
;
229 DeviceExt
= DeviceObject
->DeviceExtension
;
230 ReadLength
= Stack
->Parameters
.Read
.Length
;
231 ReadOffset
= Stack
->Parameters
.Read
.ByteOffset
;
232 Buffer
= NtfsGetUserBuffer(Irp
, BooleanFlagOn(Irp
->Flags
, IRP_PAGING_IO
));
234 Status
= NtfsReadFile(DeviceExt
,
238 ReadOffset
.u
.LowPart
,
240 &ReturnedReadLength
);
241 if (NT_SUCCESS(Status
))
243 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
245 FileObject
->CurrentByteOffset
.QuadPart
=
246 ReadOffset
.QuadPart
+ ReturnedReadLength
;
249 Irp
->IoStatus
.Information
= ReturnedReadLength
;
253 Irp
->IoStatus
.Information
= 0;
260 * @name NtfsWriteFile
263 * Writes a file to the disk. It presently borrows a lot of code from NtfsReadFile() and
264 * VFatWriteFileData(). It needs some more work before it will be complete; it won't handle
265 * page files, asnyc io, cached writes, etc.
268 * Points to the target disk's DEVICE_EXTENSION
271 * Pointer to a FILE_OBJECT describing the target file
274 * The data that's being written to the file
277 * The size of the data buffer being written, in bytes
280 * Offset, in bytes, from the beginning of the file. Indicates where to start
284 * TODO: flags are presently ignored in code.
286 * @param LengthWritten
287 * Pointer to a ULONG. This ULONG will be set to the number of bytes successfully written.
290 * STATUS_SUCCESS if successful, STATUS_NOT_IMPLEMENTED if a required feature isn't implemented,
291 * STATUS_INSUFFICIENT_RESOURCES if an allocation failed, STATUS_ACCESS_DENIED if the write itself fails,
292 * STATUS_PARTIAL_COPY or STATUS_UNSUCCESSFUL if ReadFileRecord() fails, or
293 * STATUS_OBJECT_NAME_NOT_FOUND if the file's data stream could not be found.
295 * @remarks Called by NtfsWrite(). It may perform a read-modify-write operation if the requested write is
296 * not sector-aligned. LengthWritten only refers to how much of the requested data has been written;
297 * extra data that needs to be written to make the write sector-aligned will not affect it.
300 NTSTATUS
NtfsWriteFile(PDEVICE_EXTENSION DeviceExt
,
301 PFILE_OBJECT FileObject
,
306 PULONG LengthWritten
)
308 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
310 PFILE_RECORD_HEADER FileRecord
;
311 PNTFS_ATTR_CONTEXT DataContext
;
312 ULONG AttributeOffset
;
313 ULONGLONG StreamSize
;
315 DPRINT("NtfsWriteFile(%p, %p, %p, %u, %u, %x, %p)\n", DeviceExt
, FileObject
, Buffer
, Length
, WriteOffset
, IrpFlags
, LengthWritten
);
324 return STATUS_SUCCESS
;
326 return STATUS_INVALID_PARAMETER
;
329 // get the File control block
330 Fcb
= (PNTFS_FCB
)FileObject
->FsContext
;
333 DPRINT("Fcb->PathName: %wS\n", Fcb
->PathName
);
334 DPRINT("Fcb->ObjectName: %wS\n", Fcb
->ObjectName
);
336 // we don't yet handle compression
337 if (NtfsFCBIsCompressed(Fcb
))
339 DPRINT("Compressed file!\n");
341 return STATUS_NOT_IMPLEMENTED
;
344 // allocate non-paged memory for the FILE_RECORD_HEADER
345 FileRecord
= ExAllocatePoolWithTag(NonPagedPool
, DeviceExt
->NtfsInfo
.BytesPerFileRecord
, TAG_NTFS
);
346 if (FileRecord
== NULL
)
348 DPRINT1("Not enough memory! Can't write %wS!\n", Fcb
->PathName
);
349 return STATUS_INSUFFICIENT_RESOURCES
;
352 // read the FILE_RECORD_HEADER from the drive (or cache)
353 DPRINT("Reading file record...\n");
354 Status
= ReadFileRecord(DeviceExt
, Fcb
->MFTIndex
, FileRecord
);
355 if (!NT_SUCCESS(Status
))
357 // We couldn't get the file's record. Free the memory and return the error
358 DPRINT1("Can't find record for %wS!\n", Fcb
->ObjectName
);
359 ExFreePoolWithTag(FileRecord
, TAG_NTFS
);
363 DPRINT("Found record for %wS\n", Fcb
->ObjectName
);
365 // Find the attribute with the data stream for our file
366 DPRINT("Finding Data Attribute...\n");
367 Status
= FindAttribute(DeviceExt
, FileRecord
, AttributeData
, Fcb
->Stream
, wcslen(Fcb
->Stream
), &DataContext
,
370 // Did we fail to find the attribute?
371 if (!NT_SUCCESS(Status
))
373 NTSTATUS BrowseStatus
;
374 FIND_ATTR_CONTXT Context
;
375 PNTFS_ATTR_RECORD Attribute
;
377 DPRINT1("No '%S' data stream associated with file!\n", Fcb
->Stream
);
379 // Couldn't find the requested data stream; print a list of streams available
380 BrowseStatus
= FindFirstAttribute(&Context
, DeviceExt
, FileRecord
, FALSE
, &Attribute
);
381 while (NT_SUCCESS(BrowseStatus
))
383 if (Attribute
->Type
== AttributeData
)
387 Name
.Length
= Attribute
->NameLength
* sizeof(WCHAR
);
388 Name
.MaximumLength
= Name
.Length
;
389 Name
.Buffer
= (PWCHAR
)((ULONG_PTR
)Attribute
+ Attribute
->NameOffset
);
390 DPRINT1("Data stream: '%wZ' available\n", &Name
);
393 BrowseStatus
= FindNextAttribute(&Context
, &Attribute
);
395 FindCloseAttribute(&Context
);
397 ReleaseAttributeContext(DataContext
);
398 ExFreePoolWithTag(FileRecord
, TAG_NTFS
);
402 // Get the size of the stream on disk
403 StreamSize
= AttributeDataLength(&DataContext
->Record
);
405 DPRINT("WriteOffset: %lu\tStreamSize: %I64u\n", WriteOffset
, StreamSize
);
407 // Are we trying to write beyond the end of the stream?
408 if (WriteOffset
+ Length
> StreamSize
)
410 // is increasing the stream size allowed?
411 if (!(Fcb
->Flags
& FCB_IS_VOLUME
) &&
412 !(IrpFlags
& IRP_PAGING_IO
))
414 LARGE_INTEGER DataSize
;
415 ULONGLONG AllocationSize
;
416 PFILENAME_ATTRIBUTE fileNameAttribute
;
417 ULONGLONG ParentMFTId
;
418 UNICODE_STRING filename
;
420 DataSize
.QuadPart
= WriteOffset
+ Length
;
422 AllocationSize
= ROUND_UP(DataSize
.QuadPart
, Fcb
->Vcb
->NtfsInfo
.BytesPerCluster
);
424 // set the attribute data length
425 Status
= SetAttributeDataLength(FileObject
, Fcb
, DataContext
, AttributeOffset
, FileRecord
, &DataSize
);
427 if (!NT_SUCCESS(Status
))
429 ReleaseAttributeContext(DataContext
);
430 ExFreePoolWithTag(FileRecord
, TAG_NTFS
);
435 // now we need to update this file's size in every directory index entry that references it
436 // TODO: put this code in its own function and adapt it to work with every filename / hardlink
437 // stored in the file record.
438 fileNameAttribute
= GetBestFileNameFromRecord(Fcb
->Vcb
, FileRecord
);
439 ASSERT(fileNameAttribute
);
441 ParentMFTId
= fileNameAttribute
->DirectoryFileReferenceNumber
& NTFS_MFT_MASK
;
443 filename
.Buffer
= fileNameAttribute
->Name
;
444 filename
.Length
= fileNameAttribute
->NameLength
* sizeof(WCHAR
);
445 filename
.MaximumLength
= filename
.Length
;
447 Status
= UpdateFileNameRecord(Fcb
->Vcb
, ParentMFTId
, &filename
, FALSE
, DataSize
.QuadPart
, AllocationSize
);
452 // TODO - just fail for now
453 ReleaseAttributeContext(DataContext
);
454 ExFreePoolWithTag(FileRecord
, TAG_NTFS
);
456 return STATUS_ACCESS_DENIED
;
460 DPRINT("Length: %lu\tWriteOffset: %lu\tStreamSize: %I64u\n", Length
, WriteOffset
, StreamSize
);
462 // Write the data to the attribute
463 Status
= WriteAttribute(DeviceExt
, DataContext
, WriteOffset
, Buffer
, Length
, LengthWritten
);
465 // Did the write fail?
466 if (!NT_SUCCESS(Status
))
468 DPRINT1("Write failure!\n");
469 ReleaseAttributeContext(DataContext
);
470 ExFreePoolWithTag(FileRecord
, TAG_NTFS
);
475 // This should never happen:
476 if (*LengthWritten
!= Length
)
478 DPRINT1("\a\tNTFS DRIVER ERROR: length written (%lu) differs from requested (%lu), but no error was indicated!\n",
479 *LengthWritten
, Length
);
480 Status
= STATUS_UNEXPECTED_IO_ERROR
;
483 ReleaseAttributeContext(DataContext
);
484 ExFreePoolWithTag(FileRecord
, TAG_NTFS
);
493 * Handles IRP_MJ_WRITE I/O Request Packets for NTFS. This code borrows a lot from
494 * VfatWrite, and needs a lot of cleaning up. It also needs a lot more of the code
495 * from VfatWrite integrated.
498 * Points to an NTFS_IRP_CONTEXT which describes the write
501 * STATUS_SUCCESS if successful,
502 * STATUS_INSUFFICIENT_RESOURCES if an allocation failed,
503 * STATUS_INVALID_DEVICE_REQUEST if called on the main device object,
504 * STATUS_NOT_IMPLEMENTED or STATUS_ACCESS_DENIED if a required feature isn't implemented.
505 * STATUS_PARTIAL_COPY, STATUS_UNSUCCESSFUL, or STATUS_OBJECT_NAME_NOT_FOUND if NtfsWriteFile() fails.
507 * @remarks Called by NtfsDispatch() in response to an IRP_MJ_WRITE request. Page files are not implemented.
508 * Support for large files (>4gb) is not implemented. Cached writes, file locks, transactions, etc - not implemented.
512 NtfsWrite(PNTFS_IRP_CONTEXT IrpContext
)
515 PERESOURCE Resource
= NULL
;
516 LARGE_INTEGER ByteOffset
;
518 NTSTATUS Status
= STATUS_SUCCESS
;
520 ULONG ReturnedWriteLength
= 0;
521 PDEVICE_OBJECT DeviceObject
= NULL
;
522 PDEVICE_EXTENSION DeviceExt
= NULL
;
523 PFILE_OBJECT FileObject
= NULL
;
525 ULONG BytesPerSector
;
527 DPRINT("NtfsWrite(IrpContext %p)\n", IrpContext
);
530 // This request is not allowed on the main device object
531 if (IrpContext
->DeviceObject
== NtfsGlobalData
->DeviceObject
)
533 DPRINT1("\t\t\t\tNtfsWrite is called with the main device object.\n");
535 Irp
->IoStatus
.Information
= 0;
536 return STATUS_INVALID_DEVICE_REQUEST
;
539 // get the I/O request packet
540 Irp
= IrpContext
->Irp
;
542 // get the File control block
543 Fcb
= (PNTFS_FCB
)IrpContext
->FileObject
->FsContext
;
546 DPRINT("About to write %wS\n", Fcb
->ObjectName
);
547 DPRINT("NTFS Version: %d.%d\n", Fcb
->Vcb
->NtfsInfo
.MajorVersion
, Fcb
->Vcb
->NtfsInfo
.MinorVersion
);
549 // setup some more locals
550 FileObject
= IrpContext
->FileObject
;
551 DeviceObject
= IrpContext
->DeviceObject
;
552 DeviceExt
= DeviceObject
->DeviceExtension
;
553 BytesPerSector
= DeviceExt
->StorageDevice
->SectorSize
;
554 Length
= IrpContext
->Stack
->Parameters
.Write
.Length
;
556 // get the file offset we'll be writing to
557 ByteOffset
= IrpContext
->Stack
->Parameters
.Write
.ByteOffset
;
558 if (ByteOffset
.u
.LowPart
== FILE_WRITE_TO_END_OF_FILE
&&
559 ByteOffset
.u
.HighPart
== -1)
561 ByteOffset
.QuadPart
= Fcb
->RFCB
.FileSize
.QuadPart
;
564 DPRINT("ByteOffset: %I64u\tLength: %lu\tBytes per sector: %lu\n", ByteOffset
.QuadPart
,
565 Length
, BytesPerSector
);
567 if (ByteOffset
.u
.HighPart
&& !(Fcb
->Flags
& FCB_IS_VOLUME
))
569 // TODO: Support large files
570 DPRINT1("FIXME: Writing to large files is not yet supported at this time.\n");
571 return STATUS_INVALID_PARAMETER
;
574 // Is this a non-cached write? A non-buffered write?
575 if (IrpContext
->Irp
->Flags
& (IRP_PAGING_IO
| IRP_NOCACHE
) || (Fcb
->Flags
& FCB_IS_VOLUME
) ||
576 IrpContext
->FileObject
->Flags
& FILE_NO_INTERMEDIATE_BUFFERING
)
578 // non-cached and non-buffered writes must be sector aligned
579 if (ByteOffset
.u
.LowPart
% BytesPerSector
!= 0 || Length
% BytesPerSector
!= 0)
581 DPRINT1("Non-cached writes and non-buffered writes must be sector aligned!\n");
582 return STATUS_INVALID_PARAMETER
;
588 DPRINT1("Null write!\n");
590 IrpContext
->Irp
->IoStatus
.Information
= 0;
592 // FIXME: Doesn't accurately detect when a user passes NULL to WriteFile() for the buffer
593 if (Irp
->UserBuffer
== NULL
&& Irp
->MdlAddress
== NULL
)
595 // FIXME: Update last write time
596 return STATUS_SUCCESS
;
599 return STATUS_INVALID_PARAMETER
;
603 if (Fcb
->Flags
& FCB_IS_VOLUME
)
605 Resource
= &DeviceExt
->DirResource
;
607 else if (IrpContext
->Irp
->Flags
& IRP_PAGING_IO
)
609 Resource
= &Fcb
->PagingIoResource
;
613 Resource
= &Fcb
->MainResource
;
616 // acquire exclusive access to the Resource
617 if (!ExAcquireResourceExclusiveLite(Resource
, BooleanFlagOn(IrpContext
->Flags
, IRPCONTEXT_CANWAIT
)))
619 return STATUS_CANT_WAIT
;
622 /* From VfatWrite(). Todo: Handle file locks
623 if (!(IrpContext->Irp->Flags & IRP_PAGING_IO) &&
624 FsRtlAreThereCurrentFileLocks(&Fcb->FileLock))
626 if (!FsRtlCheckLockForWriteAccess(&Fcb->FileLock, IrpContext->Irp))
628 Status = STATUS_FILE_LOCK_CONFLICT;
633 // Is this an async request to a file?
634 if (!(IrpContext
->Flags
& IRPCONTEXT_CANWAIT
) && !(Fcb
->Flags
& FCB_IS_VOLUME
))
636 DPRINT1("FIXME: Async writes not supported in NTFS!\n");
638 ExReleaseResourceLite(Resource
);
639 return STATUS_NOT_IMPLEMENTED
;
642 // get the buffer of data the user is trying to write
643 Buffer
= NtfsGetUserBuffer(Irp
, BooleanFlagOn(Irp
->Flags
, IRP_PAGING_IO
));
647 Status
= NtfsLockUserBuffer(Irp
, Length
, IoReadAccess
);
649 // were we unable to lock the buffer?
650 if (!NT_SUCCESS(Status
))
652 DPRINT1("Unable to lock user buffer!\n");
654 ExReleaseResourceLite(Resource
);
658 DPRINT("Existing File Size(Fcb->RFCB.FileSize.QuadPart): %I64u\n", Fcb
->RFCB
.FileSize
.QuadPart
);
659 DPRINT("About to write the data. Length: %lu\n", Length
);
661 // TODO: handle HighPart of ByteOffset (large files)
664 Status
= NtfsWriteFile(DeviceExt
,
670 &ReturnedWriteLength
);
672 IrpContext
->Irp
->IoStatus
.Status
= Status
;
674 // was the write successful?
675 if (NT_SUCCESS(Status
))
677 // TODO: Update timestamps
679 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
681 // advance the file pointer
682 FileObject
->CurrentByteOffset
.QuadPart
= ByteOffset
.QuadPart
+ ReturnedWriteLength
;
685 IrpContext
->PriorityBoost
= IO_DISK_INCREMENT
;
689 DPRINT1("Write not Succesful!\tReturned length: %lu\n", ReturnedWriteLength
);
692 Irp
->IoStatus
.Information
= ReturnedWriteLength
;
694 // Note: We leave the user buffer that we locked alone, it's up to the I/O manager to unlock and free it
696 ExReleaseResourceLite(Resource
);