首页 > 代码库 > 在驱动层直接使用应用层的空间

在驱动层直接使用应用层的空间

</pre><p>需求:应用层申请一个空间,然后将地址传递到驱动层,驱动直接将处理后的数据放到应用层指定的空间中,类似于Linux下的copy_from_user。</p><p></p><p>应用层代码片段:</p><p><span style="white-space:pre">将申请的地址传递到驱动层</span></p><pre code_snippet_id="576642" snippet_file_name="blog_20150110_2_1402064" name="code" class="cpp">        CHAR    buf[64] = {0};
	int iWriteLen = 0;
	char *pWaddr = NULL;
	char *pRaddr = NULL;
	unsigned long *pTmp = NULL;

	pWaddr = (char*)calloc(1, 32);
	pRaddr = (char*)calloc(1, 32);
	if ((pWaddr ==NULL) || (pRaddr==NULL))
	{
		puts("calloc error");
		CloseHandle(hDevice);
		return 0;
	}

	memset(pWaddr, 'A', 24);
	pTmp = (unsigned long*)buf;
	
	pTmp[0] = (unsigned long)0;//pWaddr;
	pTmp[1] = (unsigned long)pRaddr;

	if (WriteFile(hDevice, buf, 8, (LPDWORD)&iWriteLen, NULL))
	{
		puts("write Success");
	}
	else
	{
		puts("Write Failed");
	}

驱动层代码片段:


VOID uAddr2dAddr(PVOID pUsr, unsigned long iUsrLen, BOOLEAN bRead)
{
	int i = 0;
	LOCK_OPERATION opt = IoWriteAccess;
	PUCHAR pVir = NULL;
	PMDL mdl ;

	if (!MmIsAddressValid(pUsr))//如果没有这个判断,应用传入的是非法地址时,会导致在下面获得虚拟地址时,蓝屏
	{
		KdPrint(("MmIsAddressValid UnIvalid error\n"));
		return ;		
	}

	mdl = IoAllocateMdl(pUsr, iUsrLen, FALSE, TRUE, NULL);

	if (mdl == NULL)
	{
		KdPrint(("IoAllocateMdl error\n"));
		return ;
	}
	if (bRead)
	{
		opt = IoReadAccess;
	}
	
	MmProbeAndLockPages(mdl, UserMode, opt);


	pVir = MmMapLockedPagesSpecifyCache(mdl,KernelMode,MmCached,NULL,FALSE,NormalPagePriority);//如果pUser不合法时,调用此函数会引起蓝屏
	KdPrint(("MmMapLockedPagesSpecifyCache: %#x\n", (unsigned long)pVir));

	pVir = MmGetSystemAddressForMdlSafe(mdl, NormalPagePriority);<span style="font-family: Arial, Helvetica, sans-serif;">//如果pUser不合法时,调用此函数会引起蓝屏</span>
	KdPrint(("MmGetSystemAddressForMdlSafe: %#x\n", (unsigned long)pVir));

	pVir =  MmGetMdlVirtualAddress(mdl);<span style="font-family: Arial, Helvetica, sans-serif;">//如果pUser不合法时,调用此函数会引起蓝屏</span>
	KdPrint(("MmGetMdlVirtualAddress: %#x\n", (unsigned long)pVir));
	
	if (pVir == NULL)
	{
		KdPrint(("IoAllocateMdl error\n"));
		return ;
	}

	KdPrint(("\n----------------------DML Data------------------\n\n"));
	if (bRead)
	{
		for (i=0; i<4; i++)
		{
			for (i=0; i<4; i++)
			{
				pVir[i] = 'B';
			}
		}
	}
	else
	{
		for (i=0; i<4; i++)
		{
			KdPrint(("%c ", pVir[i]));
		}
	}
	KdPrint(("\n-------------------End DML Data------------------\n\n"));
	
	MmUnlockPages(mdl);
	
	IoFreeMdl(mdl);

}


用DbgView打印驱动中:分别通过3个函数获得的虚拟地址值如下:

MmMapLockedPagesSpecifyCache: 0xae44b3b0
MmGetSystemAddressForMdlSafe: 0xae44b3b0
MmGetMdlVirtualAddress: 0x7013b0

以上三个函数都可以完成需求。

代码下载:



在驱动层直接使用应用层的空间