发信人: 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] --
一个动态连接库提供支持,该动态连接库似乎是调用了_inp()&_outp()两个函数,直接读写端口,而这两个函数在Windows2000下是不能直接使用的。
那么,要将原来的程序升级到2000,是否意味着要为那块板卡写“驱动程序”?(已知这块板卡所占用的端口号,比如600)