一个关于outp() 的问题。

garygao 2004-04-05 10:25:42
在vc种使用outp() 函数在win98下可以正常使用,可是在win2000下却出现一堆错误,请问是什么原因,如何解决?谢谢!
...全文
78 点赞 收藏 5
写回复
5 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
roselu 2004-04-09
很简单,
outp改为_outp
回复
garygao 2004-04-05
我查了一下msdn发现outp()函数与win2000不兼容,不知道有没有别的方法可以实现outp()函数的功能呢?实在很菜,请高手指点,谢谢谢谢!
回复
garygao 2004-04-05
谢谢,本人对于驱动编程的确是个菜鸟,所以有很多东西不明白,也不知道去哪里找。我会努力的:)再次谢谢你!!
回复
nkwesley 2004-04-05
很多人回答过了
NT下对I/O操作进行了保护的,不允许直接访问i/o端口,一般的解决方法是
编写驱动程序,这样可以在Kernel层访问I/O.在NT/2000DDK\src\general目录下有个
portio的例子,拿来就可以用了.还有更好的方法,利用DDK中几个未公开的API也可以
达到同样的目的.
//portio.c
#include
/*
* 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写端口即可.

回复
garygao 2004-04-05
问题很难吗?还是分少呀!!高手都哪里去了??
回复
发动态
发帖子
硬件/系统
创建于2007-09-28

2590

社区成员

VC/MFC 硬件/系统
申请成为版主
社区公告
暂无公告