Windows File System filter driver development tutorial (8)

Source: Internet
Author: User
Windows File System filter driver development tutorial

Note: If you have any questions and suggestions, please add qq16191935, email MFC_Tan_Wen@163.com

8. Finally, volume is bound to capture and analyze read operations.

The key operations before binding volume are described above. we have made great strides and made great strides. I believe you have learned the basic methods to drive development. the future work will be nothing more than flexible use of these methods. the operations for binding fs cdo have been cited in the front. now, binding volume is nothing more than taking pictures and tigers. In the future tutorial, I will not list details one by one.CodeNow.

However, note the following points when binding a volume:

1. Obtain the storage device object. The front side has already said that in order to get VBP, I need to first get the storage device object, as shown in the following method:

Wd_irpsp * irpsp = wd_cur_io_stack (IRP );
Wd_dev * storage_dev = wd_irpsp_mount_storage (irpsp );

This is correct before the IRP is completed. but in the completion function, the situation is different. because the storage_dev stored in this irpsp may be modified (this is not my own debugging result, but the information obtained by reading the comments in the sfilter code ). since this is possible, we have to save storage_dev first. in fact, you can add a project storage_dev in the device extension. before the IRP completes, generate the device that I want to bind (but not bind) and pass the device pointer to the context of the completion function.

In this way, in the function, I can get the storage_dev, and finally find the pointer of the volmue device. Then, bind it.

2. the binding process may not be successful once. because before the initilize mark of the volmue device is cleared, my binding fails. in this case, I copied the method in sfilter, that is, the latency is 500 milliseconds, and then try again. A total of 8 attempts.

I wrapped a function for latency:

_ Inline wd_void wd_delay_milli_se (wd_ulong milli_sec)
{
Wd_llong delay = maid * (-10) * 1000;
Wd_lgint interval;
Interval. quadpart = delay;
Kedelayexecutionthread (kernelmode, false, & interval );
}

The parameter of this function is millisecond, but I do not know how small the precision is.

I wish you good luck. now we are processing irp_mj_read. If you have bound volume, the request sent to volume will be sent to you first. irp_mj_read can capture the read operations of a file.

Go to your my_disp_read () function (assuming you have registered this function to handle irp_mj_read, see the previous description of the distribution function), first determine whether the Dev is bound to a volume device. if yes, it is a file read operation.

How to judge? Remember that when we first bound volume, we set storage_dev in our device extension. If it wasn't (for example, fs cdo, we didn't set it), then we can make this decision:

If (is_my_dev (Dev ))
{
My_dev_ext * ext = (my_dev_ext *) wd_dev_ext (Dev );
If (ext-> storage_dev)
{
//... It indicates the read operation on the object.
}
}

In other cases, no capture is required. Please pass it directly to the lower layer.

The IRP of read requests is very complicated. Please be prepared. do not rely too much on help. The best way is to print all the details of the IRP and view the complete process of the file read operation in person. what I am talking about now, I cannot assert whether the Windows version I have not tried is correct.

But the basic things won't change.

The first concern is the file to be read and written. there is a fileobject pointer under IRP. this object points to a file object. you can get the name of the file object, which is the full path of the file without a drive letter. someone asked how to get the drive letter? Because you already know volume, and the front side has already said that the drive letter is just the volume symbolic connection name, it should not be a problem for the real full path.

I am a lazy. Now I only print the path name without a drive letter. First, write a function to get fileobject from IRP.

_ Inline wd_file * wd_irp_file (wd_irpsp * irpsp)
{
Return irpsp-> fileobject;
}

Then write a function to get the file name. This function references the Filemon code.

Wd_void wd_file_get_name (in wd_file * file,
In out wd_ustr * name)
{
If (file-> filename. Buffer &&
! (File-> flags & fo_direct_device_open ))
Rtlcopyunicodestring (name, & file-> filename );
}

Next we need to get the offset of the read file. unlike the VxD file system driver, the offset obtained by the file system in 2000 seems to start from the start position of the file. the offset is a large_integer. this is because some files have exceeded the size of long integers.

The following function is used to obtain the offset. wd_lgint is the redefined large_integer.

_ Inline wd_lgint wd_irp_read_offset (wd_irpsp * irpsp)
{
Return irpsp-> parameters. Read. byteoffset;
}

Note that the above parameter is not IRP. It is the current io_stack_location, that is, my wd_irpsp. We have already discussed how to obtain the current irpsp.

In addition, I want to get the data I have read. note that this request has not been completed yet when we capture this request. since it is not completed, of course there is no data readable. if you want to obtain it, set the complete function and complete the request in the complete function.

It is not easy to understand whether to ignore or copy the current io_stack_location when the IRP is completed, what status is returned, and how to end the IRP in the completed function. I would like to make a summary as follows:

1. If you are not interested in what happens after the IRP completes, ignore the current io_stack_location directly (for myProgramFor example, wd_ship_cur_io_stack is called, and the request is passed down to return the status returned by wd_irp_call.

2. not only are I not interested in what happens after the IRP is completed, but I do not intend to continue the transfer and plan to return success or failure immediately. so I do not need to ignore or copy the current io_stack_location. Fill in the parameter, call iocompleterequest, and return the result I want to return.

3. if you are interested in what happens after IRP is completed and intend to process it in the completed function, you should first copy the current io_stack_location (wd_copy_cur_io_stack (), specify the completed function, and return wd_irp_call () returned status. you do not need to call iocompleterequest to complete the function! You can directly return the current status of the IRP.

4. in the case of 3, sometimes tasks are inserted into the system worker thread or you want to complete IRP in another thread, then the wd_stat_more_processing should be returned in the completion function, call iocompleterequest when IRP is completed. another similar case is that the dispatch function waits for the completion of the function to set the event, then the completion function returns wd_stat_more_processing, And the dispatch function calls iocompleterequest after the completion.

The front side has mentioned the do_buffered_io and do_direct_io tags of the device. there are three scenarios: either one of the two tags or the other. basically none of the volume devices have do_buffered, And I have encountered none of them. do_direct_io indicates that the data should be returned to the memory pointed to by IRP-> MDL pointed to by mdladdress. if there is no mark, it indicates that the data is read well. Please return
IRP-> usebuffer.

Usebuffer is an address that is valid only in the context of the current thread. if you want to obtain data by this address, you 'd better in the context of the current thread. the completion function and my_disp_read are not in the same thread. therefore, it is wrong to obtain data by the address in the completion function. how to return to the current thread? I am using a simple method. set an event in my_disp_read, call wd_irp_call (iocalldriver in DDK), and wait for the event. set this event in the completed function. in this way, when the wait is over, the IRP has been completed, and I have returned to the original thread of my_disp_read.

Wd_stat my_disp_read (in wd_dev * Dev, in wd_pirirp)
{
My_dev_ext * ext;
Wd_dev * attached_dev;
Wd_irpsp * irpsp = wd_cur_io_stack (IRP );
Wd_stat status;
Wd_file * file = wd_irp_file (irpsp );
Wd_lgint offset = wd_irp_read_offset (irpsp );
Wd_size length = wd_irp_read_length (irpsp );
Wd_wchar name_buf [512];
Wd_ustr name;
Wd_event event;

// Check for my device
If (! Is_my_dev (Dev ))
Return wd_irp_failed (IRP, wd_stat_invalid_dev_req );

EXT = (wdff_dev_ext *) wd_dev_ext (Dev );
Attached_dev = wdff_dev_attached (Dev );

// Here we can see that this is a read operation on a bound volume.
If (ext-> storage_dev = NULL)
{
Wd_skip_io_stack (IRP );
Return wd_irp_call (attached_dev, IRP );
}

// Here, check whether the object is read.
Wd_ustr_init_em (& name, name_buf, 512 );
If (file)
Wd_file_get_name (wd_void *) file, & name );
Else
{
Wd_skip_io_stack (IRP );
Return wd_irp_call (attached_dev, IRP );
}

Wd_printf1 ("xxx irp flag = % x \ r \ n", wd_irp_flags (IRP ));
Wd_printf1 ("XXX File Read: % WZ \ r \ n", & name );
Wd_printf1 ("XXX read offset = % lD", offset );
Wd_printf1 ("XXX read length = % LD \ r \ n", length );

// I have printed the parameters related to the Read Request.
Wd_event_init (& event );
// Copy the current io_stack and specify the completion routine.

Wd_copy_io_stack (IRP );
Wd_irp_set_comp (IRP, my_disp_read_comp, & event );

// Call IRP to the actual device
Status = wd_irp_call (attached_dev, IRP );
If (status = wd_stat_pending)
Wd_event_wait (& event );

Wd_printf1 ("test read end: Status = % x \ r \ n", status );
// If status = 0 at this time, the content should be in IRP-> userbuffer. Print the content yourself...
Wd_printf1 ("test read end: Read length = % LD \ r \ n", wd_irp_infor (IRP ));

Return wd_irp_over (IRP );
}

Then there is the content of my_disp_read_comp. You can see that it is only a simple setting event, and then return wd_stat_more_processing.

Wd_stat my_disp_read_comp (in wd_dev * Dev,
In wd_irp * IRP,
In wd_void * context)
{
Wd_event * event =
(Wd_event *) context;
Unreferenced_parameter (Dev );
Unreferenced_parameter (IRP );
Wd_event_set (event );
Return wd_stat_more_processing;
}

Although we have already written a lot, even though we have obtained all the parameters and results in the read process, we still don't know how to complete the Read Request or filter the driver if we write a file system by ourselves, how to modify read requests. we will continue to discuss read operations in the next section.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.