Esempio n. 1
0
VOID FspIopCompleteIrpEx(PIRP Irp, NTSTATUS Result, BOOLEAN DeviceDereference)
{
    PAGED_CODE();

    ASSERT(STATUS_PENDING != Result);
    ASSERT(0 == (FSP_STATUS_PRIVATE_BIT & Result));

    if (0 != FspIrpRequest(Irp))
    {
        FspIopDeleteRequest(FspIrpRequest(Irp));
        FspIrpSetRequest(Irp, 0);
    }

    /* get the device object out of the IRP before completion */
    PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
    PDEVICE_OBJECT DeviceObject = IrpSp->DeviceObject;

    /*
     * HACK:
     *
     * We update the Create statistics here to avoid doing it in multiple places.
     */
    if (IRP_MJ_CREATE == IrpSp->MajorFunction)
    {
        /* only update statistics if we actually have a reference to the DeviceObject */
        if (DeviceDereference)
        {
            FSP_DEVICE_EXTENSION *DeviceExtension = FspDeviceExtension(DeviceObject);

            if (FspFsvolDeviceExtensionKind == FspDeviceExtension(DeviceObject)->Kind)
            {
                FSP_STATISTICS *Statistics = FspStatistics(
                    ((FSP_FSVOL_DEVICE_EXTENSION *)DeviceExtension)->Statistics);

                FspStatisticsInc(Statistics, Specific.CreateHits);
                if (STATUS_SUCCESS == Result)
                    FspStatisticsInc(Statistics, Specific.SuccessfulCreates);
                else
                    FspStatisticsInc(Statistics, Specific.FailedCreates);
            }
        }
    }

    if (STATUS_SUCCESS != Result &&
        STATUS_REPARSE != Result &&
        STATUS_OPLOCK_BREAK_IN_PROGRESS != Result &&
        STATUS_BUFFER_OVERFLOW != Result &&
        STATUS_SHARING_VIOLATION != Result)
        Irp->IoStatus.Information = 0;
    Irp->IoStatus.Status = Result;
    IoCompleteRequest(Irp, FSP_IO_INCREMENT);

    if (DeviceDereference)
        FspDeviceDereference(DeviceObject);
}
Esempio n. 2
0
NTSTATUS FspFsvolSetVolumeInformationComplete(
    PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response)
{
    FSP_ENTER_IOC(PAGED_CODE());

    if (!NT_SUCCESS(Response->IoStatus.Status))
    {
        Irp->IoStatus.Information = 0;
        Result = Response->IoStatus.Status;
        FSP_RETURN();
    }

    FS_INFORMATION_CLASS FsInformationClass = IrpSp->Parameters.SetVolume.FsInformationClass;
    PDEVICE_OBJECT FsvolDeviceObject = IrpSp->DeviceObject;
    PVOID Buffer = Irp->AssociatedIrp.SystemBuffer;
    ULONG Length = IrpSp->Parameters.SetFile.Length;
    FSP_FSCTL_TRANSACT_REQ *Request = FspIrpRequest(Irp);

    switch (FsInformationClass)
    {
    case FileFsLabelInformation:
        Result = FspFsvolSetFsLabelInformation(FsvolDeviceObject, Buffer, Length, 0, Request, Response);
        break;
    default:
        ASSERT(0);
        Result = STATUS_INVALID_PARAMETER;
        break;
    }

    Irp->IoStatus.Information = 0;

    FSP_LEAVE_IOC("%s",
        FsInformationClassSym(IrpSp->Parameters.SetVolume.FsInformationClass));
}
Esempio n. 3
0
FSP_FSCTL_TRANSACT_RSP *FspIopIrpResponse(PIRP Irp)
{
    PAGED_CODE();

    FSP_FSCTL_TRANSACT_REQ *Request = FspIrpRequest(Irp);
    FSP_FSCTL_TRANSACT_REQ_HEADER *RequestHeader = (PVOID)((PUINT8)Request - sizeof *RequestHeader);

    return RequestHeader->Response;
}
Esempio n. 4
0
VOID FspIopSetIrpResponse(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response)
{
    PAGED_CODE();

    FSP_FSCTL_TRANSACT_REQ *Request = FspIrpRequest(Irp);
    FSP_FSCTL_TRANSACT_REQ_HEADER *RequestHeader = (PVOID)((PUINT8)Request - sizeof *RequestHeader);

    ASSERT(0 != Request);

    if (0 != Response && RequestHeader->Response != Response)
    {
        if (0 != RequestHeader->Response)
            FspFree(RequestHeader->Response);
        RequestHeader->Response = FspAllocMustSucceed(Response->Size);
        RtlCopyMemory(RequestHeader->Response, Response, Response->Size);
        Response = RequestHeader->Response;
    }
}
Esempio n. 5
0
NTSTATUS FspFsvolSetSecurityComplete(
    PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response)
{
    FSP_ENTER_IOC(PAGED_CODE());

    if (!NT_SUCCESS(Response->IoStatus.Status))
    {
        Irp->IoStatus.Information = 0;
        Result = Response->IoStatus.Status;
        FSP_RETURN();
    }

    PFILE_OBJECT FileObject = IrpSp->FileObject;
    FSP_FILE_NODE *FileNode = FileObject->FsContext;
    FSP_FSCTL_TRANSACT_REQ *Request = FspIrpRequest(Irp);

    /* if the security descriptor that we got back is valid */
    if (0 < Response->Rsp.SetSecurity.SecurityDescriptor.Size &&
        Response->Buffer + Response->Rsp.SetSecurity.SecurityDescriptor.Size <=
            (PUINT8)Response + Response->Size &&
        RtlValidRelativeSecurityDescriptor((PVOID)Response->Buffer,
            Response->Rsp.SetSecurity.SecurityDescriptor.Size, 0))
    {
        /* update the cached security */
        FspFileNodeSetSecurity(FileNode,
            Response->Buffer, Response->Rsp.SetSecurity.SecurityDescriptor.Size);
    }
    else
    {
        /* invalidate the cached security */
        FspFileNodeSetSecurity(FileNode, 0, 0);
    }

    FspIopRequestContext(Request, RequestFileNode) = 0;
    FspFileNodeReleaseOwner(FileNode, Full, Request);

    Irp->IoStatus.Information = 0;
    Result = STATUS_SUCCESS;

    FSP_LEAVE_IOC("FileObject=%p, SecurityInformation=%x",
        IrpSp->FileObject, IrpSp->Parameters.SetSecurity.SecurityInformation);
}
Esempio n. 6
0
File: write.c Progetto: os12/winfsp
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;
}
Esempio n. 7
0
File: write.c Progetto: os12/winfsp
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;
}
Esempio n. 8
0
NTSTATUS FspIopCreateRequestFunnel(
    PIRP Irp, PUNICODE_STRING FileName, ULONG ExtraSize, FSP_IOP_REQUEST_FINI *RequestFini,
    ULONG Flags, FSP_FSCTL_TRANSACT_REQ **PRequest)
{
    PAGED_CODE();

    FSP_FSCTL_TRANSACT_REQ_HEADER *RequestHeader;
    FSP_FSCTL_TRANSACT_REQ_WORK_ITEM *RequestWorkItem = 0;
    FSP_FSCTL_TRANSACT_REQ *Request;

    *PRequest = 0;

    if (0 != FileName)
        ExtraSize += FSP_FSCTL_DEFAULT_ALIGN_UP(FileName->Length + sizeof(WCHAR));

    if (FSP_FSCTL_TRANSACT_REQ_SIZEMAX < sizeof *Request + ExtraSize)
        return STATUS_INVALID_PARAMETER;

    if (FlagOn(Flags, FspIopCreateRequestMustSucceedFlag))
    {
        RequestHeader = FspAllocatePoolMustSucceed(
            FlagOn(Flags, FspIopCreateRequestNonPagedFlag) ? NonPagedPool : PagedPool,
            sizeof *RequestHeader + sizeof *Request + ExtraSize + REQ_HEADER_ALIGN_OVERHEAD,
            FSP_ALLOC_INTERNAL_TAG);

        if (FlagOn(Flags, FspIopCreateRequestWorkItemFlag))
        {
            RequestWorkItem = FspAllocatePoolMustSucceed(
                NonPagedPool, sizeof *RequestWorkItem, FSP_ALLOC_INTERNAL_TAG);

            RtlZeroMemory(RequestWorkItem, sizeof *RequestWorkItem);
        }
    }
    else
    {
        RequestHeader = ExAllocatePoolWithTag(
            FlagOn(Flags, FspIopCreateRequestNonPagedFlag) ? NonPagedPool : PagedPool,
            sizeof *RequestHeader + sizeof *Request + ExtraSize + REQ_HEADER_ALIGN_OVERHEAD,
            FSP_ALLOC_INTERNAL_TAG);
        if (0 == RequestHeader)
            return STATUS_INSUFFICIENT_RESOURCES;

        if (FlagOn(Flags, FspIopCreateRequestWorkItemFlag))
        {
            RequestWorkItem = FspAllocNonPaged(sizeof *RequestWorkItem);
            if (0 == RequestWorkItem)
            {
                FspFree(RequestHeader);
                return STATUS_INSUFFICIENT_RESOURCES;
            }

            RtlZeroMemory(RequestWorkItem, sizeof *RequestWorkItem);
        }
    }

#if 0 != REQ_HEADER_ALIGN_MASK
    PVOID Allocation = RequestHeader;
    RequestHeader = (PVOID)(((UINT_PTR)RequestHeader + REQ_HEADER_ALIGN_OVERHEAD) &
        ~REQ_HEADER_ALIGN_MASK);
    ((PVOID *)RequestHeader)[-1] = Allocation;
#endif

    RtlZeroMemory(RequestHeader, sizeof *RequestHeader + sizeof *Request + ExtraSize);
    RequestHeader->RequestFini = RequestFini;
    RequestHeader->WorkItem = RequestWorkItem;

    Request = (PVOID)RequestHeader->RequestBuf;
    Request->Size = (UINT16)(sizeof *Request + ExtraSize);
    Request->Hint = (UINT_PTR)Irp;
    if (0 != FileName)
    {
        RtlCopyMemory(Request->Buffer, FileName->Buffer, FileName->Length);
        //Request->Buffer[FileName->Length] = '\0';
        //Request->Buffer[FileName->Length + 1] = '\0';
        //Request->FileName.Offset = 0;
        Request->FileName.Size = FileName->Length + sizeof(WCHAR);
    }

    ASSERT(0 == ((UINT_PTR)Request & (FSP_FSCTL_TRANSACT_REQ_ALIGNMENT - 1)));

    if (0 != Irp)
    {
        ASSERT(0 == FspIrpRequest(Irp));
        FspIrpSetRequest(Irp, Request);
    }
    *PRequest = Request;

    return STATUS_SUCCESS;
}
Esempio n. 9
0
NTSTATUS FspFsvolQuerySecurityComplete(
    PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response)
{
    FSP_ENTER_IOC(PAGED_CODE());

    if (!NT_SUCCESS(Response->IoStatus.Status))
    {
        Irp->IoStatus.Information = 0;
        Result = Response->IoStatus.Status;
        FSP_RETURN();
    }

    PFILE_OBJECT FileObject = IrpSp->FileObject;
    FSP_FILE_NODE *FileNode = FileObject->FsContext;
    SECURITY_INFORMATION SecurityInformation = IrpSp->Parameters.QuerySecurity.SecurityInformation;
    PVOID Buffer = Irp->AssociatedIrp.SystemBuffer;
    ULONG Length = IrpSp->Parameters.QuerySecurity.Length;
    PVOID SecurityBuffer = 0;
    FSP_FSCTL_TRANSACT_REQ *Request = FspIrpRequest(Irp);
    BOOLEAN Success;

    if (0 != FspIopRequestContext(Request, RequestFileNode))
    {
        /* check that the security descriptor we got back is valid */
        if (Response->Buffer + Response->Rsp.QuerySecurity.SecurityDescriptor.Size >
                (PUINT8)Response + Response->Size ||
            !RtlValidRelativeSecurityDescriptor((PVOID)Response->Buffer,
                Response->Rsp.QuerySecurity.SecurityDescriptor.Size, 0))
        {
            Irp->IoStatus.Information = 0;
            Result = STATUS_INVALID_SECURITY_DESCR;
            FSP_RETURN();
        }

        FspIopRequestContext(Request, RequestSecurityChangeNumber) = (PVOID)FileNode->SecurityChangeNumber;
        FspIopRequestContext(Request, RequestFileNode) = 0;

        FspFileNodeReleaseOwner(FileNode, Full, Request);
    }

    Success = DEBUGTEST(90) && FspFileNodeTryAcquireExclusive(FileNode, Main);
    if (!Success)
    {
        FspIopRetryCompleteIrp(Irp, Response, &Result);
        FSP_RETURN();
    }

    Success = !FspFileNodeTrySetSecurity(FileNode,
        Response->Buffer, Response->Rsp.QuerySecurity.SecurityDescriptor.Size,
        (ULONG)(UINT_PTR)FspIopRequestContext(Request, RequestSecurityChangeNumber));
    Success = Success && FspFileNodeReferenceSecurity(FileNode, &SecurityBuffer, 0);
    FspFileNodeRelease(FileNode, Main);
    if (Success)
    {
        Result = FspQuerySecurityDescriptorInfo(SecurityInformation, Buffer, &Length, SecurityBuffer);
        FspFileNodeDereferenceSecurity(SecurityBuffer);
    }
    else
    {
        SecurityBuffer = (PVOID)Response->Buffer;
        Result = FspQuerySecurityDescriptorInfo(SecurityInformation, Buffer, &Length, SecurityBuffer);
    }

    Irp->IoStatus.Information = Length;

    FSP_LEAVE_IOC("FileObject=%p, SecurityInformation=%x",
        IrpSp->FileObject, IrpSp->Parameters.QuerySecurity.SecurityInformation);
}