首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 嵌入开发 > 驱动开发 >

为啥wdm驱动加载后自动卸载并继续加载

2013-01-11 
【求助】为啥wdm驱动加载后自动卸载并继续加载?刚看书上wdm驱动的介绍,自己动手写了个wdm驱动,本以为编译成

【求助】为啥wdm驱动加载后自动卸载并继续加载?

刚看书上wdm驱动的介绍,自己动手写了个wdm驱动,本以为编译成功便完事,没想到winxp上一加载,就自己卸载,并继续加载,并循环下去,看了半天,不得解,求帮助~~。下面是代码,主要是参考张帆的windows驱动详解:


#ifdef __cplusplus
extern "C"
{

#endif
#include <wdm.h>
#ifdef __cplusplus
}
#endif

#define arraysize(p) (sizeof(p)/sizeof((p)[0]))

typedef struct _DEVICE_EXTENSION
{
  PDEVICE_OBJECT fdo;
  PDEVICE_OBJECT NextStackDevice;
  UNICODE_STRING ustrDeviceName;//设备名
  UNICODE_STRING ustrSymLinkName;//符号链接名
}DEVICE_EXTENSION,*PDEVICE_EXTENSION;

void HelloWDMUnload(PDRIVER_OBJECT DriverObject);

NTSTATUS HelloWDMDispatchRoutine(PDEVICE_OBJECT fdo,PIRP Irp);

NTSTATUS DefaultPnpHandler(PDEVICE_EXTENSION  pdx, PIRP Irp);

NTSTATUS  HandleRemoveDevice(PDEVICE_EXTENSION  pdx, PIRP Irp);

NTSTATUS HelloWDMPnp(PDEVICE_OBJECT fdo,
           PIRP Irp);

NTSTATUS HelloWDMAddDevice(PDRIVER_OBJECT DriverObject,
               PDEVICE_OBJECT PhysicalDeviceObject);

#pragma code_seg("INIT")
extern "C" NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject,PUNICODE_STRING pRegistryPath)
{
  _asm int 3
  NTSTATUS status;
  KdPrint(("Enter DriverEntry\n"));
  pDriverObject -> DriverExtension->AddDevice = HelloWDMAddDevice;
  pDriverObject ->MajorFunction[IRP_MJ_PNP] = HelloWDMPnp;
  pDriverObject ->MajorFunction[IRP_MJ_DEVICE_CONTROL] = HelloWDMDispatchRoutine;
  pDriverObject ->MajorFunction[IRP_MJ_CREATE] = HelloWDMDispatchRoutine;
  pDriverObject ->MajorFunction[IRP_MJ_READ] = HelloWDMDispatchRoutine;
  pDriverObject ->MajorFunction[IRP_MJ_WRITE] = HelloWDMDispatchRoutine;


  pDriverObject->DriverUnload = HelloWDMUnload;

  KdPrint(("DriverEntry end\n"));
  return status;
}



NTSTATUS HelloWDMDispatchRoutine(PDEVICE_OBJECT fdo,PIRP Irp)
{
  PAGED_CODE();
  KdPrint(("Enter HelloWDMDispatchRoutine\n"));

  Irp->IoStatus.Status = STATUS_SUCCESS;
  Irp->IoStatus.Information = 0;

  IoCompleteRequest(Irp,IO_NO_INCREMENT);

  KdPrint(("Leave HelloWDMDispatchRoutine\n"));
  return STATUS_SUCCESS;
}


#pragma code_seg("PAGE")
NTSTATUS HelloWDMAddDevice(PDRIVER_OBJECT DriverObject,
               PDEVICE_OBJECT PhysicalDeviceObject)
{
  KdPrint(("Enter HelloWDMAddDevice\n"));
  
  NTSTATUS status;
  PDEVICE_OBJECT fdo;
  UNICODE_STRING devName;
  RtlInitUnicodeString(&devName,L"\\Device\\MyWDMDevice");
  status = IoCreateDevice(
    DriverObject,
    sizeof(DEVICE_EXTENSION),
    &(UNICODE_STRING)devName,
    FILE_DEVICE_UNKNOWN,
    0,
    FALSE,
    &fdo);


  
  if(!NT_SUCCESS(status))
    return status;

  PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)fdo->DeviceExtension;
  
  pdx->fdo = fdo;
  pdx->NextStackDevice = IoAttachDeviceToDeviceStack(fdo,PhysicalDeviceObject);//挂接在设备堆栈上,返回下层堆栈位置

  UNICODE_STRING symLinkName;
  RtlInitUnicodeString(&symLinkName,L"\\DosDevice\\HelloWDM");

  pdx->ustrDeviceName = devName;
  pdx->ustrSymLinkName = symLinkName;

  status = IoCreateSymbolicLink(&(UNICODE_STRING)symLinkName,
    &(UNICODE_STRING)devName);
  
  if(!NT_SUCCESS(status))
  {
    IoDeleteSymbolicLink(&pdx->ustrSymLinkName);
    status = IoCreateSymbolicLink(&symLinkName,&devName);
    if(!NT_SUCCESS(status))
      return status;
  }

  fdo->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE;
  fdo->Flags &= ~DO_DEVICE_INITIALIZING;

  KdPrint(("Leave HelloWDMAddDevice\n"));
  return STATUS_SUCCESS;
}


#pragma code_seg("PAGE")
NTSTATUS HelloWDMPnp(PDEVICE_OBJECT fdo,
           PIRP Irp)
{
  PAGED_CODE();//该宏保证该例程运行在低于APC_LEVEL的中断优先级的级别上

  KdPrint(("Enter HelloWDMPnp\n"));
  NTSTATUS status = STATUS_SUCCESS;

  PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)fdo->DeviceExtension;
  PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);

  static NTSTATUS (*fcntab[])(PDEVICE_EXTENSION pdx,PIRP Irp) =
  {
    DefaultPnpHandler,    // IRP_MN_START_DEVICE
    DefaultPnpHandler,    // IRP_MN_QUERY_REMOVE_DEVICE
    HandleRemoveDevice,    // IRP_MN_REMOVE_DEVICE
    DefaultPnpHandler,    // IRP_MN_CANCEL_REMOVE_DEVICE
    DefaultPnpHandler,    // IRP_MN_STOP_DEVICE
    DefaultPnpHandler,    // IRP_MN_QUERY_STOP_DEVICE
    DefaultPnpHandler,    // IRP_MN_CANCEL_STOP_DEVICE
    DefaultPnpHandler,    // IRP_MN_QUERY_DEVICE_RELATIONS
    DefaultPnpHandler,    // IRP_MN_QUERY_INTERFACE
    DefaultPnpHandler,    // IRP_MN_QUERY_CAPABILITIES
    DefaultPnpHandler,    // IRP_MN_QUERY_RESOURCES
    DefaultPnpHandler,    // IRP_MN_QUERY_RESOURCE_REQUIREMENTS
    DefaultPnpHandler,    // IRP_MN_QUERY_DEVICE_TEXT
    DefaultPnpHandler,    // IRP_MN_FILTER_RESOURCE_REQUIREMENTS
    DefaultPnpHandler,    // 
    DefaultPnpHandler,    // IRP_MN_READ_CONFIG
    DefaultPnpHandler,    // IRP_MN_WRITE_CONFIG
    DefaultPnpHandler,    // IRP_MN_EJECT


    DefaultPnpHandler,    // IRP_MN_SET_LOCK
    DefaultPnpHandler,    // IRP_MN_QUERY_ID
    DefaultPnpHandler,    // IRP_MN_QUERY_PNP_DEVICE_STATE
    DefaultPnpHandler,    // IRP_MN_QUERY_BUS_INFORMATION
    DefaultPnpHandler,    // IRP_MN_DEVICE_USAGE_NOTIFICATION
    DefaultPnpHandler,    // IRP_MN_SURPRISE_REMOVAL
  };

  ULONG fcn = stack->MinorFunction;
  
  if(fcn >= arraysize(fcntab))
  {
    //未知的IRP类别
    status = DefaultPnpHandler(pdx,Irp);//对于未知的IRP类别,我们让DefaultPnpHandler函数处理
    return status;
  }


  status = (*fcntab[fcn])(pdx,Irp);//根据pnp功能号调用函数指针
  KdPrint(("Leave HelloWDMPnp\n"));
  return status;
}


#pragma code_seg("PAGE")
NTSTATUS DefaultPnpHandler(PDEVICE_EXTENSION  pdx, PIRP Irp)
{
  PAGED_CODE();
  KdPrint(("Enter DefaultPnpHandler\n"));
  IoSkipCurrentIrpStackLocation(Irp);//忽略当前堆栈
  KdPrint(("Leave DefaultPnpHandler\n"));
  return IoCallDriver(pdx->NextStackDevice,Irp);//用下层堆栈的驱动设备对象处理此IRP
}

#pragma code_seg("PAGE")
NTSTATUS  HandleRemoveDevice(PDEVICE_EXTENSION  pdx, PIRP Irp)
{
  PAGED_CODE();
  KdPrint(("Enter HandleRemoveDevice\n"));
  Irp->IoStatus.Status = STATUS_SUCCESS;
  NTSTATUS status = DefaultPnpHandler(pdx,Irp);
  IoDeleteSymbolicLink(&(UNICODE_STRING)pdx->ustrSymLinkName);
  //调用IoDetachDevice()把fdo从设备栈中脱开
  if(pdx->NextStackDevice)
    IoDetachDevice(pdx->NextStackDevice);
  //删除fdo
  IoDeleteDevice(pdx->fdo);
  KdPrint(("Leave HandleRemoveDevice\n"));
  return status;
}

#pragma code_seg("PAGE")
void HelloWDMUnload(PDRIVER_OBJECT DriverObject)
{
  PAGED_CODE();
  KdPrint(("Enter HelloWDMUnload\n"));
  KdPrint(("Leave HelloWDMUnload\n"));

}


inf文件:

/************************************************************************
* 文件名称:wdm_aaaa,inf                                              
*************************************************************************/
;; The Win2K DDK documentation contains an excellent INF reference.


;--------- Version Section ---------------------------------------------------


[Version]
Signature="$CHICAGO$"
Provider=Guzy_Device
DriverVer=11/10/2012,1.0.0.0


; If device fits one of the standard classes, use the name and GUID here,
; otherwise create your own device class and GUID as this example shows.


Class=GuzyDevice
ClassGUID={EF2962F0-0D55-4bff-B8AA-2221EE8A79B0}




;--------- SourceDiskNames and SourceDiskFiles Section -----------------------


; These sections identify source disks and files for installation. They are
; shown here as an example, but commented out.


[SourceDisksNames]
1 = "wdm_aaaa",Disk1,,


[SourceDisksFiles]
wdm_aaaa.sys = 1,,


;--------- ClassInstall/ClassInstall32 Section -------------------------------


; Not necessary if using a standard class


; 9X Style
[ClassInstall]
Addreg=Class_AddReg


; NT Style
[ClassInstall32]
Addreg=Class_AddReg


[Class_AddReg]
HKR,,,,%DeviceClassName%
HKR,,Icon,,"-5"


;--------- DestinationDirs Section -------------------------------------------


[DestinationDirs]
YouMark_Files_Driver = 10,System32\Drivers


;--------- Manufacturer and Models Sections ----------------------------------


[Manufacturer]
%MfgName%=Mfg0


[Mfg0]


; PCI hardware Ids use the form
; PCI\VEN_aaaa&DEV_bbbb&SUBSYS_cccccccc&REV_dd
;改成你自己的ID
%DeviceDesc%=YouMark_DDI, PCI\VEN_9999&DEV_9999


;---------- DDInstall Sections -----------------------------------------------
; --------- Windows 9X -----------------


; Experimentation has shown that DDInstall root names greater than 19 characters
; cause problems in Windows 98


[YouMark_DDI]
CopyFiles=YouMark_Files_Driver
AddReg=YouMark_9X_AddReg


[YouMark_9X_AddReg]
HKR,,DevLoader,,*ntkern
HKR,,NTMPDriver,,wdm_aaaa.sys
HKR, "Parameters", "BreakOnEntry", 0x00010001, 0


; --------- Windows NT -----------------


[YouMark_DDI.NT]
CopyFiles=YouMark_Files_Driver
AddReg=YouMark_NT_AddReg


[YouMark_DDI.NT.Services]
Addservice = wdm_aaaa, 0x00000002, YouMark_AddService


[YouMark_AddService]
DisplayName = %SvcDesc%
ServiceType = 1 ; SERVICE_KERNEL_DRIVER
StartType = 3 ; SERVICE_DEMAND_START
ErrorControl = 1 ; SERVICE_ERROR_NORMAL
ServiceBinary = %10%\System32\Drivers\wdm_aaaa.sys


[YouMark_NT_AddReg]
HKLM, "System\CurrentControlSet\Services\wdm_aaaa\Parameters",\
"BreakOnEntry", 0x00010001, 0


; --------- Files (common) -------------


[YouMark_Files_Driver]
wdm_aaaa.sys


;--------- Strings Section ---------------------------------------------------


[Strings]
ProviderName="Guzy."
MfgName="Guzy Soft"
DeviceDesc="Hello World WDM!"
DeviceClassName="Guzy_Device"
SvcDesc="Guzy"




[解决办法]
你的设备是PCI设备PCI\VEN_9999&DEV_9999,属于真正的PNP设备。
系统在加载你驱动之后,会调用一系列的IRP_MJ_PNP IRP。

很可能是你的HelloWDMPnp处理例程写得太简单了。

热点排行