static NTSTATUS FspFsvolQueryFsVolumeInformation( PDEVICE_OBJECT FsvolDeviceObject, PUINT8 *PBuffer, PUINT8 BufferEnd, const FSP_FSCTL_VOLUME_INFO *VolumeInfo) { PAGED_CODE(); if (*PBuffer + sizeof(FILE_FS_VOLUME_INFORMATION) > BufferEnd) return STATUS_BUFFER_TOO_SMALL; GETVOLUMEINFO(); NTSTATUS Result = STATUS_SUCCESS; FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject); PFILE_FS_VOLUME_INFORMATION Info = (PFILE_FS_VOLUME_INFORMATION)*PBuffer; PUINT8 Buffer = (PUINT8)Info->VolumeLabel; ULONG CopyLength; Info->VolumeCreationTime.QuadPart = FsvolDeviceExtension->VolumeParams.VolumeCreationTime; Info->VolumeSerialNumber = FsvolDeviceExtension->VolumeParams.VolumeSerialNumber; Info->VolumeLabelLength = VolumeInfo->VolumeLabelLength; Info->SupportsObjects = FALSE; CopyLength = VolumeInfo->VolumeLabelLength; if (Buffer + CopyLength > BufferEnd) { CopyLength = (ULONG)(BufferEnd - Buffer); Result = STATUS_BUFFER_OVERFLOW; } RtlCopyMemory(Buffer, VolumeInfo->VolumeLabel, CopyLength); Buffer += CopyLength; *PBuffer = Buffer; return Result; }
VOID FspFileNodeDelete(FSP_FILE_NODE *FileNode) { PAGED_CODE(); FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FileNode->FsvolDeviceObject); FsRtlUninitializeFileLock(&FileNode->FileLock); FsRtlTeardownPerStreamContexts(&FileNode->Header); FspMetaCacheInvalidateItem(FsvolDeviceExtension->DirInfoCache, FileNode->NonPaged->DirInfo); FspMetaCacheInvalidateItem(FsvolDeviceExtension->SecurityCache, FileNode->Security); FspDeviceDereference(FileNode->FsvolDeviceObject); if (0 != FileNode->ExternalFileName) FspFree(FileNode->ExternalFileName); ExDeleteResourceLite(&FileNode->NonPaged->PagingIoResource); ExDeleteResourceLite(&FileNode->NonPaged->Resource); FspFree(FileNode->NonPaged); FspFree(FileNode); }
static NTSTATUS FspFsvolQueryFsSizeInformation( PDEVICE_OBJECT FsvolDeviceObject, PUINT8 *PBuffer, PUINT8 BufferEnd, const FSP_FSCTL_VOLUME_INFO *VolumeInfo) { PAGED_CODE(); if (*PBuffer + sizeof(FILE_FS_SIZE_INFORMATION) > BufferEnd) return STATUS_BUFFER_TOO_SMALL; GETVOLUMEINFO(); FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject); PFILE_FS_SIZE_INFORMATION Info = (PFILE_FS_SIZE_INFORMATION)*PBuffer; UINT64 AllocationUnit = FsvolDeviceExtension->VolumeParams.SectorSize * FsvolDeviceExtension->VolumeParams.SectorsPerAllocationUnit; Info->TotalAllocationUnits.QuadPart = VolumeInfo->TotalSize / AllocationUnit; Info->AvailableAllocationUnits.QuadPart = VolumeInfo->FreeSize / AllocationUnit; Info->SectorsPerAllocationUnit = FsvolDeviceExtension->VolumeParams.SectorsPerAllocationUnit; Info->BytesPerSector = FsvolDeviceExtension->VolumeParams.SectorSize; *PBuffer += sizeof(FILE_FS_SIZE_INFORMATION); return STATUS_SUCCESS; }
BOOLEAN FspIopRetryPrepareIrp(PIRP Irp, NTSTATUS *PResult) { PAGED_CODE(); PDEVICE_OBJECT DeviceObject = IoGetCurrentIrpStackLocation(Irp)->DeviceObject; FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject); return FspIoqPostIrpBestEffort(FsvolDeviceExtension->Ioq, Irp, PResult); }
BOOLEAN FspFileNodeReferenceSecurity(FSP_FILE_NODE *FileNode, PCVOID *PBuffer, PULONG PSize) { PAGED_CODE(); FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FileNode->FsvolDeviceObject); return FspMetaCacheReferenceItemBuffer(FsvolDeviceExtension->SecurityCache, FileNode->Security, PBuffer, PSize); }
BOOLEAN FspIopRetryCompleteIrp(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response, NTSTATUS *PResult) { PAGED_CODE(); PDEVICE_OBJECT DeviceObject = IoGetCurrentIrpStackLocation(Irp)->DeviceObject; FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject); FspIopSetIrpResponse(Irp, Response); return FspIoqRetryCompleteIrp(FsvolDeviceExtension->Ioq, Irp, PResult); }
VOID FspFileNodeSetSecurity(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size) { PAGED_CODE(); FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FileNode->FsvolDeviceObject); FspMetaCacheInvalidateItem(FsvolDeviceExtension->SecurityCache, FileNode->Security); FileNode->Security = 0 != Buffer ? FspMetaCacheAddItem(FsvolDeviceExtension->SecurityCache, Buffer, Size) : 0; FileNode->SecurityChangeNumber++; }
BOOLEAN FspFileNodeReferenceDirInfo(FSP_FILE_NODE *FileNode, PCVOID *PBuffer, PULONG PSize) { // !PAGED_CODE(); FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FileNode->FsvolDeviceObject); FSP_FILE_NODE_NONPAGED *NonPaged = FileNode->NonPaged; UINT64 DirInfo; /* no need to acquire the DirInfoSpinLock as the FileNode is acquired */ DirInfo = NonPaged->DirInfo; return FspMetaCacheReferenceItemBuffer(FsvolDeviceExtension->DirInfoCache, DirInfo, PBuffer, PSize); }
static VOID FspFileNodeInvalidateDirInfo(FSP_FILE_NODE *FileNode) { // !PAGED_CODE(); PDEVICE_OBJECT FsvolDeviceObject = FileNode->FsvolDeviceObject; FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject); FSP_FILE_NODE_NONPAGED *NonPaged = FileNode->NonPaged; KIRQL Irql; UINT64 DirInfo; /* acquire the DirInfoSpinLock to protect against concurrent FspFileNodeSetDirInfo */ KeAcquireSpinLock(&NonPaged->DirInfoSpinLock, &Irql); DirInfo = NonPaged->DirInfo; KeReleaseSpinLock(&NonPaged->DirInfoSpinLock, Irql); FspMetaCacheInvalidateItem(FsvolDeviceExtension->DirInfoCache, DirInfo); }
VOID FspFileNodeNotifyChange(FSP_FILE_NODE *FileNode, ULONG Filter, ULONG Action) { /* FileNode must be acquired (exclusive or shared) Main */ PAGED_CODE(); PDEVICE_OBJECT FsvolDeviceObject = FileNode->FsvolDeviceObject; FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject); UNICODE_STRING Parent, Suffix; FSP_FILE_NODE *ParentNode; FspUnicodePathSuffix(&FileNode->FileName, &Parent, &Suffix); switch (Action) { case FILE_ACTION_ADDED: case FILE_ACTION_REMOVED: //case FILE_ACTION_MODIFIED: case FILE_ACTION_RENAMED_OLD_NAME: case FILE_ACTION_RENAMED_NEW_NAME: FspFsvolDeviceInvalidateVolumeInfo(FsvolDeviceObject); FspFsvolDeviceLockContextTable(FsvolDeviceObject); ParentNode = FspFsvolDeviceLookupContextByName(FsvolDeviceObject, &Parent); if (0 != ParentNode) FspFileNodeReference(ParentNode); FspFsvolDeviceUnlockContextTable(FsvolDeviceObject); if (0 != ParentNode) { FspFileNodeInvalidateDirInfo(ParentNode); FspFileNodeDereference(ParentNode); } break; } FspNotifyReportChange( FsvolDeviceExtension->NotifySync, &FsvolDeviceExtension->NotifyList, &FileNode->FileName, (USHORT)((PUINT8)Suffix.Buffer - (PUINT8)FileNode->FileName.Buffer), 0, Filter, Action); }
static NTSTATUS FspFsvolQueryFsAttributeInformation( PDEVICE_OBJECT FsvolDeviceObject, PUINT8 *PBuffer, PUINT8 BufferEnd) { PAGED_CODE(); if (*PBuffer + sizeof(FILE_FS_ATTRIBUTE_INFORMATION) > BufferEnd) return STATUS_BUFFER_TOO_SMALL; NTSTATUS Result = STATUS_SUCCESS; FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject); PFILE_FS_ATTRIBUTE_INFORMATION Info = (PFILE_FS_ATTRIBUTE_INFORMATION)*PBuffer; PUINT8 Buffer = (PUINT8)Info->FileSystemName; ULONG CopyLength; Info->FileSystemAttributes = (FsvolDeviceExtension->VolumeParams.CaseSensitiveSearch ? FILE_CASE_SENSITIVE_SEARCH : 0) | (FsvolDeviceExtension->VolumeParams.CasePreservedNames ? FILE_CASE_PRESERVED_NAMES : 0) | (FsvolDeviceExtension->VolumeParams.UnicodeOnDisk ? FILE_UNICODE_ON_DISK : 0) | (FsvolDeviceExtension->VolumeParams.PersistentAcls ? FILE_PERSISTENT_ACLS : 0) | (FsvolDeviceExtension->VolumeParams.ReparsePoints ? FILE_SUPPORTS_REPARSE_POINTS : 0) | (FsvolDeviceExtension->VolumeParams.NamedStreams ? FILE_NAMED_STREAMS : 0) | //(FsvolDeviceExtension->VolumeParams.HardLinks ? FILE_SUPPORTS_HARD_LINKS : 0) | //(FsvolDeviceExtension->VolumeParams.ExtendedAttributes ? FILE_SUPPORTS_EXTENDED_ATTRIBUTES : 0) | (FsvolDeviceExtension->VolumeParams.ReadOnlyVolume ? FILE_READ_ONLY_VOLUME : 0); Info->MaximumComponentNameLength = FsvolDeviceExtension->VolumeParams.MaxComponentLength; Info->FileSystemNameLength = sizeof L"" DRIVER_NAME - sizeof(WCHAR); CopyLength = Info->FileSystemNameLength; if (Buffer + CopyLength > BufferEnd) { CopyLength = (ULONG)(BufferEnd - Buffer); Result = STATUS_BUFFER_OVERFLOW; } RtlCopyMemory(Buffer, L"" DRIVER_NAME, CopyLength); Buffer += CopyLength; *PBuffer = Buffer; return Result; }
VOID FspFileNodeSetFileInfo(FSP_FILE_NODE *FileNode, PFILE_OBJECT CcFileObject, const FSP_FSCTL_FILE_INFO *FileInfo) { PAGED_CODE(); FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FileNode->FsvolDeviceObject); UINT64 AllocationSize = FileInfo->AllocationSize > FileInfo->FileSize ? FileInfo->AllocationSize : FileInfo->FileSize; UINT64 AllocationUnit; AllocationUnit = FsvolDeviceExtension->VolumeParams.SectorSize * FsvolDeviceExtension->VolumeParams.SectorsPerAllocationUnit; AllocationSize = (AllocationSize + AllocationUnit - 1) / AllocationUnit * AllocationUnit; FileNode->Header.AllocationSize.QuadPart = AllocationSize; FileNode->Header.FileSize.QuadPart = FileInfo->FileSize; FileNode->FileAttributes = FileInfo->FileAttributes; FileNode->ReparseTag = FileInfo->ReparseTag; FileNode->CreationTime = FileInfo->CreationTime; FileNode->LastAccessTime = FileInfo->LastAccessTime; FileNode->LastWriteTime = FileInfo->LastWriteTime; FileNode->ChangeTime = FileInfo->ChangeTime; FileNode->InfoExpirationTime = FspExpirationTimeFromMillis( FsvolDeviceExtension->VolumeParams.FileInfoTimeout); FileNode->InfoChangeNumber++; if (0 != CcFileObject) { NTSTATUS Result = FspCcSetFileSizes( CcFileObject, (PCC_FILE_SIZES)&FileNode->Header.AllocationSize); if (!NT_SUCCESS(Result)) { DEBUGLOG("FspCcSetFileSizes error: %s", NtStatusSym(Result)); DEBUGBREAK_CRIT(); CcUninitializeCacheMap(CcFileObject, 0, 0); } } }
VOID FspFileNodeSetDirInfo(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size) { // !PAGED_CODE(); FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FileNode->FsvolDeviceObject); FSP_FILE_NODE_NONPAGED *NonPaged = FileNode->NonPaged; KIRQL Irql; UINT64 DirInfo; /* no need to acquire the DirInfoSpinLock as the FileNode is acquired */ DirInfo = NonPaged->DirInfo; FspMetaCacheInvalidateItem(FsvolDeviceExtension->DirInfoCache, DirInfo); DirInfo = 0 != Buffer ? FspMetaCacheAddItem(FsvolDeviceExtension->DirInfoCache, Buffer, Size) : 0; FileNode->DirInfoChangeNumber++; /* acquire the DirInfoSpinLock to protect against concurrent FspFileNodeInvalidateDirInfo */ KeAcquireSpinLock(&NonPaged->DirInfoSpinLock, &Irql); NonPaged->DirInfo = DirInfo; KeReleaseSpinLock(&NonPaged->DirInfoSpinLock, Irql); }
static NTSTATUS FspFsvolWriteCached( PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp, BOOLEAN CanWait) { PAGED_CODE(); /* assert: must be top-level IRP */ ASSERT(0 == FspIrpTopFlags(Irp)); NTSTATUS Result; BOOLEAN Retrying = 0 != FspIrpRequest(Irp); PFILE_OBJECT FileObject = IrpSp->FileObject; FSP_FILE_NODE *FileNode = FileObject->FsContext; LARGE_INTEGER WriteOffset = IrpSp->Parameters.Write.ByteOffset; ULONG WriteLength = IrpSp->Parameters.Write.Length; BOOLEAN WriteToEndOfFile = FILE_WRITE_TO_END_OF_FILE == WriteOffset.LowPart && -1L == WriteOffset.HighPart; BOOLEAN SynchronousIo = BooleanFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO); FSP_FSCTL_FILE_INFO FileInfo; CC_FILE_SIZES FileSizes; FILE_END_OF_FILE_INFORMATION EndOfFileInformation; UINT64 WriteEndOffset; BOOLEAN ExtendingFile; BOOLEAN Success; /* should we defer the write? */ Success = DEBUGTEST(90) && CcCanIWrite(FileObject, WriteLength, CanWait, Retrying); if (!Success) { Result = FspWqCreateIrpWorkItem(Irp, FspFsvolWriteCached, 0); if (NT_SUCCESS(Result)) { IoMarkIrpPending(Irp); CcDeferWrite(FileObject, FspFsvolWriteCachedDeferred, Irp, 0, WriteLength, Retrying); return STATUS_PENDING; } /* if we are unable to defer we will go ahead and (try to) service the IRP now! */ } /* try to acquire the FileNode Main exclusive */ Success = DEBUGTEST(90) && FspFileNodeTryAcquireExclusiveF(FileNode, FspFileNodeAcquireMain, CanWait); if (!Success) return FspWqRepostIrpWorkItem(Irp, FspFsvolWriteCached, 0); /* perform oplock check */ Result = FspFileNodeOplockCheckAsync( FileNode, FspFileNodeAcquireMain, FspFsvolWriteCached, Irp); if (STATUS_PENDING == Result) return Result; if (!NT_SUCCESS(Result)) { FspFileNodeRelease(FileNode, Main); return Result; } /* check the file locks */ if (!FsRtlCheckLockForWriteAccess(&FileNode->FileLock, Irp)) { FspFileNodeRelease(FileNode, Main); return STATUS_FILE_LOCK_CONFLICT; } /* compute new file size */ ASSERT(FspTimeoutInfinity32 == FspFsvolDeviceExtension(FsvolDeviceObject)->VolumeParams.FileInfoTimeout); FspFileNodeGetFileInfo(FileNode, &FileInfo); if (WriteToEndOfFile) WriteOffset.QuadPart = FileInfo.FileSize; WriteEndOffset = WriteOffset.QuadPart + WriteLength; ExtendingFile = FileInfo.FileSize < WriteEndOffset; if (ExtendingFile && !CanWait) { /* need CanWait==TRUE for FspSendSetInformationIrp */ FspFileNodeRelease(FileNode, Main); return FspWqRepostIrpWorkItem(Irp, FspFsvolWriteCached, 0); } /* initialize cache if not already initialized! */ if (0 == FileObject->PrivateCacheMap) { FileSizes.AllocationSize.QuadPart = FileInfo.AllocationSize; FileSizes.FileSize.QuadPart = FileInfo.FileSize; FileSizes.ValidDataLength.QuadPart = MAXLONGLONG; Result = FspCcInitializeCacheMap(FileObject, &FileSizes, FALSE, &FspCacheManagerCallbacks, FileNode); if (!NT_SUCCESS(Result)) { FspFileNodeRelease(FileNode, Main); return Result; } } /* are we extending the file? */ if (ExtendingFile) { ASSERT(CanWait); /* send EndOfFileInformation IRP; this will also set TruncateOnClose, etc. */ EndOfFileInformation.EndOfFile.QuadPart = WriteEndOffset; Result = FspSendSetInformationIrp(FsvolDeviceObject/* bypass filters */, FileObject, FileEndOfFileInformation, &EndOfFileInformation, sizeof EndOfFileInformation); if (!NT_SUCCESS(Result)) { FspFileNodeRelease(FileNode, Main); return Result; } /* double-check that the cache still exists in case CcSetFileSizes failed */ if (0 == FileObject->SectionObjectPointer->SharedCacheMap) { FspFileNodeRelease(FileNode, Main); return STATUS_INSUFFICIENT_RESOURCES; // or STATUS_SECTION_TOO_BIG? } } /* * From this point forward we must jump to the CLEANUP label on failure. */ /* are we using the copy or MDL interface? */ if (!FlagOn(IrpSp->MinorFunction, IRP_MN_MDL)) { PVOID Buffer; Buffer = 0 == Irp->MdlAddress ? Irp->UserBuffer : MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority); if (0 == Buffer) { Result = STATUS_INSUFFICIENT_RESOURCES; goto cleanup; } Result = FspCcCopyWrite(FileObject, &WriteOffset, WriteLength, CanWait, Buffer); if (!NT_SUCCESS(Result) || STATUS_PENDING == Result) goto cleanup; Irp->IoStatus.Information = WriteLength; } else { Result = FspCcPrepareMdlWrite(FileObject, &WriteOffset, WriteLength, &Irp->MdlAddress, &Irp->IoStatus); if (!NT_SUCCESS(Result)) goto cleanup; ASSERT(STATUS_PENDING != Result); } /* update the current file offset if synchronous I/O */ if (SynchronousIo) FileObject->CurrentByteOffset.QuadPart = WriteEndOffset; /* mark the file object as modified (if not paging I/O) */ SetFlag(FileObject->Flags, FO_FILE_MODIFIED); FspFileNodeRelease(FileNode, Main); return STATUS_SUCCESS; cleanup: FspFileNodeRelease(FileNode, Main); if (STATUS_PENDING == Result) return FspWqRepostIrpWorkItem(Irp, FspFsvolWriteCached, 0); return Result; }
static NTSTATUS FspFsvolWriteNonCached( PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp, BOOLEAN CanWait) { PAGED_CODE(); /* assert: either a top-level IRP or Paging I/O */ ASSERT(0 == FspIrpTopFlags(Irp) || FlagOn(Irp->Flags, IRP_PAGING_IO)); NTSTATUS Result; PFILE_OBJECT FileObject = IrpSp->FileObject; FSP_FILE_NODE *FileNode = FileObject->FsContext; FSP_FILE_DESC *FileDesc = FileObject->FsContext2; LARGE_INTEGER WriteOffset = IrpSp->Parameters.Write.ByteOffset; ULONG WriteLength = IrpSp->Parameters.Write.Length; ULONG WriteKey = IrpSp->Parameters.Write.Key; BOOLEAN WriteToEndOfFile = FILE_WRITE_TO_END_OF_FILE == WriteOffset.LowPart && -1L == WriteOffset.HighPart; BOOLEAN PagingIo = BooleanFlagOn(Irp->Flags, IRP_PAGING_IO); FSP_FSCTL_TRANSACT_REQ *Request; BOOLEAN Success; ASSERT(FileNode == FileDesc->FileNode); /* no MDL requests on the non-cached path */ if (FlagOn(IrpSp->MinorFunction, IRP_MN_MDL)) return STATUS_INVALID_PARAMETER; /* paging I/O cannot change the file size */ if (PagingIo && WriteToEndOfFile) return STATUS_INVALID_PARAMETER; /* stop CcWriteBehind from calling me! */ if (FspIoqStopped(FspFsvolDeviceExtension(FsvolDeviceObject)->Ioq)) return FspFsvolDeviceStoppedStatus(FsvolDeviceObject); /* probe and lock the user buffer */ Result = FspLockUserBuffer(Irp, WriteLength, IoReadAccess); if (!NT_SUCCESS(Result)) return Result; /* acquire FileNode exclusive Full */ Success = DEBUGTEST(90) && FspFileNodeTryAcquireExclusiveF(FileNode, FspFileNodeAcquireFull, CanWait); if (!Success) return FspWqRepostIrpWorkItem(Irp, FspFsvolWriteNonCached, 0); /* perform oplock check */ if (!PagingIo) { Result = FspFileNodeOplockCheckAsync( FileNode, FspFileNodeAcquireFull, FspFsvolWriteNonCached, Irp); if (STATUS_PENDING == Result) return Result; if (!NT_SUCCESS(Result)) { FspFileNodeRelease(FileNode, Full); return Result; } } /* check the file locks */ if (!PagingIo && !FsRtlCheckLockForWriteAccess(&FileNode->FileLock, Irp)) { FspFileNodeRelease(FileNode, Full); return STATUS_FILE_LOCK_CONFLICT; } /* if this is a non-cached transfer on a cached file then flush and purge the file */ if (!PagingIo && 0 != FileObject->SectionObjectPointer->DataSectionObject) { if (!CanWait) { FspFileNodeRelease(FileNode, Full); return FspWqRepostIrpWorkItem(Irp, FspFsvolWriteNonCached, 0); } Result = FspFileNodeFlushAndPurgeCache(FileNode, IrpSp->Parameters.Write.ByteOffset.QuadPart, IrpSp->Parameters.Write.Length, TRUE); if (!NT_SUCCESS(Result)) { FspFileNodeRelease(FileNode, Full); return Result; } } Request = FspIrpRequest(Irp); if (0 == Request) { /* create request */ Result = FspIopCreateRequestEx(Irp, 0, 0, FspFsvolWriteNonCachedRequestFini, &Request); if (!NT_SUCCESS(Result)) { FspFileNodeRelease(FileNode, Full); return Result; } } else { /* reuse existing request */ ASSERT(Request->Size == sizeof *Request); ASSERT(Request->Hint == (UINT_PTR)Irp); FspIopResetRequest(Request, FspFsvolWriteNonCachedRequestFini); RtlZeroMemory(&Request->Req, sizeof *Request - FIELD_OFFSET(FSP_FSCTL_TRANSACT_REQ, Req)); } Request->Kind = FspFsctlTransactWriteKind; Request->Req.Write.UserContext = FileNode->UserContext; Request->Req.Write.UserContext2 = FileDesc->UserContext2; Request->Req.Write.Offset = WriteOffset.QuadPart; Request->Req.Write.Length = WriteLength; Request->Req.Write.Key = WriteKey; Request->Req.Write.ConstrainedIo = !!PagingIo; FspFileNodeSetOwner(FileNode, Full, Request); FspIopRequestContext(Request, RequestIrp) = Irp; FSP_STATISTICS *Statistics = FspFsvolDeviceStatistics(FsvolDeviceObject); if (PagingIo) { FspStatisticsInc(Statistics, Base.UserFileWrites); FspStatisticsAdd(Statistics, Base.UserFileWriteBytes, WriteLength); FspStatisticsInc(Statistics, Base.UserDiskWrites); } else { FspStatisticsInc(Statistics, Specific.NonCachedWrites); FspStatisticsAdd(Statistics, Specific.NonCachedWriteBytes, WriteLength); FspStatisticsInc(Statistics, Specific.NonCachedDiskWrites); } return FSP_STATUS_IOQ_POST; }