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

📄 kfc.c

📁 操作系统引导的一些介绍,对学习引导的有很大的帮助与提高
💻 C
📖 第 1 页 / 共 2 页
字号:
//
// (C) Copyright 1996 OSR Open Systems Resources, Inc.
// All Rights Reserved
//
// Permission to use this code is granted provided that the OSR
// copyright is retained in the original source code and that
// the OSR copyright is displayed anywhere a copyright notice is
// displayed for the product in which this code is used.
//

//
// This sample program demonstrates how to copy data between two
// files.
//

#include "kfc.h"

//
// Forward declarations
//

static NTSTATUS KfcCreateClose(PDEVICE_OBJECT, PIRP);
static NTSTATUS KfcDeviceControl(PDEVICE_OBJECT, PIRP);
static NTSTATUS KfcCopyFile(PFILE_OBJECT, PFILE_OBJECT);
static VOID KfcGetFileStandardInformation(PFILE_OBJECT, PFILE_STANDARD_INFORMATION, PIO_STATUS_BLOCK);
static VOID KfcRead(PFILE_OBJECT, PLARGE_INTEGER, ULONG, PMDL, PIO_STATUS_BLOCK);
static VOID KfcWrite(PFILE_OBJECT, PLARGE_INTEGER, ULONG, PMDL, PIO_STATUS_BLOCK);
static VOID KfcSetFileAllocation(PFILE_OBJECT, PLARGE_INTEGER, PIO_STATUS_BLOCK);
static VOID KfcUnload(PDRIVER_OBJECT);
static NTSTATUS KfcIoCompletion(PDEVICE_OBJECT, PIRP, PVOID);

//
// Internal constants
//

#define KFC_MAX_TRANSFER_SIZE (0x10000)
#define KFC_DEVICE_NAME L"\\Device\\OsrKfc"
#define KFC_DOS_NAME L"\\DosDevices\\OsrKfc"

//
// DriverEntry
//
//  This is the entry point for the driver, responsible for initializing the
//  data structures used by the driver, setting up the driver object and
//  preparing for normal operation.
//
// Inputs:
//  DriverObject - the driver object representing THIS driver.  This is
//                  created by the I/O Manager when our driver loads.
//
//  RegistryPath - A pointer to the registry path to the key for this driver.
//
//
// Outputs:
//  None.
//
// Context:
//  Like all driver entry routines, this routine is called in the context
//  of the system process.
//

NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
    UNICODE_STRING deviceName;
    UNICODE_STRING dosDeviceName;
    PDEVICE_OBJECT deviceObject;
    NTSTATUS status;
    
    DbgPrint("KFC Driver Entry called\n");
    
    
    RtlInitUnicodeString(&deviceName, KFC_DEVICE_NAME);
    
    
    //
    // Create a named device object for the KFC device. This will allow
    // communications with the KFC driver.
    //
    
    status = IoCreateDevice(DriverObject,
                            0,
                            &deviceName,
                            FILE_DEVICE_UNKNOWN,
                            0,
                            FALSE,
                            &deviceObject);
    
    if (!NT_SUCCESS(status)) {
        //
        // Indicate the error
        //
        
        DbgPrint("IoCreateDevice failed 0x%x\n", status);
        
        return status;
        
    }
    
    //
    // Create a symbolic link into the DosDevices area to allow access
    // to Win32 applications.
    //
    
    RtlInitUnicodeString(&dosDeviceName, KFC_DOS_NAME);
    
    status = IoCreateSymbolicLink(&dosDeviceName, &deviceName);
    
    if (!NT_SUCCESS(status)) {
        //
        // Indicate the error
        //
        
        DbgPrint("IoCreateSymbolicLink failed 0x%x\n", status);
        
        IoDeleteDevice(deviceObject);
        
        return status;
        
    }
    
    
    //
    // Overwrite the driver dispatch entry points this driver will
    // implement.  Remember that the others all point to the "trivial"
    // function that returns STATUS_NOT_IMPLEMENTED.
    //
    
    DriverObject->MajorFunction[IRP_MJ_CREATE] = KfcCreateClose;
    
    DriverObject->MajorFunction[IRP_MJ_CLOSE] = KfcCreateClose;
    
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = KfcDeviceControl;
    
    //
    // Set up the unload function
    //
    
    DriverObject->DriverUnload = KfcUnload;
    
    
    //
    // We are done. Note that if you wanted to export the functionality of
    // this driver to Win32 applications, this would be the IDEAL place to
    // add a symbolic link.  We skip that step for this example, since the
    // samke kfcopy application will use the native NT interface instead.
    //
    
    return STATUS_SUCCESS;
}

//
// KfcUnload
//
//  This routine is called to unload the driver.
//
// Inputs:
//  DriverObject - the driver object for this driver
//
// Outputs:
//  None.
//
// Returns:
//  None.
//
// Notes:
//  None.

static VOID KfcUnload(PDRIVER_OBJECT DriverObject)
{
    UNICODE_STRING symLinkName;
    
    //
    // First, delete the symbolic link.
    //
    
    RtlInitUnicodeString(&symLinkName, KFC_DOS_NAME);
    
    IoDeleteSymbolicLink(&symLinkName);
    
    //
    // Now, delete the device object.
    //
    
    IoDeleteDevice(DriverObject->DeviceObject);
    
    //
    // Done!
    //
    
    return;
}




//
// KfcCreateClose
//
//

static NTSTATUS KfcCreateClose(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
    
    Irp->IoStatus.Status = STATUS_SUCCESS;
    
    Irp->IoStatus.Information = 0;
    
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    
    return STATUS_SUCCESS;
    
}



//
// KfcDeviceControl
//

static NTSTATUS KfcDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
    PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
    PHANDLE fileHandles;
    PFILE_OBJECT source, target;
    NTSTATUS status;
    
    switch(irpSp->Parameters.DeviceIoControl.IoControlCode) {
        
    case KFC_COPY_FILE:
        //
        // Extract the file handles
        //
        
        if (irpSp->Parameters.DeviceIoControl.InputBufferLength < 2 * sizeof(PHANDLE)) {
            
            //
            // The buffer is not large enough to contain the file handles.
            //
            
            Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
            
            Irp->IoStatus.Information = 0;
            
            break;
        }
        
        fileHandles = (PHANDLE)Irp->AssociatedIrp.SystemBuffer;
        
        status = ObReferenceObjectByHandle(fileHandles[0],
                                           FILE_READ_ACCESS, // ACCESS_MASK
                                           *IoFileObjectType, // POBJECT_TYPE
                                           UserMode, // Access mode
                                           &source, // output file object
                                           0);
        
        if (!NT_SUCCESS(status)) {
            
            Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
            
            Irp->IoStatus.Information = 0;
            
            break;
            
        }
        
        status = ObReferenceObjectByHandle(fileHandles[1],
                                           FILE_WRITE_ACCESS, // ACCESS_MASK
                                           *IoFileObjectType,
                                           UserMode,
                                           &target,
                                           0);
        
        if (!NT_SUCCESS(status)) {
            
            //
            // Failure to dereference the object will cause file object leakage in
            // the system.
            //
            
            ObDereferenceObject(source);
            
            //
            // Fail the request.
            //
            
            Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
            
            Irp->IoStatus.Information = 0;
            
            break;
            
        }
        
        //
        // If we get to this point, we perform the copy.
        //
        
        Irp->IoStatus.Status = KfcCopyFile(target, source);
        
        Irp->IoStatus.Information = 0;
        
        //
        // Now release the file object references
        //
        
        ObDereferenceObject(source);
        
        ObDereferenceObject(target);
        
        break;
        
    default:
        Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
        
        Irp->IoStatus.Information = 0;
        
    }
    
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    
    return STATUS_SUCCESS;
    
}



//
// KfcCopyFile
//
//  This routine implements the fast file copy code.
//
// Inputs:
//  TargetFileObject - copying TO
//  SourceFileObject - copying FROM
//
// Outputs:
//  None.
//
// Returns:
//  SUCCESS when it works, otherwise an appropriate error
//
// Notes:
//  None.
//

static NTSTATUS KfcCopyFile(PFILE_OBJECT TargetFileObject, PFILE_OBJECT SourceFileObject)
{
    PVOID buffer;
    PMDL mdl;
    IO_STATUS_BLOCK iosb;
    FILE_STANDARD_INFORMATION standardInformation;
    LARGE_INTEGER currentOffset;
    LONGLONG bytesToTransfer;
    
    
    //
    // The algorithm used by this routine is straight-forward: read 64k chunks from the
    // source file and write it to the target file, until the entire file itself has been copied.
    //
    
    buffer = ExAllocatePoolWithTag(NonPagedPool,
                                   KFC_MAX_TRANSFER_SIZE,
                                   'BcfK');
    
    
    if (!buffer) {
        //
        // Allocation must have failed.
        //
        
        return STATUS_INSUFFICIENT_RESOURCES;
        
    }
    
    //
    // Build an MDL describing the buffer.  We'll use THAT to do the
    // I/O (rather than a direct buffer address.)
    //
    
    mdl = IoAllocateMdl(buffer, KFC_MAX_TRANSFER_SIZE, FALSE, TRUE, 0);
    
    MmBuildMdlForNonPagedPool(mdl);
    
    //
    // Set up the current offset information
    //
    
    currentOffset.QuadPart = 0;
    
    //
    // Get the size of the input file.
    //
    
    KfcGetFileStandardInformation(SourceFileObject, &standardInformation, &iosb);
    
    if (!NT_SUCCESS(iosb.Status)) {
        //
        // This is a failure condition.
        //
        
        return (iosb.Status);
        
    }
    
    //
    // Set the allocation size of the output file.
    //
    
    KfcSetFileAllocation(TargetFileObject,
                         &standardInformation.AllocationSize,
                         &iosb);
    
    if (!NT_SUCCESS(iosb.Status)) {
        
        //
        // Failure...
        //
        
        return (iosb.Status);
        
    }
    
    //
    // Save away the information about the # of bytes to transfer.
    //
    
    bytesToTransfer = standardInformation.EndOfFile.QuadPart;
    
    //
    // Now copy the source to the target until we run out...
    //
    
    while (bytesToTransfer) {
        ULONG nextTransferSize;
        
        //
        // The # of bytes to copy in the next operation is based upon the maximum of
        // the balance IN the file, or KFC_MAX_TRANSFER_SIZE
        //
        
        nextTransferSize = (bytesToTransfer < KFC_MAX_TRANSFER_SIZE) ?
            (ULONG) bytesToTransfer : KFC_MAX_TRANSFER_SIZE;
        
        KfcRead(SourceFileObject, &currentOffset, nextTransferSize, mdl, &iosb);
        
        if (!NT_SUCCESS(iosb.Status)) {
            
            //
            // An error condition occurred.
            //
            
            return (iosb.Status);
            
        }
        
        KfcWrite(TargetFileObject, &currentOffset, nextTransferSize, mdl, &iosb);
        
        if (!NT_SUCCESS(iosb.Status)) {
            
            //
            // An error condition occurred.
            //
            
            return (iosb.Status);
            
        }
        
        //
        // Now, update the offset/bytes to transfer information
        //
        
        currentOffset.QuadPart += nextTransferSize;
        
        bytesToTransfer -= nextTransferSize;
        
    }
    
    //
    // At this point, we're done with the copy operation.  Return success
    // 
    
    return (STATUS_SUCCESS);
}



//
// KfcGetFileStandardInformation
//

⌨️ 快捷键说明

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