谁有在Win2k下读写I/O端口的动态连接库 我想读写一个ISA槽上的数据采集卡的数据,但是在Win2k系统下不能直接读写I/O端口,谁有读写I/O端口的动态连接库,多谢!!! 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 用WINIO,去硬件系统版,那里可以找到方法 发信人: April (椰风海韵), 信区: VisualC 标 题: Re: 关于端口读写,help 发信站: BBS 水木清华站 (Tue Apr 17 13:12:56 2001) NT下对I/O操作进行了保护的,不允许直接访问i/o端口,一般的解决方法是 编写驱动程序,这样可以在Kernel层访问I/O.在NT/2000DDK\src\general目录下有个 portio的例子,拿来就可以用了.还有更好的方法,利用DDK中几个未公开的API也可以 达到同样的目的. //portio.c #include <ntddk.h> /* * The name of our device driver. */ #define DEVICE_NAME_STRING L"portio" #define IOPM_SIZE 0x2000 typedef UCHAR IOPM[IOPM_SIZE]; IOPM *IOPM_local = 0; void Ke386SetIoAccessMap(int, IOPM *); void Ke386QueryIoAccessMap(int, IOPM *); void Ke386IoSetAccessProcess(PEPROCESS, int); /********************************************************************* Release any allocated objects. *********************************************************************/ VOID GiveioUnload(IN PDRIVER_OBJECT DriverObject) { WCHAR DOSNameBuffer[] = L"\\DosDevices\\" DEVICE_NAME_STRING; UNICODE_STRING uniDOSString; if(IOPM_local) MmFreeNonCachedMemory(IOPM_local, sizeof(IOPM)); RtlInitUnicodeString(&uniDOSString, DOSNameBuffer); IoDeleteSymbolicLink (&uniDOSString); IoDeleteDevice(DriverObject->DeviceObject); } VOID SetIOPermissionMap(int OnFlag) { Ke386IoSetAccessProcess(PsGetCurrentProcess(), OnFlag); Ke386SetIoAccessMap(1, IOPM_local); } void GiveIO(void) { SetIOPermissionMap(1); } NTSTATUS GiveioCreateDispatch( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { GiveIO(); // give the calling process I/O access Irp->IoStatus.Information = 0; Irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_SUCCESS; } NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ) { PDEVICE_OBJECT deviceObject; NTSTATUS status; WCHAR NameBuffer[] = L"\\Device\\" DEVICE_NAME_STRING; WCHAR DOSNameBuffer[] = L"\\DosDevices\\" DEVICE_NAME_STRING; UNICODE_STRING uniNameString, uniDOSString; // // Allocate a buffer for the local IOPM and zero it. // IOPM_local = MmAllocateNonCachedMemory(sizeof(IOPM)); if(IOPM_local == 0) return STATUS_INSUFFICIENT_RESOURCES; RtlZeroMemory(IOPM_local, sizeof(IOPM)); // // Set up device driver name and device object. // RtlInitUnicodeString(&uniNameString, NameBuffer); RtlInitUnicodeString(&uniDOSString, DOSNameBuffer); status = IoCreateDevice(DriverObject, 0, &uniNameString, FILE_DEVICE_UNKNOWN, 0, FALSE, &deviceObject); if(!NT_SUCCESS(status)) return status; status = IoCreateSymbolicLink (&uniDOSString, &uniNameString); if (!NT_SUCCESS(status)) return status; // // Initialize the Driver Object with driver's entry points. // All we require are the Create and Unload operations. // DriverObject->MajorFunction[IRP_MJ_CREATE] = GiveioCreateDispatch; DriverObject->DriverUnload = GiveioUnload; return STATUS_SUCCESS; } //在同一个目录下建造sources文件,内容: TARGETNAME=portio TARGETPATH=. TARGETTYPE=DRIVER INCLUDES=e:\ntddk\inc ;//这儿填写DDK下inc目录的路径 SOURCES=portio.c //在同一个目录下建造makefile文件,内容: !INCLUDE $(NTMAKEENV)\makefile.def 利用命令行:SetEnv e:\ntddk //设置DDK环境 在该目录下 build,然后会在该目录的I386中产生portio.sys文件,将文件 copy到WINNT\system32\drivers里面,在注册表中手工安装驱动程序(别告诉我你不会 ,到驱动程序版查查,最好设置为驱动程序自动启动,service的key为portio),重起机子。 编写用户态程序: HANDLE h; h = CreateFile("\\\\.\\portio", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NUULL); if(h == INVALID_HANDLE_VALUE) { printf("Couldn't access giveio device\n"); return -1; } CloseHandle(h); //然后以后用嵌入汇编或者_inp,_oup写端口即可. 【 在 qaq (qaq) 的大作中提到: 】 : 标 题: 关于端口读写,help : 发信站: BBS 水木清华站 (Tue Apr 17 11:04:26 2001) : : 各位大虾,dos下可以用inp(),outp()对端口操作。 : win95/98可以用-inp(),-outp(), : winnt 和 2000 呢,别告我不能对端口操作. : 3x : : -- : : ※ 来源:·BBS 水木清华站 smth.org·[FROM: 203.93.178.115] -- http://www.internals.com/utilities/winio.zip 1 才发现2000下不用谢驱动也可以,可以利用访问虚拟端口的方法实现(winio就是使用的这种方法)#include <conio.h>//注意必须包含着个读端口: switch (bSize) { case 1: *pdwPortVal = _inp(wPortAddr); break; case 2: *pdwPortVal = _inpw(wPortAddr); break; case 4: *pdwPortVal = _inpd(wPortAddr); break; }写端口: switch (bSize) { case 1: _outp(wPortAddr, dwPortVal); break; case 2: _outpw(wPortAddr, (WORD)dwPortVal); break; case 4: _outpd(wPortAddr, dwPortVal); break; }不过这种方法是访问的虚拟端口,虚拟端口被映射到物理端口,所以可能会有些限制,不过访问并口是绝对可以的2 写驱动程序,在里面使用汇编来完成或者使用DDK提供的访问端口函数,这样保险一些3 还可以使用winio,这是最简单的方法下面是我以前写的访问并口的程序,使用第二种方法,里面还包含winiohttp://vip.6to23.com/NowCan1/ctrl/portion.rar 关于端口的读写参看csdn里bhw98的专栏,你会有比较多收获!http://www.csdn.net/develop/author/netauthor/bhw98/实战DeviceIoControl 之六:访问物理端口 (原创) wireshark能够抓ppp上网拨号的包吗? 如何通过 文件名 来得到它执行后的 窗口名 和 进程标识 ? 高分求助:请问一个给VC装sdk的问题 怎么去掉Formview中的滚动条? 问题:怎样通过串口读手机SIM卡中的短信? 连接错误,望大虾帮助解决。 如何调用chm文件,vc中????散分 哪来有可用的、能现实IP地址的QQ下载?可给50分专家分 关于组合控件的用法 关于spy++的几个小问题 CSDN的朋友们,心中的困惑还需你们的热心帮助。 程序在系统启动时起动,如何做?
#include <conio.h>//注意必须包含着个
读端口:
switch (bSize)
{
case 1: *pdwPortVal = _inp(wPortAddr); break; case 2: *pdwPortVal = _inpw(wPortAddr); break; case 4: *pdwPortVal = _inpd(wPortAddr); break;
}
写端口:
switch (bSize)
{
case 1: _outp(wPortAddr, dwPortVal); break; case 2: _outpw(wPortAddr, (WORD)dwPortVal); break; case 4: _outpd(wPortAddr, dwPortVal); break;
}不过这种方法是访问的虚拟端口,虚拟端口被映射到物理端口,所以可能会有些限制,不过访问并口是绝对可以的2 写驱动程序,在里面使用汇编来完成或者使用DDK提供的访问端口函数,这样保险一些3 还可以使用winio,这是最简单的方法下面是我以前写的访问并口的程序,使用第二种方法,里面还包含winio
http://vip.6to23.com/NowCan1/ctrl/portion.rar