Tomgin
驱动牛犊
驱动牛犊
  • 注册日期2001-08-08
  • 最后登录2005-06-06
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:9495回复:22

Win2K 下动态加载驱动程序

楼主#
更多 发布于:2001-09-24 14:45
加载一个驱动程序,主要就是,在
 SYSTEM\CurrentControlSet\Services  建一个键。
如:
 SYSTEM\CurrentControlSet\Services\Twdm1
  Type(1)
ErrorControl(0)
Start(3)

多数驱动程序都是通过设置 Start 的值为 0, 1, 2 。
在系统启动的过程中加载驱动程序。

在 win2k 下驱动程序的加载处理上述方式外,
还可以在应用程序里用 Service Api 实现,驱动程序的动态加载。
这时候的 Start 为 3 。

所用到的 Api 为:
 OpenSCManager, CreateService, OpenService, StartService
 ControlService, DeleteService, CloseServiceHandle

其中需要说明的是:
 CreateService :他通过参数在注册表里自动创建驱动程序需要的键值。
 DeleteService :他自动删除驱动程序在注册表里创的键值。

下面是一个,简单的例子:

应用程序:

#include "stdafx.h"
#include <windows.h>
#include <winsvc.h>
#include <conio.h>

void DelSvr( char * szSvrName ); //自动卸载驱动程序。

int main(int argc, char* argv[])
{
  HANDLE hWdm;
  printf("Hello World!\n");

  SC_HANDLE hServiceMgr, hServiceTwdm;
  BOOL bRtn;
  DWORD dwRtn, dwSize = 256;
  char szDir[256];

  if( argc > 1 ) //加任一个参数表示卸载驱动程序。
  {
    DelSvr( "Twdm1" );
    return 0;
  }

  GetCurrentDirectory( dwSize, szDir );//取当前目录
  strcat( szDir, "\\Twdm.sys" ); //取驱动程序的全路径

  LPCTSTR lpszBinaryPathName = TEXT(szDir);
  hServiceMgr = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS ); //打开服务控制管理器

  if( hServiceMgr == NULL )
  {
    printf( "OpenSCManager() Faild  %d ! \n", GetLastError() );
    return 0;
  }
  else
  {
    printf( "OpenSCManager()  ok ! \n" );
  }

  hServiceTwdm = CreateService( hServiceMgr,
TEXT("Twdm1"),        //SYSTEM\CurrentControlSet\Services 驱动程序的在注册表中的名字
TEXT("Twdm1"),        // 注册表驱动程序的 DisplayName 值
SERVICE_ALL_ACCESS,   // 加载驱动程序的访问权限
SERVICE_KERNEL_DRIVER,// 表示加载的服务是驱动程序
SERVICE_DEMAND_START, // 注册表驱动程序的 Start 值
SERVICE_ERROR_IGNORE, // 注册表驱动程序的 ErrorControl 值
lpszBinaryPathName,   // 注册表驱动程序的 ImagePath 值
NULL,
NULL,
NULL,
NULL,
NULL);

  if( hServiceTwdm == NULL )
  {
    dwRtn = GetLastError();
    if( dwRtn != ERROR_IO_PENDING && dwRtn != ERROR_SERVICE_EXISTS )
    {
      CloseServiceHandle( hServiceMgr );
      printf( "CrateService() Faild %d ! \n", dwRtn );
      return 0;
    }
    else
    {
      printf( "CrateService() Faild Service is ERROR_IO_PENDING or ERROR_SERVICE_EXISTS! \n" );
    }

    // 驱动程序已经加载,只需要打开
    hServiceTwdm = OpenService( hServiceMgr, TEXT("Twdm1"), SERVICE_ALL_ACCESS );
    if( hServiceTwdm == NULL )
    {
      dwRtn = GetLastError();
      CloseServiceHandle( hServiceMgr );
      printf( "OpenService() Faild %d ! \n", dwRtn );
      return 0;
    }
    else
    {
      printf( "OpenService() ok ! \n" );
    }
  }
  else
  {
    printf( "CrateService() ok  ! \n" );
  }

  // 启动驱动程序,调用驱动程序的 DriverEntry 函数
  bRtn = StartService( hServiceTwdm, NULL, NULL );
  if( !bRtn )
  {
    dwRtn = GetLastError();
    if( dwRtn != ERROR_IO_PENDING && dwRtn != ERROR_SERVICE_ALREADY_RUNNING )
    {
      printf( "StartService() Faild  %d ! \n", dwRtn );
      CloseServiceHandle( hServiceTwdm );
      CloseServiceHandle( hServiceMgr );
      return 0;
    }
    else
    {
      if( dwRtn != ERROR_IO_PENDING  )
      {
        printf( "StartService() Faild  ERROR_IO_PENDING ! \n");
      }
      else
      {
        printf( "StartService() Faild  ERROR_SERVICE_ALREADY_RUNNING ! \n");
      }
    }
  }

  //测试驱动程序
  hWdm = CreateFile("\\\\.\\Twdm1",
     GENERIC_WRITE | GENERIC_READ,
     0,
     NULL,
     OPEN_EXISTING,
     0,
     NULL);
  if( hWdm != INVALID_HANDLE_VALUE )
  {
    printf( "Open Driver Twdm ok ! \n" );
  }
  else
  {
    printf( "Open Driver Twdm faild %d ! \n", GetLastError() );
  }
  CloseHandle( hWdm );
  CloseServiceHandle( hServiceTwdm );
  CloseServiceHandle( hServiceMgr );

  //这时候你可以通过注册表,或其他查看符号连接的软件验证。
  printf( "按任意键 卸载驱动程序 !\n" );
  getch();
  //卸载驱动程序。
  DelSvr( "Twdm1" );
  return 0;
}

//卸载驱动程序。
void DelSvr( char * szSvrName )
{
  SC_HANDLE hServiceMgr, hServiceTwdm;
  SERVICE_STATUS  SvrSta;
  hServiceMgr = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS );
  if( hServiceMgr == NULL )
  {
    printf( "DelSvr::OpenSCManager() Faild  %d ! \n", GetLastError() );
    return;
  }
  else
  {
    printf( "DelSvr::OpenSCManager()  ok ! \n" );
  }
  hServiceTwdm = OpenService( hServiceMgr, TEXT(szSvrName), SERVICE_ALL_ACCESS );

  if( hServiceTwdm == NULL )
  {
    CloseServiceHandle( hServiceMgr );
    printf( "DelSvr::OpenService() Faild %d ! \n", GetLastError() );
    return;
  }
  else
  {
    printf( "DelSvr::OpenService() ok ! \n" );
  }
  //停止驱动程序,如果停止失败,只有重新启动才能,再动态加载。
  if( !ControlService( hServiceTwdm, SERVICE_CONTROL_STOP , &SvrSta ) )
  {
    printf( "DelSvr::ControlService() Faild  %d !\n", GetLastError() );
  }
  else
  {
    printf( "DelSvr::ControlService() ok !\n" );
  }
  //动态卸载驱动程序。
  if( !DeleteService( hServiceTwdm ) )
  {
    printf( "DelSvr::DeleteSrevice() Faild  %d !\n", GetLastError() );
  }
  else
  {
    printf( "DelSvr::DeleteSrevice() ok !\n" );
  }
  CloseServiceHandle( hServiceTwdm );
  CloseServiceHandle( hServiceMgr );
  return;
}

驱动程序:驱动程序很简单,
只有一个文件,实现了DriverEntry,DispatchCreate,DispatchClose,GpdUnload 四个函数。

#include <ntddk.h>

#define NT_DEVICE_NAME L"\\Device\\Twdm1"
#define DOS_DEVICE_NAME L"\\DosDevices\\Twdm1"

NTSTATUS DriverEntry( IN PDRIVER_OBJECT  DriverObject, IN PUNICODE_STRING RegistryPath );
NTSTATUS DispatchCreate(PDEVICE_OBJECT fdo, PIRP Irp);
NTSTATUS DispatchClose(PDEVICE_OBJECT fdo, PIRP Irp);
VOID GpdUnload(PDRIVER_OBJECT DriverObject);

//////////////////////
PDEVICE_OBJECT fdo;
BOOLEAN         fSymbolicLink;


NTSTATUS DriverEntry( IN PDRIVER_OBJECT  DriverObject, IN PUNICODE_STRING RegistryPath )
{

    //UNREFERENCED_PARAMETER (RegistryPath);
    NTSTATUS status;
    UNICODE_STRING              ntDeviceName;
    UNICODE_STRING              win32DeviceName;

    DbgPrint( "TWDM: DriverEntry for Twdm.sys ...... \n" );
    fSymbolicLink = FALSE;
    
    //
    // Create dispatch points for the IRPs.
    //
    
    DriverObject->MajorFunction[IRP_MJ_CREATE]          = DispatchCreate;
    DriverObject->MajorFunction[IRP_MJ_CLOSE]           = DispatchClose;
    //DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]  = GpdDispatch;
    DriverObject->DriverUnload                          = GpdUnload;
    //DriverObject->MajorFunction[IRP_MJ_PNP]            = GpdDispatchPnp;
    //DriverObject->MajorFunction[IRP_MJ_POWER]          = GpdDispatchPower;
    //DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = GpdDispatchSystemControl;
    //DriverObject->DriverExtension->AddDevice           = GpdAddDevice;

    RtlInitUnicodeString(&ntDeviceName, NT_DEVICE_NAME);

    //创建设备
    status = IoCreateDevice(DriverObject,
0,
&ntDeviceName,
FILE_DEVICE_UNKNOWN,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&fdo);

    if (!NT_SUCCESS (status))
    {
DbgPrint( "TWDM: IoCreateDevice() faild ! \n" );
    }
    else
    {
DbgPrint( "TWDM: IoCreateDevice() ok ! \n" );
RtlInitUnicodeString(&win32DeviceName, DOS_DEVICE_NAME);

//创建符号连接
status = IoCreateSymbolicLink( &win32DeviceName, &ntDeviceName );
     if (!NT_SUCCESS(status))
{
 DbgPrint( "TWDM: IoCreateSymbolicLink() faild ! \n" );
}
else
{
    DbgPrint( "TWDM: IoCreateSymbolicLink() ok ! \n" );
 fSymbolicLink = TRUE;
}
     fdo->Flags &= ~DO_DEVICE_INITIALIZING;
    }

    if (!NT_SUCCESS(status))
    {
if(fdo)
{
 IoDeleteDevice(fdo);
}
if(fSymbolicLink)
{
 IoDeleteSymbolicLink(&win32DeviceName);
}
    }
    return status;
}

NTSTATUS DispatchCreate(PDEVICE_OBJECT fdo, PIRP Irp)
{
NTSTATUS status;
DbgPrint( "TWDM: IRP_MJ_CREATE for Twdm.sys ...... \n" );
status = STATUS_SUCCESS;
return status;
} // DispatchCreate

NTSTATUS DispatchClose(PDEVICE_OBJECT fdo, PIRP Irp)
{ // DispatchClose
NTSTATUS status;
DbgPrint( "TWDM: IRP_MJ_CLOSE for Twdm.sys ...... \n" );
status = STATUS_SUCCESS;
return status;
} // DispatchClose

VOID GpdUnload(PDRIVER_OBJECT DriverObject)
{
    UNICODE_STRING                  win32DeviceName;

    DbgPrint( "TWDM: GpdUnload() for Twdm.sys ...... \n" );

    RtlInitUnicodeString(&win32DeviceName, DOS_DEVICE_NAME);
    if(fdo)
    {
IoDeleteDevice(fdo);
    }
    if(fSymbolicLink)
    {
IoDeleteSymbolicLink(&win32DeviceName);
    }
}


努力呀,还有许多东西不会呢。
Tomgin
驱动牛犊
驱动牛犊
  • 注册日期2001-08-08
  • 最后登录2005-06-06
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2001-09-24 14:48
Test1.zip 是源代码。

其中驱动程序部分的一个文件,修改以下就可以了。

Mk.cmd

@echo off
echo Aouther     : Qian
echo Date        : 2001.9.20
echo Function    :  Start DDK Environment And Build Driver
call c:\NTDDK\bin\setenv.bat c:\NTDDK checked    //此处改为你的 2k ddk 的路径
rem call c:\NTDDK\bin\setenv.bat c:\NTDDK free
echo on

d:        //此处改为你的编写驱动程序的驱动器
cd \work\qian\wdm\test1\sys  ////此处改为你的编写驱动程序的目录


build -b -w -nmake /a

努力呀,还有许多东西不会呢。
matt
驱动中牛
驱动中牛
  • 注册日期2001-07-24
  • 最后登录2016-02-25
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2001-10-23 17:38
动态卸载行不行?
我试过Filemon,但不能动态卸载,这样调试起来不太方便!
System Internals http://sys.xiloo.com
Tomgin
驱动牛犊
驱动牛犊
  • 注册日期2001-08-08
  • 最后登录2005-06-06
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地板#
发布于:2001-10-24 08:42
当然没有问题,你说过的情况我遇到过。
在 unload 里只删除创建的 device ,而没有删除 符号连接的
时候,查看设备表时发现设备已经卸载。但是重新加载驱动程序
却会失败。重新启动机器就可以加载了。

你可以下载 test1.zip 试试。
努力呀,还有许多东西不会呢。
z_j_cd
驱动中牛
驱动中牛
  • 注册日期2001-09-13
  • 最后登录2012-11-30
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望2点
  • 贡献值0点
  • 好评度2点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2001-10-24 10:47
Asm386 说的有道理,我看filemon时也对动态卸载报错搞不懂
wangzai
驱动牛犊
驱动牛犊
  • 注册日期2002-03-08
  • 最后登录2015-12-21
  • 粉丝2
  • 关注0
  • 积分139分
  • 威望252点
  • 贡献值0点
  • 好评度12点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2002-04-15 11:08
请问 test1.zip  在 哪里??
Tomgin
驱动牛犊
驱动牛犊
  • 注册日期2001-08-08
  • 最后登录2005-06-06
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2002-04-16 08:56
http://www.csdn.net/develop/read_article.asp?id=10729

这里也有。这是最简单的例子。
如果驱动里使用了 irp 或者需要
应用程序用 deviceiocontrol 与驱动通信的话,还要加点处理。

在 create 和 close 里加上下面的处理。
status = STATUS_SUCCESS;
Irp->IoStatus.Status  = status;
Irp->IoStatus.Information = 0;
IoCompleteRequest( Irp, IO_NO_INCREMENT );

努力呀,还有许多东西不会呢。
yoboo_y
驱动牛犊
驱动牛犊
  • 注册日期2001-11-23
  • 最后登录2005-01-10
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2002-04-28 17:42
关注!
yb_fly
AChen
驱动牛犊
驱动牛犊
  • 注册日期2002-02-25
  • 最后登录2002-10-15
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
8楼#
发布于:2002-04-28 18:22
Filemon 在 Free版把 irp_mj_unload屏蔽了,自然不能unload.
在checked版,运行应用程序关闭时不能unload这是因为还有
未完成的IRP,此时你断开所以监控的盘,一段时间(有长有短)
它就能顺利unload的。
This posting is provided "AS IS" with no warranties, and confers no rights.
wesintj
驱动牛犊
驱动牛犊
  • 注册日期2002-12-05
  • 最后登录2007-04-29
  • 粉丝0
  • 关注0
  • 积分10分
  • 威望1点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
9楼#
发布于:2002-12-11 18:24
http://www.csdn.net/develop/read_article.asp?id=10729
的test1.zip
DOWN不下来,谁能给我发一份或是类似这个例子的VC工程,多谢了!
100分奉上!
WESIN@MYREALBOX.COM


[编辑 -  12/11/02 by  wesintj]

[编辑 -  12/11/02 by  wesintj]
zxy2845986
驱动牛犊
驱动牛犊
  • 注册日期2002-08-21
  • 最后登录2016-01-07
  • 粉丝0
  • 关注0
  • 积分1分
  • 威望10点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
10楼#
发布于:2002-12-11 20:07
我也要一份
zxy2845986@163.com
DUPONTYP
驱动牛犊
驱动牛犊
  • 注册日期2002-11-30
  • 最后登录2004-04-20
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
11楼#
发布于:2002-12-11 21:20
我也要一份
dupontyp@hotmail.com
guard2002
驱动中牛
驱动中牛
  • 注册日期2002-05-21
  • 最后登录2017-03-07
  • 粉丝0
  • 关注0
  • 积分46分
  • 威望65点
  • 贡献值0点
  • 好评度4点
  • 原创分0分
  • 专家分0分
  • 社区居民
12楼#
发布于:2002-12-12 08:59
我也要一份
jsguard2002@163.com
domore
驱动中牛
驱动中牛
  • 注册日期2002-04-06
  • 最后登录2008-04-05
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
13楼#
发布于:2002-12-12 09:54
请给我发一份
domore@vip.sina.com
Tomgin
驱动牛犊
驱动牛犊
  • 注册日期2001-08-08
  • 最后登录2005-06-06
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
14楼#
发布于:2002-12-12 13:09
上传
附件名称/大小 下载次数 最后更新
2002-12-12_Test1.zip (48KB)  123
努力呀,还有许多东西不会呢。
wesintj
驱动牛犊
驱动牛犊
  • 注册日期2002-12-05
  • 最后登录2007-04-29
  • 粉丝0
  • 关注0
  • 积分10分
  • 威望1点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
15楼#
发布于:2002-12-12 14:33
万分 感谢Tomgin的善举
100分在
http://www.driverdevelop.com/forum/html_29515.html?1039674769
送出
Tomgin
驱动牛犊
驱动牛犊
  • 注册日期2001-08-08
  • 最后登录2005-06-06
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
16楼#
发布于:2002-12-13 12:44
不必,应该做的。
我在这个论坛上也学到了不少东西。
努力呀,还有许多东西不会呢。
wenzihe
驱动牛犊
驱动牛犊
  • 注册日期2003-12-02
  • 最后登录2005-10-08
  • 粉丝0
  • 关注0
  • 积分2分
  • 威望1点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
17楼#
发布于:2004-03-27 21:40
谁编译过test1.zip?
我编译通过,但没有生成sys
倒是作者给的sys可以加载
怎么回事?
顶住 一个业余大菜鸟
cicada
驱动小牛
驱动小牛
  • 注册日期2003-12-09
  • 最后登录2008-07-11
  • 粉丝1
  • 关注0
  • 积分74分
  • 威望15点
  • 贡献值0点
  • 好评度7点
  • 原创分0分
  • 专家分0分
18楼#
发布于:2004-10-16 10:40
我为什么不能动态加载呢?
执行CreateService时返回0。
可是执行OpenService时确实正确的。
之后执行到StartService时返回的又是0。最好是执行失败。
这是为什么?望指点。
xbzjackey
驱动小牛
驱动小牛
  • 注册日期2002-12-27
  • 最后登录2016-01-07
  • 粉丝0
  • 关注0
  • 积分5分
  • 威望34点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
19楼#
发布于:2005-01-11 14:51
好帖子啊
回答好的不要忘了给分哦。。。
上一页
游客

返回顶部