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

📄 speedcd.c

📁 虚拟光驱程序
💻 C
📖 第 1 页 / 共 3 页
字号:
				    if (NT_SUCCESS(
					    SPEEDCDReadOffset(
						    &track,Irp->AssociatedIrp.SystemBuffer,length,
						    &diskExtension->DataFileName)
					    
					    ))
				    {
					    Irp->IoStatus.Status = STATUS_SUCCESS;
					    Irp->IoStatus.Information = length;
					    break;
				    }else
				    {
					    Irp->IoStatus.Information = 0;
					    Irp->IoStatus.Status = STATUS_DEVICE_NOT_READY;
					    break;
				    }
                }
			}
		}
		Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
		Irp->IoStatus.Information = 0;
		break;
	case IOCTL_CDROM_READ_TOC:
		SPEEDCDLogS("IOCTL_CDROM_READ_TOC");
//*********
//		Irp->IoStatus.Information = 0;
//		Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
//		break;
//*********
		{
//            PDISK_GEOMETRY outputBuffer;
			ULONG length = irpSp->Parameters.DeviceIoControl.OutputBufferLength;
			LARGE_INTEGER track;
			track = RtlConvertUlongToLargeInteger(2*1024);

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

                if (FILE_FORMAT_ISO == diskExtension->DataFormat)
                {
                    SPEEDCDFillToc((CDROM_TOC *) Irp->AssociatedIrp.SystemBuffer);
					Irp->IoStatus.Status = STATUS_SUCCESS;
					Irp->IoStatus.Information = length;
                    break;
                }else
                {
				    if (NT_SUCCESS(SPEEDCDReadOffset(&track,Irp->AssociatedIrp.SystemBuffer,length,&diskExtension->DataFileName)))
				    {
					    Irp->IoStatus.Status = STATUS_SUCCESS;
					    Irp->IoStatus.Information = length;
					    break;
				    }else
				    {
					    Irp->IoStatus.Information = 0;
					    Irp->IoStatus.Status = STATUS_DEVICE_NOT_READY;
					    break;
				    }
                }
			}
		}
		Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
		Irp->IoStatus.Information = 0;
		break;
	case IOCTL_CDROM_GET_LAST_SESSION:
		SPEEDCDLogS("IOCTL_CDROM_GET_LAST_SESSION");
		Irp->IoStatus.Information = 0;
		Irp->IoStatus.Status = STATUS_DEVICE_NOT_READY;
		break;
	case IOCTL_CDROM_GET_VOLUME:
		SPEEDCDLogS("IOCTL_CDROM_GET_VOLUME");
		Irp->IoStatus.Information = 0;
		Irp->IoStatus.Status = STATUS_DEVICE_NOT_READY;
		break;
	case IOCTL_CDROM_READ_Q_CHANNEL:
		SPEEDCDLogS("IOCTL_CDROM_READ_Q_CHANNEL");
		Irp->IoStatus.Information = 0;
		Irp->IoStatus.Status = STATUS_DEVICE_NOT_READY;
		break;

	// ioctls that we just need to return success codes
	case IOCTL_STORAGE_FIND_NEW_DEVICES:
	case IOCTL_CDROM_SEEK_AUDIO_MSF:
	case IOCTL_CDROM_PLAY_AUDIO_MSF:
	case IOCTL_CDROM_SET_VOLUME:
	case IOCTL_CDROM_STOP_AUDIO:
	case IOCTL_CDROM_PAUSE_AUDIO:
	case IOCTL_CDROM_RESUME_AUDIO:
	case IOCTL_STORAGE_EJECT_MEDIA:
	case IOCTL_CDROM_EJECT_MEDIA: // <==== old
		Irp->IoStatus.Information = 0;
		Irp->IoStatus.Status = STATUS_SUCCESS;
		break;
	
	// special debug ctrl code to add a device
	case IOCTL_SPEEDCD_ADD_DEVICE:
		{
			SPEEDCDLogS("-----Adding Device in responce to IOCTL-----");
            /*
			{
			//	UNICODE_STRING  paramPath;
				UNICODE_STRING      imagePathString;     
				NTSTATUS        ntStatus1;

				RtlInitUnicodeString( &imagePathString, L"\\??\\c:\\notarealpath.iso");
				ntStatus1 = SPEEDCDInitializeVolumes(DeviceObject->DriverObject, &paramPath,NULL,&imagePathString,FALSE);


				if (NT_SUCCESS(ntStatus1))
				{
					ntStatus = STATUS_SUCCESS;
				}else
				{
					ntStatus = ntStatus1;
				}
			}
			*/
			if (irpSp->Parameters.DeviceIoControl.InputBufferLength <
				sizeof(SPEEDCD_ADD_DEVICE))
			{
				UNICODE_STRING      driveLetterString;     
				UNICODE_STRING      imagePathString;     
                WCHAR               letterBuf[10];

				SPEEDCD_ADD_DEVICE * fdp;

				fdp = (SPEEDCD_ADD_DEVICE *)Irp->UserBuffer;

                // Force the drive letter to be A-Z caps only.
                if (fdp->wcDriveLetter < L'A' || fdp->wcDriveLetter > L'Z')
                {
			        Irp->IoStatus.Information = 0;
			        Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
                    break;
                }
                // init the drive letter string
                letterBuf[0] = fdp->wcDriveLetter; 
                driveLetterString.Buffer = letterBuf;
                driveLetterString.Length = 1 * sizeof (WCHAR);
                driveLetterString.MaximumLength = 9 * sizeof (WCHAR);
              	RtlAppendUnicodeToString(&driveLetterString, L":");

                // init the path string
                fdp->szFileName[499] = L'\0'; // cap the end to prevent overflow
				RtlInitUnicodeString( &imagePathString, fdp->szFileName);

				Irp->IoStatus.Information = 0;
				Irp->IoStatus.Status = SPEEDCDInitializeVolumes(
					DeviceObject->DriverObject, NULL,&driveLetterString,
                    &imagePathString, TRUE);
				break;
			}
			Irp->IoStatus.Information = 0;
			Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
			break;
		}
	// special ctrl code to remove device
	case IOCTL_SPEEDCD_REMOVE_DEVICE:
		{
			SPEEDCDLogS("-----Unloading Device in responce to IOCTL-----");

			// we need to delete only this one device that we are in now

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

					ExFreePool( diskExtension->Win32NameString.Buffer );
				}

			}
			if (diskExtension != NULL)
				IoDeleteDevice( diskExtension->DeviceObject );

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

    case IOCTL_SPEEDCD_GET_VERSION:
		{
			ULONG *pVersionNum;
			// if they want the version number
			SPEEDCDLogSL("IOCTL_SPEEDCD_GET_VERSION: sizeof(ULONG)=",
				sizeof(ULONG));
			SPEEDCDLogSL("IOCTL_SPEEDCD_GET_VERSION: SPEED_CD_VERSION_NUMBER=",
				SPEED_CD_VERSION_NUMBER);

            if (irpSp->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(ULONG))
            {
				pVersionNum = (PULONG)Irp->AssociatedIrp.SystemBuffer;
				*pVersionNum = SPEED_CD_VERSION_NUMBER;
				Irp->IoStatus.Information = sizeof(ULONG);
        		Irp->IoStatus.Status = STATUS_SUCCESS;
            }else
            {
				Irp->IoStatus.Information = 0;
				Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
            }
		}
		break;

    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.
        //
		{
			SPEEDCDLogSL("ERROR:  unrecognized IOCTL ",
				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 );

    return ntStatus;
}

NTSTATUS
SPEEDCDReadWrite(
    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
    SPEEDCDDispatchDeviceControl() 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.

--*/

{
    PSPEEDCD_EXTENSION  diskExtension;
    PIO_STACK_LOCATION  irpSp;
    PUCHAR              CurrentAddress;
	NTSTATUS status;

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

    //
    // 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;
    }

    SPEEDCDLogSL("RAMDISK: Irp of Request: 0x",(ULONG)Irp);
    SPEEDCDLogSL("         Vmem Address of Transfer: 0x",(ULONG)CurrentAddress);
	SPEEDCDLogSL("                                 - 0x",(ULONG)((PUCHAR)CurrentAddress) + irpSp->Parameters.Read.Length);
    SPEEDCDLogSL("         Length of Transfer: 0x",(ULONG)irpSp->Parameters.Read.Length);
    SPEEDCDLogSL("         Operation: 0x",(ULONG)irpSp->MajorFunction);
    SPEEDCDLogSL("         Starting ByteOffset: 0x",(ULONG)irpSp->Parameters.Read.ByteOffset.LowPart);

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

    switch (irpSp->MajorFunction)
    {
    case IRP_MJ_READ:

		{
			// try to read the data from the file!!!
			ULONG length = irpSp->Parameters.Read.Length;
			LARGE_INTEGER track;
            ULONG ulOffset;

            // FILE_FORMAT_ISO or FILE_FORMAT_SPEED_CD
            if (FILE_FORMAT_ISO == diskExtension->DataFormat)
            {
                SPEEDCDLogS("Reading with ISO Format offset 0");
                ulOffset = 0;
            }else
            {
                SPEEDCDLogS("Reading with SPEEDCD Format offset 64k");
                ulOffset = 64*1024;
            }

            SPEEDCDLogPU(&diskExtension->DataFileName);
            SPEEDCDLogSL("ulOffset = ",ulOffset);

            track = RtlLargeIntegerAdd(
				RtlConvertUlongToLargeInteger(ulOffset), // this is the offset to get past the header
                irpSp->Parameters.Read.ByteOffset);


			if (NT_SUCCESS(SPEEDCDReadOffset(&track,CurrentAddress,length, &diskExtension->DataFileName)))
			{
				Irp->IoStatus.Status = STATUS_SUCCESS;
				Irp->IoStatus.Information = length;
				IoCompleteRequest( Irp, IO_NO_INCREMENT );
				return STATUS_SUCCESS;
			}
		}

		// if there is an error we want to return not ready
		Irp->IoStatus.Status = STATUS_DEVICE_NOT_READY;
        Irp->IoStatus.Information = 0;
        IoCompleteRequest( Irp, IO_NO_INCREMENT );
		return STATUS_DEVICE_NOT_READY;

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

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

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

    return STATUS_SUCCESS;
}

VOID

SPEEDCDUnloadDriver(
    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;

	SPEEDCDLogS("-----Unloading Driver-----");

	// we need to delete all the devices that this driver has created
    while ( deviceObject != NULL )
    {
        PSPEEDCD_EXTENSION      diskExtension = deviceObject->DeviceExtension;

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

                ExFreePool( diskExtension->Win32NameString.Buffer );
            }

        }
		deviceObject = deviceObject->NextDevice;
		if (diskExtension != NULL)
			IoDeleteDevice( diskExtension->DeviceObject );
    }
}

⌨️ 快捷键说明

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