发信人: 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]     --   

解决方案 »

  1.   

    DDK哪里可以下载?微软的网站好像链接有问题。
      

  2.   

    公司里面使用了一块ISA卡,在Windows98下面使用无需驱动程序,但是要
    一个动态连接库提供支持,该动态连接库似乎是调用了_inp()&_outp()两个函数,直接读写端口,而这两个函数在Windows2000下是不能直接使用的。
    那么,要将原来的程序升级到2000,是否意味着要为那块板卡写“驱动程序”?(已知这块板卡所占用的端口号,比如600)
      

  3.   

    可以给例程,若需要将你的要求和EMail发成短消息给我!