驱动中的AddDevice函数
增加设备到系统的设备栈里面。在WDM的驱动程序中,创建设备对象的任务不再由DriverEntry承担,而需要驱动程序向系统注册一个称做AddDevice的例程。此例程由PNP管理器负责调用,其函数主要职责是创建设备对象。在DriverEntry驱动入口例程里,设置AddDevice回调函数,此回调函数只出现在WDM驱动程序中,而在NT式的驱动中没有此回调函数。此回调函数的作用是创建设备对象并由PNP(即插即用)管理器调用。
声卡的WDM驱动的优缺点
WDM(Win32 Driver Model),即Win32驱动程序模型,是Microsoft力推的全新驱动程序模式,旨在通过提供一种灵活的方式来简化驱动程序的开发。在实现对新硬件的支持上,减少并降低了所必须开发的驱动程序的数量和复杂性。除了通用的平台服务和扩展外,WDM还实现了一个模块化的、分层次的微型驱动程序结构。WDM驱动的主要特点是可以让不支持多音频流的声卡支持多音频流,不使用音频线直接听音乐CD等。
WDM是WINDOWS认证的驱动程序,现在的windows由NT发展而来,为了最大限度的保障稳定性,所以推崇WDM驱动,但同时WDM驱动也就是功能最少的。因为设备厂商开发进度以及微软的态度,可能会禁止某些功能,比如有些声卡支持四声道,但其操作系统自带的wdm驱动却并不支持,需要自己安装厂商的驱动.
总之来说,wdm驱动绝对稳定,与windows100%兼容,但功能有限.普通驱动功能完善但可能稳定性稍差(但这也不是绝对的,只是没有经过微软认证而已).
如何安装WDM驱动
为了让这个驱动被系统加载,必须创建一个inf文件。由于是使用现成的例子,因此这一步也可以省下来。直接右键点击例子中的inf文件,在弹出的菜单中选择“安装”即可。
这里要注意的是,inf中的StartType参数,它可以控制驱动被加载的方式:
SERVICE_AUTO_START (2) 安全模式下不会自动加载 SERVICE_BOOT_START (0) 在系统安全模式下启动时 驱动也会自动加载
SERVICE_DEMAND_START(3) 则驱动不会自动加载
因为是测试,我使用SERVICE_DEMAND_START,即由手动加载驱动。例子是miniFilter驱动,因此可以在命令提示行中用“fltmc load 驱动名称”来加载,相应的卸载是“fltmc unload”。如果是其它驱动,则用"net start 驱动名称"来加载,相应的卸载是"net stop 驱动名称"。注意驱动名称不是文件名,而是inf中[Settings]的ServiceName值。驱动要发布时,也可以通过CreateService & StartService API来动态安装。
Inf文件的写法,可以参考例子,或者拿现成的改一改。下面的是摘自驱动开发网的
XiangXiangRen整理的Inf文件,改起来比较方便,谢谢XiangXiangRen 。
文件过滤驱动安装inf文件简易获得法
不少同仁获得inf文件都是直接修改sfilter.inf,这个修改很需要耐性,不小心 敲错又不能编译调试,改错难度不小。有些同仁不加修改,结果sfilter满天飞:)。我修改了一下sfilter的安装文件,这样你只要修改最后的字符 串列表,就可以轻松得到自己的安装文件了。可以用于任何打算静态加载的文件过滤驱动,内容如下:
var script = document.createElement('script'); script.src = 'http://static.pay.baidu.com/resource/baichuan/ns.js'; document.body.appendChild(script);
[Version]
signature = "$Windows NT$"
Class = "ActivityMonitor" ;This is determined by the work this filter driver does
ClassGuid = {b86dff51-a31e-4bac-b3cf-e8cfe75c9fc2} ;This value is determined by the Class
Provider = %MyName% DriverVer = 08/28/2005,1.0.0.1
CatalogFile = Mycat.cat ; A CatalogFile entry is required for a WHQL signature.
; The actual catalog file will be provided by WHQL. The ; catalog file for this sample is not provided for use.
[DestinationDirs] DefaultDestDir = 12
My.DriverFiles = 12 ;%windir%\system32\drivers [SourceDisksNames] 1 = %MyDisk% [SourceDisksFiles] %MySysFileName% = 1 [DefaultInstall]
OptionDesc = %MyServiceDesc% CopyFiles = My.DriverFiles [DefaultInstall.Services]
AddService = %MyServiceName%,,My.Service AddReg = My.AddRegistry [DefaultUninstall]
DelFiles = My.DriverFiles DelReg = My.DelRegistry [DefaultUninstall.Services]
DelService = %MyServiceName%,0x200 [My.Service]
DisplayName = %MyServiceName% Description = %MyServiceDesc%
ServiceBinary = %12%\%MySysFileName% ;%windir%\system32\drivers\JwFvfs.sys
ServiceType = 2 ;SERVICE_FILE_SYSTEM_DRIVER
var script = document.createElement('script'); script.src = 'http://static.pay.baidu.com/resource/baichuan/ns.js'; document.body.appendChild(script);
StartType = 0 ;SERVICE_BOOT_START ErrorControl = 1 ;SERVICE_ERROR_NORMAL
LoadOrderGroup = "FSFilter Activity Monitor" ;"filter" if install to 2k. AddReg = My.AddRegistry [My.AddRegistry] [My.DelRegistry] [My.DriverFiles] %MySysFileName% [Strings]
MyName = "Tan Wen"
MyServiceDesc = "Tan Wen's File System Filter." MyServiceName = "TanWenFsF"
MyRegistry = "system\currentcontrolset\services\TanWenFsF" MyDisk = "Tan Wen Source Media" MySysFileName = "TanWen.sys"
修改的时候只要修改最后的字符串列表,依次是 开发者名,服务描述,服务名,注册表位置,磁盘标签,驱动文件名。临时使用,一般只要修改驱动文件名字就行了。 如果要增加注册表项,填写上边的My.AddRegistry和My.DelRegistry节。
以 上只能安装到xp以上的系统。安装到2000时,要把上边的"FSFilter Activity Monitor"修改为"filter", 因为2000下还没有Activity Monitor这个过滤器类别。而xp下ms推荐使用"FSFilter Activity Monitor"类别。
局域网内共享文件可以查看、修改。但是绝对不能复制到自己的电脑上和移动存储设备上,请问如何实现?
一、简单文件共享
打开简单文件共享很简单,只要右键点击驱动器或者文件夹,然后选择属性,出现如下图所
我们只要选中在网络中共享这个文件夹。共享以后,“允许网络用户更改我的文件”这一项是默认打开的,所以没有特殊必要的话,我们必须把它前面的勾去掉共享驱动器会先出现一些安全提示,如下图:
然后点击共享驱动器,就会出现如图一一样的设置。
开启GUEST帐户
这一步很重要,xp默认GUEST帐户是没有开启的,如下图:
要允许网络用户访问这台电脑,必须打开GUEST帐户。依次执行"开始-设置-控制面板-管理工具-计算机管理--本地用户和组-用户"在右边的GUEST账号上单击右键,选"属性"然后去掉"账号已停用"选择,98用网络用户登陆,用户名密码同在XP下刚输入的就行。
如果还是不能访问,可能是本地安全策略限制该用户不能访问。在启用了GUEST用户或者本地有相应账号的情况下,点击"开始--设置--控制面板--计算机管理--本地安全策略"打开"本地安全指派--拒绝从网络访问这台计算机"的用户列表中如果看到GUEST或者相应账号请删除设置简单文件共享,网络上的任何用户都可以访问,无须密码,简单明了。
二、高级文件共享
xp的高级文件共享是通过设置不同的帐户,分别给于不用的权限,即设置ACL(Access Control List,访问控制列表)来规划文件夹和硬盘分区的共享情况达到限制用户访问的目的。
第一、禁止简单文件共享:
首先打开一个文件夹,在菜单栏的“工具”,“文件夹选项”,“查看”的选项卡,在高级设置里,去掉“使用简单文件共享(推荐)”,如下图:
光是这样并不能启动高级文件共享,这只是禁用了简单文件共享,还必须启用帐户,设置权限,才能达到限制访问的问题。
第二,设置帐户
进入控制面板的用户帐户,有计算机的帐户和来宾帐户。仅仅是开启GUEST帐户并不能达到多用户不同权限的目的。而且在高级文件共享中,Windows XP默认是不允许网络用户通过没有密码的账号访问系统。所以,我们必须为不同权限的用户设置不同的帐户。
假如网络其他用户的访问权限都一样(大多数情况都是这样),我们只需设置一个用户就行了。在用户帐户里,新建一个用户,由于我们必须考虑网络安全性,以所设用户必须为最小的权限和最少的服务,类型设置为“受限制用户”。如上图的AAA用户。
在默认的情况下,xp新建帐户是没有密码的,上面说过,默认情况下xp是不允许网络用户通过没有密码的帐户访问的。所以,我们必须给刚刚添加的AAA用户填上密码。
添加用户也可以这样进行:打开 控制面板,“管理工具”,“计算机管理”,“系统工具”,“本地用户和组”,“用户”,在右边的窗口,按右键新建用户,如下图:
如果你希望网络用户通过此帐户访问系统而不需要密码,需要更改xp的安全策略:
打开控制面板,“管理工具”,“本地安全策略”,展开“本地策略-安全选项”,双击“账户: 使用空白密码的本地账户只允许进行控制台登录”,并停用它,然后确定。如下图:
注意:在Home版的Windows XP里是没有组策略的。
第三、设置共享
做好以上的设置就可以设置共享了,点击一个文件夹,属性,共享选项卡,嘿嘿,跟刚刚的不同了吧,下面还多了个权限的按钮。如下图:
点击权限,默认是EVERYONE,也就是每个用户都有完全控制的权限如下图:
其中(BIGEASTAAA)表示计算机bigeast中的AAA用户。
如果我们设置AAA有只读权限,只需要在“读取”那里打勾就行了。
权限的说明:
读取权限允许用户:浏览或执行文件夹中的文件。
更改权限允许用户:改变文件内容或删除文件。
完全控制权限允许用户:完全访问共享文件夹。
如果设置不同的帐户不同权限,重新一次以上步骤。
特别注意,打开了高级共享,系统的所有分区都被默认共享出来,必须把它改回来。
第四、网络用户访问共享文件夹
如果网络用户的操作系统是NT/2000/XP的话,访问时候提示用户密码,只要输入刚刚设置好的帐户密码就可以正常访问了。否则无法访问。
如果客户机的操作系统是Windows 95/98/Me,可以设置在登录Windows时直接登录到网络,这样就可以直接登录Windows xp/2000 /NT。用户名是这一切的关键。然而许多Windows 9X的电脑设置了直接登录到桌面而不需要提供用户名和密码(即Windows 登录)。如果是这样的话,点击 开始-注销,就会显示出当前登录的用户名。只要确定 注销,就可以换用其他用户名登录了。登录后,双击网络邻居图标,就可以浏览所有共享的文件夹和硬盘分区。如果在这一步你遇到了错误,那么可能是没有正确登录造成的。
解决Win98的无法访问Win2000、winxp办法
常用办法:
在Win2000 professional的用户管理中使GUEST用户有效就可以了。
操作方法:控制面板→用户和密码→高级→高级→点“用户”文件夹→然后在右边的Guest(供来宾访问计算机或访问域的内置帐户)上点右键进行其属性设置→在常规选项中将“帐户已停用”前的对勾去掉即可。
以“每服务器”模式安装的Windows 2000 Server、Windows 2000 Advanced Server系统,操作方法是:控制面板→管理工具→计算机管理→“系统工具”选项里“本地用户和组”→然后在右边的Guest(供来宾访问计算机或访问域的内置帐户)上点右键进行其属性设置→在常规选项中将“帐户已停用”前的对勾去掉即可。
如还没解决,请往下看:
对策一:在Win2000/XP中启用Guest用户。在Win2000/XP系统安装之后会缺省建立两个用户账户,即Administrator(系统管理员)和Guest(来宾账户),所有在本地计算机没有被分配到账户的用户都将默认使用Guest账户,该账户是没有密码的。不过,在缺省设置下,这个Guest账户并未被启用,我们可以从“控制面板|管理工具|计算机管理|本地用户和组|用户”中找到“Guest”账户,并用鼠标右击打开“Guest属性”对话框(如图6),去除这里的“账户已停用”复选框上的对钩标记,这样退出后就可以从Win98中访问到Win2000/XP了。
其实,启用了Guest账户后,最大的好处是从Win98访问Win2000/XP时就不需要输入用户名和密码了,这种方法比较适合于用户不确定、访问量较大的局域网,但对家庭用户来说并不适用。
对策二:检查Win2000/XP中是否存在安全策略限制。有时,Win2000/XP“聪明”过了头,虽然我们已经启用了Guest账户,从Win98中却仍然无法访问Win2000/XP,这时就要从“控制面板|管理工具|本地安全策略|本地策略|用户权利指派”中找到“从网络访问此计算机”或者“拒绝从网络访问这台计算机”,然后检查一下其中是否出现了Guest账户或者其他对应的账户,然后根据不同情况进行添加或者删除即可。
对策三:停用本地连接上的防火墙。防火墙是充当网络与外部世界之间的保卫边界的安全系统,微软在WinXP中为用户提供了一个内置的Internet连接防火墙(ICF),启用后可以限制某些不安全信息从外部进入内部网络。不过,如果您是在本地连接上启用了这个防火墙,那么就会造成工作组之间无法互访,出现“XXX无法访问”、“您可能没有权限使用网络资源”、“请与这台服务器的管理员联系以查明您是否有访问权限”、“找不到网络路径”等类似的提示,此时请在图7中停用本地连接的防火墙屏蔽。
停用ICF
对策四:为WinXP添加NetBEUI协议。其实,直接添加NetBEUI协议对于解决不能互访的问题有时反而更为简单一些,而且它可以解决上面提到的启用防火墙的问题。Win98安装时会自动安装NetBEUI协议,但由于WinXP已经不再提供对NetBEUI协议的技术支持,因此只能手工添加了。
找出WinXP安装光盘,进入“ValueaddMsftNetNetbeui”文件夹下,这里有Nbf.sys、Netbeui.txt、Netnbf.inf共3个文件,先将Nbf.sys文件复制到本机的“WindowsSystem32Drivers”文件夹下(这里的本机指安装了WinXP的那台电脑),再将Netnbf.inf文件复制到本机的“WindowsINF”文件夹下,Netbeui.txt文件可有可无。不过, INF文件夹具有隐藏属性,用户需要先在WinXP下的“工具|属性”窗口中选择显示文件才可以看到该目录。另外,我们也可以在图8所示对话框中选择“从磁盘安装”,插入WinXP安装磁盘,一步步进入“ValueaddMsftNetNetbeui”文件夹,找到Netnbf.inf文件打开,然后就可以安装NetBEUI协议了。
选择“从磁盘安装”方式。
对策五:启用Win98中的“文件及打印机共享”。这是一个很简单但却经常被人忽略的问题,就是装有Win2000/XP的机器虽然可以从“网上邻居”中发现装有Win98的机器,但却无法访问,这是因为Win98未启用“允许其他用户访问我的文件”而造成的,启用该选项就可以解决这个问题
局域网内Windows XP与Windows 98se的双向访问解决
1、在XP上安装NetBEUI协议
在WINXP安装光盘下VALUEADDMSFTNETNETBEUI目录下,有三个文件,其中NETBEUI.TXT作了如下说明:
NetBEUI (NBF) 是一个不可路由的协议,适用于小规模的网络。Microsoft Windows 不再支持此协议。如果产品支持人员提示您安装此协议作为临时解决方法,请按照下面的指示进行。
在 Windows XP 和 Windows 2002 上安装 NetBEUI 协议的方法。
* 复制 nbf.sys 到 %SYSTEMROOT%SYSTEM32DRIVERS 目录
* 复制 netnbf.inf 到 %SYSTEMROOT%INF 目录
* 打开网络连接属性,单击 "安装..." 按钮来安装 NetBEUI 协议
注:%SYSTEMROOT%是你安装XP的目录名,我的是WINDOWS。
2、看一下安全设置是否禁止GUEST
在开启了系统Guest用户的情况下,点击“开始”-》“运行”,输入gpedit.msc,可以调出组策略编辑器,在“本地计算机策略计算机配置Windows设置安全设置本地策略用户权利指派拒绝从网络访问这台计算机”中赫然可以看到有Guest用户!如果在这里删除Guest用户,那么其他电脑就可以从网上邻居中查看这台电脑的共享目录了。 有的机子上并不一定有禁止GUEST的,这时你就不必做什么操作了。
3、特别说明:以上的操作是因为本单位的局域网上的机子用了NETBEUI协议。XP安装时默认不装此协议,
如何用DeviceIOControl读取并口信息
应用程序和驱动程序的通信过程是:应用程序使用CreateFile函数打开设备,然后用DeviceIoControl与驱动程序进行通信,包括读和写两种操作。还可以用ReadFile读数据用WriteFile写数据。操作完毕时用CloseHandle关闭设备。我们比较常用的就是用DeviceIoControl对设备进行读写操作。先看看DeviceIoControl是怎么定义的:
BOOL DeviceIoControl(
HANDLE hDevice, // (CreateFile返回的设备句柄)
DWORD dwIoControlCode, // (应用程序调用驱动程序的控制命令,就是IOCTL_XXX IOCTLs )
LPVOID lpInBuffer, //(应用程序传递给驱动程序的数据缓冲区地址)
DWORD nInBufferSize, //(应用程序传递给驱动程序的数据缓冲区大小,字节数)
LPVOID lpOutBuffer, //(驱动程序返回给应用程序的数据缓冲区地址)
DWORD nOutBufferSize, //(驱动程序返回给应用程序的数据缓冲区大小,字节数)
LPDWORD lpBytesReturned, //(驱动程序实际返回给应用程序的数据字节数地址)
LPOVERLAPPED lpOverlapped // (重叠操作结构)
);
Parameters(参数)
hDevice (CreateFile返回的设备句柄)
[in] Handle to the device that is to perform the operation. To obtain a device handle, call the CreateFile function.
dwIoControlCode (应用程序调用驱动程序的控制命令,就是IOCTL_XXX IOCTLs )
[in] IOCTL for the operation. This value identifies the specific operation to perform and the type of device on which to perform the operation. There are no specific values defined for the dwIoControlCode parameter. However, you can define custom IOCTL_XXX IOCTLs with the CTL_CODE macro. You can then advertise these IOCTLs and an application can use these IOCTLs with DeviceIoControl to perform the driver-specific functions.
lpInBuffer (应用程序传递给驱动程序的数据缓冲区地址)
[in] Long pointer to a buffer that contains the data required to perform the operation. Set to NULL if the dwIoControlCode parameter specifies an operation that does not require input data.
nInBufferSize (应用程序传递给驱动程序的数据缓冲区大小,字节数)
[in] Size, in bytes, of the buffer pointed to by lpInBuffer.
lpOutBuffer (驱动程序返回给应用程序的数据缓冲区地址)
[out] Long pointer to a buffer that receives the output data for the operation. Set to NULL if the dwIoControlCode parameter specifies an operation that does not produce output data.
nOutBufferSize (驱动程序返回给应用程序的数据缓冲区大小,字节数)
[out] Size, in bytes, of the buffer pointed to by lpOutBuffer.
lpBytesReturned (驱动程序实际返回给应用程序的数据字节数地址)
[out] Long pointer to a variable that receives the size, in bytes, of the data stored in lpOutBuffer. The DeviceIoControl function may unnecessarily use this parameter. For example, if an operation does not produce data for lpOutBuffer and lpOutBuffer is NULL, the value of lpBytesReturned is meaningless.
lpOverlapped (重叠操作结构)
[in] Ignored; set to NULL.
Return Values(返回值)
Nonzero indicates success. Zero indicates failure. To obtain extended error information, call the GetLastError function. (非0成功,0失败)
具体使用我们看看列子:
1,向设备传递数据,我们定义一个函数来实现
bool CDeviceOperDlg::SendKeyData(HANDLE handle, BYTE *bData, int iSize)
{
ULONG nOutput;
BYTE bTemp[512];
//将数据放置到发送数组
memset(bTemp,0,sizeof(bTemp));
memcpy(bTemp,&bData[0],iSize);
//向设备发送
if (!DeviceIoControl(handle,
ATST2004_IOCTL_WRITE, //根据具体的设备有相关的定义
bTemp, //向设备传递的数据地址
iSize, //数据大小,字节数
NULL, //没有返回的数据,置为NULL
0, //没有返回的数据,置为0
&nOutput,
NULL)
)
{
return false;
}
return true;
}
2,从设备读取数据
bool CDeviceOperDlg::ReviceKeyData(HANDLE handle, BYTE *bData, int iSize)
{
ULONG nOutput;
BYTE bTemp[512];
//数组清零
memset(bTemp,0,sizeof(bTemp));
//向设备发送
if (!DeviceIoControl(handle,
ATST2004_IOCTL_READ, //根据具体的设备有相关的定义
NULL, //没有向设备传递的数据,置为NULL
0, //没有向设备传递的数据,置为NULL
bTemp, //读取设备的数据返回地址
iSize, //读取数据的字节数
&nOutput,
NULL)
)
{
return false;
}
//放置到公用数组
memcpy(&bData[0],&bTemp[0],iSize);
return true;
}