Windows File System filter driver development tutorial
3. Distribution routine, fast io
In the previous section, only the control device object is generated. But don't forget that the main task of driver development is to write the distribution routine (dispatch functions.). Next, we know that our DriverObject is saved in the driver of the above Code. Now I write the following function to specify a default dispatch function for it.
// ----------------- Code in wdf. h ----------------------
Typedef PDRIVER_DISPATCH wd_disp_fuc;
_ Inline wd_void wd_drv_set_dispatch (in wd_drv * driver,
In wd_disp_fuc disp)
{
Wd_size I;
For (I = 0; I <= IRP_MJ_MAXIMUM_FUNCTION; I ++)
Driver-> MajorFunction [I] = disp;
}
In wd_main on the front side, I only need to add
Wd_drv_set_dispatch (driver, my_dispatch_func );
A default Dispatch Function is specified for this driver. All irp requests will be sent to this Function. However, I may not want this function to be too complex, but want to separate some common requests, such as Read, Write, Create, Close, then I wrote several other Functions specifically used to set the Dispatch Functions.
// ----------------- Code in wdf. h ----------------------
_ Inline wd_void wd_drv_set_read (
In wd_drv * driver,
In wd_disp_fuc read)
{
Driver-> MajorFunction [IRP_MJ_READ] = read;
}
_ Inline wd_void wd_drv_set_write (
In wd_drv * driver,
In wd_disp_fuc write)
{
Driver-> MajorFunction [IRP_MJ_WRITE] = write;
}
Wd_void wd_drv_set_create (in wd_drv * driver,
In wd_disp_fuc create)
{
Driver-> MajorFunction [IRP_MJ_CREATE] = create;
Driver-> MajorFunction [IRP_MJ_CREATE_NAMED_PIPE] = create;
Driver-> MajorFunction [IRP_MJ_CREATE_MAILSLOT] = create;
}
Wd_void wd_drv_set_file_sys_control (in wd_drv * driver,
In wd_disp_fuc control)
{
Driver-> MajorFunction [IRP_MJ_FILE_SYSTEM_CONTROL] = control;
}
Wd_void wd_drv_set_clean_up (in wd_drv * driver,
In wd_disp_fuc clean_up)
{
Driver-> MajorFunction [IRP_MJ_CLEANUP] = clean_up;
}
Wd_void wd_drv_set_close (in wd_drv * driver,
In wd_disp_fuc close)
{
Driver-> MajorFunction [IRP_MJ_CLOSE] = close;
}
Don't look at the n multi-code list. In fact, I am setting the driver-> MajorFunction array. Therefore, the setting of dispatch functions in wd_main is changed to the following:
// Start to set several distribution routines
Wd_drv_set_dispatch (driver, my_disp_default );
Wd_drv_set_create (driver, my_disp_create );
Wd_drv_set_clean_up (driver, my_disp_clean_up );
Wd_drv_set_file_sys_control (driver, my_disp_file_sys_ctl );
Wd_drv_set_close (driver, my_disp_close );
Wd_drv_set_read (driver, my_disp_read );
Wd_drv_set_write (driver, my_disp_write );
The following tasks are all writing these functions in the my_xxx series. However, the DriverObject setting is not that simple.
Because your driver will be bound to the file system driver, the file system must handle the so-called FastIo in addition to the normal IRP. fastIo is a non-irp request caused by a Cache Manager call. In other words, in addition to the normal Dispatch Functions, you have to write another set of Fast Io Functions for DriverObject. the pointer of this set of functions is in driver-> FastIoDispatch. I don't know if this pointer is left empty will cause the system to crash. There is no space here, so to save this set of pointers, you must allocate space by yourself.
Below are my commonly used memory allocation functions.
// ----------------- Code in wdf. h ----------------------
// The simplest function for allocating memory. You can specify non-Paging pages.
_ Inline wd_pvoid wd_malloc (wd_bool paged, wd_size size)
{
If (paged)
Return ExAllocatePool (PagedPool, size );
Else
Return ExAllocatePool (NonPagedPool, size );
}
// Release the memory
_ Inline wd_void wd_free (wd_pvoid point)
{
ExFreePool (point );
}
_ Inline wd_void wd_memzero (
Wd_pvoid point,
Wd_size size)
{
RtlZeroMemory (point, size );
}
With the above foundation, I can write a function to initialize the FastIoDispatch pointer.
// ----------------- Code in wdf. h ----------------------
Wd_bool wd_fio_disp_init (wd_drv * driver, wd_ulong size)
{
Wd_fio_disp * disp = wd_malloc (wd_false, size );
If (disp = wd_null)
Return wd_false;
Wd_memzero (wd_pvoid) disp, size );
Driver-> FastIoDispatch = disp;
Driver-> FastIoDispatch-> SizeOfFastIoDispatch = size;
Return wd_true;
}
This function allocates enough space for the FastIoDispacth pointer and fills in its size. Next, write a series of functions to set this function pointer array. In fact, there are too many FastIo interface functions, so I just wrote a few of these setting functions as an example:
// ----------------- Code in wdf. h ----------------------
_ Inline wd_void wd_fio_disp_set_query_standard (
Wd_drv * driver,
Wd_fio_query_standard_func func)
{
Driver-> FastIoDispatch-> FastIoQueryStandardInfo = func;
}
_ Inline wd_void wd_fio_disp_set_io_lock (
Wd_drv * driver,
Wd_fio_io_lock_func func)
{
Driver-> FastIoDispatch-> FastIoLock = func;
}
_ Inline wd_void wd_fio_disp_set_io_unlock_s (
Wd_drv * driver,
Wd_fio_unlock_single_func func)
{
Driver-> FastIoDispatch-> FastIoUnlockSingle = func;
}
...
Well, if you insist on reading it here, congratulations. Let's review what we should do in wd_main.
A. Generate a control device. You must specify a name for the control settings.
B. Set Dispatch Functions.
C. set Fast Io Functions.
// ---------------- Current Situation of wd_main ----------------------------
...
Wd_dev * g_cdo = NULL;
Wd_stat wd_main (in wd_drv * driver,
In wd_ustr * reg_path)
{
Wd_ustr name;
Wd_stat status = wd_stat_suc;
// Then I generate a control device, although my control device does nothing
Wd_ustr_init (& name, L \ "\ FileSystem \ Filters \ our_fs_filters \");
Status = wdff_cdo_create (driver, 0, & name, & g_cdo );
If (! Wd_suc (status ))
{
If (status = wd_stat_path_not_found)
{
// This occurs when the FileSystemFilters path does not exist. This path is
// Added on xp. So 2000 may run here
Wd_ustr_init (& name, L \ "\ FileSystem \ our_fs_filters \");
Status = wdff_cdo_create (driver, 0, & name, & g_cdo );
};
If (! Wd_suc (status ))
{
Wd_printf0 (\ "error: create cdo failed. rn \");
Return status;
}
}
Wd_printf0 (\ "success: create cdo OK. rn \");
// Start to set several distribution routines
Wd_drv_set_dispatch (driver, my_disp_default );
Wd_drv_set_create (driver, my_disp_create );
Wd_drv_set_clean_up (driver, my_disp_clean_up );
Wd_drv_set_file_sys_control (driver, my_disp_file_sys_ctl );
Wd_drv_set_close (driver, my_disp_close );
Wd_drv_set_read (driver, my_disp_read );
Wd_drv_set_write (driver, my_disp_write );
// Specify the fast io processing function
If (! Wd_fio_disp_init (driver, sizeof (wd_fio_disp )))
{
Wd_dev_del (g_cdo );
Wd_printf0 (\ "error: fast io disp init failed. rn \");
Return wd_stat_insufficient_res;
}
// The functions specified below are defined in wdf_filter_fio.h. In fact, all these functions are
// If the value of 1 is false
Wd_fio_disp_set_check (
Driver,
My_fio_check );
Wd_fio_disp_set_read (
Driver,
My_fio_read );
Wd_fio_disp_set_write (
Driver,
My_fio_write );
Wd_fio_disp_set_query_basic (
Driver,
My_fio_query_basic_info );
...
}
The number of FastIo functions is unknown. I only think there are many. Therefore, we do not want to list all the items in the format. Some readers may think that the Code cannot be debugged and installed. You can complete the code yourself by referring to the example in sfilter.
Currently, the my_xxx series functions have not been written, so the driver cannot be compiled. I will introduce it later.