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

📄 ramdisk.c

📁 本软件是一款可以把内存模拟为硬盘的驱动程序.
💻 C
📖 第 1 页 / 共 3 页
字号:
/*++

Copyright (c) 1990-2000 Microsoft Corporation, All Rights Reserved
Copyright (c)      2002 QSoft                                     

Module Name:

    Ramdisk.c

Abstract:

    This is the Ramdisk sample driver.

Author:

    Robert Nelson (RobertN) 10-Mar-1993.

Environment:

    Kernel mode only.

Notes:
    If the device is not ready, queue the I/O IRPs instead of rejecting

Revision History:
    Added the IOCTL_DISK_GET_PARTITION_INFO query to make it work with NTFS
    driver loaded (thanks Robert Vierthaler (RobertVi)).


  Raju Ramanathan (Rajuram)

  Converted the sample driver to Windows 2000   02/22/2000
  Code cleaning                                 04/19/2000
  Minor changes                                 09/28/2002 by QSoft   

--*/


#include "ramdisk.h"
#include <mountmgr.h>
#include <ntddstor.h>
#include <ntddft.h>

#ifdef ALLOC_PRAGMA
#pragma alloc_text( INIT, DriverEntry )
#pragma alloc_text( PAGE, RamDiskCreateClose) 
#pragma alloc_text( PAGE, RamDiskUnload)
#pragma alloc_text( PAGE, RamDiskQueryDiskRegParameters )
#pragma alloc_text( PAGE, RamDiskFormatDisk )
#pragma alloc_text( PAGE, RamDiskAddDevice )
#pragma alloc_text( PAGE, RamDiskDispatchPnp )
#pragma alloc_text( PAGE, RamDiskDispatchPower )
#pragma alloc_text( PAGE, RamDiskDispatchSystemControl )
#pragma alloc_text( PAGE, RamDiskRemoveDevice )
#pragma alloc_text( PAGE, GetPnpIrpName )
#if DBG
#pragma alloc_text( PAGE, RamDiskQueryDebugRegParameters )
#endif
#endif // ALLOC_PRAGMA

#if DBG
ULONG  BreakOnEntry = FALSE;
ULONG  DbgLevel = -1 ; // DBG_LEVEL_NONE;
ULONG  DbgComp  = DBG_COMP_ALL;
// To disable selected components 
//ULONG  DbgComp  = DBG_COMP_ALL & ~DBG_COMP_PNP;
#endif    // DBG


NTSTATUS
DriverEntry(
    IN PDRIVER_OBJECT DriverObject,
    IN PUNICODE_STRING RegistryPath
    )

/*++

Routine Description:

    Installable driver initialization entry point.
    This entry point is called directly by the I/O system.

Arguments:

    DriverObject - pointer to the driver object

    RegistryPath - pointer to a unicode string representing the path
                   to driver-specific key in the registry

Return Value:

    STATUS_SUCCESS if successful.

--*/
{
    PRAMDISK_DRIVER_EXTENSION   driverExtension;
    NTSTATUS                    status;

#if DBG
    CHAR VersionHerald[]    = "Windows 2000 Ramdisk Driver - Version %s built on %s\n";
    CHAR VersionNumber[]    = "1.0";
    CHAR VersionTimestamp[] = __DATE__ " " __TIME__;

    DBGPRINT( DBG_COMP_INIT, DBG_LEVEL_NOTIFY, ( VersionHerald, VersionNumber, VersionTimestamp) );
#endif

    DBGPRINT( DBG_COMP_INIT, DBG_LEVEL_VERBOSE, ("DriverEntry - IN\n") );


    //
    // Create extension for the driverobject to store driver specific 
    // information. Device specific information should be stored in
    // Device Extension

    status = IoAllocateDriverObjectExtension(DriverObject,
                                             RAMDISK_DRIVER_EXTENSION_KEY,
                                             sizeof(RAMDISK_DRIVER_EXTENSION),
                                             &driverExtension);

    if(!NT_SUCCESS(status)) {
         DBGPRINT( DBG_COMP_INIT, DBG_LEVEL_ERROR, 
            ("Ramdisk driver extension could not be allocated %lx \n", status ) );
        return status;
    }

    //
    // Copy the registry path into the driver extension so we can use it later
    //

    driverExtension->RegistryPath.Length = RegistryPath->Length;
    driverExtension->RegistryPath.MaximumLength = RegistryPath->MaximumLength + 
                                                    sizeof(UNICODE_NULL);

    driverExtension->RegistryPath.Buffer =
        ExAllocatePoolWithTag(PagedPool,
                              driverExtension->RegistryPath.MaximumLength,
                              RAMDISK_TAG_GENERAL);

    if(driverExtension->RegistryPath.Buffer == NULL) {
        status = STATUS_INSUFFICIENT_RESOURCES;
        return status;
    }

    RtlCopyUnicodeString( &(driverExtension->RegistryPath), RegistryPath);
	driverExtension->DeviceInitialized = FALSE;

#if DBG
    // Query registry paramters

    RamDiskQueryDebugRegParameters( RegistryPath );

    // Break if required
    if ( BreakOnEntry ) {
        KdBreakPoint();
    }
#endif

    //
    // Create dispatch points for Create, Close, Unload, Pnp, Power & WMI
    //

    DriverObject->MajorFunction[IRP_MJ_CREATE]         = RamDiskCreateClose;
    DriverObject->MajorFunction[IRP_MJ_CLOSE]          = RamDiskCreateClose;
    DriverObject->MajorFunction[IRP_MJ_READ]           = RamDiskReadWrite;
    DriverObject->MajorFunction[IRP_MJ_WRITE]          = RamDiskReadWrite;
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = RamDiskIOCtl;
    DriverObject->MajorFunction[IRP_MJ_PNP]            = RamDiskDispatchPnp;
    DriverObject->MajorFunction[IRP_MJ_POWER]          = RamDiskDispatchPower;
    DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = RamDiskDispatchSystemControl;
    DriverObject->DriverExtension->AddDevice           = RamDiskAddDevice;
    DriverObject->DriverUnload                         = RamDiskUnload;

    DBGPRINT( DBG_COMP_INIT, DBG_LEVEL_VERBOSE, ("DriverEntry - OUT.\n") );
    return STATUS_SUCCESS;
}   // End of DriverEntry()


NTSTATUS
RamDiskCreateClose(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )
/*++

Routine Description:

    This routine is called by the I/O system to create or close a
    handle to the device that we control. 

Arguments:

    DeviceObject - a pointer to the object that represents the device
    Irp - a pointer to the I/O Request Packet for this request.

Return Value:

    STATUS_SUCCESS

--*/
{
    PIO_STACK_LOCATION  irpStack;
    NTSTATUS            status = STATUS_SUCCESS;

    PAGED_CODE();

    DBGPRINT( DBG_COMP_INIT, DBG_LEVEL_VERBOSE, ("CreateClose - IN\n") );

    irpStack = IoGetCurrentIrpStackLocation( Irp );

    switch ( irpStack->MajorFunction ) {

        case IRP_MJ_CREATE:
            DBGPRINT( DBG_COMP_INIT, DBG_LEVEL_INFO, ("IRP_MJ_CREATE (%p)\n", Irp) );
            COMPLETE_REQUEST( Irp, status, 0 );
            break;

        case IRP_MJ_CLOSE:
            DBGPRINT( DBG_COMP_INIT, DBG_LEVEL_INFO, ("IRP_MJ_CLOSE (%p)\n", Irp) );
            COMPLETE_REQUEST( Irp, status, 0 );
            break;

        default:
            status = STATUS_NOT_IMPLEMENTED;
            COMPLETE_REQUEST( Irp, status, 0 );
            ASSERTMSG("BUG: we should never get here", 0);
            break;

    } // switch

    DBGPRINT( DBG_COMP_INIT, DBG_LEVEL_VERBOSE, ("CreateClose - OUT\n") );
    return status;
}   // End of RamDiskCreateClose()

VOID
RamDiskUnload(
    IN PDRIVER_OBJECT DriverObject
    )
/*++

Routine Description:

    This routine is called when the driver is unloaded from the
    system. This released the memory allocated during DriverEntry

Arguments:

    DriverObject - a pointer to the driver object 

Return Value:

    None

--*/
{
    PRAMDISK_DRIVER_EXTENSION   driverExtension;

    DBGPRINT( DBG_COMP_INIT, DBG_LEVEL_INFO, ("Driver Unload\n") );
    ASSERT(DriverObject->DeviceObject == NULL);
    driverExtension = IoGetDriverObjectExtension(DriverObject,
                                             RAMDISK_DRIVER_EXTENSION_KEY);
    ASSERT ( driverExtension != NULL );
    if ( driverExtension->RegistryPath.Buffer ) {
        ExFreePool( driverExtension->RegistryPath.Buffer );
    }
    return;
}   // End of RamDiskUnload()


NTSTATUS
RamDiskIOCtl(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )
/*++

Routine Description:

    This is the IOCTL handler for our driver. This is called whenever
    the driver on top sends any IOCTL requests

Arguments:

    DeviceObject - a pointer to the object that represents the device
    Irp - a pointer to the I/O Request Packet for this request.

Return Value:

    Status based on the request

--*/
{

    PIO_STACK_LOCATION  irpStack;
    NTSTATUS            status = STATUS_INVALID_DEVICE_REQUEST;
    ULONG               command;
    ULONG               information = 0;

    PDEVICE_EXTENSION    devExt = DeviceObject->DeviceExtension;

    status = IoAcquireRemoveLock(&devExt->RemoveLock, Irp);
    if (!NT_SUCCESS(status)) {
        DBGPRINT( DBG_COMP_IOCTL, DBG_LEVEL_ERROR, ("Acquire RemoveLock failed\n" ) );
        COMPLETE_REQUEST( Irp, status, 0 );
        return status;
    }

    irpStack = IoGetCurrentIrpStackLocation(Irp);
    command = irpStack->Parameters.DeviceIoControl.IoControlCode;

    DBGPRINT( DBG_COMP_IOCTL, DBG_LEVEL_VERBOSE, ("IOCtl- IN : command = 0x%08lX\n" , command ) );

    switch ( command )
    {

    case IOCTL_DISK_GET_PARTITION_INFO: {

        DBGPRINT( DBG_COMP_IOCTL, DBG_LEVEL_INFO, ("IOCTL_DISK_GET_PARTITION_INFO \n" ) );
        if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
            sizeof(PARTITION_INFORMATION)) {
            DBGPRINT( DBG_COMP_IOCTL, DBG_LEVEL_INFO, ("Output buffer too small... \n" ) );
            status = STATUS_BUFFER_TOO_SMALL;       // Inform the caller we need bigger buffer
            information = sizeof(PARTITION_INFORMATION);
        } else {
            PPARTITION_INFORMATION outputBuffer;
            PBOOT_SECTOR    bootSector = (PBOOT_SECTOR) devExt->DiskImage;

            outputBuffer = ( PPARTITION_INFORMATION )Irp->AssociatedIrp.SystemBuffer;

            outputBuffer->PartitionType = 
                (bootSector->bsFileSystemType[4] == '6') ? PARTITION_FAT_16 : PARTITION_FAT_12;

            outputBuffer->BootIndicator       = FALSE;
            outputBuffer->RecognizedPartition = TRUE;
            outputBuffer->RewritePartition    = FALSE;
            outputBuffer->StartingOffset      = RtlConvertUlongToLargeInteger(0);
            outputBuffer->PartitionLength     = RtlConvertUlongToLargeInteger(devExt->DiskRegInfo.DiskSize);
            outputBuffer->HiddenSectors       = 0 ; // (ULONG) (1L);
            outputBuffer->PartitionNumber     = (ULONG) (-1L);

            status = STATUS_SUCCESS;
            information = sizeof( PARTITION_INFORMATION );
        }

        break;
    }                                        
    case IOCTL_DISK_GET_MEDIA_TYPES: {

        if ( irpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof( DISK_GEOMETRY ) )
        {
            //
            // Instead of returning STATUS_INVALID_PARAMETER, we will return
            // STATUS_BUFFER_TOO_SMALL and the required buffer size. 
            // So that the called will send a bigger buffer
            //
            status = STATUS_BUFFER_TOO_SMALL;       // Inform the caller we need bigger buffer

⌨️ 快捷键说明

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