阅读:4740回复:2
菜鸟的设备驱动开发之路2003-0319
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的构造去。否则程序看到这就没有办法再看下去了。 |
|
沙发#
发布于:2003-10-11 11:01
so good
|
|
板凳#
发布于:2008-12-25 16:02
VERY GOOD!
|
|