wordstar
驱动牛犊
驱动牛犊
  • 注册日期2003-03-18
  • 最后登录2003-08-15
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:4740回复:2

菜鸟的设备驱动开发之路2003-0319

楼主#
更多 发布于:2003-03-19 22:32
2003-3-19日,上午去听了一上午无聊的SCADA,下午开始研究昨天晚上下来的资料。

WDM驱动程序有一个主要的初始化入口点,即一个必须称为DriverEntry的例程。它有一个标准的函数原型。当WDM驱动程序被装入时,内
核调用DriverEntry例程。

看到这句话,我第一个反应就是到Numega生成的代码中区寻找这个东东。代码是C++封装的。大概在这个地方

NTSTATUS MyWDM0::DriverEntry(PUNICODE_STRING RegistryPath)
{
t << \"In DriverEntry\\n\";


// Open the \"Parameters\" key under the driver
KRegistryKey Params(RegistryPath, L\"Parameters\");
if ( NT_SUCCESS(Params.LastError()) )
{
#if DBG
ULONG bBreakOnEntry = FALSE;
// Read \"BreakOnEntry\" value from registry
Params.QueryValue(L\"BreakOnEntry\", &bBreakOnEntry);
// If requested, break into debugger
if (bBreakOnEntry) DbgBreakPoint();
#endif
// Load driver data members from the registry
LoadRegistryParameters(Params);
}
m_Unit = 0;

return STATUS_SUCCESS;
}
这里做的事情好像就是从注册表里面读取了一个参数。我理解读写等等IRP处理函数都应该在这里注册,怎么没有看到呢?是不是全部被Numega
封装了呢?我不得其解。也许我到了一定境界,可以看懂DS的源代码才能明白?

然后有点茫然不知所措。再研究Numega生成的代码,发现主要有三部分组成。
一部分是class MyWDM0 : public KDriver,主要有AddDevice,DriverEntry,和LoadRegistryParamete三个函数
还有一个变量ULONG m_bBreakOnEntry;是接收注册表中参数的。我不知道我在哪一步生成了它。

第二部分是class MyWDM0Device : public KPnpDevice
看上去应该是设备驱动的主体。因为我看到了读写IRP的处理,设备控制IRP的处理等等。打住,我们先看看到底有多少种IRP需要处理:

1驱动程序的初始化。
2 创建和删除设备。
3 处理Win32程序打开和关闭文件句柄的请求。
4 处理Win32程序输入/输出请求。
5 实现对设备的串行化访问。
6 访问硬件。
7 取消I/O请求。
8 超时I/O请求。
9 调用其他驱动程序。
10 处理电源管理请求。
11 使用Windows管理诊断(WMI)向系统管理员报告。
12 处理一个可热插/拔的设备被加入或删除的情况。

第三部分是class MyWDM0Device_DriverManagedQueue : public KDriverManagedQueueEx,应该是一个管理性质的东东。第二部分的对象
实例化的过程就在这里面的StartIo函数里面运行。

VOID MyWDM0Device_DriverManagedQueue::StartIo(KIrp I)
{
t  << \"Entering MyWDM0Device_DriverManagedQueue StartIo, \" << I;

// The KDriverManagedQueueEx class gives us the Irp in a non-cancelable state
// (cancel routine set to NULL) so we can process it without having to worry
// about clearing the cancel routine first, as is the case with system queuing,
// or the legacy class KDriverManagedQueue. You may want to set a different cancel
// routine here, or at other points during the processing of this Irp.

// Find the device class so we can call the serialized
// routines in the device class.  The handlers can be
// moved to the DriverManagedQueue class if it is more
// convenient.
MyWDM0Device *pDev = (MyWDM0Device *) KDevicePTR(I.DeviceObject());

// Start processing request.

// Switch on the IRP\'s function:
switch (I.MajorFunction())
{
case IRP_MJ_READ:
pDev->SerialRead(I);
break;

case IRP_MJ_WRITE:
pDev->SerialWrite(I);
break;

case IRP_MJ_FLUSH_BUFFERS:
pDev->SerialFlushBuffers(I);
break;

case IRP_MJ_DEVICE_CONTROL:
switch (I.IoctlCode())
{
default:
// We queued a request that shouldn\'t have been queued
// (should never get here)
ASSERT(FALSE);
break;
}
break;

default:
// Error - unexpected IRP received
// NextIrp completes this IRP and starts processing
// for the next IRP in the queue.
ASSERT(FALSE);
I.Status() = STATUS_INVALID_PARAMETER;
PnpNextIrp(I);
break;
}
}

好了,终于找到IRP处理的入口了。这里只处理了四个IRP,其余的都被传走了。
我们看看到底程序从这里开始都做了些什么?
首先是MyWDM0Device的构造函数。

MyWDM0Device::MyWDM0Device(PDEVICE_OBJECT Pdo, ULONG Unit) :
KPnpDevice(Pdo, &MyWDM0Device_Guid)
{
t << \"Entering MyWDM0Device::MyWDM0Device (constructor)\\n\";


// Check constructor status
    if ( ! NT_SUCCESS(m_ConstructorStatus) )
{
   return;
}

// Remember our unit number
m_Unit = Unit;

// Initialize the lower device
m_Lower.Initialize(this, Pdo);

    // Inform the base class of the lower edge device object
SetLowerDevice(&m_Lower);

// Initialize the PnP Policy settings to the \"standard\" policy
SetPnpPolicy();

// TODO: Customize the PnP Policy for this device by setting
// flags in m_Policies.

// Initialize the Power Policy settings to the \"standard\" policy
SetPowerPolicy();

// TODO: Customize the Power Policy for this device by setting
// flags in m_PowerPolicies.

}
这里做的是一些初始化的工作,初始化了一个KPnpLowerDevice m_Lower;
这个不知道是个什么设备。看到这,这里又看到了一个奇怪的东东,
MyWDM0Device_DriverManagedQueue m_DriverManagedQueue;
奇怪了。明明Device类是在这里实例化的,怎么又成了Device的成员变量呢?KPnpDevice的构造又做了什么事情呢?
要搞明白这个,看样子还是要去看Numega的源码。55555555

我们去看KPnpDevice的构造去。否则程序看到这就没有办法再看下去了。


savage213
驱动牛犊
驱动牛犊
  • 注册日期2003-10-01
  • 最后登录2004-03-28
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2003-10-11 11:01
 so  good
cekonglizhen
驱动牛犊
驱动牛犊
  • 注册日期2008-07-02
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分22分
  • 威望128点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2008-12-25 16:02
VERY GOOD!
游客

返回顶部