Kernel Mode Driver Framework >> C/C++ (PNP) >> Timer

WDF


參考資訊:
1. Source Code
2. using-timers

WDF重新封裝出一個新的Timer計時器,基本上,用法跟DPC Timer相似,可以設定成週期性或單一次觸發類型,使用步驟如下:
1. WdfTimerCreate()
2. WdfTimerStart()
3. WdfTimerStop()

main.c

#include <ntddk.h>
#include <wdf.h>

#define DEV_NAME L"\\Device\\MyDriver"
#define SYM_NAME L"\\DosDevices\\MyDriver"

#define IOCTL_START CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_STOP  CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)

ULONG cnt=0;
WDFTIMER hTimer;
PDEVICE_OBJECT pDevice;

VOID OnTimer(WDFTIMER Timer)
{
  cnt+= 1;
  DbgPrint("WdfTimer: %d", cnt);
}

void IrpFileCreate(WDFDEVICE Device, WDFREQUEST Request, WDFFILEOBJECT FileObject)
{  
  DbgPrint("IrpFieCreate");
  WdfRequestComplete(Request, STATUS_SUCCESS);
}

void IrpFileClose(WDFFILEOBJECT FileObject)
{
  DbgPrint("IrpFieClose");
}

void IrpIOCTL(WDFQUEUE Queue, WDFREQUEST Request, size_t OutputBufferLength, size_t InputBufferLength, ULONG IoControlCode)
{
  LARGE_INTEGER tt;
  
  switch(IoControlCode){
  case IOCTL_START:
    DbgPrint("IOCTL_START");
    cnt = 0;
    tt.HighPart = -1;
    tt.LowPart = (ULONG)-10000000;
    WdfTimerStart(hTimer, tt.QuadPart);
    break;
  case IOCTL_STOP:
    DbgPrint("IOCTL_STOP");
    WdfTimerStop(hTimer, FALSE);
    break;
  }
  WdfRequestComplete(Request, STATUS_SUCCESS);
}

NTSTATUS AddDevice(WDFDRIVER Driver, PWDFDEVICE_INIT pDeviceInit)
{
  WDFDEVICE device;
  UNICODE_STRING suDevName;
  UNICODE_STRING szSymName;
  WDF_TIMER_CONFIG timer_cfg;
  WDF_FILEOBJECT_CONFIG file_cfg;
  WDF_IO_QUEUE_CONFIG ioqueue_cfg;
  WDF_OBJECT_ATTRIBUTES timer_attribute;
  
  RtlInitUnicodeString(&suDevName, DEV_NAME);
  RtlInitUnicodeString(&szSymName, SYM_NAME);
  WdfDeviceInitAssignName(pDeviceInit, &suDevName);
  
  WdfDeviceInitSetIoType(pDeviceInit, WdfDeviceIoBuffered);
  WDF_FILEOBJECT_CONFIG_INIT(&file_cfg, IrpFileCreate, IrpFileClose, NULL);
  WdfDeviceInitSetFileObjectConfig(pDeviceInit, &file_cfg, WDF_NO_OBJECT_ATTRIBUTES);
  WdfDeviceCreate(&pDeviceInit, WDF_NO_OBJECT_ATTRIBUTES, &device);
  WdfDeviceCreateSymbolicLink(device, &szSymName);
  
  WDF_TIMER_CONFIG_INIT_PERIODIC(&timer_cfg, OnTimer, 1000);
  WDF_OBJECT_ATTRIBUTES_INIT(&timer_attribute);
  timer_attribute.ParentObject = device;
  WdfTimerCreate(&timer_cfg, &timer_attribute, &hTimer);
  
  WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioqueue_cfg, WdfIoQueueDispatchSequential);
  ioqueue_cfg.EvtIoDeviceControl = IrpIOCTL;
  return WdfIoQueueCreate(device, &ioqueue_cfg, WDF_NO_OBJECT_ATTRIBUTES, WDF_NO_HANDLE);
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pOurDriver, PUNICODE_STRING pRegistry)
{
  WDF_DRIVER_CONFIG config;

  WDF_DRIVER_CONFIG_INIT(&config, AddDevice);
  return WdfDriverCreate(pOurDriver, pRegistry, WDF_NO_OBJECT_ATTRIBUTES, &config, WDF_NO_HANDLE);
}

AddDevice()初始化I/O Timer
IrpIOCTL()啟動或停止I/O Timer
OnTimer()僅列印訊息,其餘事情不做

app.c

#define INITGUID
#include <windows.h>
#include <winioctl.h>
#include <strsafe.h>
#include <setupapi.h>
#include <stdio.h>
#include <stdlib.h>

#define IOCTL_START CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_STOP  CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)

int __cdecl main(int argc, char* argv[])
{
  HANDLE hFile = NULL;
  DWORD dwRet = 0;

  hFile = CreateFile("\\\\.\\MyDriver", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
  if (hFile == INVALID_HANDLE_VALUE) {
    printf("failed to open mydriver\n");
    return -1;
  }
  DeviceIoControl(hFile, IOCTL_START, NULL, 0, NULL, 0, &dwRet, NULL);
  Sleep(3000);
  DeviceIoControl(hFile, IOCTL_STOP, NULL, 0, NULL, 0, &dwRet, NULL);
  CloseHandle(hFile);
  return 0;
}

結果


返回上一頁