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

📄 ramdisk.c

📁 RAM Disk Driver with custom BoundsChecker events This sample illustrates how to add custom Bounds
💻 C
📖 第 1 页 / 共 2 页
字号:
                ~ ( DIR_ENTRIES_PER_SECTOR - 1 );
    }

    //
    // We need to have the 0xeb and 0x90 since this is one of the
    // checks the file system recognizer uses
    //
    bootSector->bsJump[0] = 0xeb;
    bootSector->bsJump[1] = 0x3c;
    bootSector->bsJump[2] = 0x90;

    strncpy(bootSector->bsOemName, "RobertN ", 8);
    bootSector->bsBytesPerSec = (SHORT)DiskExtension->BytesPerSector;
    bootSector->bsResSectors = 1;
    bootSector->bsFATs = 1;
    bootSector->bsRootDirEnts = (USHORT)rootDirEntries;

    bootSector->bsSectors =
        (USHORT)( DiskExtension->DiskLength / DiskExtension->BytesPerSector );
    bootSector->bsMedia = RAMDISK_MEDIA_TYPE;

    bootSector->bsSecPerClus = (UCHAR)sectorsPerCluster;

    //
    // Calculate number of sectors required for FAT
    //
    fatEntries =
        (bootSector->bsSectors - bootSector->bsResSectors -
            bootSector->bsRootDirEnts / DIR_ENTRIES_PER_SECTOR) /
                bootSector->bsSecPerClus + 2;

    //
    // Choose between 12 and 16 bit FAT based on number of clusters we
    // need to map
    //
    if (fatEntries > 4087)
    {
        fatType =  16;

        fatSectorCnt = (fatEntries * 2 + 511) / 512;

        fatEntries -= fatSectorCnt;

        fatSectorCnt = (fatEntries * 2 + 511) / 512;
    }
    else
    {
        fatType =  12;

        fatSectorCnt = (((fatEntries * 3 + 1) / 2) + 511) / 512;
        
        fatEntries -= fatSectorCnt;
        
        fatSectorCnt = (((fatEntries * 3 + 1) / 2) + 511) / 512;
    }

    bootSector->bsFATsecs = fatSectorCnt;
    bootSector->bsSecPerTrack = (USHORT)DiskExtension->SectorsPerTrack;
    bootSector->bsHeads = (USHORT)DiskExtension->TracksPerCylinder;
    bootSector->bsBootSignature = 0x29;
    bootSector->bsVolumeID = 0x12345678;
    strncpy(bootSector->bsLabel, "RamDisk    ", 11);
    strncpy(bootSector->bsFileSystemType, "FAT1?   ", 8);
    bootSector->bsFileSystemType[4] = ( fatType == 16 ) ? '6' : '2';
    
    bootSector->bsSig2[0] = 0x55;
    bootSector->bsSig2[1] = 0xAA;
    

	BOUNDS_CHECKER(GENERIC_1, (bootSector,
		"RamDiskFormatFat pObject:bootSector Ulong1:FatType ULong2:fatEntries",
		 fatType, fatEntries));

    //
    // The FAT is located immediately following the boot sector.
    //
    firstFatSector = (PUCHAR)(bootSector + 1);
    firstFatSector[0] = RAMDISK_MEDIA_TYPE;
    firstFatSector[1] = 0xFF;
    firstFatSector[2] = 0xFF;

    if (fatType == 16)
        firstFatSector[3] = 0xFF;

    //
    // The Root Directory follows the FAT
    //
    rootDir = (PDIR_ENTRY)(bootSector + 1 + fatSectorCnt);
    strcpy(rootDir->deName, "MS-RAMDR");
    strcpy(rootDir->deExtension, "IVE");
    rootDir->deAttributes = DIR_ATTR_VOLUME;
}

NTSTATUS
RamDiskCreateClose(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )
/*++

Routine Description:

    This routine is called by the I/O system when the RamDisk is opened or
    closed.

    No action is performed other than completing the request successfully.

Arguments:

    DeviceObject - a pointer to the object that represents the device
    that I/O is to be done on.

    Irp - a pointer to the I/O Request Packet for this request.

Return Value:

    STATUS_INVALID_PARAMETER if parameters are invalid,
    STATUS_SUCCESS otherwise.

--*/

{
    Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = 0;
    
    BOUNDS_CHECKER(GENERIC_1, (NULL,
		"RamDiskCreateClose called",
		 0, 0));

	IoCompleteRequest( Irp, IO_NO_INCREMENT );
    
    return STATUS_SUCCESS;
}

NTSTATUS
RamDiskDeviceControl(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )

/*++

Routine Description:

    This routine is called by the I/O system to perform a device I/O
    control function.

Arguments:

    DeviceObject - a pointer to the object that represents the device
        that I/O is to be done on.

    Irp - a pointer to the I/O Request Packet for this request.

Return Value:

    STATUS_SUCCESS if recognized I/O control code,
    STATUS_INVALID_DEVICE_REQUEST otherwise.

--*/

{
    PRAMDISK_EXTENSION  diskExtension;
    PIO_STACK_LOCATION  irpSp;
    NTSTATUS            ntStatus;

    //
    // Set up necessary object and extension pointers.
    //

    diskExtension = DeviceObject->DeviceExtension;
    irpSp = IoGetCurrentIrpStackLocation( Irp );

    //
    // Assume failure.
    //

    Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;

    //
    // Determine which I/O control code was specified.
    //
     BOUNDS_CHECKER(GENERIC_1, (NULL,
		"DeviceControl called ULong1 = I/O control code",
		 irpSp->Parameters.DeviceIoControl.IoControlCode, 0));


    switch ( irpSp->Parameters.DeviceIoControl.IoControlCode )
    {
    
    case IOCTL_DISK_GET_MEDIA_TYPES:
    case IOCTL_DISK_GET_DRIVE_GEOMETRY:
        //
        // Return the drive geometry for the ram disk.  Note that
        // we return values which were made up to suit the disk size.
        //

        if ( irpSp->Parameters.DeviceIoControl.OutputBufferLength <
            sizeof( DISK_GEOMETRY ) )
        {

            Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
            
        }
        else
        {
            PDISK_GEOMETRY outputBuffer;

            outputBuffer = ( PDISK_GEOMETRY ) Irp->AssociatedIrp.SystemBuffer;
            outputBuffer->MediaType = RemovableMedia;
            outputBuffer->Cylinders = RtlConvertUlongToLargeInteger(
                diskExtension->NumberOfCylinders );
            outputBuffer->TracksPerCylinder = diskExtension->TracksPerCylinder;
            outputBuffer->SectorsPerTrack = diskExtension->SectorsPerTrack;
            outputBuffer->BytesPerSector = diskExtension->BytesPerSector;

            Irp->IoStatus.Status = STATUS_SUCCESS;
            Irp->IoStatus.Information = sizeof( DISK_GEOMETRY );
        }
        break;

    case IOCTL_DISK_GET_PARTITION_INFO: 
        //
        // Return the information about the partition.
        //

        if ( irpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof( PARTITION_INFORMATION ) )
        {
            Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
        }
        else
        {
            PPARTITION_INFORMATION outputBuffer;
            PBOOT_SECTOR    bootSector = (PBOOT_SECTOR) diskExtension->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(diskExtension->DiskLength);
        
	    outputBuffer->HiddenSectors =  1L;
        
            Irp->IoStatus.Status = STATUS_SUCCESS;
            Irp->IoStatus.Information = sizeof( PARTITION_INFORMATION );
        }
        break;


    case IOCTL_DISK_VERIFY:
        {
            //
            // Move parameters from the VerifyInformation structure to
            // the READ parameters area, so that we'll find them when
            // we try to treat this like a READ.
            //
            
            PVERIFY_INFORMATION	verifyInformation;

            verifyInformation = Irp->AssociatedIrp.SystemBuffer;

            irpSp->Parameters.Read.ByteOffset.LowPart =
                verifyInformation->StartingOffset.LowPart;
            irpSp->Parameters.Read.ByteOffset.HighPart =
                verifyInformation->StartingOffset.HighPart;
            irpSp->Parameters.Read.Length = verifyInformation->Length;

            //
            // A VERIFY is identical to a READ, except for the fact that no
            // data gets transferred.  So follow the READ code path.
            //

            ntStatus = RamDiskReadWrite( DeviceObject, Irp );
        }
        return ntStatus;

    default:
        //
        // The specified I/O control code is unrecognized by this driver.
        // The I/O status field in the IRP has already been set so just
        // terminate the switch.
        //

        RamDiskDump(
        RAMDDIAG1,
            ("RAMDISK: ERROR:  unrecognized IOCTL %x\n",
            irpSp->Parameters.DeviceIoControl.IoControlCode));

        break;
    }

    //
    // Finish the I/O operation by simply completing the packet and returning
    // the same status as in the packet itself.
    //

    ntStatus = Irp->IoStatus.Status;

    IoCompleteRequest( Irp, IO_NO_INCREMENT );

    BOUNDS_CHECKER(GENERIC_1, (NULL,
		"Exiting DeviceControl ULong1 = status",
		 ntStatus, 0));


    return ntStatus;
}

NTSTATUS
RamDiskReadWrite(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )
/*++

Routine Description:

    This routine is called by the I/O system to read or write to a
    device that we control.  It can also be called by
    RamDiskDispatchDeviceControl() to do a VERIFY.

Arguments:

    DeviceObject - a pointer to the object that represents the device
    that I/O is to be done on.

    Irp - a pointer to the I/O Request Packet for this request.

Return Value:

    STATUS_INVALID_PARAMETER if parameters are invalid,
    STATUS_SUCCESS otherwise.

--*/

{
    PRAMDISK_EXTENSION  diskExtension;
    PIO_STACK_LOCATION  irpSp;
    PUCHAR              CurrentAddress;

    //
    // Set up necessary object and extension pointers.
    //

    diskExtension = DeviceObject->DeviceExtension;

    irpSp = IoGetCurrentIrpStackLocation( Irp );

    //
    // Check for invalid parameters.  It is an error for the starting offset
    // + length to go past the end of the buffer, or for the length to
    // not be a proper multiple of the sector size.
    //
    // Others are possible, but we don't check them since we trust the
    // file system and they aren't deadly.
    //

    if (RtlLargeIntegerGreaterThan(
            RtlLargeIntegerAdd(
                irpSp->Parameters.Read.ByteOffset,
                RtlConvertUlongToLargeInteger(irpSp->Parameters.Read.Length)),
            RtlConvertUlongToLargeInteger(diskExtension->DiskLength)) ||
        (irpSp->Parameters.Read.Length & (diskExtension->BytesPerSector - 1)))
    {
        //
        // Do not give an I/O boost for parameter errors.
        //

        RamDiskDump(
            RAMDERRORS,
            (
                "RAMDISK: Error invalid parameter\n"
                "         ByteOffset: %x\n"
                "         Length: %d\n"
                "         Operation: %x\n",
                Irp,
                irpSp->Parameters.Read.ByteOffset,
                irpSp->Parameters.Read.Length,
                irpSp->MajorFunction
            ));

        Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
        IoCompleteRequest( Irp, IO_NO_INCREMENT );

        return STATUS_INVALID_PARAMETER;
    }

    //
    // Get a system-space pointer to the user's buffer.  A system
    // address must be used because we may already have left the
    // original caller's address space.
    //

    if ( Irp->MdlAddress != NULL )
    {
        CurrentAddress = MmGetSystemAddressForMdl( Irp->MdlAddress );
    }
    else
    {
        //
        // Strictly speaking this isn't necessary, the only time we
        // won't have an MDL is if we're processing IOCTL_DISK_VERIFY.
        // In which case, we don't reference CurrentAddress.  But at
        // least this should keep the compiler from warning us.

        CurrentAddress = 0;
    }

    RamDiskDump(
        RAMDDIAG2,
        (
            "RAMDISK: Irp of Request: %x\n"
            "         Vmem Address of Transfer: %x - %x\n"
            "         Length of Transfer: %d\n"
            "         Operation: %x\n"
            "         Starting ByteOffset: %x\n",
            Irp,
            CurrentAddress,
            ((PUCHAR)CurrentAddress) + irpSp->Parameters.Read.Length,
            irpSp->Parameters.Read.Length,
            irpSp->MajorFunction,
            irpSp->Parameters.Read.ByteOffset.LowPart
        ));

    Irp->IoStatus.Information = irpSp->Parameters.Read.Length;

    switch (irpSp->MajorFunction)
    {
    case IRP_MJ_READ:
        RtlMoveMemory(
            CurrentAddress,
            diskExtension->DiskImage + irpSp->Parameters.Read.ByteOffset.LowPart,
            irpSp->Parameters.Read.Length);
        break;

    case IRP_MJ_DEVICE_CONTROL:
        //
        // The only way we can get this major code is if the VERIFY
        // ioctl called RamDiskDispatchReadWrite().
        //
        break;

    case IRP_MJ_WRITE:
        RtlMoveMemory(
            diskExtension->DiskImage + irpSp->Parameters.Read.ByteOffset.LowPart,
            CurrentAddress, irpSp->Parameters.Read.Length);
        break;

    default:
        Irp->IoStatus.Information = 0;
        break;
    }

       BOUNDS_CHECKER(GENERIC_1, (NULL,
		"RamDiskReadWrite ULong1 = Major job",
		 irpSp->MajorFunction, 0));


    Irp->IoStatus.Status = STATUS_SUCCESS;
    IoCompleteRequest( Irp, IO_NO_INCREMENT );

    return STATUS_SUCCESS;
}

VOID
RamDiskUnloadDriver(
    IN PDRIVER_OBJECT DriverObject
    )
/*++

Routine Description:

    This routine is called by the I/O system to unload the driver.

    Any resources previously allocated must be freed.

Arguments:

    DriverObject - a pointer to the object that represents our driver.

Return Value:

    None
--*/

{
    PDEVICE_OBJECT      deviceObject = DriverObject->DeviceObject;

    if ( deviceObject != NULL )
    {
        PRAMDISK_EXTENSION      diskExtension = deviceObject->DeviceExtension;

        if (diskExtension != NULL)
        {
            if (diskExtension->DiskImage != NULL)
            {
                ExFreePool( diskExtension->DiskImage );
            }
            if (diskExtension->Win32NameString.Buffer != NULL)
            {
                IoDeleteSymbolicLink( &diskExtension->Win32NameString );

                ExFreePool( diskExtension->Win32NameString.Buffer );
            }
        }
        IoDeleteDevice( deviceObject );
    }
}

⌨️ 快捷键说明

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