DriverObject->MajorFunction[IRP_MJ_CLOSE] =
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = CommonDispatch;
// 為什么不用RtlInitUnicodeString( &ntUnicodeString, NT_DEVICE_NAME );代替
RtlInitAnsiString(&SourceString, NT_DEVICE_NAME);
RtlAnsiStringToUnicodeString(&DeviceName, &SourceString, TRUE);
RtlInitAnsiString(&SourceString, DOS_DEVICE_NAME);
RtlAnsiStringToUnicodeString(&SymbolicLinkName, &SourceString, TRUE);
ntStatus = IoCreateDevice(
DriverObject, // Our Driver Object
0, // We don’t use a device extension
&DeviceName,
FILE_DEVICE_NULL, // Device type
0, // Device characteristics //此處應該用FILE_DEVICE_SECURE_OPEN吧?
FALSE, // Not an exclusive device
&DeviceObject ); // Returned ptr to Device Object
if ( !NT_SUCCESS( ntStatus ) )
{
goto End;
}
ntStatus = IoCreateSymbolicLink( &SymbolicLinkName, &DeviceName );
if ( !NT_SUCCESS( ntStatus ) )
{
cur_device_object = DriverObject->DeviceObject;
while (cur_device_object)
{
next_device_object = DeviceObject->NextDevice;
IoDeleteDevice(cur_device_object);
cur_device_object = next_device_object;
}
}
End:
RtlFreeUnicodeString(&DeviceName);
RtlFreeUnicodeString(&SymbolicLinkName);
return STATUS_SUCCESS;
}
VOID
Unload(
IN PDRIVER_OBJECT DriverObject
)
{
ANSI_STRING SourceString;
PDEVICE_OBJECT DeviceObject = NULL; // ptr to device object
UNICODE_STRING SymbolicLinkName;
PDEVICE_OBJECT cur_device_object;
PDEVICE_OBJECT next_device_object;
if (g_ResData)
{
ExFreePool(g_ResData);
}
if (DriverObject)
{
RtlInitAnsiString(&SourceString, DOS_DEVICE_NAME);
RtlAnsiStringToUnicodeString(&SymbolicLinkName, &SourceString, TRUE);
IoDeleteSymbolicLink(&SymbolicLinkName);
RtlFreeUnicodeString(&SymbolicLinkName);
cur_device_object = DriverObject->DeviceObject;
while (cur_device_object)
{
next_device_object = DeviceObject->NextDevice;
IoDeleteDevice(cur_device_object);
cur_device_object = next_device_object;
}
}
}
NTSTATUS
CommonDispatch(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PDEVICE_OBJECT DRO_DeviceObject = NULL; // ptr to device object
PFILE_OBJECT DRO_FileObject;
ANSI_STRING SourceString;
UNICODE_STRING DRO_DeviceName;
PIO_STACK_LOCATION irpSp;// Pointer to current stack location
NTSTATUS ntStatus = STATUS_SUCCESS;// Assume success
ULONG inBufLength; // Input buffer length
ULONG outBufLength; // Output buffer length
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
irpSp = IoGetCurrentIrpStackLocation( Irp );
inBufLength = irpSp->Parameters.DeviceIoControl.InputBufferLength;
outBufLength = irpSp->Parameters.DeviceIoControl.OutputBufferLength;
if(!inBufLength || !outBufLength)
{
ntStatus = STATUS_INVALID_PARAMETER;
goto End;
}
switch ( irpSp->MajorFunction )
{
case IRP_MJ_CREATE:
RtlInitAnsiString(&SourceString, DR0_DEVICE_NAME);
RtlAnsiStringToUnicodeString(&DRO_DeviceName, &SourceString, TRUE);
IoGetDeviceObjectPointer(&DRO_DeviceName, 0x80,&DRO_FileObject, &DRO_DeviceObject);
g_DR0_DeviceObject = DRO_FileObject->DeviceObject;
//保存DR0上的附加設備,然后斷開(kāi)附加,等IRP_MJ_CLOSE時(shí)恢復附加
if (DRO_FileObject->DeviceObject->AttachedDevice)
{
g_OldAttachedDeviceOfDR0 = DRO_FileObject->DeviceObject->AttachedDevice;
DRO_FileObject->DeviceObject->AttachedDevice= NULL;
}
ObDereferenceObject(DRO_FileObject);
RtlFreeUnicodeString(&DRO_DeviceName);
break;
case IRP_MJ_CLOSE:
if (g_DR0_DeviceObject)
{
if (g_OldAttachedDeviceOfDR0)
{
g_DR0_DeviceObject->AttachedDevice = g_OldAttachedDeviceOfDR0;
}
}
break;
case IRP_MJ_DEVICE_CONTROL:
if ( irpSp->Parameters.DeviceIoControl.IoControlCode == 0x0F0003C04)
{
if (outBufLength < g_ResDataSize)
goto End;
// 此處就是提取驅動(dòng)里的資源解碼返回給ap層,很簡(jiǎn)單,不再反匯編了,此處省略
// 唯一不理解的是既然是雙緩沖應該用IRP.AssociatedIrp.SystemBuffer返回給ap才是
// 難道此時(shí)Irp->AssociatedIrp.SystemBuffer和Irp->UserBuffer地址相同??
RtlCopyMemory(Irp->UserBuffer, g_ResData, g_ResDataSize);
Irp->IoStatus.Information = g_ResDataSize;
}
else
{
ntStatus = STATUS_INVALID_DEVICE_REQUEST;
}
break;
default:
//
// The specified I/O control code is unrecognized by this driver.
//
ntStatus = STATUS_INVALID_DEVICE_REQUEST;
break;
}
End:
//
// Finish the I/O operation by simply completing the packet and returning
// the same status as in the packet itself.
//
Irp->IoStatus.Status = ntStatus;
IoCompleteRequest( Irp, IO_NO_INCREMENT );
return ntStatus;
}