当前位置:编程学习 > Delphi >>

Delphi研究之驱动开发篇(七)--利用共享内存与用户模式程序通讯(上)

作 者: 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:[

补充:软件开发 , Delphi ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,