NTSTATUS GreDeviceIoControl(PDEVICE_OBJECT DeviceObject,ULONG IoControlCode,
void
*
InputBuffer,ULONG InputBufferSize,
void
*
OutputBuffer,ULONG OutputBufferSize,PULONG ReturnLength) { IO_STATUS_BLOCK Iosb;PIRP pIrp;NTSTATUS Status; pIrp
=
IoBuildDeviceIoControlRequest(IoControlCode,DeviceObject,InputBuffer,InputBufferSize,OutputBuffer,OutputBufferSize,FALSE,NULL,
&
Iosb);
if
(pIrp) { Status
=
IofCallDriver(DeviceObject,pIrp);
*
ReturnLength
=
Iosb.Information; } } NTSTATUS GetDeviceObjectByName(PUNICODE_STRING DeviceName,BOOLEAN CaseInsensitive,PDRIVER_OBJECT
*
DriverObject,PDEVICE_OBJECT
*
DeviceObject) { MakeUnicodeString(on,
"
\\Driver
"
);OBJECT_ATTRIBUTES oa;NTSTATUS status;HANDLE Dir;BOOLEAN Found
=
0
; InitializeObjectAttributes(
&
oa,
&
on,OBJ_CASE_INSENSITIVE,
0
,
0
); status
=
ZwOpenDirectoryObject(
&
Dir,DIRECTORY_QUERY,
&
oa);
if
(status
==
0
) { PDIRECTORY_BASIC_INFORMATION dbi;ULONG Context,ReturnLength;PUNICODE_STRING name; dbi
=
ExAllocatePoolWithTag(PagedPool,
4096
,
0
); name
=
ExAllocatePoolWithTag(PagedPool,
1024
,
0
);
if
(dbi
&&
name) { status
=
ZwQueryDirectoryObject(Dir,dbi,
4096
,
1
,
1
,
&
Context,
&
ReturnLength);
while
(status
==
STATUS_MORE_ENTRIES
||
status
==
STATUS_BUFFER_TOO_SMALL
||
status
==
0
) { PDRIVER_OBJECT driverobj; name
->
MaximumLength
=
768
; name
->
Buffer
=
(wchar_t
*
)(name
+
1
); memcpy(name
->
Buffer,L
"
\\Driver\\
"
,
sizeof
L
"
\\Driver\\
"
-
2
); memcpy((
char
*
)name
->
Buffer
+
sizeof
L
"
\\Driver\\
"
-
2
,dbi
->
ObjectName.Buffer,dbi
->
ObjectName.Length); name
->
Length
=
dbi
->
ObjectName.Length
+
sizeof
L
"
\\Driver\\
"
-
2
;
if
((status
=
ObReferenceObjectByName(name,OBJ_CASE_INSENSITIVE,
0
,
0
,IoDriverObjectType,KernelMode,
0
,(
void
**
)
&
driverobj))
==
0
) { PDEVICE_OBJECT deviceobj; deviceobj
=
driverobj
->
DeviceObject;
while
(deviceobj) {
if
(deviceobj)
if
((status
=
ObQueryNameString(deviceobj,name,
1024
,
&
ReturnLength))
==
0
) {
if
(name
->
Length)
if
(RtlCompareUnicodeString(DeviceName,name,CaseInsensitive)
==
0
) { Found
=
TRUE;
if
(DriverObject)
*
DriverObject
=
driverobj;
if
(DeviceObject)
*
DeviceObject
=
deviceobj;
break
; } } deviceobj
=
deviceobj
->
NextDevice; } ObfDereferenceObject(driverobj); }
if
(Found)
break
; status
=
ZwQueryDirectoryObject(Dir,dbi,
4096
,
1
,
0
,
&
Context,
&
ReturnLength); } ExFreePoolWithTag(dbi,
0
); ExFreePoolWithTag(name,
0
); status
=
Found
?
0
:STATUS_OBJECT_NAME_NOT_FOUND; } ZwClose(Dir); }
if
(
!
Found) {
if
(DriverObject)
*
DriverObject
=
0
;
if
(DeviceObject)
*
DeviceObject
=
0
; }
return
status; }
void
NTAPI DriverUnload(
struct
_DRIVER_OBJECT
*
DriverObject) { IoDeleteDevice(DriverObject
->
DeviceObject); } NTSTATUS NTAPI DispatchCreateClose(PDEVICE_OBJECT DeviceObject,PIRP Irp) { Irp
->
IoStatus.Status
=
Irp
->
IoStatus.Information
=
0
; IofCompleteRequest(Irp,IO_NO_INCREMENT);
return
0
; } NTSTATUS NTAPI DispatchDeviceControl(PDEVICE_OBJECT DeviceObject,PIRP Irp) { PIO_STACK_LOCATION IrpSp;NTSTATUS Status; IrpSp
=
IoGetCurrentIrpStackLocation(Irp);
switch
(IrpSp
->
Parameters.DeviceIoControl.IoControlCode) {
case
IOCTL_COPYMEMORY: { PMEMORY_BLOCK mem
=
(PMEMORY_BLOCK)IrpSp
->
Parameters.DeviceIoControl.Type3InputBuffer;
char
*
dest
=
(
char
*
)mem
->
dest,
*
src
=
(
char
*
)mem
->
src;size_t len
=
mem
->
len;
int
rev
=
mem
->
rev;
if
(mem
->
rev
==
0
) memcpy(dest,src,len);
else
{ size_t i;
for
(i
=
0
;i
<
len;i
+=
rev) { memcpy(dest
+
i,src
+
len
-
i
-
rev,rev); } } Irp
->
IoStatus.Information
=
mem
->
len; Status
=
0
; }
break
;
case
IOCTL_GETDEVICE: { PDEVNAME devname
=
(PDEVNAME)IrpSp
->
Parameters.DeviceIoControl.Type3InputBuffer; PDEVOBJS devobjs
=
(PDEVOBJS)Irp
->
UserBuffer; Status
=
GetDeviceObjectByName(
&
devname
->
DeviceName,devname
->
CaseInsensitive,(PDRIVER_OBJECT
*
)
&
devobjs
->
DriverObject,(PDEVICE_OBJECT
*
)
&
devobjs
->
DeviceObject); Irp
->
IoStatus.Information
=
Status
==
0
?
sizeof
(DEVOBJS):
0
; }
break
;
case
IOCTL_MAP_VIDEO_MEMORY: { PDEVICEADDR devaddr
=
(PDEVICEADDR)IrpSp
->
Parameters.DeviceIoControl.Type3InputBuffer; PDEVICE_OBJECT device
=
(size_t)devaddr
->
Device
>
65535
?
devaddr
->
Device:DeviceObjects[(size_t)devaddr
->
Device]; Status
=
GreDeviceIoControl(device,IOCTL_VIDEO_MAP_VIDEO_MEMORY,
&
devaddr
->
rqva,
sizeof
(VIDEO_MEMORY),(PVIDEO_MEMORY_INFORMATION)Irp
->
UserBuffer,
sizeof
(VIDEO_MEMORY_INFORMATION),
&
Irp
->
IoStatus.Information); }
break
;
case
IOCTL_UNMAP_VIDEO_MEMORY: { PDEVICEADDR devaddr
=
(PDEVICEADDR)IrpSp
->
Parameters.DeviceIoControl.Type3InputBuffer; PDEVICE_OBJECT device
=
(size_t)devaddr
->
Device
>
65535
?
devaddr
->
Device:DeviceObjects[(size_t)devaddr
->
Device]; Status
=
GreDeviceIoControl(device,IOCTL_VIDEO_UNMAP_VIDEO_MEMORY,
&
devaddr
->
rqva,
sizeof
(VIDEO_MEMORY),
0
,
0
,
&
Irp
->
IoStatus.Information); }
break
;
case
IOCTL_DEVICE_IO_CONTROL: { PDEVIOCTRL
params
=
(PDEVIOCTRL)IrpSp
->
Parameters.DeviceIoControl.Type3InputBuffer; Status
=
GreDeviceIoControl((PDEVICE_OBJECT)
params
->
DeviceObject,
params
->
IoControlCode,
params
->
InputBuffer,
params
->
InputBufferSize,
params
->
OutputBuffer,
params
->
OutputBufferSize,
&
Irp
->
IoStatus.Information); }
break
;
default
:Irp
->
IoStatus.Information
=
0
; } Irp
->
IoStatus.Status
=
Status; IofCompleteRequest(Irp,IO_NO_INCREMENT);
return
Status; } NTSTATUS NTAPI DriverEntry(
struct
_DRIVER_OBJECT
*
DriverObject,PUNICODE_STRING RegistryPath) { NTSTATUS Status;MakeUnicodeString(DeviceName,
"
\\??\\viddev
"
); MakeUnicodeString(n,
"
ObQueryNameString
"
); ObQueryNameString
=
MmGetSystemRoutineAddress(
&
n);
if
((Status
=
IoCreateDevice(DriverObject,
0
,
&
DeviceName,FILE_DEVICE_UNKNOWN,
0
,
0
,
&
ThisDeviceObject))
==
0
) { DriverObject
->
MajorFunction[IRP_MJ_CREATE]
=
DriverObject
->
MajorFunction[IRP_MJ_CLOSE]
=
DispatchCreateClose; DriverObject
->
MajorFunction[IRP_MJ_DEVICE_CONTROL]
=
DispatchDeviceControl; DriverObject
->
DriverUnload
=
DriverUnload; }
return
Status; }