tycoon
驱动牛犊
驱动牛犊
  • 注册日期2007-07-25
  • 最后登录2008-02-26
  • 粉丝0
  • 关注0
  • 积分330分
  • 威望34点
  • 贡献值0点
  • 好评度33点
  • 原创分0分
  • 专家分0分
阅读:1262回复:3

Driver如何给App发消息的问题

楼主#
更多 发布于:2007-08-28 11:44
参照 http://bbs.driverdevelop.com/htm_data/45/0307/47706.html,客户端程序改造如下:
我想让驱动回传一个字符放在 TCHAR testdata[1];中。

驱动端怎么写??上面的例子中给出的驱动端的程序看不明白,哪位指点一下啊


另外我把
//         while (TRUE)
//             if (_getche() == 0xd)
//                 break;
//            
//             CloseHandle(hEvent);
//             CloseHandle(h);

这段代码屏蔽掉了,我想给驱动端发一个消息后,不结束等待线程,可以多次接受驱动端返回的数据,这个想法可行吗???

#include "stdafx.h"
#include <windows.h>                
#include <stdlib.h>
#include <stdio.h>
#include <winioctl.h>
#include <string.h>
#include <crtdbg.h>

#define CD_DEVICE_NAME  TEXT("\\\\.\\CryptionDirectory")
#define IOCTL_GET_TEST_DATA    (ULONG) CTL_CODE( FILE_DEVICE_DISK_FILE_SYSTEM, 0x00, METHOD_NEITHER, FILE_READ_ACCESS )
#define IOCTL_SET_TEST_DATA_EVENT    (ULONG) CTL_CODE( FILE_DEVICE_DISK_FILE_SYSTEM, 0x00, METHOD_NEITHER, FILE_WRITE_ACCESS )



TCHAR testdata[1];

HANDLE h, hEvent;

/////////////////////////////////////////////////////////////////
// ServiceThread
//
// This thread is awakened by the driver to tell the app to come
// and get the interrupt records
//
DWORD WINAPI ServiceThread(PVOID hEvent)
{
    ULONG nBytesRead;    
    while (TRUE)
    {
        WaitForSingleObject(hEvent, INFINITE);
        
        printf("New event:\n");
            
            if (!DeviceIoControl(
                h,
                IOCTL_GET_TEST_DATA,
                NULL,
                0,
                testdata,
                sizeof(testdata),
                &nBytesRead,
                NULL) )
            {
                printf("DeviceIoControl failed %x\n", GetLastError());
                exit(1);
            }
            printf("%c", testdata[0]);
    }
    
    return 0;
}

/////////////////////////////////////////////////////////////////
//
// Main
//
void __cdecl main(int ac, char* av[])
{
    DWORD Tid;
    ULONG error;
    ULONG nRet;
    
    // Open the device
    
    h = CreateFile(CD_DEVICE_NAME,
        GENERIC_READ,
        FILE_SHARE_READ,
        NULL,
        OPEN_EXISTING,
        0,
        NULL);
    
    if (h == INVALID_HANDLE_VALUE)
    {
        error=GetLastError();
        fprintf(stderr, "Cannot open device, error %d (0x%x)\n", error, error);
            exit(1);
    }
    
    // Create an event for notification
    
    hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
    
    if (! DeviceIoControl(
        h,
        IOCTL_SET_TEST_DATA_EVENT,
        &hEvent,
        sizeof(hEvent),
        NULL,
        0,
        &nRet,
        NULL
        ) )
    {
        printf("Ioctl failed: %x\n", GetLastError());
            exit(1);
    }
    
    // Create the thread that waits for the event
    
    CreateThread(0, 0x1000, ServiceThread, (PVOID)hEvent, 0, &Tid);
    
    // printf("press return to exit . . .\n");
        
        // Look for a key to terminate
        
//         while (TRUE)
//             if (_getche() == 0xd)
//                 break;
//            
//             CloseHandle(hEvent);
//             CloseHandle(h);
}
abc13271552
驱动小牛
驱动小牛
  • 注册日期2007-08-13
  • 最后登录2023-12-05
  • 粉丝0
  • 关注0
  • 积分34分
  • 威望552点
  • 贡献值0点
  • 好评度160点
  • 原创分0分
  • 专家分0分
  • 社区居民
沙发#
发布于:2007-08-28 17:37
我的理解(不一定对)
驱动一般运行在pass_level与dispatch_level两层软多
pass_level就是你上层的api来访问所解发的, 它是一个被动态, 你可以在应用程序层
来请求资料,下面贴下代码,不知道对你有没有用,^_^
驱网无线,快乐无限
abc13271552
驱动小牛
驱动小牛
  • 注册日期2007-08-13
  • 最后登录2023-12-05
  • 粉丝0
  • 关注0
  • 积分34分
  • 威望552点
  • 贡献值0点
  • 好评度160点
  • 原创分0分
  • 专家分0分
  • 社区居民
板凳#
发布于:2007-08-28 17:39
与驱动通信
        应用程序与内核通信
应用程序:
1.
#define DEVICE_HELLO_INDEX 0x860
// IOCTL宏
#define START_HELLPWORLD CTL_CODE(FILE_DEVICE_UNKNOWN, DEVICE_HELLO_INDEX,  METHOD_BUFFERED,  FILE_ANY_ACCESS)
2.载入驱动并启动
    LoadDeviceDriver("HelloWorld", "C:\\hel\\objchk_wnet_x86\\i386\\helloword.sys",
                      &hDrv, &dwError );
3,
DeviceIoControl(hDrv,                        //设备名柄
                START_HELLPWORLD,        //传入的控制码.
                ";c:\\test\\abc\\1.doc;;",            //输入的BUFFER
                strlen(";c:\\test\\abc\\1.doc; "),    //输入BUFFER的大小
                buf,                           //输出BUFFER
                128,                           //输出BUFFER的大小
                &nb,                       //返回的实际字节数
                NULL ) )                       //
4,
printf("%s\r\n%d\r\n", buf, nb);
驱动:
    1.
#define DEVICE_HELLO_INDEX 0x860
// IOCTL宏
#define START_HELLPWORLD CTL_CODE(FILE_DEVICE_UNKNOWN, DEVICE_HELLO_INDEX,  METHOD_BUFFERED,  FILE_ANY_ACCESS)
2,
//设置IRP派遣例程和卸载例程
    DriverObject->MajorFunction[IRP_MJ_CREATE]=  //未控制
    DriverObject->MajorFunction[IRP_MJ_CLOSE]=   //未控制
        DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]=HelloWorldDispatch;
    DriverObject->DriverUnload=HelloWorldUnLoad;
3,
NTSTATUS HelloWorldDispatch (IN PDEVICE_OBJECT DeviceObject,IN PIRP pIrp)
{
    NTSTATUS ntStatus=STATUS_SUCCESS;
    PIO_STACK_LOCATION IrpStack=NULL;   //IRP堆栈
    ULONG IoControlCodes=0;                 //I/O控制代码
    UCHAR *in_buffer,*out_buffer;

    in_buffer = out_buffer = pIrp->AssociatedIrp.SystemBuffer;

    //设置IRP状态
    pIrp->IoStatus.Status=STATUS_SUCCESS;
    pIrp->IoStatus.Information=0;
//取得I/O控制代码
        IoControlCodes = IrpStack->Parameters.DeviceIoControl.IoControlCode;
    
        switch (IoControlCodes)
        {
        //启动
        case START_HELLPWORLD:
        {
                 DbgPrint("%s", in_buffer);
                 RtlCopyBytes(out_buffer, "hi ,this is from the kernel",30);
                 pIrp->IoStatus.Information = 30;
//Irp->IOstAtus.InformAtion 表示要返回多少字节,当=0
//时,user-mode的returnsize=0,buffer中也没有数据返回
      }
            break;
    case STOP_HELLPWORLD:
            DbgPrint("this is Stoping \"Hello World\"\n");
            break;
            
        default:
            pIrp->IoStatus.Status=STATUS_INVALID_PARAMETER;
            break;
        }
        default:
            break;
    }
    
    ntStatus=pIrp->IoStatus.Status;
    IoCompleteRequest(pIrp,IO_NO_INCREMENT);
}
//这个complete很重要,,没加这个的时候,user-mode程序不返回,驱动也卸载不下来,用这个函数来returning the given IRP to the I/O Manager,这样就完成了一个完整的irp,,现在应该弄清IRP和IO_STACK_LOCATION的关系,在《windows 操作系统原理》上找到,“任何内核模式程序在创建一个IRP时,同时还创建一个与之关联的I/O堆栈,堆栈中的I/O堆栈单元由IO_STACK_LOCATION结构定义,每个堆栈单元都对应一个将处理该IRP的驱动程序。为了在一个给定的IRP中确定当前IRP I/O堆栈单元,驱动程序可以调用IoGetCurrentStAckLOcAtion函数,该函数返回指向当前I/O堆栈单元的指针。”
return ntStatus;
}
驱网无线,快乐无限
abc13271552
驱动小牛
驱动小牛
  • 注册日期2007-08-13
  • 最后登录2023-12-05
  • 粉丝0
  • 关注0
  • 积分34分
  • 威望552点
  • 贡献值0点
  • 好评度160点
  • 原创分0分
  • 专家分0分
  • 社区居民
地板#
发布于:2007-08-28 17:40
filemon是定时请求的,你可以参考一下
驱网无线,快乐无限
游客

返回顶部