static NTSTATUS FspFsvolQuerySecurity( PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp) { PAGED_CODE(); /* is this a valid FileObject? */ if (!FspFileNodeIsValid(IrpSp->FileObject->FsContext)) return STATUS_INVALID_DEVICE_REQUEST; NTSTATUS Result; PFILE_OBJECT FileObject = IrpSp->FileObject; FSP_FILE_NODE *FileNode = FileObject->FsContext; FSP_FILE_DESC *FileDesc = FileObject->FsContext2; SECURITY_INFORMATION SecurityInformation = IrpSp->Parameters.QuerySecurity.SecurityInformation; PVOID Buffer = Irp->UserBuffer; ULONG Length = IrpSp->Parameters.QuerySecurity.Length; PVOID SecurityBuffer; FSP_FSCTL_TRANSACT_REQ *Request; ASSERT(FileNode == FileDesc->FileNode); FspFileNodeAcquireShared(FileNode, Main); if (FspFileNodeReferenceSecurity(FileNode, &SecurityBuffer, 0)) { FspFileNodeRelease(FileNode, Main); Result = FspQuerySecurityDescriptorInfo(SecurityInformation, Buffer, &Length, SecurityBuffer); FspFileNodeDereferenceSecurity(SecurityBuffer); Irp->IoStatus.Information = Length; return Result; } FspFileNodeAcquireShared(FileNode, Pgio); Result = FspBufferUserBuffer(Irp, Length, IoWriteAccess); if (!NT_SUCCESS(Result)) { FspFileNodeRelease(FileNode, Full); return Result; } Result = FspIopCreateRequestEx(Irp, 0, 0, FspFsvolQuerySecurityRequestFini, &Request); if (!NT_SUCCESS(Result)) { FspFileNodeRelease(FileNode, Full); return Result; } Request->Kind = FspFsctlTransactQuerySecurityKind; Request->Req.QuerySecurity.UserContext = FileNode->UserContext; Request->Req.QuerySecurity.UserContext2 = FileDesc->UserContext2; FspFileNodeSetOwner(FileNode, Full, Request); FspIopRequestContext(Request, RequestFileNode) = FileNode; return FSP_STATUS_IOQ_POST; }
static NTSTATUS FspFsvolSetSecurity( PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp) { PAGED_CODE(); /* is this a valid FileObject? */ if (!FspFileNodeIsValid(IrpSp->FileObject->FsContext)) return STATUS_INVALID_DEVICE_REQUEST; NTSTATUS Result; PFILE_OBJECT FileObject = IrpSp->FileObject; FSP_FILE_NODE *FileNode = FileObject->FsContext; FSP_FILE_DESC *FileDesc = FileObject->FsContext2; SECURITY_INFORMATION SecurityInformation = IrpSp->Parameters.SetSecurity.SecurityInformation; PSECURITY_DESCRIPTOR SecurityDescriptor = IrpSp->Parameters.SetSecurity.SecurityDescriptor; ULONG SecurityDescriptorSize = 0; ASSERT(FileNode == FileDesc->FileNode); #if 0 /* captured security descriptor is always valid */ if (0 == SecurityDescriptor || !RtlValidSecurityDescriptor(SecurityDescriptor)) return STATUS_INVALID_PARAMETER; #endif SecurityDescriptorSize = RtlLengthSecurityDescriptor(SecurityDescriptor); FspFileNodeAcquireExclusive(FileNode, Full); FSP_FSCTL_TRANSACT_REQ *Request; Result = FspIopCreateRequestEx(Irp, 0, SecurityDescriptorSize, FspFsvolSetSecurityRequestFini, &Request); if (!NT_SUCCESS(Result)) { FspFileNodeRelease(FileNode, Full); return Result; } Request->Kind = FspFsctlTransactSetSecurityKind; Request->Req.SetSecurity.UserContext = FileNode->UserContext; Request->Req.SetSecurity.UserContext2 = FileDesc->UserContext2; Request->Req.SetSecurity.SecurityInformation = SecurityInformation; Request->Req.SetSecurity.SecurityDescriptor.Offset = 0; Request->Req.SetSecurity.SecurityDescriptor.Size = (UINT16)SecurityDescriptorSize; RtlCopyMemory(Request->Buffer, SecurityDescriptor, SecurityDescriptorSize); FspFileNodeSetOwner(FileNode, Full, Request); FspIopRequestContext(Request, RequestFileNode) = FileNode; return FSP_STATUS_IOQ_POST; }
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; }