作 者: mickeylan
時 間: 2008-06-16,11:33
鏈 接: http://bbs.pediy.com/showthread.php?t=66661
上篇教程我們學習了通過Section在用戶進程和內核驅動程序之間共享信息的方法,但是這種方法有一個缺點,就是驅動程序被硬性限制在具體進程的地址上下文中,即驅動程序所使用的虛擬地址位於此進程的地址空間中。我們在本例中使用的方法將沒有這個缺點。對於驅動程序來說,這種方法更為自然些。
首先來看看驅動程序。
代碼:unit SharingMemory;
interface
uses
nt_status, ntoskrnl, native, winioctl, fcall, macros;
function _DriverEntry(pDriverObject:PDRIVER_OBJECT; pusRegistryPath:PUNICODE_STRING): NTSTATUS; stdcall;
implementation
uses
seh;
var
g_pSharedMemory: PVOID;
g_pMdl: PVOID;
g_pUserAddress: PVOID;
g_fTimerStarted: boolean;
g_usDeviceName, g_usSymbolicLinkName: UNICODE_STRING;
{更新系統時間到共享內存}
procedure UpdateTime; stdcall;
var
SysTime:LARGE_INTEGER;
begin
KeQuerySystemTime(@SysTime);
ExSystemTimeToLocalTime(@SysTime, g_pSharedMemory);
end;
procedure TimerRoutine(pDeviceObject:PDEVICE_OBJECT; pContext:PVOID); stdcall;
begin
UpdateTime;
end;
{清理過程--釋放資源}
procedure Cleanup(pDeviceObject:PDEVICE_OBJECT); stdcall;
begin
if g_fTimerStarted then
begin
IoStopTimer(pDeviceObject);
DbgPrint(SharingMemory: Timer stopped#13#10);
end;
if (g_pUserAddress <> nil) and (g_pMdl <> nil) then
begin
MmUnmapLockedPages(g_pUserAddress, g_pMdl);
DbgPrint(SharingMemory: Memory at address %08X unmapped#13#10,
g_pUserAddress);
g_pUserAddress := nil;
end;
if g_pMdl <> nil then
begin
IoFreeMdl(g_pMdl);
DbgPrint(SharingMemory: MDL at address %08X freed#13#10,
g_pMdl);
g_pMdl := nil;
end;
if g_pSharedMemory <> nil then
begin
ExFreePool(g_pSharedMemory);
DbgPrint(SharingMemory: Memory at address %08X released#13#10,
g_pSharedMemory);
g_pSharedMemory := nil;
end;
end;
function DispatchCleanup(pDeviceObject:PDEVICE_OBJECT; p_Irp:PIRP): NTSTATUS; stdcall;
begin
DbgPrint(#13#10SharingMemory: Entering DispatchCleanup#13#10);
Cleanup(pDeviceObject);
p_Irp^.IoStatus.Status := STATUS_SUCCESS;
p_Irp^.IoStatus.Information := 0;
IofCompleteRequest(p_Irp, IO_NO_INCREMENT);
DbgPrint(SharingMemory: Leaving DispatchCleanup#13#10);
result := STATUS_SUCCESS;
end;
function DispatchCreateClose(p_DeviceObject:PDEVICE_OBJECT; p_Irp:PIRP): NTSTATUS; stdcall;
begin
p_Irp^.IoStatus.Status := STATUS_SUCCESS;
p_Irp^.IoStatus.Information := 0;
IofCompleteRequest(p_Irp, IO_NO_INCREMENT);
result := STATUS_SUCCESS;
end;
function DispatchControl(p_DeviceObject: PDEVICE_OBJECT; p_Irp:PIRP): NTSTATUS; stdcall;
label
SafePlace;
var
dwContext:DWORD;
psl:PIO_STACK_LOCATION;
IOCTL_GIVE_ME_YOUR_MEMORY: DWORD;
pSystemBuffer: PVOID;
begin
DbgPrint(#13#10SharingMemory: Entering DispatchControl#13#10);
IOCTL_GIVE_ME_YOUR_MEMORY := CTL_CODE(FILE_DEVICE_UNKNOWN,
$800, METHOD_BUFFERED,
FILE_READ_ACCESS);
p_Irp^.IoStatus.Status := STATUS_UNSUCCESSFUL;
p_Irp^.IoStatus.Information := 0;
psl := IoGetCurrentIrpStackLocation(p_Irp); {取IRP的stack location的指針}
if psl^.Parameters.DeviceIoControl.IoControlCode = IOCTL_GIVE_ME_YOUR_MEMORY then
begin
{是我們控制碼就開始處理}
if psl^.Parameters.DeviceIoControl.OutputBufferLength >= sizeof(PVOID) then
begin
g_pSharedMemory := ExAllocatePool(NonPagedPool, PAGE_SIZE);
if g_pSharedMemory <> nil then
begin
DbgPrint(SharingMemory: %X bytes of nonpaged memory allocated at address %08X#13#10,
PAGE_SIZE, g_pSharedMemory);
g_pMdl := IoAllocateMdl(g_pSharedMemory, PAGE_SIZE,
false, false, nil);
if g_pMdl <> nil then
begin
DbgPrint(SharingMemory: MDL allocated at address %08X#13#10,
g_pMdl);
MmBuildMdlForNonPagedPool(g_pMdl);
{安裝SEH}
asm
push offset DefaultExceptionHandler
push fs:[0]
mov fs:[