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

📄 file.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 5 页
字号:
/*
 * PROJECT:         ReactOS Kernel
 * LICENSE:         GPL - See COPYING in the top level directory
 * FILE:            ntoskrnl/io/file.c
 * PURPOSE:         Functions that deal with managing the FILE_OBJECT itself.
 * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
 *                  Gunnar Dalsnes
 *                  Eric Kohl
 *                  Filip Navara (navaraf@reactos.org)
 */

/* INCLUDES *****************************************************************/

#include <ntoskrnl.h>
#define NDEBUG
#include <debug.h>

/* PRIVATE FUNCTIONS *********************************************************/

VOID
NTAPI
IopCheckBackupRestorePrivilege(IN PACCESS_STATE AccessState,
                               IN OUT PULONG CreateOptions,
                               IN KPROCESSOR_MODE PreviousMode,
                               IN ULONG Disposition)
{
    ACCESS_MASK DesiredAccess, ReadAccess, WriteAccess;
    PRIVILEGE_SET Privileges;
    BOOLEAN AccessGranted, HaveBackupPriv = FALSE, CheckRestore = FALSE;
    PAGED_CODE();

    /* Don't do anything if privileges were checked already */
    if (AccessState->Flags & SE_BACKUP_PRIVILEGES_CHECKED) return;

    /* Check if the file was actually opened for backup purposes */
    if (*CreateOptions & FILE_OPEN_FOR_BACKUP_INTENT)
    {
        /* Set the check flag since were doing it now */
        AccessState->Flags |= SE_BACKUP_PRIVILEGES_CHECKED;

        /* Set the access masks required */
        ReadAccess = READ_CONTROL |
                     ACCESS_SYSTEM_SECURITY |
                     FILE_GENERIC_READ |
                     FILE_TRAVERSE;
        WriteAccess = WRITE_DAC |
                      WRITE_OWNER |
                      ACCESS_SYSTEM_SECURITY |
                      FILE_GENERIC_WRITE |
                      FILE_ADD_FILE |
                      FILE_ADD_SUBDIRECTORY |
                      DELETE;
        DesiredAccess = AccessState->RemainingDesiredAccess;

        /* Check if desired access was the maximum */
        if (DesiredAccess & MAXIMUM_ALLOWED)
        {
            /* Then add all the access masks required */
            DesiredAccess |= (ReadAccess | WriteAccess);
        }

        /* Check if the file already exists */
        if (Disposition & FILE_OPEN)
        {
            /* Check if desired access has the read mask */
            if (ReadAccess & DesiredAccess)
            {
                /* Setup the privilege check lookup */
                Privileges.PrivilegeCount = 1;
                Privileges.Control = PRIVILEGE_SET_ALL_NECESSARY;
                Privileges.Privilege[0].Luid = SeBackupPrivilege;
                Privileges.Privilege[0].Attributes = 0;
                AccessGranted = SePrivilegeCheck(&Privileges,
                                                 &AccessState->
                                                 SubjectSecurityContext,
                                                 PreviousMode);
                if (AccessGranted)
                {
                    /* Remember that backup was allowed */
                    HaveBackupPriv = TRUE;

                    /* Append the privileges and update the access state */
                    SeAppendPrivileges(AccessState, &Privileges);
                    AccessState->PreviouslyGrantedAccess |= (DesiredAccess & ReadAccess);
                    AccessState->RemainingDesiredAccess &= ~ReadAccess;
                    DesiredAccess &= ~ReadAccess;

                    /* Set backup privilege for the token */
                    AccessState->Flags |= TOKEN_HAS_BACKUP_PRIVILEGE;
                }
            }
        }
        else
        {
            /* Caller is creating the file, check restore privileges later */
            CheckRestore = TRUE;
        }

        /* Check if caller wants write access or if it's creating a file */
        if ((WriteAccess & DesiredAccess) || (CheckRestore))
        {
            /* Setup the privilege lookup and do it */
            Privileges.PrivilegeCount = 1;
            Privileges.Control = PRIVILEGE_SET_ALL_NECESSARY;
            Privileges.Privilege[0].Luid = SeRestorePrivilege;
            Privileges.Privilege[0].Attributes = 0;
            AccessGranted = SePrivilegeCheck(&Privileges,
                                             &AccessState->SubjectSecurityContext,
                                             PreviousMode);
            if (AccessGranted)
            {
                /* Remember that privilege was given */
                HaveBackupPriv = TRUE;

                /* Append the privileges and update the access state */
                SeAppendPrivileges(AccessState, &Privileges);
                AccessState->PreviouslyGrantedAccess |= (DesiredAccess & WriteAccess);
                AccessState->RemainingDesiredAccess &= ~WriteAccess;

                /* Set restore privilege for the token */
                AccessState->Flags |= TOKEN_HAS_RESTORE_PRIVILEGE;
            }
        }

        /* If we don't have the privilege, remove the option */
        if (!HaveBackupPriv) *CreateOptions &= ~FILE_OPEN_FOR_BACKUP_INTENT;
    }
}

NTSTATUS
NTAPI
IopCheckDeviceAndDriver(IN POPEN_PACKET OpenPacket,
                        IN PDEVICE_OBJECT DeviceObject)
{
    /* Make sure the object is valid */
    if ((IoGetDevObjExtension(DeviceObject)->ExtensionFlags &
        (DOE_UNLOAD_PENDING |
         DOE_DELETE_PENDING |
         DOE_REMOVE_PENDING |
         DOE_REMOVE_PROCESSED)) ||
        (DeviceObject->Flags & DO_DEVICE_INITIALIZING))
    {
        /* It's unloading or initializing, so fail */
        DPRINT1("You are seeing this because the following ROS driver: %wZ\n"
                " sucks. Please fix it's AddDevice Routine\n",
                &DeviceObject->DriverObject->DriverName);
        return STATUS_NO_SUCH_DEVICE;
    }
    else if ((DeviceObject->Flags & DO_EXCLUSIVE) &&
             (DeviceObject->ReferenceCount) &&
             !(OpenPacket->RelatedFileObject) &&
             !(OpenPacket->Options & IO_ATTACH_DEVICE))
    {
        return STATUS_ACCESS_DENIED;
    }

    else
    {
        /* Increase reference count */
        DeviceObject->ReferenceCount++;
        return STATUS_SUCCESS;
    }
}

NTSTATUS
NTAPI
IopParseDevice(IN PVOID ParseObject,
               IN PVOID ObjectType,
               IN OUT PACCESS_STATE AccessState,
               IN KPROCESSOR_MODE AccessMode,
               IN ULONG Attributes,
               IN OUT PUNICODE_STRING CompleteName,
               IN OUT PUNICODE_STRING RemainingName,
               IN OUT PVOID Context OPTIONAL,
               IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL,
               OUT PVOID *Object)
{
    POPEN_PACKET OpenPacket = (POPEN_PACKET)Context;
    PDEVICE_OBJECT OriginalDeviceObject = (PDEVICE_OBJECT)ParseObject;
    PDEVICE_OBJECT DeviceObject, OwnerDevice;
    NTSTATUS Status;
    PFILE_OBJECT FileObject;
    PVPB Vpb = NULL;
    PIRP Irp;
    PEXTENDED_IO_STACK_LOCATION StackLoc;
    IO_SECURITY_CONTEXT SecurityContext;
    IO_STATUS_BLOCK IoStatusBlock;
    BOOLEAN DirectOpen = FALSE, OpenCancelled, UseDummyFile;
    OBJECT_ATTRIBUTES ObjectAttributes;
    KIRQL OldIrql;
    PDUMMY_FILE_OBJECT DummyFileObject;
    PFILE_BASIC_INFORMATION FileBasicInfo;
    ULONG ReturnLength;
    KPROCESSOR_MODE CheckMode;
    BOOLEAN VolumeOpen = FALSE;
    ACCESS_MASK DesiredAccess, GrantedAccess;
    BOOLEAN AccessGranted, LockHeld = FALSE;
    PPRIVILEGE_SET Privileges = NULL;
    IOTRACE(IO_FILE_DEBUG, "ParseObject: %p. RemainingName: %wZ\n",
            ParseObject, RemainingName);

    /* Assume failure */
    *Object = NULL;

    /* Validate the open packet */
    if (!IopValidateOpenPacket(OpenPacket)) return STATUS_OBJECT_TYPE_MISMATCH;

    /* Check if we have a related file object */
    if (OpenPacket->RelatedFileObject)
    {
        /* Use the related file object's device object */
        OriginalDeviceObject = OpenPacket->RelatedFileObject->DeviceObject;
    }

    /* Validate device status */
    Status = IopCheckDeviceAndDriver(OpenPacket, OriginalDeviceObject);
    if (!NT_SUCCESS(Status))
    {
        /* We failed, return status */
        OpenPacket->FinalStatus = Status;
        return Status;
    }

    /* Map the generic mask and set the new mapping in the access state */
    RtlMapGenericMask(&AccessState->RemainingDesiredAccess,
                      &IoFileObjectType->TypeInfo.GenericMapping);
    RtlMapGenericMask(&AccessState->OriginalDesiredAccess,
                      &IoFileObjectType->TypeInfo.GenericMapping);
    SeSetAccessStateGenericMapping(AccessState,
                                   &IoFileObjectType->TypeInfo.GenericMapping);
    DesiredAccess = AccessState->RemainingDesiredAccess;

    /* Check what kind of access checks to do */
    if ((AccessMode != KernelMode) ||
        (OpenPacket->Options & IO_FORCE_ACCESS_CHECK))
    {
        /* Call is from user-mode or kernel is forcing checks */
        CheckMode = UserMode;
    }
    else
    {
        /* Call is from the kernel */
        CheckMode = KernelMode;
    }

    /* Check privilege for backup or restore operation */
    IopCheckBackupRestorePrivilege(AccessState,
                                   &OpenPacket->CreateOptions,
                                   CheckMode,
                                   OpenPacket->Disposition);

    /* Check if we are re-parsing */
    if (((OpenPacket->Override) && !(RemainingName->Length)) ||
        (AccessState->Flags & SE_BACKUP_PRIVILEGES_CHECKED))
    {
        /* Get granted access from the last call */
        DesiredAccess |= AccessState->PreviouslyGrantedAccess;
    }

    /* Check if this is a volume open */
    if ((OpenPacket->RelatedFileObject) &&
        (OpenPacket->RelatedFileObject->Flags & FO_VOLUME_OPEN) &&
        !(RemainingName->Length))
    {
        /* It is */
        VolumeOpen = TRUE;
    }

    /* Now check if we need access checks */
    if (((AccessMode != KernelMode) ||
         (OpenPacket->Options & IO_FORCE_ACCESS_CHECK)) &&
        (!(OpenPacket->RelatedFileObject) || (VolumeOpen)) &&
        !(OpenPacket->Override))
    {
        /* Check if a device object is being parsed  */
        if (!RemainingName->Length)
        {
            /* Lock the subject context */
            SeLockSubjectContext(&AccessState->SubjectSecurityContext);
            LockHeld = TRUE;

            /* Do access check */
            AccessGranted = SeAccessCheck(OriginalDeviceObject->
                                          SecurityDescriptor,
                                          &AccessState->SubjectSecurityContext,
                                          LockHeld,
                                          DesiredAccess,
                                          0,
                                          &Privileges,
                                          &IoFileObjectType->
                                          TypeInfo.GenericMapping,
                                          UserMode,
                                          &GrantedAccess,
                                          &Status);
            if (Privileges)
            {
                /* Append and free the privileges */
                SeAppendPrivileges(AccessState, Privileges);
                SeFreePrivileges(Privileges);
            }

            /* Check if we got access */
            if (AccessGranted)
            {
                /* Update access state */
                AccessState->PreviouslyGrantedAccess |= GrantedAccess;
                AccessState->RemainingDesiredAccess &= ~(GrantedAccess &
                                                         MAXIMUM_ALLOWED);
                OpenPacket->Override= TRUE;
            }

            /* FIXME: Do Audit/Alarm for open operation */
        }
        else
        {
            /* Check if we need to do traverse validation */
            if (!(AccessState->Flags & TOKEN_HAS_TRAVERSE_PRIVILEGE) ||
                ((OriginalDeviceObject->DeviceType == FILE_DEVICE_DISK) ||
                 (OriginalDeviceObject->DeviceType == FILE_DEVICE_CD_ROM)))
            {
                /* Check if this is a restricted token */
                if (!(AccessState->Flags & TOKEN_IS_RESTRICTED))
                {
                    /* FIXME: Do the FAST traverse check */
                    AccessGranted = FALSE;
                }
                else
                {
                    /* Fail */
                    AccessGranted = FALSE;
                }

                /* Check if we failed to get access */
                if (!AccessGranted)
                {
                    /* Lock the subject context */
                    SeLockSubjectContext(&AccessState->SubjectSecurityContext);
                    LockHeld = TRUE;

                    /* Do access check */
                    AccessGranted = SeAccessCheck(OriginalDeviceObject->
                                                  SecurityDescriptor,
                                                  &AccessState->SubjectSecurityContext,
                                                  LockHeld,
                                                  FILE_TRAVERSE,
                                                  0,
                                                  &Privileges,
                                                  &IoFileObjectType->
                                                  TypeInfo.GenericMapping,
                                                  UserMode,
                                                  &GrantedAccess,
                                                  &Status);
                    if (Privileges)
                    {
                        /* Append and free the privileges */
                        SeAppendPrivileges(AccessState, Privileges);
                        SeFreePrivileges(Privileges);
                    }
                }

                /* FIXME: Do Audit/Alarm for traverse check */
            }
            else
            {
                /* Access automatically granted */
                AccessGranted = TRUE;
            }
        }

        /* Check if we hold the lock */
        if (LockHeld)
        {
            /* Release it */

⌨️ 快捷键说明

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