NTModel框架与通信(含使用服务加载驱动)

原代码如下

#include <ntddk.h>

#define     DEVICE_NAME                 L"\\device\\NTModelDrv"
#define     LINK_NAME                   L"\\dosDevices\\NTModelDrv"

#define IOCTL_BASE  0x8000
#define MY_CTL_CODE(i)     CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_BASE+i, METHOD_BUFFERED, FILE_ANY_ACCESS)

#define IOCTL_HELLO MY_CTL_CODE(0)

typedef struct _DEVICE_EXTENSION {
    PDEVICE_OBJECT pDevice;
    UNICODE_STRING ustrDeviceName;  //设备名称
    UNICODE_STRING ustrSymLinkName; //符号链接名
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;

// function to dispatch the IRPs
NTSTATUS DispatchOK(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
   Irp->IoStatus.Status = STATUS_SUCCESS;
   IoCompleteRequest(Irp,IO_NO_INCREMENT);
   return STATUS_SUCCESS;
}

VOID DriverUnload (
    IN PDRIVER_OBJECT   pDriverObject)
{
    UNICODE_STRING strLink;
    RtlInitUnicodeString(&strLink, LINK_NAME);

    IoDeleteSymbolicLink(&strLink);
    IoDeleteDevice(pDriverObject->DeviceObject);
    DbgPrint("[NTModelDrv] Unloaded\n"); }

NTSTATUS DispatchIoctl(
    PDEVICE_OBJECT pDevObj,
    PIRP pIrp
    )
{
    NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
    PIO_STACK_LOCATION pIrpStack;
    ULONG uIoControlCode;
    PVOID pIoBuffer;
    ULONG uInSize;
    ULONG uOutSize;

    pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
    uIoControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode;
    pIoBuffer = pIrp->AssociatedIrp.SystemBuffer;
    uInSize = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;
    uOutSize = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;

    switch(uIoControlCode)
    {
        case IOCTL_HELLO:
        {
            DbgPrint("[NTModelDrv] Hello\n");
            status = STATUS_SUCCESS;
        }
        break;
    }

    if(status == STATUS_SUCCESS)
        pIrp->IoStatus.Information = uOutSize;
    else
        pIrp->IoStatus.Information = 0;

    /////////////////////////////////////
    pIrp->IoStatus.Status = status;
    IoCompleteRequest(pIrp, IO_NO_INCREMENT);

    return status;
}

//处理应用层的write()函数
NTSTATUS DispatchWrite (
    IN PDEVICE_OBJECT   pDevObj,
    IN PIRP pIrp)
{
    NTSTATUS    status = STATUS_SUCCESS;
    PVOID       userBuffer;
    PVOID       drvBuffer;
    ULONG       xferSize;

    //获得IRP堆栈的当前位置
    PIO_STACK_LOCATION pIrpStack =
        IoGetCurrentIrpStackLocation( pIrp );
    //获得当前写的长度和缓冲
    xferSize = pIrpStack->Parameters.Write.Length;
    userBuffer = pIrp->AssociatedIrp.SystemBuffer;
    drvBuffer = ExAllocatePoolWithTag(PagedPool, xferSize, 'tseT');
    if (drvBuffer == NULL)
    {
        status = STATUS_INSUFFICIENT_RESOURCES;
        xferSize = 0;
    }
    //将当前缓冲中的数据写入
    RtlCopyMemory( drvBuffer, userBuffer, xferSize );
    //完成IO,填写完成状态和传输的数据长度
        ExFreePool(drvBuffer);
        drvBuffer = NULL;
    pIrp->IoStatus.Status = status;
    pIrp->IoStatus.Information = xferSize;
    //完成IRP,不向下层传递
    IoCompleteRequest( pIrp, IO_NO_INCREMENT );
    return status;
}
//处理应用层的read()函数
NTSTATUS DispatchRead (
    IN PDEVICE_OBJECT   pDevObj,
    IN PIRP pIrp)
{
    NTSTATUS    status = STATUS_SUCCESS;
    PVOID       userBuffer;
    ULONG       xferSize;

    //获取IRP堆栈的当前位置
    PIO_STACK_LOCATION pIrpStack =
        IoGetCurrentIrpStackLocation( pIrp );
    //获取传输的字节数和缓冲
    xferSize = pIrpStack->Parameters.Read.Length;
    userBuffer = pIrp->AssociatedIrp.SystemBuffer;
    //从驱动中读数据
    RtlCopyMemory( userBuffer, L"Hello, world",
        xferSize );
    //填写IRP中的完成状态,结束IRP操作,不向下层发送
    pIrp->IoStatus.Status = status;
    pIrp->IoStatus.Information = xferSize;
    IoCompleteRequest( pIrp, IO_NO_INCREMENT );
    return status;
}

NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath)
{
    UNICODE_STRING  DeviceName;
    UNICODE_STRING  LinkName;
    NTSTATUS        status;
    PDEVICE_OBJECT  pDriverDeviceObject;
    PDEVICE_EXTENSION   pDevExt;
    ULONG i;

    //DbgPrint("Driver loaded.");
    pDriverObject->DriverUnload = DriverUnload;   

    // init strings
    RtlInitUnicodeString(&DeviceName, DEVICE_NAME);
    RtlInitUnicodeString(&LinkName, LINK_NAME);

    // to communicate with usermode, we need a device
    status = IoCreateDevice(
           pDriverObject,        // ptr to caller object
           sizeof(DEVICE_EXTENSION),  // extension device allocated byte number
           &DeviceName,         // device name
           FILE_DEVICE_UNKNOWN,
           0,                   // no special caracteristics
           FALSE,               // we can open many handles in same time
           &pDriverDeviceObject); // [OUT] ptr to the created object

    if ( !NT_SUCCESS(status) )
       return STATUS_NO_SUCH_DEVICE;

    pDriverDeviceObject-> Flags |= DO_BUFFERED_IO;
        pDevExt = (PDEVICE_EXTENSION)pDriverDeviceObject->DeviceExtension;
    pDevExt->pDevice = pDriverDeviceObject;
    pDevExt->ustrDeviceName = DeviceName;

    // we also need a symbolic link
    status = IoCreateSymbolicLink(&LinkName,&DeviceName);
    if( !NT_SUCCESS(status) )
    {
        IoDeleteDevice( pDriverDeviceObject );
        return STATUS_NO_SUCH_DEVICE;
    }  

    pDevExt->ustrSymLinkName = LinkName;

    for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
        pDriverObject->MajorFunction[i] = DispatchOK; 

    // handle IRPs

    pDriverObject->MajorFunction[IRP_MJ_READ]   = DispatchRead;
    pDriverObject->MajorFunction[IRP_MJ_WRITE]  = DispatchWrite;
    pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchIoctl; 

    //Do other things...   

    return STATUS_SUCCESS;
}

上面是真正的框架

下面是测试使用的框架:

#include <ntddk.h>

#define DEVICE_NAME L"\\device\\ntmodeldrv"
#define LINK_NAME L"\\dosdevices\\ntmodeldrv"

#define IOCTRL_BASE 0x800

#define MYIOCTRL_CODE(i)     CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTRL_BASE+i, METHOD_BUFFERED,FILE_ANY_ACCESS)

#define CTL_HELLO MYIOCTRL_CODE(0)
#define CTL_PRINT MYIOCTRL_CODE(1)
#define CTL_BYE MYIOCTRL_CODE(2)

NTSTATUS DispatchCommon(PDEVICE_OBJECT pObject, PIRP pIrp)
{
    pIrp->IoStatus.Status=STATUS_SUCCESS;
    pIrp->IoStatus.Information = 0;

    IoCompleteRequest(pIrp, IO_NO_INCREMENT);

    return STATUS_SUCCESS;
}

NTSTATUS DispatchCreate(PDEVICE_OBJECT pObject, PIRP pIrp)
{
    pIrp->IoStatus.Status=STATUS_SUCCESS;
    pIrp->IoStatus.Information = 0;

    IoCompleteRequest(pIrp, IO_NO_INCREMENT);

    return STATUS_SUCCESS;
}

NTSTATUS DispatchRead(PDEVICE_OBJECT pObject, PIRP pIrp)
{
    PVOID pReadBuffer = NULL;
    ULONG uReadLength = 0;
    PIO_STACK_LOCATION pStack = NULL;
    ULONG uMin = 0;
    ULONG uHelloStr = 0;

    uHelloStr = (wcslen(L"hello world")+1)*sizeof(WCHAR);

    pReadBuffer = pIrp->AssociatedIrp.SystemBuffer;
    pStack = IoGetCurrentIrpStackLocation(pIrp);

    uReadLength = pStack->Parameters.Read.Length;
    uMin = uReadLength>uHelloStr?uHelloStr:uReadLength;

    RtlCopyMemory(pReadBuffer, L"hello world", uMin);

    pIrp->IoStatus.Status = STATUS_SUCCESS;
    pIrp->IoStatus.Information = uMin;

    IoCompleteRequest(pIrp,IO_NO_INCREMENT);

    return STATUS_SUCCESS;

}

NTSTATUS DispatchWrite(PDEVICE_OBJECT pObject, PIRP pIrp)
{
    PVOID pWriteBuff = NULL;
    ULONG uWriteLength = 0;
    PIO_STACK_LOCATION pStack = NULL;

    PVOID pBuffer = NULL;

    pWriteBuff = pIrp->AssociatedIrp.SystemBuffer;

    pStack = IoGetCurrentIrpStackLocation(pIrp);
    uWriteLength = pStack->Parameters.Write.Length;

    pBuffer = ExAllocatePoolWithTag(PagedPool, uWriteLength, 'TSET');
    if(pBuffer == NULL)
    {
        pIrp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
        pIrp->IoStatus.Information = 0;
        IoCompleteRequest(pIrp,IO_NO_INCREMENT);
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    memset(pBuffer, 0, uWriteLength);

    RtlCopyMemory(pBuffer, pWriteBuff, uWriteLength);

    ExFreePool(pBuffer);
    pBuffer=NULL;

    pIrp->IoStatus.Status = STATUS_SUCCESS;
    pIrp->IoStatus.Information = uWriteLength;

    IoCompleteRequest(pIrp,IO_NO_INCREMENT);

    return STATUS_SUCCESS;

}

NTSTATUS DispatchIoctrl(PDEVICE_OBJECT pObject, PIRP pIrp)
{
    ULONG uIoctrlCode = 0;
    PVOID pInputBuff = NULL;
    PVOID pOutputBuff = NULL;

    ULONG uInputLength = 0;
    ULONG uOutputLength = 0;
    PIO_STACK_LOCATION pStack = NULL;

    pInputBuff = pOutputBuff = pIrp->AssociatedIrp.SystemBuffer;

    pStack = IoGetCurrentIrpStackLocation(pIrp);
    uInputLength = pStack->Parameters.DeviceIoControl.InputBufferLength;
    uOutputLength = pStack->Parameters.DeviceIoControl.OutputBufferLength;

    uIoctrlCode = pStack->Parameters.DeviceIoControl.IoControlCode;

    switch(uIoctrlCode)
    {
    case CTL_HELLO:
        DbgPrint("Hello iocontrol\n");
        break;
    case CTL_PRINT:
        DbgPrint("%ws\n", pInputBuff);
        break;
    case CTL_BYE:
        DbgPrint("Goodbye iocontrol\n");
        break;
    default:
        DbgPrint("Unknown iocontrol\n");

    }

    pIrp->IoStatus.Status = STATUS_SUCCESS;
    pIrp->IoStatus.Information = 0;
    IoCompleteRequest(pIrp,IO_NO_INCREMENT);

    return STATUS_SUCCESS;

}

NTSTATUS DispatchClean(PDEVICE_OBJECT pObject, PIRP pIrp)
{
    pIrp->IoStatus.Status=STATUS_SUCCESS;
    pIrp->IoStatus.Information = 0;

    IoCompleteRequest(pIrp, IO_NO_INCREMENT);

    return STATUS_SUCCESS;
}

NTSTATUS DispatchClose(PDEVICE_OBJECT pObject, PIRP pIrp)
{
    pIrp->IoStatus.Status=STATUS_SUCCESS;
    pIrp->IoStatus.Information = 0;

    IoCompleteRequest(pIrp, IO_NO_INCREMENT);

    return STATUS_SUCCESS;
}

VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
    UNICODE_STRING uLinkName={0};
    RtlInitUnicodeString(&uLinkName, LINK_NAME);
    IoDeleteSymbolicLink(&uLinkName);

    IoDeleteDevice(pDriverObject->DeviceObject);

    DbgPrint("Driver unloaded\n");

}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject,
                     PUNICODE_STRING pRegPath)
{
    UNICODE_STRING uDeviceName = {0};
    UNICODE_STRING uLinkName={0};
    NTSTATUS ntStatus = 0;
    PDEVICE_OBJECT pDeviceObject = NULL;
    ULONG i=0;

    DbgPrint("Driver load begin\n");

    RtlInitUnicodeString(&uDeviceName, DEVICE_NAME);
    RtlInitUnicodeString(&uLinkName,LINK_NAME);

    ntStatus = IoCreateDevice(pDriverObject,
     0,&uDeviceName,FILE_DEVICE_UNKNOWN,0,FALSE,&pDeviceObject);

    if(!NT_SUCCESS(ntStatus))
    {
        DbgPrint("IoCreateDevice failed:%x", ntStatus);
        return ntStatus;
    }

    pDeviceObject->Flags |= DO_BUFFERED_IO;

    ntStatus = IoCreateSymbolicLink(&uLinkName,&uDeviceName);
    if(!NT_SUCCESS(ntStatus))
    {
        IoDeleteDevice(pDeviceObject);
        DbgPrint("IoCreateSymbolicLink failed:%x\n", ntStatus);
        return ntStatus;
    }

    for(i=0;i<IRP_MJ_MAXIMUM_FUNCTION+1;i++)
    {
        pDriverObject->MajorFunction[i] = DispatchCommon;
    }

    pDriverObject->MajorFunction[IRP_MJ_CREATE]=DispatchCreate;
    pDriverObject->MajorFunction[IRP_MJ_READ]=DispatchRead;
    pDriverObject->MajorFunction[IRP_MJ_WRITE]=DispatchWrite;
    pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]=DispatchIoctrl;
    pDriverObject->MajorFunction[IRP_MJ_CLEANUP]=DispatchClean;
    pDriverObject->MajorFunction[IRP_MJ_CLOSE]=DispatchClose;

    pDriverObject->DriverUnload=DriverUnload;

    DbgPrint("Driver load ok!\n");

    return STATUS_SUCCESS;
}

下面是R3加载驱动和通信代码:

#include <windows.h>
#include <winsvc.h>
#include <conio.h>
#include <stdio.h>
#include <winioctl.h>

#define DRIVER_NAME "ntmodeldrv"
#define DRIVER_PATH ".\\ntmodeldrv.sys"

#define IOCTRL_BASE 0x8000

#define MYIOCTRL_CODE(i)     CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTRL_BASE+i, METHOD_BUFFERED,FILE_ANY_ACCESS)

#define CTL_HELLO MYIOCTRL_CODE(0)
#define CTL_PRINT MYIOCTRL_CODE(1)
#define CTL_BYE MYIOCTRL_CODE(2)

//装载NT驱动程序
BOOL LoadDriver(char* lpszDriverName,char* lpszDriverPath)
{
    //char szDriverImagePath[256] = "D:\\DriverTest\\ntmodelDrv.sys";
    char szDriverImagePath[256] = {0};
    //得到完整的驱动路径
    GetFullPathName(lpszDriverPath, 256, szDriverImagePath, NULL);

    BOOL bRet = FALSE;

    SC_HANDLE hServiceMgr=NULL;//SCM管理器的句柄
    SC_HANDLE hServiceDDK=NULL;//NT驱动程序的服务句柄

    //打开服务控制管理器
    hServiceMgr = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS );

    if( hServiceMgr == NULL )
    {
        //OpenSCManager失败
        printf( "OpenSCManager() Failed %d ! \n", GetLastError() );
        bRet = FALSE;
        goto BeforeLeave;
    }
    else
    {
        ////OpenSCManager成功
        printf( "OpenSCManager() ok ! \n" );
    }

    //创建驱动所对应的服务
    hServiceDDK = CreateService( hServiceMgr,
        lpszDriverName, //驱动程序的在注册表中的名字
        lpszDriverName, // 注册表驱动程序的 DisplayName 值
        SERVICE_ALL_ACCESS, // 加载驱动程序的访问权限
        SERVICE_KERNEL_DRIVER,// 表示加载的服务是驱动程序
        SERVICE_DEMAND_START, // 注册表驱动程序的 Start 值  自动启动 开机启动 手动启动 禁用
        SERVICE_ERROR_IGNORE, // 注册表驱动程序的 ErrorControl 值
        szDriverImagePath, // 注册表驱动程序的 ImagePath 值
        NULL,  //GroupOrder HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\GroupOrderList
        NULL,
        NULL,
        NULL,
        NULL);  

    DWORD dwRtn;
    //判断服务是否失败
    if( hServiceDDK == NULL )
    {
        dwRtn = GetLastError();
        if( dwRtn != ERROR_IO_PENDING && dwRtn != ERROR_SERVICE_EXISTS )
        {
            //由于其他原因创建服务失败
            printf( "CrateService() Failed %d ! \n", dwRtn );
            bRet = FALSE;
            goto BeforeLeave;
        }
        else
        {
            //服务创建失败,是由于服务已经创立过
            printf( "CrateService() Failed Service is ERROR_IO_PENDING or ERROR_SERVICE_EXISTS! \n" );
        }

        // 驱动程序已经加载,只需要打开
        hServiceDDK = OpenService( hServiceMgr, lpszDriverName, SERVICE_ALL_ACCESS );
        if( hServiceDDK == NULL )
        {
            //如果打开服务也失败,则意味错误
            dwRtn = GetLastError();
            printf( "OpenService() Failed %d ! \n", dwRtn );
            bRet = FALSE;
            goto BeforeLeave;
        }
        else
        {
            printf( "OpenService() ok ! \n" );
        }
    }
    else
    {
        printf( "CrateService() ok ! \n" );
    }

    //开启此项服务
    bRet= StartService( hServiceDDK, NULL, NULL );
    if( !bRet )
    {
        DWORD dwRtn = GetLastError();
        if( dwRtn != ERROR_IO_PENDING && dwRtn != ERROR_SERVICE_ALREADY_RUNNING )
        {
            printf( "StartService() Failed %d ! \n", dwRtn );
            bRet = FALSE;
            goto BeforeLeave;
        }
        else
        {
            if( dwRtn == ERROR_IO_PENDING )
            {
                //设备被挂住
                printf( "StartService() Failed ERROR_IO_PENDING ! \n");
                bRet = FALSE;
                goto BeforeLeave;
            }
            else
            {
                //服务已经开启
                printf( "StartService() Failed ERROR_SERVICE_ALREADY_RUNNING ! \n");
                bRet = TRUE;
                goto BeforeLeave;
            }
        }
    }
    bRet = TRUE;
//离开前关闭句柄
BeforeLeave:
    if(hServiceDDK)
    {
        CloseServiceHandle(hServiceDDK);
    }
    if(hServiceMgr)
    {
        CloseServiceHandle(hServiceMgr);
    }
    return bRet;
}

//卸载驱动程序
BOOL UnloadDriver( char * szSvrName )
{
    BOOL bRet = FALSE;
    SC_HANDLE hServiceMgr=NULL;//SCM管理器的句柄
    SC_HANDLE hServiceDDK=NULL;//NT驱动程序的服务句柄
    SERVICE_STATUS SvrSta;
    //打开SCM管理器
    hServiceMgr = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS );
    if( hServiceMgr == NULL )
    {
        //带开SCM管理器失败
        printf( "OpenSCManager() Failed %d ! \n", GetLastError() );
        bRet = FALSE;
        goto BeforeLeave;
    }
    else
    {
        //带开SCM管理器失败成功
        printf( "OpenSCManager() ok ! \n" );
    }
    //打开驱动所对应的服务
    hServiceDDK = OpenService( hServiceMgr, szSvrName, SERVICE_ALL_ACCESS );  

    if( hServiceDDK == NULL )
    {
        //打开驱动所对应的服务失败
        printf( "OpenService() Failed %d ! \n", GetLastError() );
        bRet = FALSE;
        goto BeforeLeave;
    }
    else
    {
        printf( "OpenService() ok ! \n" );
    }
    //停止驱动程序,如果停止失败,只有重新启动才能,再动态加载。
    if( !ControlService( hServiceDDK, SERVICE_CONTROL_STOP , &SvrSta ) )
    {
        printf( "ControlService() Failed %d !\n", GetLastError() );
    }
    else
    {
        //打开驱动所对应的失败
        printf( "ControlService() ok !\n" );
    } 

    //动态卸载驱动程序。  

    if( !DeleteService( hServiceDDK ) )
    {
        //卸载失败
        printf( "DeleteSrevice() Failed %d !\n", GetLastError() );
    }
    else
    {
        //卸载成功
        printf( "DelServer:deleteSrevice() ok !\n" );
    }  

    bRet = TRUE;
BeforeLeave:
//离开前关闭打开的句柄
    if(hServiceDDK)
    {
        CloseServiceHandle(hServiceDDK);
    }
    if(hServiceMgr)
    {
        CloseServiceHandle(hServiceMgr);
    }
    return bRet;
} 

void TestDriver()
{
    //测试驱动程序
    HANDLE hDevice = CreateFile("\\\\.\\NTmodeldrv",
        GENERIC_WRITE | GENERIC_READ,
        0,
        NULL,
        OPEN_EXISTING,
        0,
        NULL);
    if( hDevice != INVALID_HANDLE_VALUE )
    {
        printf( "Create Device ok ! \n" );
    }
    else
    {
        printf( "Create Device Failed %d ! \n", GetLastError() );
        return;
    }
    CHAR bufRead[1024]={0};
    WCHAR bufWrite[1024]=L"Hello, world";

    DWORD dwRead = 0;
    DWORD dwWrite = 0;

    ReadFile(hDevice, bufRead, 1024, &dwRead, NULL);
    printf("Read done!\n");
    WriteFile(hDevice, bufWrite, (wcslen(bufWrite)+1)*sizeof(WCHAR), &dwWrite, NULL);

    printf("Write done!\n");

    CHAR bufInput[1024] ="Hello, world";
    CHAR bufOutput[1024] = {0};
    DWORD dwRet = 0;

    WCHAR bufFileInput[1024] =L"c:\\docs\\hi.txt";

    DeviceIoControl(hDevice,
        CTL_PRINT,
        bufFileInput,
        sizeof(bufFileInput),
        bufOutput,
        sizeof(bufOutput),
        &dwRet,
        NULL);
    DeviceIoControl(hDevice,
        CTL_HELLO,
        NULL,
        0,
        NULL,
        0,
        &dwRet,
        NULL);

    DeviceIoControl(hDevice,
        CTL_BYE,
        NULL,
        0,
        NULL,
        0,
        &dwRet,
        NULL);
    printf("DeviceIoControl done!\n");
    CloseHandle( hDevice );
} 

int main(int argc, char* argv[])
{
    //加载驱动
    BOOL bRet = LoadDriver(DRIVER_NAME,DRIVER_PATH);
    if (!bRet)
    {
        printf("LoadNTDriver error\n");
        return 0;
    }
    //加载成功

    printf( "press any key to create device!\n" );
    getch();  

    TestDriver();

    //这时候你可以通过注册表,或其他查看符号连接的软件验证。
    printf( "press any key to stop service!\n" );
    getch();  

    //卸载驱动
    bRet = UnloadDriver(DRIVER_NAME);
    if (!bRet)
    {
        printf("UnloadNTDriver error\n");
        return 0;
    }

    return 0;
}

下面是我自己的驱动模板

通信代码依旧是上面的 只是改了设备名和驱动名 和 testDriver中打开驱动的名称

#include <ntddk.h>

#define DEVICE_NAME L"\\device\\DjWow"
#define LINK_NAME L"\\dosdevices\\DjWow" //\\??\\xxxx

#define IOCTRL_BASE 0x800

#define IOCTL_CODE(i)	CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTRL_BASE+i, METHOD_BUFFERED, FILE_ANY_ACCESS)

#define CTL_HELLO IOCTL_CODE(0)
#define CTL_ULONG IOCTL_CODE(1)
#define CTL_WCHAR IOCTL_CODE(2)

NTSTATUS DispatchCommon(PDEVICE_OBJECT pDeviceObject, PIRP pIrp)
{
	pIrp->IoStatus.Status = STATUS_SUCCESS;
	pIrp->IoStatus.Information = 0;

	UNREFERENCED_PARAMETER(pDeviceObject);

	IoCompleteRequest(pIrp, IO_NO_INCREMENT);

	return STATUS_SUCCESS;
}

NTSTATUS DispatchCreate(PDEVICE_OBJECT pDeviceObject, PIRP pIrp)
{
	pIrp->IoStatus.Status = STATUS_SUCCESS;
	pIrp->IoStatus.Information = 0;

	UNREFERENCED_PARAMETER(pDeviceObject);

	IoCompleteRequest(pIrp, IO_NO_INCREMENT);

	return STATUS_SUCCESS;
}

NTSTATUS DispatchClose(PDEVICE_OBJECT pDeviceObject, PIRP pIrp)
{
	pIrp->IoStatus.Status = STATUS_SUCCESS;
	pIrp->IoStatus.Information = 0;

	UNREFERENCED_PARAMETER(pDeviceObject);

	IoCompleteRequest(pIrp, IO_NO_INCREMENT);

	return STATUS_SUCCESS;
}

NTSTATUS DispatchClear(PDEVICE_OBJECT pDeviceObject, PIRP pIrp)
{
	pIrp->IoStatus.Status = STATUS_SUCCESS;
	pIrp->IoStatus.Information = 0;

	UNREFERENCED_PARAMETER(pDeviceObject);

	IoCompleteRequest(pIrp, IO_NO_INCREMENT);

	return STATUS_SUCCESS;
}

NTSTATUS DispatchRead(PDEVICE_OBJECT pDeviceObject, PIRP pIrp)
{
	PVOID pBuff = 0;
	ULONG pBuffLen = 0;
	ULONG pStackLen = 0;
	PIO_STACK_LOCATION pStack = 0;
	ULONG uMin = 0;

	UNREFERENCED_PARAMETER(pDeviceObject);

	pBuff = pIrp->AssociatedIrp.SystemBuffer;

	pStack = IoGetCurrentIrpStackLocation(pIrp);

	pStackLen = pStack->Parameters.Read.Length;

	pBuffLen = (wcslen(L"hello world") + 1) * sizeof(WCHAR);

	uMin = pBuffLen < pStackLen ? pBuffLen:pStackLen;

	RtlCopyMemory(pBuff, L"hello wolrd", uMin);

	pIrp->IoStatus.Status = STATUS_SUCCESS;
	pIrp->IoStatus.Information = uMin;

	IoCompleteRequest(pIrp, IO_NO_INCREMENT);

	return STATUS_SUCCESS;
}

NTSTATUS DispatchWrite(PDEVICE_OBJECT pDeviceObject, PIRP pIrp)
{
	PVOID pWriteBuff = 0;
	PVOID pBuff = 0;
	ULONG uWriteBuffLen = 0;
	PIO_STACK_LOCATION pStack = 0;

	UNREFERENCED_PARAMETER(pDeviceObject);

	pWriteBuff = pIrp->AssociatedIrp.SystemBuffer;

	pStack = IoGetCurrentIrpStackLocation(pIrp);

	uWriteBuffLen = pStack->Parameters.Write.Length;

	pBuff = ExAllocatePoolWithTag(PagedPool, uWriteBuffLen,'TSET');

	if(pBuff == NULL)
	{
		pIrp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
		pIrp->IoStatus.Information = 0;
		return STATUS_INSUFFICIENT_RESOURCES;
	}

	RtlZeroMemory(pBuff, uWriteBuffLen);

	RtlCopyMemory(pBuff,pWriteBuff, uWriteBuffLen);

	ExFreePool(pBuff);
	pBuff = 0;

	IoCompleteRequest(pIrp, IO_NO_INCREMENT);

	pIrp->IoStatus.Status = STATUS_SUCCESS;
	pIrp->IoStatus.Information = uWriteBuffLen;

	return STATUS_SUCCESS;
}

NTSTATUS DispatchIoctrl(PDEVICE_OBJECT pDeviceObject, PIRP pIrp)
{
	PIO_STACK_LOCATION pStack = 0;
	PVOID pBuff = 0;
	ULONG uOutLen = 0;
	ULONG uInLen = 0;
	ULONG uCtlCode = 0;

	UNREFERENCED_PARAMETER(pDeviceObject);

	pStack = IoGetCurrentIrpStackLocation(pIrp);

	uOutLen = pStack->Parameters.DeviceIoControl.OutputBufferLength;
	uInLen = pStack->Parameters.DeviceIoControl.InputBufferLength;

	pBuff = pIrp->AssociatedIrp.SystemBuffer;

	uCtlCode = pStack->Parameters.DeviceIoControl.IoControlCode;

	switch (uCtlCode)
	{
	case CTL_HELLO:
		DbgPrint("hello!\n");
		break;
	case CTL_ULONG:
		{
			DbgPrint("pid:%d\n",*(ULONG*)pBuff);
			RtlCopyMemory(pBuff,L"ok",uOutLen);
			break;
		}
	case CTL_WCHAR:
			DbgPrint("%ws",pBuff);
			break;
	default:
		DbgPrint("UNKNUW CTLCODE!\n");
	}

	pIrp->IoStatus.Status = STATUS_SUCCESS;
	pIrp->IoStatus.Information = uOutLen;

	IoCompleteRequest(pIrp, IO_NO_INCREMENT);

	return STATUS_SUCCESS;
}

VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
	UNICODE_STRING strLinkName ={0};

	RtlInitUnicodeString(&strLinkName,LINK_NAME);

	IoDeleteSymbolicLink(&strLinkName);

	if(pDriverObject->DeviceObject)
	{
		IoDeleteDevice(pDriverObject->DeviceObject);
	}

	DbgPrint("DriverUnload");

	return;
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegPath)
{
	UNICODE_STRING strDeviceName = {0};
	UNICODE_STRING strLinkName = {0};
	NTSTATUS status = 0;
	PDEVICE_OBJECT pDeviceObject = 0;
	ULONG i = 0;

	DbgPrint("[DJWOW]DriverEntry!\n");

	UNREFERENCED_PARAMETER(pRegPath);

	RtlInitUnicodeString(&strDeviceName, DEVICE_NAME);
	RtlInitUnicodeString(&strLinkName, LINK_NAME);

	status = IoCreateDevice(pDriverObject, 0, &strDeviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, &pDeviceObject);

	if(!NT_SUCCESS(status))
	{
		DbgPrint("CretaDevice Faild:0x%x\n",status);
		return status;
	}

	pDeviceObject->Flags |= DO_BUFFERED_IO;

	status = IoCreateSymbolicLink(&strLinkName,&strDeviceName);

	if(!NT_SUCCESS(status))
	{
		IoDeleteDevice(pDeviceObject);
		DbgPrint("IoCreateSymbolicdLink Faild:0x%x\n",status);
		return status;
	}

	for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION + 1; i++)
	{
		pDriverObject->MajorFunction[i] = DispatchCommon;
	}

	pDriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;
	pDriverObject->MajorFunction[IRP_MJ_READ] = DispatchRead;
	pDriverObject->MajorFunction[IRP_MJ_WRITE] = DispatchWrite;
	pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchIoctrl;
	pDriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;
	pDriverObject->MajorFunction[IRP_MJ_CLEANUP] = DispatchClear;

	pDriverObject->DriverUnload = DriverUnload;

	return STATUS_SUCCESS;

}
时间: 2024-10-13 17:09:36

NTModel框架与通信(含使用服务加载驱动)的相关文章

Openstack学习笔记之——Neutron-server服务加载与启动源码分析(三)

本文是在学习Openstack的过程中整理和总结,由于时间和个人能力有限,错误之处在所难免,欢迎指正! 在Neutron-server服务加载与启动源码分析(二)中搞定模块功能的扩展和加载,我们就回到Neutron-server服务加载与启动源码分析(一)中的_run_wsgi函数 <span style="font-size:14px;">def _run_wsgi(app_name): app = config.load_paste_app(app_name) ifno

ArcGIS API for Silverlight 调用GP服务加载等值线图层

原文:ArcGIS API for Silverlight 调用GP服务加载等值线图层 第二篇.Silverlight客户端调用GP服务 利用ArcGIS API for Silverlight实现GP服务调用,这里的雨量数据是通过一个WebService获取而来,主要信息是雨量站点的经纬度坐标值和某个时间段内的降雨量值三个主要字段. 以下是核心代码部分: <UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/pr

如何让aspnet服务加载静态资源html(我的动态网页静态化) 转

我们知道,IIS自身是不能处理像ASPX扩展名这样的页面,只能直接请求像HTML这样的静态文件. 当客户端请求一个服务器资源时,这个HTTP请求会被inetinfo.exe进程截获(www服务),然后Check请求资源的类型,并依据资源映射信息(存储在IIS元库中,一种IIS专用的配置数据库)将请求的资源分配给特定的处理程序模块.1,如果是静态资源的请求,则分配由IIS处理(IIS在本地Web Server上访问请求的文件),将内容输出到控制台,发出请求的浏览器就能接收到它了.-----End2

Android 三级联动选择城市+后台服务加载数据库

技术渣,大家将就着看 首先我们需要一个xml数据保存到数据库,这里我从QQ下面找到一个loclist.xml文件 <CountryRegion Name="中国" Code="1"> <State Name="北京" Code="11"> <City Name="东城" Code="1" /> <City Name="西城"

java加载驱动

加载驱动方法 1.Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); 2. DriverManager.registerDriver(new com.mysql.jdbc.Driver()); 3.System.setProperty("jdbc.drivers", "com.mysql.jdbc.Driver");

java基础-jdbc——三种方式加载驱动建立连接

1 String url = "jdbc:mysql://localhost:3306/student?Unicode=true&characterEncoding=utf-8"; 2 Properties info = new Properties(); 3 info.put("user", "canon"); 4 info.put("password", "123456"); 5 6 /** 7

JDBC详解系列(二)之加载驱动

---[来自我的CSDN博客](http://blog.csdn.net/weixin_37139197/article/details/78838091)--- ??在JDBC详解系列(一)之流程中,我将数据库的连接分解成了六个步骤. JDBC流程: 第一步:加载Driver类,注册数据库驱动: 第二步:通过DriverManager,使用url,用户名和密码建立连接(Connection): 第三步:通过Connection,使用sql语句打开Statement对象: 第四步:执行语句,将结

Android批量图片加载经典系列——afinal框架实现图片的异步缓存加载

一.问题描述 在之前的系列文章中,我们使用了Volley和Xutil框架实现图片的缓存加载(查看系列文章:http://www.cnblogs.com/jerehedu/p/4607599.html#pltpjz),接下来我们再介绍一下afinal 框架的使用. Afinal 是一个android的http框架.sqlite orm 和 ioc 框架.使其更加简单易用,Afinal的宗旨是简洁,快速.约定配置的方式之后,尽量一行代码完成所有事情,代码入侵性小,在三者中比较推荐.在这里我们主要使用

原 Volley框架之网络请求和图片加载

Volley是 Google 推出的 Android 异步网络请求框架和图片加载框架. Volley的特性 (1).封装了的异步的请求API.Volley 中大多是基于接口的设计,可配置性强.(2).一个优雅和稳健的请求队列,一定程度符合 Http 规范,包括请求头的处理,缓存机制的支持等.(3).自定义的网络图像加载视图(NetworkImageView,ImageLoader等) .(4). 提供简便的图片加载工具. 本案例包含get,post请求和几种网络图片加载的方式,效果如图: