📄 speedcd.c
字号:
//
// Include files.
//
// Comment this out to turn off the debug log
//#define DEBUG_LOG
#include <ntddk.h> // various NT definitions
#include <ntdddisk.h> // disk device driver I/O control codes
// needed for general cdrom structs and defines
#include <ntddcdrm.h>
// needed for check verify
#include <devioctl.h>
#include <ntiologc.h>
#include <string.h>
#include "SPEEDCD.h"
#if DBG
ULONG SPEEDCDDebugLevel = 0;
#endif
//#define DEBUG_LOG 1
//
// Debug Log Functions
//
VOID SPEEDCDLogWriteString(char * pMessage)
{
#ifdef DEBUG_LOG
HANDLE FileHandle;
IO_STATUS_BLOCK IoStatusBlock;
OBJECT_ATTRIBUTES ObjectAttributes;
NTSTATUS status;
UNICODE_STRING fileName;
WCHAR fileNameBuf[] = L"\\SystemRoot\\system32\\drivers\\SPEEDCD.log";
ULONG length;
// find the length of the string that is passed in
for (length = 0; length < 512 && pMessage[length] != 0; length++)
{
// do nothing!!
}
RtlInitUnicodeString( &fileName, fileNameBuf );
InitializeObjectAttributes(
&ObjectAttributes,
&fileName,
OBJ_CASE_INSENSITIVE, // attributes
NULL,
NULL
);
status = ZwCreateFile(
&FileHandle,
FILE_APPEND_DATA,
&ObjectAttributes,
&IoStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ,
FILE_OPEN_IF,
FILE_SYNCHRONOUS_IO_NONALERT,
NULL, /* optional */
0
);
if (NT_SUCCESS(status))
{
// good!!!
// write something out and then close the file
status = ZwWriteFile(
FileHandle,NULL,NULL,NULL,
&IoStatusBlock,pMessage,length,NULL,NULL);
ZwClose(FileHandle);
}
#endif
}
VOID SPEEDCDLogWriteULong(ULONG ulValue)
{
#ifdef DEBUG_LOG
UNICODE_STRING uMessage;
ANSI_STRING asValue;
WCHAR uMessageBuffer[50];
char bufValue[55];
RtlInitUnicodeString( &uMessage, NULL );
uMessage.Length = 0;
uMessage.MaximumLength = sizeof (uMessageBuffer)-sizeof(WCHAR);
uMessage.Buffer = uMessageBuffer;
RtlInitAnsiString(&asValue,NULL);
asValue.Length = 0;
asValue.MaximumLength = 50;
asValue.Buffer = bufValue;
RtlIntegerToUnicodeString(ulValue,16,&uMessage);
if (NT_SUCCESS(
RtlUnicodeStringToAnsiString(
&asValue,
&uMessage,
TRUE)
))
{
if (asValue.Length < 45)
{
// add the null to the end of the string
asValue.Buffer[asValue.Length] = 0;
asValue.Length++;
SPEEDCDLogWriteString(asValue.Buffer);
}
}
#endif
}
VOID SPEEDCDLogL(ULONG ulValue)
{
#ifdef DEBUG_LOG
SPEEDCDLogWriteULong(ulValue);
SPEEDCDLogWriteString("\x0d\x0a");
#endif
}
VOID SPEEDCDLogSL(char * pMessage,ULONG ulValue)
{
#ifdef DEBUG_LOG
SPEEDCDLogWriteString(pMessage);
SPEEDCDLogWriteULong(ulValue);
SPEEDCDLogWriteString("\x0d\x0a");
#endif
}
VOID SPEEDCDLogS(char * pMessage)
{
#ifdef DEBUG_LOG
SPEEDCDLogWriteString(pMessage);
SPEEDCDLogWriteString("\x0d\x0a");
#endif
}
VOID SPEEDCDLogPU(PUNICODE_STRING puMessage)
{
#ifdef DEBUG_LOG
ANSI_STRING asValue;
char bufValue[512];
RtlInitAnsiString(&asValue,NULL);
asValue.Length = 0;
asValue.MaximumLength = 500;
asValue.Buffer = bufValue;
if (NT_SUCCESS(
RtlUnicodeStringToAnsiString( &asValue ,puMessage, FALSE)
))
{
if (asValue.Length < 501)
{
// add the null to the end of the string
asValue.Buffer[asValue.Length] = 0;
asValue.Length++;
SPEEDCDLogS(asValue.Buffer);
}
}
#endif
}
//
// Utility Function for reading the data file for the CD
//
NTSTATUS SPEEDCDReadOffset(PLARGE_INTEGER offset,PVOID dest,ULONG length,
PUNICODE_STRING pFileName)
{
IO_STATUS_BLOCK IoStatusBlock;
OBJECT_ATTRIBUTES ObjectAttributes;
NTSTATUS status;
HANDLE FileHandle;
SPEEDCDLogS("begin SPEEDCDReadOffset");
if (pFileName == NULL)
return STATUS_DEVICE_NOT_READY;
InitializeObjectAttributes(
&ObjectAttributes,
pFileName,//&fileName,
OBJ_CASE_INSENSITIVE, // attributes
NULL,
NULL
);
status = ZwCreateFile(
&FileHandle,
GENERIC_READ,
&ObjectAttributes,
&IoStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ, // share read so we can open the same file more than once
FILE_OPEN,
FILE_SYNCHRONOUS_IO_NONALERT,
NULL, /* optional */
0
);
if (NT_SUCCESS(status))
{
SPEEDCDLogS("open success");
// good!!!
// write something out and then close the file
status = ZwReadFile(
FileHandle,NULL,NULL,NULL,
&IoStatusBlock,dest,length,offset,NULL);
if (NT_SUCCESS(status))
SPEEDCDLogS("read success");
else
SPEEDCDLogS("read fail");
ZwClose(FileHandle);
}
return status;
}
//
// DRIVER ENTRY
//
NTSTATUS
DriverEntry(
IN OUT PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
/*++
Routine Description:
This routine is called by the Operating System to initialize the driver.
It fills in the dispatch entry points in the driver object. Then
SPEEDCDInitializeDisk is called to create the device object and complete
the initialization.
Arguments:
DriverObject - a pointer to the object that represents this device
driver.
RegistryPath - a pointer to our Services key in the registry.
... Services\\SPEEDCD
Return Value:
STATUS_SUCCESS if this disk is initialized; an error otherwise.
--*/
{
NTSTATUS ntStatus;
WCHAR DriveChar;
static WCHAR SubKeyString[] = L"\\Parameters";
UNICODE_STRING paramPath;
SPEEDCDLogS("-----Loading Driver-----");
//
// The registry path parameter points to our key, we will append
// the Parameters key and look for any additional configuration items
// there. We add room for a trailing NUL for those routines which
// require it.
paramPath.MaximumLength = RegistryPath->Length + sizeof(SubKeyString);
paramPath.Buffer = ExAllocatePool(PagedPool, paramPath.MaximumLength);
if (paramPath.Buffer != NULL)
{
RtlMoveMemory(
paramPath.Buffer, RegistryPath->Buffer, RegistryPath->Length);
RtlMoveMemory(
¶mPath.Buffer[RegistryPath->Length / 2], SubKeyString,
sizeof(SubKeyString));
paramPath.Length = paramPath.MaximumLength;
}
else
{
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// Initialize the driver object with this driver's entry points.
//
DriverObject->MajorFunction[IRP_MJ_CREATE] = SPEEDCDCreateClose;
DriverObject->MajorFunction[IRP_MJ_READ] = SPEEDCDReadWrite;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = SPEEDCDDeviceControl;
//
// register the driver unload function
//
#ifdef SPEEDCD_UNLOADABLE
DriverObject->DriverUnload = SPEEDCDUnloadDriver;
#endif
//
// We create one device object for our driver. This the special device that
// we can talk to from our win32 program to send ioctls to creat and destroy
// mounted cd devices.
//
// \\Devices\\SPEEDCD ====>> \\DosDevices\\SPEEDCD
//
{
UNICODE_STRING imagePathString;
NTSTATUS ntStatus1;
RtlInitUnicodeString( &imagePathString, L"\\??\\c:\\notarealpath.iso");
ntStatus1 = SPEEDCDInitializeVolumes(DriverObject, ¶mPath,NULL,&imagePathString,FALSE);
if (NT_SUCCESS(ntStatus1))
{
ntStatus = STATUS_SUCCESS;
}else
{
ntStatus = ntStatus1;
}
}
////////////
// DriveChar = L'A' -> 'Z'
for (DriveChar = L'A'; DriveChar <= L'Z'; DriveChar++)
// Init the volumes as stored in the registry.
{
//
// We use this to query into the registry as to whether we
// should mount a Z drive.
//
RTL_QUERY_REGISTRY_TABLE paramTable[2];
WCHAR ZStringBuf[500];
UNICODE_STRING ZString;
WCHAR DName[3];
DName[0] = DriveChar;
DName[1] = L'\0';
ZString.Buffer = ZStringBuf;
ZString.MaximumLength = 499 * sizeof(WCHAR);
ZString.Length = 0;
RtlZeroMemory(¶mTable[0], sizeof(paramTable));
paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
paramTable[0].Name = DName;
paramTable[0].EntryContext = &ZString;
if (!NT_SUCCESS(RtlQueryRegistryValues(
RTL_REGISTRY_ABSOLUTE,
paramPath.Buffer, paramTable, NULL, NULL)))
{
SPEEDCDLogS("Error quering Y string");
// oops failed
}else
{
SPEEDCDLogS("Success quering Y string");
SPEEDCDLogPU(&ZString);
if (ZString.Length > 0)
{
// success maybe :)
UNICODE_STRING Letter;
NTSTATUS ntStatus2;
SPEEDCDLogS("Y string length > 0");
DName[0] = DriveChar;
DName[1] = L':';
DName[2] = L'\0';
RtlInitUnicodeString( &Letter, DName);
ntStatus2 = SPEEDCDInitializeVolumes(DriverObject,
¶mPath,&Letter,&ZString,FALSE);
}
}
}
//
// We don't need that path anymore.
//
/*
if (paramPath.Buffer)
{
ExFreePool( paramPath.Buffer );
}
*/
return ntStatus;
}
NTSTATUS
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -