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

📄 speedcd.c

📁 虚拟光驱程序
💻 C
📖 第 1 页 / 共 3 页
字号:
SPEEDCDInitializeVolumes(
    IN PDRIVER_OBJECT   DriverObject,
    IN PUNICODE_STRING  ParamPath,
    IN PUNICODE_STRING  DriveLetterString, // "Z:"
    IN PUNICODE_STRING  ImagePathString, // Kernel mode full file path
	IN BOOLEAN bDoDiveceInitializing
    )

/*++

Routine Description:
    This routine is called each time a new cd image is mounted. It may be called 
	at initiliazation or later.

    It creates and initializes a device object for the disk. 

    Two parameters may be configured using the registry.  DiskSize specifies
    the desired size (in bytes).  If the requested memory is not available in
    the nonpaged pool then STATUS_INSUFFICIENT_RESOURCES is returned.  The
    default value is 0x00100000 (1MB).

    DriveLetter is used to indicate the drive letter for the SPEEDCD.  The
    string must be a letter, optionally followed by :.

Arguments:
    DriverObject - a pointer to the object that represents this device
    driver.

    ParamPath - a pointer to the Parameters key under our key in the Services
        section of the registry.

Return Value:
    STATUS_SUCCESS if this disk is initialized; an error otherwise.

--*/

{
    UNICODE_STRING      Win32PathString;    // Win32 Name "\DosDevices\Z:"
    UNICODE_STRING      KernelPrefix;    // Win32 Name "\DosDevices\Z:"
    UNICODE_STRING      fileExtString;
    UNICODE_STRING      fileExtString1;
    WCHAR               fileExtBuffer1[100];
    
    PDEVICE_OBJECT      deviceObject = NULL;    // ptr to device object
    PSPEEDCD_EXTENSION  diskExtension = NULL;   // ptr to device extension
    
    NTSTATUS            ntStatus;

	// kernel device name like "\\Device\\xxFakeCD0"
    UNICODE_STRING      deviceString;     
    WCHAR               deviceBuffer[100];

    UNICODE_STRING      cdromNumString;     
    WCHAR               cdromNumBuffer[20];
    LONG                DeviceNumOffset;
	int iType;

	// get the number of the cdrom device
	PCONFIGURATION_INFORMATION pConfigInfo;

    pConfigInfo = IoGetConfigurationInformation(); 

	// name for the kernel device object for this drive
    RtlInitUnicodeString( &deviceString,NULL);
	deviceString.Buffer = deviceBuffer;
	deviceString.MaximumLength = sizeof(WCHAR) * 99;

    RtlInitUnicodeString( &cdromNumString,NULL);
	cdromNumString.Buffer = cdromNumBuffer;
	cdromNumString.MaximumLength = sizeof(WCHAR) * 19;

	RtlAppendUnicodeToString(&deviceString, L"\\Device\\SPEEDCD");

    if (DriveLetterString == NULL)
    {
        DeviceNumOffset = -1;
		iType = FILE_DEVICE_UNKNOWN;
    }
	else
	{
        DeviceNumOffset = DriveLetterString->Buffer[0]- 'A';
        RtlIntegerToUnicodeString(DeviceNumOffset,10,&cdromNumString); 
		RtlAppendUnicodeStringToString(&deviceString, &cdromNumString);
		iType = FILE_DEVICE_SPEEDCD;
	}
	// now the device name should have the correct number on the end of it.

    ntStatus = IoCreateDevice(
        DriverObject,                   // Our Driver Object
        sizeof( RAMDISK_EXTENSION ),    // Size of state information
        &deviceString,					// Device name "\Device\SPEEDCD"
        iType,							// Device type
        /*FILE_REMOVABLE_MEDIA|*/FILE_READ_ONLY_DEVICE,// Device characteristics
        FALSE,                          // Exclusive device
        &deviceObject );                // Returned ptr to Device Object

    if ( !NT_SUCCESS( ntStatus ) )
    {
		SPEEDCDLogS("Couldn't create the device object");
        goto SPEEDCDInitializeDiskExit;
    }

    //
    // Initialize device object and extension.
    //
    
    deviceObject->Flags |= DO_DIRECT_IO;
    deviceObject->AlignmentRequirement = FILE_WORD_ALIGNMENT;
    diskExtension = (PSPEEDCD_EXTENSION)deviceObject->DeviceExtension;

    RtlInitUnicodeString( &diskExtension->Win32NameString, NULL );

    //
    // Allocate and initialize a Unicode String containing the Win32 name
    // for our device.
    //

    RtlInitUnicodeString( &Win32PathString, WIN32_PATH );

    diskExtension->Win32NameString.Buffer = ExAllocatePool(
                                    PagedPool, 
                                    sizeof(WIN32_PATH) + 30 * sizeof(WCHAR) );

    if (!diskExtension->Win32NameString.Buffer) {
        SPEEDCDDump(
            RAMDERRORS,
            ("RAMDISK: Couldn't allocate buffer for the symbolic link\n")
            );

		ntStatus = STATUS_INSUFFICIENT_RESOURCES;

        goto SPEEDCDInitializeDiskExit;
    }

    diskExtension->Win32NameString.MaximumLength = sizeof(WIN32_PATH) + sizeof(WCHAR)*29;
	diskExtension->DeviceObject = deviceObject; //store a back pointer to the device object
        
    RtlAppendUnicodeStringToString(
             &diskExtension->Win32NameString, &Win32PathString );

    if (!DriveLetterString)
    {
    	RtlAppendUnicodeToString(&diskExtension->Win32NameString, L"SPEEDCD");
    }else
    {
        RtlAppendUnicodeStringToString(
                 &diskExtension->Win32NameString, DriveLetterString );
    }


    //
    // Create a symbolic link between our device name "\Device\SPEEDCD0" and
    // the Win32 name (ie "\DosDevices\Z:").
    //
    ntStatus = IoCreateSymbolicLink(
                        &diskExtension->Win32NameString, &deviceString );

	// save the path to the file for later use

    diskExtension->DataFileName.Buffer = ExAllocatePool(PagedPool,500 * sizeof(WCHAR) );

    if (!diskExtension->DataFileName.Buffer) {
        SPEEDCDDump(
            RAMDERRORS,
            ("SpeedCD: Couldn't allocate buffer for image name\n")
            );

		ntStatus = STATUS_INSUFFICIENT_RESOURCES;

        goto SPEEDCDInitializeDiskExit;
    }

	diskExtension->DataFileName.MaximumLength = sizeof(WCHAR)*499;
    diskExtension->DataFileName.Length = 0;

    RtlInitUnicodeString( &KernelPrefix, L"\\??\\" );
	RtlAppendUnicodeStringToString(&diskExtension->DataFileName, &KernelPrefix);
	RtlAppendUnicodeStringToString(&diskExtension->DataFileName,ImagePathString);

    //
    //  Set the Image type to the constant based on the extention.
    //

    RtlInitUnicodeString( &fileExtString,  L".ISO");

    RtlInitUnicodeString( &fileExtString1, 
        &(ImagePathString->Buffer[ ImagePathString->Length/sizeof(WCHAR)-4 ]));

    if (RtlCompareUnicodeString(&fileExtString,&fileExtString1,TRUE) == 0)
    {
		SPEEDCDLogS("Setting Image Format to ISO");
        diskExtension->DataFormat = FILE_FORMAT_ISO; // 0k For ISO standard format
    }
    else
    {
		SPEEDCDLogS("Setting Image Format to SPEEDCD");
        diskExtension->DataFormat = FILE_FORMAT_SPEED_CD; // 64k for SPEEDCD format
    }
	


SPEEDCDInitializeDiskExit:

    if ( !NT_SUCCESS( ntStatus ) )
    {
        // Delete everything that this routine has allocated.
        
        if ( deviceObject != NULL )
        {
            IoDeleteDevice( deviceObject );
        }
    }else
	{
		if(bDoDiveceInitializing)
			deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
	}

    return ntStatus;
}


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

Routine Description:

    This routine is called by the I/O system when the SPEEDCD 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;
    
    IoCompleteRequest( Irp, IO_NO_INCREMENT );
    
    return STATUS_SUCCESS;
}



VOID SPEEDCDFillGeometry(PDISK_GEOMETRY pDG)
{
    pDG->BytesPerSector = 0x800;
    pDG->Cylinders.QuadPart = 0x92;
    pDG->MediaType = RemovableMedia;
    pDG->SectorsPerTrack = 0x20;
    pDG->TracksPerCylinder = 0x40;
}

VOID SPEEDCDFillToc(CDROM_TOC *pToc)
{
    pToc->Length[0]  =    0;
    pToc->Length[1]  = 0x12;
    pToc->FirstTrack =    1;
    pToc->LastTrack  =    1;

    pToc->TrackData[0].Control =   0x4;
    pToc->TrackData[0].Adr     =     1;
    pToc->TrackData[0].TrackNumber = 1;
    pToc->TrackData[0].Address[0]  = 0;
    pToc->TrackData[0].Address[1]  = 0;
    pToc->TrackData[0].Address[2]  = 2;
    pToc->TrackData[0].Address[3]  = 0;

    pToc->TrackData[1].Control =   0x4;
    pToc->TrackData[1].Adr     =     1;
    pToc->TrackData[1].TrackNumber = 0xaa;
    pToc->TrackData[1].Address[0]  = 0;
    pToc->TrackData[1].Address[1]  = 0x2e;
    pToc->TrackData[1].Address[2]  = 0x3b;
    pToc->TrackData[1].Address[3]  = 0x3a;
}


NTSTATUS
SPEEDCDDeviceControl(
    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.

--*/

{
    PSPEEDCD_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.
    //

    switch ( irpSp->Parameters.DeviceIoControl.IoControlCode )
    {
	// stubs that take complex success :)
	case IOCTL_CDROM_CHECK_VERIFY:  // <==== old
	case IOCTL_STORAGE_CHECK_VERIFY:
		{
			ULONG *pMediaChangeCount;
		
			// if they want the media change count
			if (irpSp->Parameters.DeviceIoControl.OutputBufferLength !=0)
			{
                if (irpSp->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(ULONG))
                {
				    pMediaChangeCount = (PULONG)Irp->AssociatedIrp.SystemBuffer;
				    *pMediaChangeCount = 1;
				    Irp->IoStatus.Information = sizeof(ULONG);
        			Irp->IoStatus.Status = STATUS_SUCCESS;
                }else
                {
				    Irp->IoStatus.Information = 0;
				    Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
                }

			}else
			{
				Irp->IoStatus.Information = 0;
				Irp->IoStatus.Status = STATUS_SUCCESS;
			}
			break;
		}

	// other codes that we don't want to see while we are debuging
	// I get this one sometimes, but I don't know what to return!
	case IOCTL_CDROM_DISK_TYPE:
		SPEEDCDLogS("Ignoring: IOCTL_CDROM_DISK_TYPE");
		Irp->IoStatus.Information = 0;
		Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
		break;
	// we get this code sometimes but don't want to see it in the debug popup
	case IOCTL_DISK_GET_DRIVE_GEOMETRY:
		SPEEDCDLogS("Ignoring: IOCTL_DISK_GET_DRIVE_GEOMETRY");
		Irp->IoStatus.Information = 0;
		Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
		break;

	//
	// we need to say that the device does not handle this mode yet
	//

	case IOCTL_CDROM_RAW_READ:
		SPEEDCDLogS("Ignoring: IOCTL_CDROM_RAW_READ");
		Irp->IoStatus.Information = 0;
		Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
		break;

	//
	// We need to return the drive geomotry that we have saved in the file.
	//

	case IOCTL_CDROM_GET_DRIVE_GEOMETRY:
		SPEEDCDLogS("IOCTL_CDROM_GET_DRIVE_GEOMETRY");
		{
			ULONG length = irpSp->Parameters.DeviceIoControl.OutputBufferLength;
			LARGE_INTEGER track;
			track = RtlConvertUlongToLargeInteger(1024);

			if ( length >= sizeof( DISK_GEOMETRY ) )
			{
				length = sizeof( DISK_GEOMETRY );

                if (FILE_FORMAT_ISO == diskExtension->DataFormat)
                {
                    SPEEDCDFillGeometry((DISK_GEOMETRY *) Irp->AssociatedIrp.SystemBuffer);
					Irp->IoStatus.Status = STATUS_SUCCESS;
					Irp->IoStatus.Information = length;
                    break;
                }else
                {

⌨️ 快捷键说明

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