none
ReadFile 读取 自己的驱动的数据 出错 ?? RRS feed

  • 问题

  • RT
    自己的Win驱动程序,要写一个 exe 获取驱动的信息,用了异步ReadFile方式。∵在ReadFile时发现了错误的数据,所以自己写了个测试的驱动程序,驱动只向 异步的ReadFile返回 数值1000 。

    本来这个 exe是用 C++ 来写的,现在想改成 C#,但是我 C# ReadFile 得到的数据有时居然不是 1000...
    用C++ 和 C#分别写了测试的exe发现只有 C#的exe会在 ReadFile返回时得到 非1000 的值...

    由于本人C#水平很菜,查了几天没查出原因... 所以只能来求助了...

    (exe代码的注释里有很多 感叹号 的地方就是我不希望出现的现象),求大家帮帮忙~~~

     

    给出代码的打包下载:C#异步ReadFile自己的驱动,总有错误的数据出现 

    打包文件里面的内容是 :测试程序_Test_ca_vs08.exe及其源码 + 测试驱动HelloDDK.sys及其源码 + 本驱动安装工具DriverMonitor 。

    (这个测试驱动是<<Windows驱动开发技术详解>> 第一章的HelloDDK程序 与 第十章的 DPC定时器 合在一起写成的。是NT式的驱动程序,需要用 DriverMonitor 来加载启动。)

    驱动我是用WDK6编译的,exe是用vs08编写编译的。
    里面是有源码 也有编译好的 exe 和 sys 的,不想编译的话直接用就可以了,只求有人能指点下为啥会出现上面所描述之现象,以及如何修改。

    万分感谢啊万分感谢~~~!!!!!

    贴一下exe和sys的代码吧:

    exe:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;
    using System.Threading;
    namespace _Test_cs_vs08
    {
        public partial class Form1 : Form
        {
            // *** *** *** *** *** ***
            // 结构体
            [StructLayout(LayoutKind.Sequential)]
            public struct SECURITY_ATTRIBUTES
            {
                public int nLength;
                public IntPtr lpSecurityDescriptor;
                public int bInheritHandle;
            }
            [StructLayout(LayoutKind.Sequential)]
            public struct OVERLAPPED
            {
                public IntPtr Internal;
                public IntPtr InternalHigh;
                public int Offset;
                public int OffsetHigh;
                public IntPtr hEvent;
            }
            // 常量
            const uint GENERIC_READ = 0x80000000;
            const uint GENERIC_WRITE = 0x40000000;
            const uint OPEN_EXISTING = 3;
            const uint FILE_ATTRIBUTE_NORMAL = 0x00000080;
            const uint FILE_FLAG_OVERLAPPED = 0x40000000;
            //const uint INVALID_HANDLE_VALUE = unchecked((uint)-1);
            IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);
            const uint FILE_DEVICE_NETWORK = 0x00000012;
            const uint METHOD_NEITHER = 3;
            const uint FILE_READ_ACCESS = 0x0001;
            const uint FILE_WRITE_ACCESS = 0x0002;
            const uint ERROR_IO_PENDING = 997;
            const uint INFINITE = 0xFFFFFFFF;
            const uint WAIT_FAILED = 0xFFFFFFFF;
            const uint WAIT_TIMEOUT = 258;
            const uint WAIT_OBJECT_0 = 0;
            const uint AF_INET = 2;
            const uint SOCK_STREAM = 1;
            const uint SOCK_DGRAM = 2;
            const uint IPPROTO_TCP = 6;
            const uint IPPROTO_UDP = 17;
            IntPtr SOCKET_ERROR = new IntPtr(-1);
    // *** *** ***
            [DllImport("kernel32", SetLastError = true, EntryPoint = "CreateFile")]
            static extern unsafe System.IntPtr CreateFile
            (
                string FileName,          // file name
                uint DesiredAccess,       // access mode
                uint ShareMode,           // share mode
                uint SecurityAttributes,  // Security Attributes
                uint CreationDisposition, // how to create
                uint FlagsAndAttributes,  // file attributes
                int hTemplateFile         // handle to template file
            );
            [DllImport("kernel32.dll", SetLastError = true, EntryPoint = "GetLastError")]
            public static extern uint GetLastError();
            [DllImport("kernel32", SetLastError = true, EntryPoint = "ReadFile")]
            static extern unsafe uint ReadFile
            (
                IntPtr hFile,             // handle to file
                void* pBuffer,            // data buffer
                uint NumberOfBytesToRead,  // number of bytes to read
                uint* pNumberOfBytesRead,  // number of bytes read
                OVERLAPPED* Overlapped            // overlapped buffer
            );
            [DllImport("kernel32.dll", SetLastError = true, EntryPoint = "CreateEventW")]
            public static extern IntPtr CreateEventW(
                IntPtr /*LPSECURITY_ATTRIBUTES*/ lpEventAttributes,
                int bManualReset,
                int bInitialState,
                IntPtr /*LPCWSTR*/ lpName
            );
            [DllImport("Kernel32.dll", SetLastError = true, EntryPoint = "GetOverlappedResult")]
            public static extern unsafe bool GetOverlappedResult(
                IntPtr hFile,
                ref OVERLAPPED lpOverlapped,
                ref uint lpNumberOfBytesTransferred,
                bool bWait
            );
            [DllImport("Kernel32.dll", SetLastError = true, EntryPoint = "ResetEvent")]
            public static extern bool ResetEvent(IntPtr hEvent);
            [DllImport("kernel32.dll", SetLastError = true, EntryPoint = "WaitForMultipleObjects")]
            static extern uint WaitForMultipleObjects(uint uiCount, ref IntPtr lpHandles,
               int bWaitAll, uint dwMilliseconds);
    // *** *** ***
            IntPtr FhDevice = IntPtr.Zero;
            public Form1()
            {
                InitializeComponent();
            }
            private void button1_Click(object sender, EventArgs e)
            {
                tbMsg.Text = "";
            }
           
            private void button2_Click(object sender, EventArgs e)
            {
                FhDevice = CreateFile(
                    "\\\\.\\HelloDDK",
                    GENERIC_READ | GENERIC_WRITE,
                    0,	//FILE_SHARE_READ
                    0,
                    OPEN_EXISTING,
                    FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
                    0);
                uint uiErr = GetLastError();
                if (FhDevice == INVALID_HANDLE_VALUE)// INVALID_HANDLE_VALUE ==> -1
                {
                    tbMsg.AppendText("CreateFile err : " + uiErr.ToString() + "\r\n");
                }
                tbMsg.AppendText("CreateFile over\r\n");
                Thread t = new Thread(new ThreadStart(thread2));
                t.Name = "BBB";
                t.IsBackground = true;
                t.Start();
            }
            const int ASYNC_READ_NUM = 5;
            const int BUFFER_SIZE = 32;
            OVERLAPPED[] Fols = new OVERLAPPED[ASYNC_READ_NUM];
            IntPtr[] FhEvents = new IntPtr[ASYNC_READ_NUM];
            struct RzcBuf
            {
                public byte[] buf;
            }
            RzcBuf[] Fbufs = new RzcBuf[ASYNC_READ_NUM];
            int FiWrongCnt = 0;
            void thread2()
            {
                unsafe
                {
                    for (int jj = 0; jj < ASYNC_READ_NUM; jj++)
                    {
                        Fols[jj].hEvent = CreateEventW(IntPtr.Zero, 1, 0, IntPtr.Zero);
                        FhEvents[jj] = Fols[jj].hEvent;
                        Fbufs[jj].buf = new byte[BUFFER_SIZE];
                        uint ulRead = 0;
                        fixed (byte* pbyte = &(Fbufs[jj].buf[0]))
                        fixed (OVERLAPPED* pol = &Fols[jj])
                        {
                            *((int*)pbyte) = jj + 1;
                            uint uiRet = ReadFile(FhDevice, pbyte, BUFFER_SIZE, &ulRead, pol);
                            if (uiRet == 0)
                            {
                                uint dwErr = GetLastError();
                                if (dwErr != ERROR_IO_PENDING)
                                {
                                    zcMsgAdd_Thread("ReadFile(1)[" + jj.ToString() + "] err : " + dwErr.ToString());
                                }
                            }
                        }
                    }
                    while (true)
                    {
                        uint uiIdx = WaitForMultipleObjects(ASYNC_READ_NUM, ref FhEvents[0], 0, INFINITE);
                        if ((uiIdx == WAIT_FAILED) || (uiIdx == WAIT_TIMEOUT))
                        {
                            zcMsgAdd_Thread("WaitForMultipleObjects(1) failed : " + uiIdx.ToString());
                            break;
                        }
                        uiIdx -= WAIT_OBJECT_0;
                        for (uint ui1 = uiIdx; ui1 < ASYNC_READ_NUM; ui1++)
                        {
                            uint uiIdx1 = WaitForMultipleObjects(1, ref FhEvents[ui1], 1, 1);
                            if ((uiIdx1 == WAIT_FAILED) || (uiIdx1 == WAIT_TIMEOUT))
                            {
                                zcMsgAdd_Thread(
                                    "WaitForMultipleObjects(2)[" + ui1.ToString() + "] failed(" + Convert.ToString(WAIT_FAILED, 16) + " , " + Convert.ToString(WAIT_TIMEOUT, 16) + ") : " + Convert.ToString(uiIdx1, 16));
                                continue;
                            }
                            uint dwTrans = 0; // 异步操作传送了多少数据
                            GetOverlappedResult(FhDevice, ref Fols[ui1], ref dwTrans, true);
                            ResetEvent(FhEvents[ui1]); // 手动设置 事件 为 无信号状态
                            //zcMsgAdd_Thread("After GetOverlappedResult dwTrans : " + dwTrans.ToString());
                            // 处理 驱动接收来的数据
                                uint uiRtn = System.BitConverter.ToUInt32(Fbufs[ui1].buf, 0);
                                //RbufAsyncRead bar = Fbufs[ui];
                                //uint uiRtn = (uint)Marshal.ReadInt32((IntPtr)bar.buf);
                                zcMsgAdd_Thread("Read get data : " + uiRtn.ToString() + " , (" + FiWrongCnt.ToString() + ")");
                                if (uiRtn != 1000)
                                {
    // !!!  !!!  !!!  !!!  !!!  !!!  !!!  !!!  !!!  !!!  !!!   !!!  !!!  !!!  !!!   !!!  !!!  !!!  !!! 
                                    // 这里 ,会有如下字符串打印出来,这是我不希望看到的 
                                    //zcMsgAdd_Thread("<== <== <== <== <== <== <== <== <== <== <== <== <==");
                                    FiWrongCnt ++;
                                }
                            // 继续投递 READ操作
                                uint ulRead = 0;
                                fixed (byte* pbyte = &(Fbufs[ui1].buf[0]))
                                fixed (OVERLAPPED* pol = &Fols[ui1])
                                {
                                    *((uint*)pbyte) = (ui1 + 1) * 10;
                                    uint uiRet = ReadFile(FhDevice, pbyte, BUFFER_SIZE, &ulRead, pol);
                                    if (uiRet == 0)
                                    {
                                        uint dwErr = GetLastError();
                                        if (dwErr != ERROR_IO_PENDING)
                                        {
                                            zcMsgAdd_Thread("ReadFile(2)[" + ui1.ToString() + "] err : " + dwErr.ToString());
                                        }
                                    }
                                }
                            break;
                        }
                    }
                }
            }
    // *** *** *** *** *** *** *** *** *** *** *** *** ***
            private delegate void delegate_proc();
            private delegate void delegate_func(object obj);
            void zcMsgAdd(object _obj)
            {
                tbMsg.AppendText(_obj.ToString() + "\r\n");
            }
            void zcMsgAdd_Thread(string _str)
            {
                this.Invoke(new delegate_func(zcMsgAdd), _str);
            }
        }
    }

    sys:

    #include "Driver.h"
    #include "Ndis.h"
    KDPC			g_pollingDPC;	// 存储DPC对象
    KTIMER			g_pollingTimer;// 存储计时器对象
    LARGE_INTEGER	g_pollingInterval;	// 记录计时器间隔时间
    VOID PollingTimerDpc( IN PKDPC, IN PVOID, IN PVOID, IN PVOID );
    #define IRP_NUM		8
    // 锁
    NDIS_SPIN_LOCK g_lock;
    PIRP g_pIrps[IRP_NUM] = {0};
    //#pragma INITCODE
    extern "C" NTSTATUS DriverEntry (
    			IN PDRIVER_OBJECT pDriverObject,
    			IN PUNICODE_STRING pRegistryPath	) 
    {
    	NTSTATUS status;
    	KdPrint(("Enter DriverEntry\n"));
    	//注册其他驱动调用函数入口
    	pDriverObject->DriverUnload = HelloDDKUnload;
    	pDriverObject->MajorFunction[IRP_MJ_CREATE] = HelloDDKDispatchRoutine;
    	pDriverObject->MajorFunction[IRP_MJ_CLOSE] = HelloDDKDispatchRoutine;
    	pDriverObject->MajorFunction[IRP_MJ_WRITE] = HelloDDKDispatchRoutine;
    	pDriverObject->MajorFunction[IRP_MJ_READ] = HelloDDKDispatchRoutine;
    	
    	//创建驱动设备对象
    	status = CreateDevice(pDriverObject);
    	KdPrint(("DriverEntry end\n"));
    	return status;
    }
    //#pragma INITCODE
    NTSTATUS CreateDevice (
    		IN PDRIVER_OBJECT	pDriverObject) 
    {
    	NTSTATUS status;
    	PDEVICE_OBJECT pDevObj;
    	PDEVICE_EXTENSION pDevExt;
    	
    	//创建设备名称
    	UNICODE_STRING devName;
    	RtlInitUnicodeString(&devName,L"\\Device\\MyDDKDevice");
    	
    	//创建设备
    	status = IoCreateDevice( pDriverObject,
    						sizeof(DEVICE_EXTENSION),
    						&(UNICODE_STRING)devName,
    						FILE_DEVICE_UNKNOWN,
    						0, TRUE,
    						&pDevObj );
    	if (!NT_SUCCESS(status))
    		return status;
    	pDevObj->Flags |= DO_DIRECT_IO;//DO_BUFFERED_IO;
    	pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;
    	pDevExt->pDevice = pDevObj;
    	pDevExt->ustrDeviceName = devName;
    // *** ZC begin
    	// 初始化螺旋锁
    		NdisAllocateSpinLock(&g_lock);
    	KeInitializeTimer( &g_pollingTimer );
    	KeInitializeDpc( &g_pollingDPC,
    						PollingTimerDpc,
    						(PVOID) pDevObj );
    // *** ZC end
    	//创建符号链接
    	UNICODE_STRING symLinkName;
    	RtlInitUnicodeString(&symLinkName,L"\\??\\HelloDDK");
    	pDevExt->ustrSymLinkName = symLinkName;
    	status = IoCreateSymbolicLink( &symLinkName,&devName );
    	if (!NT_SUCCESS(status)) 
    	{
    		IoDeleteDevice( pDevObj );
    		return status;
    	}
    	return STATUS_SUCCESS;
    }
    #pragma PAGEDCODE
    VOID HelloDDKUnload (IN PDRIVER_OBJECT pDriverObject) 
    {
    	PDEVICE_OBJECT	pNextObj;
    	KdPrint(("Enter DriverUnload\n"));
    	pNextObj = pDriverObject->DeviceObject;
    	while (pNextObj != NULL) 
    	{
    		PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)
    			pNextObj->DeviceExtension;
    		//删除符号链接
    		UNICODE_STRING pLinkName = pDevExt->ustrSymLinkName;
    		IoDeleteSymbolicLink(&pLinkName);
    		pNextObj = pNextObj->NextDevice;
    		IoDeleteDevice( pDevExt->pDevice );
    	}
    	// un初始化螺旋锁
    	NdisFreeSpinLock(&g_lock);
    }
    void zcCancelReadIRP(
        IN PDEVICE_OBJECT _pDeviceObject,
        IN PIRP _pIrp)
    {
    	KdPrint(("Enter zcCancelReadIRP\n"));
    	NdisAcquireSpinLock(&g_lock); // 进螺旋锁
    	{
    		int i = 0;
    		for (i=0; i<IRP_NUM; i++)
    		{
    			if (g_pIrps[i] == _pIrp)
    			{
    				g_pIrps[i] = NULL;
    				break; 
    			}
    		}
    	}
    	NdisReleaseSpinLock(&g_lock); // 出螺旋锁
    	
    	//设置完成状态为STATUS_CANCELLED
     	_pIrp->IoStatus.Status = STATUS_CANCELLED;
     	_pIrp->IoStatus.Information = 0;	// bytes xfered
     	IoCompleteRequest( _pIrp, IO_NO_INCREMENT );
    	//释放Cancel自旋锁
    	IoReleaseCancelSpinLock(_pIrp->CancelIrql);
    	KdPrint(("Leave zcCancelReadIRP\n"));
    }
    #pragma PAGEDCODE
    NTSTATUS HelloDDKDispatchRoutine(IN PDEVICE_OBJECT pDevObj,
    								 IN PIRP pIrp) 
    {
    	PIO_STACK_LOCATION  irpStack = IoGetCurrentIrpStackLocation(pIrp);
        UNREFERENCED_PARAMETER(pDevObj);
    	switch (irpStack->MajorFunction)
    	{
    	case IRP_MJ_CREATE:
    		{
    			g_pollingInterval.QuadPart = 1000*500 * (-10); // 0.5s
    			KeSetTimer(
    				&g_pollingTimer,
    				g_pollingInterval,
    				&g_pollingDPC );
    			KdPrint(("IRP_MJ_CREATE\n"));
    			break;
    		}
    	case IRP_MJ_CLOSE:
    		{
    			KeCancelTimer(&g_pollingTimer);
    			KdPrint(("IRP_MJ_CLOSE\n"));
    			break;
    		}
    	case IRP_MJ_WRITE:
    		{
    			KdPrint(("IRP_MJ_WRITE\n"));
    			break;
    		}
    	case IRP_MJ_READ:
    		{
    			PUCHAR		puc = NULL;
    			ULONG		dwBufLength = 0;			
    			NdisQueryBufferSafe(pIrp->MdlAddress, &puc, &dwBufLength, NormalPagePriority);
    			
    			KdPrint(("IRP_MJ_READ : %d , (%X , %X)\n", *((int*)puc), puc, pIrp));
    			NdisAcquireSpinLock(&g_lock); // 进螺旋锁
    			{
    				BOOLEAN bFind = FALSE;
    				int i = 0;
    				for (i =0; i<IRP_NUM; i++)
    				{
    					if (g_pIrps[i] == NULL)
    					{
    						g_pIrps[i] = pIrp;
    						bFind = TRUE;
    						break;
    					}
    				}
    				if (! bFind) // 插入 not 成功
    				{
    					KdPrint(("PIRP insert fail ."));
    				}
    				else
    				{
    					KdPrint(("PIRP insert OK ."));
    				}
    			}
    			
    			// 设置 IRP取消例程
    			IoSetCancelRoutine(pIrp, zcCancelReadIRP); 
    			//将IRP设置为挂起
    			IoMarkIrpPending(pIrp);
    			//返回pending状态
    			NTSTATUS Status = STATUS_PENDING;
    			
    			NdisReleaseSpinLock(&g_lock); // 出螺旋锁
    			return Status;
    			break;
    		}
    	default:
    		{
    			KdPrint(("default\n"));
    			break;
    		}
    	}
    	KdPrint(("Enter HelloDDKDispatchRoutine\n"));
    	NTSTATUS status = STATUS_SUCCESS;
    	// 完成IRP
    	pIrp->IoStatus.Status = status;
    	pIrp->IoStatus.Information = 0;	// bytes xfered
    	IoCompleteRequest( pIrp, IO_NO_INCREMENT );
    	KdPrint(("Leave HelloDDKDispatchRoutine\n"));
    	return status;
    }
    int g_iIdx = 0;
    #pragma LOCKEDCODE
    VOID PollingTimerDpc( IN PKDPC pDpc,
    					  IN PVOID pContext,
    					  IN PVOID SysArg1,
    					  IN PVOID SysArg2 ) 
    {
    	PIRP pIrp = NULL;
    	NdisAcquireSpinLock(&g_lock); // 进螺旋锁
    	{ // 轮流完成 异步Read IRP数组里面的各个IRP
    		int i=g_iIdx;
    		for (i=g_iIdx; i<(IRP_NUM+g_iIdx); i++)
    		{
    			int j = i;
    			if (j >= IRP_NUM)
    				{j -= IRP_NUM;}
    			if (g_pIrps[j] != NULL)
    			{
    				pIrp = g_pIrps[j];
    				g_pIrps[j] = NULL;
    				break;
    			}
    		}
    		g_iIdx ++;
    		if (g_iIdx >= IRP_NUM)
    		{
    			g_iIdx -= IRP_NUM;
    		}
    	}
    	NdisReleaseSpinLock(&g_lock); // 出螺旋锁
    KdPrint(("PollingTimerDpc : %X\n", pIrp));
    	if (pIrp != NULL)
    	{
    		int i = 1000;
    		PUCHAR		puc = NULL;
    		ULONG		dwBufLength = 0;
    		NdisQueryBufferSafe(pIrp->MdlAddress, &puc, &dwBufLength, NormalPagePriority);
    		RtlCopyMemory(puc, &i, sizeof(int));
    		// 完成 IRP
    		pIrp->IoStatus.Status = STATUS_SUCCESS;
    		pIrp->IoStatus.Information = sizeof(UINT);
    		IoCompleteRequest( pIrp, IO_NO_INCREMENT );
    	}
    //	PDEVICE_OBJECT pDevObj = (PDEVICE_OBJECT)pContext;
    //	PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;
    	KeSetTimer(
    		&g_pollingTimer,
    		g_pollingInterval,
    		&g_pollingDPC);
    	//检验是运行在任意线程上下文
        PEPROCESS pEProcess = IoGetCurrentProcess();
        PTSTR ProcessName = (PTSTR)((ULONG)pEProcess + 0x174);
        KdPrint(("PollingTimerDpc : %s\n",ProcessName));
    }

    2013年4月11日 2:27

全部回复

  • 你的代码我在vs 2010下winxpsp3下可以打印出1000哇

    CreateFile over
    Read get data : 1000 , (0)
    Read get data : 1000 , (0)
    Read get data : 1000 , (0)
    Read get data : 1000 , (0)

    2013年4月22日 7:31
  • 你的代码我在vs 2010下winxpsp3下可以打印出1000哇

    CreateFile over
    Read get data : 1000 , (0)
    Read get data : 1000 , (0)
    Read get data : 1000 , (0)
    Read get data : 1000 , (0)

    好多天都没人关心,谢谢你能帮忙测试代码~~

    但是,貌似你没看清楚我的问题。我的问题,在顶楼的描述是 “C# ReadFile 得到的数据有时居然不是 1000...” 。

    也就是说,我的代码,应该一直都是在打印 1000 的,   但是跑着跑着,有时打印的信息居然不是 1000 ,这是我苦恼的地方,一直找不到我代码里面那边错误了...

    为了不浪费你的宝贵时间,吃个饭30分钟左右差不多吧,你可以在吃饭前让这个程序跑着,然后吃完饭回来,应该就能看到 非1000 的信息被打印出来了...

    再次感谢你的关注和回复~~

    2013年4月24日 4:42
  • 还有人来 帮助下么?

    2013年5月1日 4:25
  • 期待帮忙啊~~ 这么多天了啊
    2013年5月13日 0:26