⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 file.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 5 页
字号:
            /* Make absolutely sure this is a device object */
            if (!(FileObject) || !(FileObject->Flags & FO_STREAM_FILE))
            {
                /* Assign the Security Descriptor */
                DeviceObject->SecurityDescriptor = SecurityDescriptor;
            }

            /* Return success */
            return STATUS_SUCCESS;
        }
        else
        {
            DPRINT1("FIXME: Set SD unimplemented for Devices\n");
            return STATUS_SUCCESS;
        }
    }
    else if (OperationCode == DeleteSecurityDescriptor)
    {
        /* Same as for devices, do nothing */
        return STATUS_SUCCESS;
    }

    /* At this point, we know we're a file. Reference it */
    ObReferenceObject(FileObject);

    /* Check if we should use Sync IO or not */
    if (FileObject->Flags & FO_SYNCHRONOUS_IO)
    {
        /* Lock the file object */
        IopLockFileObject(FileObject);
    }
    else
    {
        /* Use local event */
        KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
        LocalEvent = TRUE;
    }

    /* Clear the File Object event */
    KeClearEvent(&FileObject->Event);

    /* Get the device object */
    DeviceObject = IoGetRelatedDeviceObject(FileObject);

    /* Allocate the IRP */
    Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
    if (!Irp) return IopCleanupFailedIrp(FileObject, NULL, NULL);

    /* Set the IRP */
    Irp->Tail.Overlay.OriginalFileObject = FileObject;
    Irp->Tail.Overlay.Thread = PsGetCurrentThread();
    Irp->RequestorMode = ExGetPreviousMode();
    Irp->UserIosb = &IoStatusBlock;
    Irp->UserEvent = (LocalEvent) ? &Event : NULL;
    Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0;
    Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL;

    /* Set Stack Parameters */
    StackPtr = IoGetNextIrpStackLocation(Irp);
    StackPtr->FileObject = FileObject;

    /* Check if this is a query or set */
    if (OperationCode == QuerySecurityDescriptor)
    {
        /* Set the major function and parameters */
        StackPtr->MajorFunction = IRP_MJ_QUERY_SECURITY;
        StackPtr->Parameters.QuerySecurity.SecurityInformation =
            *SecurityInformation;
        StackPtr->Parameters.QuerySecurity.Length = *BufferLength;
        Irp->UserBuffer = SecurityDescriptor;
    }
    else
    {
        /* Set the major function and parameters for a set */
        StackPtr->MajorFunction = IRP_MJ_SET_SECURITY;
        StackPtr->Parameters.SetSecurity.SecurityInformation =
            *SecurityInformation;
        StackPtr->Parameters.SetSecurity.SecurityDescriptor =
            SecurityDescriptor;
    }

    /* Queue the IRP */
    IopQueueIrpToThread(Irp);

    /* Update operation counts */
    IopUpdateOperationCount(IopOtherTransfer);

    /* Call the Driver */
    Status = IoCallDriver(DeviceObject, Irp);

    /* Check if this was async I/O */
    if (LocalEvent)
    {
        /* Check if the IRP is pending completion */
        if (Status == STATUS_PENDING)
        {
            /* Wait on the local event */
            KeWaitForSingleObject(&Event,
                                  Executive,
                                  KernelMode,
                                  FALSE,
                                  NULL);
            Status = IoStatusBlock.Status;
        }
    }
    else
    {
        /* Check if the IRP is pending completion */
        if (Status == STATUS_PENDING)
        {
            /* Wait on the file object */
            KeWaitForSingleObject(&FileObject->Event,
                                  Executive,
                                  KernelMode,
                                  FALSE,
                                  NULL);
            Status = FileObject->FinalStatus;
        }

        /* Release the lock */
        IopUnlockFileObject(FileObject);
    }

    /* This Driver doesn't implement Security, so try to give it a default */
    if (Status == STATUS_INVALID_DEVICE_REQUEST)
    {
        /* Was this a query? */
        if (OperationCode == QuerySecurityDescriptor)
        {
            /* Set a World Security Descriptor */
            Status = SeSetWorldSecurityDescriptor(*SecurityInformation,
                                                  SecurityDescriptor,
                                                  BufferLength);
        }
        else
        {
            /* It wasn't a query, so just fake success */
            Status = STATUS_SUCCESS;
        }
    }
    else if (OperationCode == QuerySecurityDescriptor)
    {
        /* Callers usually expect the normalized form */
        if (Status == STATUS_BUFFER_OVERFLOW) Status = STATUS_BUFFER_TOO_SMALL;

        /* Return length */
        *BufferLength = IoStatusBlock.Information;
    }

    /* Return Status */
    return Status;
}

NTSTATUS
NTAPI
IopQueryNameFile(IN PVOID ObjectBody,
                 IN BOOLEAN HasName,
                 OUT POBJECT_NAME_INFORMATION ObjectNameInfo,
                 IN ULONG Length,
                 OUT PULONG ReturnLength,
                 IN KPROCESSOR_MODE PreviousMode)
{
    POBJECT_NAME_INFORMATION LocalInfo;
    PFILE_NAME_INFORMATION LocalFileInfo;
    PFILE_OBJECT FileObject = (PFILE_OBJECT)ObjectBody;
    ULONG LocalReturnLength, FileLength;
    NTSTATUS Status;
    PWCHAR p;
    IOTRACE(IO_FILE_DEBUG, "ObjectBody: %p\n", ObjectBody);

    /* Validate length */
    if (Length < sizeof(OBJECT_NAME_INFORMATION))
    {
        /* Wrong length, fail */
        return STATUS_INFO_LENGTH_MISMATCH;
    }

    /* Allocate Buffer */
    LocalInfo = ExAllocatePoolWithTag(PagedPool, Length, TAG_IO);
    if (!LocalInfo) return STATUS_INSUFFICIENT_RESOURCES;

    /* Query the name */
    Status = ObQueryNameString(FileObject->DeviceObject,
                               LocalInfo,
                               Length,
                               &LocalReturnLength);
    if (!NT_SUCCESS(Status))
    {
        /* Free the buffer and fail */
        ExFreePool(LocalInfo);
        return Status;
    }

    /* Copy the information */
    RtlCopyMemory(ObjectNameInfo,
                  LocalInfo,
                  (LocalReturnLength > Length) ?
                  Length : LocalReturnLength);

    /* Set buffer pointer */
    p = (PWCHAR)(ObjectNameInfo + 1);
    ObjectNameInfo->Name.Buffer = p;

    /* Advance in buffer */
    p += (LocalInfo->Name.Length / sizeof(WCHAR));

    /* Check if this already filled our buffer */
    if (LocalReturnLength > Length)
    {
        /* Free the buffer and fail */
        ExFreePool(LocalInfo);
        return STATUS_BUFFER_OVERFLOW;
    }

    /* Now get the file name buffer and check the length needed */
    LocalFileInfo = (PFILE_NAME_INFORMATION)LocalInfo;
    FileLength = Length -
                 LocalReturnLength +
                 FIELD_OFFSET(FILE_NAME_INFORMATION, FileName);

    /* Query the File name */
    Status = IoQueryFileInformation(FileObject,
                                    FileNameInformation,
                                    FileLength,
                                    LocalFileInfo,
                                    &LocalReturnLength);
    if (NT_ERROR(Status))
    {
        /* Fail on errors only, allow warnings */
        ExFreePool(LocalInfo);
        return Status;
    }

    /* ROS HACK. VFAT SUCKS */
    if (NT_WARNING(Status)) LocalReturnLength = FileLength;

    /* Now calculate the new lengths left */
    FileLength = LocalReturnLength -
                 FIELD_OFFSET(FILE_NAME_INFORMATION, FileName);
    LocalReturnLength = (ULONG_PTR)p -
                        (ULONG_PTR)ObjectNameInfo +
                        LocalFileInfo->FileNameLength;

    /* Write the Name and null-terminate it */
    RtlCopyMemory(p, LocalFileInfo->FileName, FileLength);
    p += (FileLength / sizeof(WCHAR));
    *p = UNICODE_NULL;
    LocalReturnLength += sizeof(UNICODE_NULL);

    /* Return the length needed */
    *ReturnLength = LocalReturnLength;

    /* Setup the length and maximum length */
    FileLength = (ULONG_PTR)p - (ULONG_PTR)ObjectNameInfo;
    ObjectNameInfo->Name.Length = (USHORT)FileLength -
                                          sizeof(OBJECT_NAME_INFORMATION);
    ObjectNameInfo->Name.MaximumLength = (USHORT)ObjectNameInfo->Name.Length +
                                                 sizeof(UNICODE_NULL);

    /* Free buffer and return */
    ExFreePool(LocalInfo);
    return Status;
}

VOID
NTAPI
IopCloseFile(IN PEPROCESS Process OPTIONAL,
             IN PVOID ObjectBody,
             IN ACCESS_MASK GrantedAccess,
             IN ULONG HandleCount,
             IN ULONG SystemHandleCount)
{
    PFILE_OBJECT FileObject = (PFILE_OBJECT)ObjectBody;
    KEVENT Event;
    PIRP Irp;
    PIO_STACK_LOCATION StackPtr;
    NTSTATUS Status;
    PDEVICE_OBJECT DeviceObject;
    KIRQL OldIrql;
    IOTRACE(IO_FILE_DEBUG, "ObjectBody: %p\n", ObjectBody);

    /* If this isn't the last handle for the current process, quit */
    if (HandleCount != 1) return;

    /* Check if the file is locked and has more then one handle opened */
    if ((FileObject->LockOperation) && (SystemHandleCount != 1))
    {
        DPRINT1("We need to unlock this file!\n");
        KEBUGCHECK(0);
    }

    /* Make sure this is the last handle */
    if (SystemHandleCount != 1) return;

    /* Check if this is a direct open or not */
    if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
    {
        /* Get the attached device */
        DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
    }
    else
    {
        /* Get the FO's device */
        DeviceObject = IoGetRelatedDeviceObject(FileObject);
    }

    /* Set the handle created flag */
    FileObject->Flags |= FO_HANDLE_CREATED;

    /* Check if this is a sync FO and lock it */
    if (FileObject->Flags & FO_SYNCHRONOUS_IO) IopLockFileObject(FileObject);

    /* Clear and set up Events */
    KeClearEvent(&FileObject->Event);
    KeInitializeEvent(&Event, SynchronizationEvent, FALSE);

    /* Allocate an IRP */
    Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
    if (!Irp) return;

    /* Set it up */
    Irp->UserEvent = &Event;
    Irp->UserIosb = &Irp->IoStatus;
    Irp->Tail.Overlay.Thread = PsGetCurrentThread();
    Irp->Tail.Overlay.OriginalFileObject = FileObject;
    Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL;
    Irp->Flags = IRP_CLOSE_OPERATION | IRP_SYNCHRONOUS_API;

    /* Set up Stack Pointer Data */
    StackPtr = IoGetNextIrpStackLocation(Irp);
    StackPtr->MajorFunction = IRP_MJ_CLEANUP;
    StackPtr->FileObject = FileObject;

    /* Queue the IRP */
    IopQueueIrpToThread(Irp);

    /* Update operation counts */
    IopUpdateOperationCount(IopOtherTransfer);

    /* Call the FS Driver */
    Status = IoCallDriver(DeviceObject, Irp);
    if (Status == STATUS_PENDING)
    {
        /* Wait for completion */
        KeWaitForSingleObject(&Event, UserRequest, KernelMode, FALSE, NULL);
    }

    /* Unqueue the IRP */
    KeRaiseIrql(APC_LEVEL, &OldIrql);
    IopUnQueueIrpFromThread(Irp);
    KeLowerIrql(OldIrql);

    /* Free the IRP */
    IoFreeIrp(Irp);

    /* Release the lock if we were holding it */
    if (FileObject->Flags & FO_SYNCHRONOUS_IO) IopUnlockFileObject(FileObject);
}

NTSTATUS
NTAPI
IopQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes,
                       IN FILE_INFORMATION_CLASS FileInformationClass,
                       IN ULONG FileInformationSize,
                       OUT PVOID FileInformation)
{
    NTSTATUS Status = STATUS_SUCCESS;
    KPROCESSOR_MODE AccessMode = ExGetPreviousMode();
    DUMMY_FILE_OBJECT DummyFileObject;
    FILE_NETWORK_OPEN_INFORMATION NetworkOpenInfo;
    HANDLE Handle;
    OPEN_PACKET OpenPacket;
    BOOLEAN IsBasic;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -