analytics

2010年9月25日星期六

在驱动中使用DLL

MS允许在驱动中使用DLL,除了不能调用UserMode API外,几乎没有其他限制,包括支持动态调用和静态编译调用。

1.Kernel DLL 生成
使用DDK生成kernel dll是非常简单的,只要注意少数几个地方既可以
  • source
    关键点在于声明EXPORT_DRIVER和指定DEF
TARGETNAME=sampledll
TARGETTYPE=EXPORT_DRIVER
TARGETPATH = obj$(BUILD_ALT_DIR)
DRIVERTYPE = WDM
DLLDEF=sampledll.def
MSC_WARNING_LEVEL=/W3
INCLUDES=$(DDK_INC_PATH)       
SOURCES=sampledll.cpp
  
 
  • def
   def中除了指定导出函数外,不可缺少的是必须定义DllInittiallize和DllUnload并且声明为Private
NAME SAMPLEDLL.SYS

EXPORTS
  DllInitialize PRIVATE
  DllUnload PRIVATE
  SampleOutput
  • c/cpp
   C/CPP 中除了要实现def中定义的函数外,必须有DriverEntry。当然,这个DriverEntry不需要做任何处理,只要存在即可。
#include <wdm.h>

EXTERN_C NTSTATUS
DriverEntry(
  IN PDRIVER_OBJECT DriverObject,
  IN PUNICODE_STRING RegistryPath
);
EXTERN_C DECLSPEC_IMPORT NTSTATUS SampleOutput(char *output);

NTSTATUS
DriverEntry(
  IN PDRIVER_OBJECT DriverObject,
  IN PUNICODE_STRING RegistryPath
)
{
    return STATUS_SUCCESS;
}

NTSTATUS DllInitialize(IN PUNICODE_STRING RegistryPath)
{
  DbgPrint("SAMPLE: DllInitialize(%wZ)\n", RegistryPath);
  return STATUS_SUCCESS;
}

NTSTATUS DllUnload()
{
  DbgPrint("SAMPLE: DllUnload\n");
  return STATUS_SUCCESS;
}

NTSTATUS SampleOutput(char *output)
{
    DbgPrint("SampleOutput: %s\n", output);
    return STATUS_SUCCESS;
}
2.Kernel DLL 调用
  如前文所述,MS同时支持使用导出Lib静态link或者动态调用,但实际上,考虑到使用DLL的初衷,动态调用几乎没有意义。因为MS并没有提供kernel可用的类似于LoadLibrary的API,而需要使用IOCTL来定义导出函数,也就是说DLL同样需要像驱动一样安装,才能在其他驱动中通过IOCTL来调用,这样一来似乎没什么必要的理由来使用DLL了,kernel提供很多类似方式,loaddriver,callback等等,DLL没有优势。所以通常的我们选择将编译生成的导出Lib直接link进驱动中,即可在驱动中使用DLL中提供的函数,需要注意的是DLL要和driver一样复制到SYSTEM32\driver下面。通过DbgPrint可以看到,driver 被load时,DLLInitialize就被调用了。理论上只要不更改DEF的定义,替换DLL可以不重新编译driver。

没有评论:

发表评论