阅读:1271回复:3
又碰到新问题了,设备名DOS名都怎样定义?
假设我写了个驱动abc.sys,在abc.h中定义 L\"\\\\Device\\\\abc0\",那么打开它的时候怎样连接到一块?
|
|
沙发#
发布于:2002-10-25 09:27
建议看看Walter Oney的《Programming the Microsoft Windows Driver Model》,本站有中文版下载。
----------------- 创建设备对象 调用IoCreateDevice函数创建设备对象,例如: PDEVICE_OBJECT fdo; NTSTATUS status = IoCreateDevice(DriverObject, sizeof(DEVICE_EXTENSION), NULL, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &fdo); 第一个参数(DriverObject) 就是AddDevice的第一个参数。该参数用于在驱动程序和新设备对象之间建立连接,这样I/O管理器就可以向设备发送指定的IRP。 第二个参数是设备扩展结构的大小。正如我在本章前面讲到的,I/O管理器自动分配这个内存,并把设备对象中的DeviceExtension指针指向这块内存。 第三个参数在本例中为NULL。它可以是命名该设备对象的UNICODE_STRING串的地址。决定是否命名设备对象以及以什么名字命名还需要仔细考虑,我将在本节后面深入讨论这个问题。 第四个参数(FILE_DEVICE_UNKNOWN) 是表2-4中列出的设备类型。这个值可以被设备硬件键或类键中的超越值所替代,如果这两个键都含有该参数的超越值,那么硬件键中的超越值具有更高的优先权。对于属于某个已存在类的设备,必须在这些地方指定正确的值,因为驱动程序与外围系统的交互需要依靠这个值。另外,设备对象的默认安全设置也依靠这个设备类型值。 第五个参数(FILE_DEVICE_SECURE_OPEN) 为设备对象提供Characteristics标志(见表2-3)。这些标志主要关系到块存储设备(如软盘、CDROM、Jaz等等)。未公开标志位FILE_AUTOGENERATED_DEVICE_NAME仅用于内部使用,并不是DDK文档忘记提到该标志。这个参数同样也能被硬件键或类键中的对应值超越,如果两个值都存在,那么硬件键中的超越值具有更高的优先权。 第六个参数(FALSE) 指出设备是否是排斥的。通常,对于排斥设备,I/O管理器仅允许打开该设备的一个句柄。这个值同样也能被注册表中硬件键和类键中的值超越,如果两个超越值都存在,硬件键中的超越值具有更高的优先权。 注意 -------------------------------------------------------------------------------- 排斥属性仅关系到打开请求的目标是命名设备对象。如果你遵守Microsoft推荐的WDM驱动程序设计方针,没有为设备对象命名,那么打开请求将直接指向PDO。PDO通常不能被标记为排斥,因为总线驱动程序没有办法知道设备是否需要排斥特征。把PDO标为排斥的唯一的机会在注册表中,即设备硬件键或类键的Properties子键含有Exclusive超越值。为了完全避免依赖排斥属性,你应该利用IRP_MJ_CREAT例程弹出任何有违规行为的打开请求。 第七个参数(&fdo) 是存放设备对象指针的地址,IoCreateDevice函数使用该变量保存刚创建设备对象的地址。 如果IoCreateDevice由于某种原因失败,则它返回一个错误代码,不改变fdo中的值。如果IoCreateDevice函数返回成功代码,那么它同时也设置了fdo指针。然后我们进行到下一步,初始化设备扩展,做与创建新设备对象相关的其它工作,如果在这之后又发现了错误,那么在返回前应先释放刚创建的设备对象并返回状态码。见下面例子代码: NTSTATUS status = IoCreateDevice(...); if (!NT_SUCCESS(status)) return status; ... if (<some other error discovered>) { IoDeleteDevice(fdo); return status; } 符号连接 符号连接有点象桌面上的快捷方式,符号连接在Windows NT中的主要用途是把处于列表前面的DOS形式的名称连接到设备上。图2-17显示了\\??目录的部分内容,这里就有一些符号名,例如,“C:”和其它一些用DOS命名方案命名的驱动器名称,它们被连接到\\Device目录中,而这些设备对象的真正名称就放在\\Device目录中。符号连接可以使对象管理器在分析一个名称时能跳到命名空间的某个地方。例如,如果我用CreateFile打开名称为“C:\\MYFILE.CPP”的对象,对象管理器将以下面过程打开该文件: 内核模式代码最开始看到的名称是\\??\\C:\\MYFILE.CPP。对象管理器在根目录中查找“??”。 找到\\??目录后,对象管理器在其中查找“C:”。它发现找到的对象是一个符号连接,所以它就用这个符号连接组成一个新的内核模式路径名:\\Device\\HarddiskVolume1\\MYFILE.CPP,然后析取它。 使用新路径名后,对象管理器重新在根目录中查找“Device”。 找到\\Device目录后,对象管理器在其中查找“HarddiskVolume1”,最后它找到一个以该名字命名的设备现在,对象管理器要创建一个IRP,然后把它发到HarddiskVolume1设备的驱动程序。该IRP最终将使某个文件系统驱动程序或其它驱动程序定位并打开一个磁盘文件。描述文件系统驱动程序的工作过程已经超出了本书的范围。如果我们使用设备名COM1,那么最终收到该IRP的将是\\Device\\Serial0的驱动程序。 用户模式程序可以调用DefineDosDevice创建一个符号连接,如下例: BOOL okay = DefineDosDevice(DDD_RAW_TARGET_PATH, \"barf\", \"\\\\Device\\\\SECTEST_0\"); 如果你需要在WDM驱动程序中创建一个符号连接,可以调用IoCreateSymbolicLink函数: IoCreateSymbolicLink(linkname, targname); linkname是要创建的符号连接名,targname是要连接的名字。顺便说一下,对象管理器并不关心targname是否是已存在对象的名字,如果连接到一个未定义的符号名,那么访问该符号连接将简单地收到一个错误。如果你想允许用户模式程序能超越这个连接而转到其它地方,应使用IoCreateUnprotectedSymbolicLink函数替代上面函数。 |
|
|
板凳#
发布于:2002-10-25 09:29
在驱动程序中:
在abc.h中不是定义成 L\"\\\\Device\\\\abc0\",而就是L\"\\\\Device\\\\abc\" 在应用程序中: char *sLinkName = \"\\\\\\\\.\\\\abc0\"; HANDLE OpenByName(void) { // Create a handle to the driver return CreateFile(sLinkName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); } |
|
|
地板#
发布于:2002-10-25 16:44
在驱动程序中:
在abc.h中定义成 L\"\\\\Device\\\\abc\" 驱动程序指定其第一个设备对象的内核名称为\\device\\abc0,还需调用IOCREATESYMBOLICLINK创建一个名字为\\??\\abc1(\\dosdevices)的符号连接,这样CreateFile打开\\\\.\\abc1。传入时为\\\\\\\\.\\\\abc1 |
|
|