File filtering drives to achieve directory redirection (iii)

Source: Internet
Author: User
Tags ftp connection semaphore ftp client
Wrote by Fanxiushu 2015-03-30, quote or reprint, please indicate original author.
Take the above.
Because the entire drive structure is processed by forwarding all the data to the application layer,
Therefore, it is necessary to process various file requests at the application level in order to achieve the final directory redirection.
The various requests for the file are very numerous, and now summarize the requests that need to be sent to the application layer processing include:
1,create file opens the Create request, which is triggered by the driver receiving Irp_mj_create
2,close file shutdown request, this request is triggered in the driver received Irp_mj_close
3,read file read request, driver received Irp_mj_read trigger
4,write file write request, driver receives Irp_mj_write trigger
5,queryinfo file information Query request, driver received irp_mj_query_information trigger
6,setinfo file information set request, driver received irp_mj_set_information trigger
7,querydir Query folder file request, driver received Irp_mj_directory_control trigger
At least 7 large requests need to be sent to the application layer processing, and create,queryinfo,setinfo and so on, there are many child requests, so the whole structure is very complex.

In order to simplify processing and merge all the things that can be merged, such as Create,queryinfo and so on, I combine various requests to send to the application tier.
Also for simplicity, use two IOCTL control codes to communicate all these requests, as described in the previous article.
One is the BEGIN IOCTL, the driver triggers the request to the application layer; one is the end IOCTL, the application layer notifies the driver when it completes the request.
Each communication uses the same structure, but this structure is very complex and can be compared with the structure of the IRP.

The application-layer interface function looks pseudo code as follows:

struct IOCTL_FSVAR_T;////This structure is the data structure that communicates with the driver, which is listed below.
struct fsdev_request_t////This structure is similar to ioctl_fsvar_t, just simpler than it is, mainly in the application of internal communication

First, the drive device is opened, a semaphore is created, the handle is passed to the driver, and the driver uses him to notify the application layer that a new request has been reached.
void* Fsdev_open ()
{
HANDLE hfile = Createfilea ("\\\\.\\xfsredir", Generic_read |                                         Generic_write, File_share_read | File_share_write, NULL, open_existing, 0, NULL);

HANDLE Hsemaphore = CreateSemaphore (null, 0, maxlong, NULL);

DeviceIoControl (hfile, Ioctl_set_semaphore_handle, (pvoid) &hsemaphore, sizeof (HANDLE), ... );

..........
}

And then tell the driver that we need to monitor what the directory is
int Fsdev_set_monitor_directory (void* handle, const char* mon_dir)
{
........

DeviceIoControl (Dev->hfile, Ioctl_set_monitor_directory, Wmondir, wdirlen, NULL, NULL, &bytes, NULL);

.........
}

Then realize two core functions
This function gets the driven file request package
fsdev_request_t* fsdev_begin_request (void* handle);
{
_fsdev_t*dev = (_fsdev_t*) handle;
........
Buffer = (LPBYTE) malloc (sizeof (ioctl_fsvar_t) + sizeof (fsdev_request_t));
if (!buffer) return NULL;
IOCTL = (ioctl_fsvar_t*) buffer;
Req = (fsdev_request_t*) (buffer + sizeof (ioctl_fsvar_t));

:: WaitForSingleObject (Dev->hsemaphore, dev->wait_time); Wait, as long as the driver has a file request, it will increase the semaphore, the program will wake up from here
.......
Obtain the request information from the drive and fill in the ioctl_fsvar_t structure.
DeviceIoControl (dev->hfile, ioctl_trans_data_begin, NULL, 0, IOCTL, sizeof (ioctl_fsvar_t), &bytes, NULL);

Analysis and processing, and transformed into fsdev_request_t structure
.........
}

int Fsdev_end_request (void* handle, fsdev_request_t* req)
{
Analyze and process req structure and convert it into ioctl_fsvar_t structure
..........
Notification driver, this request has been completed
DeviceIoControl (Dev->hfile, Ioctl_trans_data_end, IOCTL, Inlen, Outbuf, Outlen, &bytes, NULL);
......
Rehabilitation Treatment
}

The structure of the ioctl_fsvar_t is as follows:
(fsdev_request_t is similar to ioctl_fsvar_t, just simpler, this is not listed here, for more information, please see the source code published on Csdn.) )

/////////
#define CREATE 0
#define CLOSE 1
#define READ 2
#define WRITE 3
#define QUERYINFO 4
#define SETINFO 5
#define QUERYDIR 6 Union fs_create_t
{
struct {
ULONG createdisposition;
ULONG createoptions;
ULONG AccessMode; Generic_read Generic_write
ULONG ShareMode; ///
Ularge_integer PathName;
///////
Uchar bcasesensitive; Whether the file name should be case-sensitive
Uchar Bforceaccesscheck; Access check ...
Uchar Bpagingfile; The pagefile file is open.
Uchar Bopentargetdirctory; This flag indicates that it is not true to open the specified file system object, but to check whether the object can be deleted and whether the directory in which it resides can be created.
Typically, such a request occurs before the file system object is renamed
};
CREATE Success Result
struct {
Uchar bdirectory;
Large_integer FileSize;
Large_integer Allocationsize;
The bottom is useless.
Large_integer Validdatalength;
ULONG Attributes;
Large_integer CreationTime;
Large_integer LastAccessTime;
Large_integer LastWriteTime;
}success;
}; struct fs_readwrite_t
{
Large_integer Offset;
ULONG Length;
ULONG Iotype; Read and write type, currently on two, 0 is the general reading and writing, 1 is page IO, add such a field is actually unable to solve why the Pageio irp->mdladdress mapping to user space, call recv function will fail or even blue screen.
}; struct fs_queryinfo_t
{
Large_integer CreationTime;
Large_integer LastAccessTime;
Large_integer LastWriteTime;
Large_integer Changetime;
ULONG fileattributes;
ULONG bdirectory;
Large_integer Allocationsize;
Large_integer FileSize;
}; #define TPINFO_BASICINFO 0
#define TPINFO_DELFILE 1
#define TPINFO_RENAME 2
#define TPINFO_CURPOS 3
#define TPINFO_NEWSIZE 4 struct fs_setinfo_t
{
ULONG type;
////
USHORT replaceifexists;
union{
struct{
Large_integer CreationTime;
Large_integer LastAccessTime;
Large_integer LastWriteTime;
Large_integer Changetime;
ULONG fileattributes;
};
Uchar DeleteFile;
Large_integer Newfilesize;
Large_integer Currentoffset;
Ularge_integer NewFileName; New file name changed to
};
}; #define MAX_FILENAME_LENGTH 260
struct fs_fileinfo_t
{
WCHAR Filename[max_filename_length]; Max_path
////
Large_integer CreationTime;
Large_integer LastAccessTime;
Large_integer LastWriteTime;
Large_integer Changetime;
Large_integer FileSize;
Large_integer Allocationsize;
ULONG fileattributes;
ULONG bdirectory;
};
struct fs_querydir_t
{
USHORT Brestart; Driver, indicating that the directory needs to be scanned again
USHORT Bonlyone; Returns only one record
ULONG requestlength;    Ularge_integer Optionname; The name to look for, can be empty, you can bring wildcard characters
}; struct ioctl_fsvar_t
{
ULONGLONG Inter_handle; Is the file IRP pointer waiting to be processed
////
ULONGLONG File_object;
ULONGLONG User_context;                The context USHORT type passed by the user; Mode of operation
USHORT bmorerequest; More requests
////
Union {
fs_create_t Create;
fs_readwrite_t ReadWrite;
fs_queryinfo_t QueryInfo;
fs_setinfo_t SetInfo;
fs_querydir_t Querydir;
}; Data transfer buffers
ULONG buffer_size;
Ularge_integer buffer_address;///is supposed to be pvoid here, but for the convenience of 64 and 32-bit drivers to communicate directly with 32-bit programs, this is set up. return results
LONG Status;
LONG information;
};
/////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////
///////////////////////////////////////////////////

You can see that both fsdev_begin_request and fsdev_end_request are active invocations to get the data from the driver.
This does not conform to the custom of file requests.
Because a file request comes in, it is passive to get notification and processing data,
Just like the server, the client has a request and the server responds.

Therefore, we should also simplify and design as a callback function.
For example, when the create comes, a callback function associated with Create is invoked.
We handle the real file open operation in this callback function, and then return.
The specific approach is to open a few threads, each of which calls the Fsdev_begin_request function,
After the Fsdev_begin_request function returns, the data is parsed and the callback function for the corresponding operation is called.
You are interested in designing your own, or you can view the source code that I published to Csdn.

After layers of encapsulation, the simpler interfaces are as follows:
struct fsdev_init_t
{
Const char* Mon_dir; Monitor Directory
int thread_cnt;///Number of threads
PVOID param;////Extra Parameters
///
Open_flag value Create_new,create_awlays,open_existeng,open_always
Int (*create) (const char* Pathname, int is_tryopen_dir, int is_open_target_dir,
int open_flag, int access_mode, int request_pid, pvoid param, pvoid* pcontext); File open or create callback
void (*close) (pvoid context, int request_pid); file Close callback
Int (*read) (pvoid context, out char* buf, __int64 offset, int len, int iotype, int request_pid); file read
Int (*write) (pvoid context, in char* buf, __int64 offset, int len, int iotype, int request_pid); file write
Int (*query_information) (pvoid context, fileinfo_t* info, int request_pid); query file information
void (*query_directory) (pvoid context, const char* findname, int is_restart, int is_onlyone, int request_pid); query directory information
Set Info
Int (*set_basicinfo) (pvoid context, time_t atime, time_t mtime, time_t ctime, int attr, int request_pid); Set file Basic properties
Int (*del_file) (pvoid context, const char* pathname, int request_pid);
Int (*ren_name) (pvoid context, const char* oldname, const char* newname, int request_pid);
Int (*set_curpos) (pvoid context, __int64 cur_pos, int request_pid); Set location
Int (*set_newsize) (pvoid context, __int64 new_size, int request_pid); set new size
};  int Fsdev_init (fsdev_init_t* FS); Initialize the function.
Initialize the fsdev_init_t structure, implement the various callback functions above, and then call the Fsdev_init function.

The callback function interface is done, and then there is the need to correlate the real file operation, where FTP traffic is used to map directories on the FTP server to local.

The reason why I thought of using FTP, is because of the thought of off-the-shelf Wininet.dll library to provide similar local file operations WIN32 API functions,
And the server is ready for FTP Server, do not have to develop a server-side program, so want to lazy less write point code, can quickly put the application layer program.
But when I really took advantage of WinInet's set of functions, it was the beginning of a nightmare.
File system operation is very frequent, for example, I use Explorer to browse my monitor directory, it is very possible to perform hundreds of create open operation at the same time,
In the callback function for create, I have to connect to the FTP server to query for the existence of files that need to be opened and the relevant file information.
Therefore, at the same time there will be a lot of FTP connection to the FTP server, so it does not matter, anyway, the network system can support a very many TCP connections.
But a lot of connection, the InternetConnect function frequently, in the inside never returned. It's a very bad thing.
This will cause the explorer and other access to the Monitoring directory program suspended animation. Later I thought of various methods, such as blocking settings timed out, and then made asynchronous calls, the problem still exists.
As a result, we can only conclude that this is the WinInet library has bugs in handling ftp.
Later, simply use the pure socket, the implementation of their own FTP client, the final solution to this problem.
And then think about spending so much time tossing on the FTP client, in fact these time, completely can be lightly loose to realize the private protocol client and service end,
And the problem of FTP itself, communication efficiency is not high, it is not suitable for file systems such access to very frequent places.
So later versions, completely abandoned the FTP, using their own development of the communication protocol, interested friends can be realized by themselves.

At this point, a complete directory redirection system is finally complete.

But it's not over yet, and the test found a bit of a conflict with the 360 file filter driver,
The conflict is that, in a machine equipped with 360, if the EXE file is executed directly in the redirected directory, the system will be blue screen.

360 also has file filter driver Qutmdrv.sys, we know that Windows filter drive is a layer of mount, thus forming a device stack.
For example, an NTFS file system volume mount a c filter driver, C filter Drive top and then hang a B-filter drive, b hanging a a filter driver ...
A at the top, Windows filters-driven calls are started from the top, and should not be leapfrog.
is the upper interface, can only invoke a device stack of a drive, a driver is responsible for transmission to B-drive, B passed to C-drive, such a layer of transmission,
Instead of the upper-layer interface directly calling B-drive, B-drive over C-drive, call C-driven driver below, which does not conform to the filter-driven development specification.
And I don't know why 360 is a jump call when dealing with some IRP requests for EXE files.
The specific is irp_mj_create open EXE file, 360 according to normal filter drive device stack call file filter driver,
This time to get an open File_object file object.
In some other IRP requests for this open file_object, it is not the device stack, but the filtering drive directly over some of the upper layers,
But instead of bypassing all filter drivers, call the Ntfs.sys dispatch function directly,
360 will also call the Partmgr drive, it is not done absolutely, this can ensure that the Minifilter frame filter driver can be used normally.
Our filter driver uses a traditional NT filter driver that, without special handling, will be mounted to the top of the partmgr,
In this way, when processing EXE files, 360 will bypass our filter driver. That's going to be a problem.
Because of our directory redirection, the IRP is intercepted in the Irp_mj_create, and the IRP is not sent down to the lower driver, and we handle the IRP ourselves.
So these IRP, the lower drive is not recognized, even some private data structures, such as fscontext and FsContext2 and so on with the underlying driver does not meet,
If we deal with the IRP, passed to the lower drive, they will only fail to return because they do not recognize, or even because the data does not match the system blue screen panic.

This is why in the 360 machine, if the EXE in the redirected directory directly execute the blue screen reason,
Luckily 360 is not done so absolutely, not all file accesses are skipped by some filter drivers.
As for other anti-virus software is not also the case, I did not test again, also lazy to test. Be interested in testing the experiment by yourself.

There's no way to solve this problem.
Approach One:
If you insist on using a directory redirection drive on a 360 machine, try to mount our filter drive before partmgr.
This can be done as long as the drive is started in the boot phase and the boot sequence is more than partmgr before the
Drive the boot sequence, you can study other data, there is no more explanation, the source code engineering can also be done.

Option two:
If your requirement is to redirect the remote directory to a new letter, it is not redirected to a directory.
Instead of using a filter driver to implement this function, the alternative is to develop a new file system.
Because the file system is always at the bottom of the filter drive, so 360 how to play, will not affect your new file system.
Source code Engineering does not provide this part of the implementation, but in addition to how to register a new file system and other frameworks, specifically to deal with various IRP details,
It's no different from our file filter driver implementing directory redirection. You can query the FASTFAT implementation code.

To achieve directory redirection, is a very complex topic, here is just a superficial introduction, I hope you have some help.

This article on the CSDN blog:
http://blog.csdn.net/fanxiushu/article/details/43636575 and subsequent chapters

The procedures provided in this article on CSDN:
http://download.csdn.net/detail/fanxiushu/8448785

This article provides the source code engineering on the CSDN:
http://download.csdn.net/detail/fanxiushu/8545567

2017-01 Update, full version of the program download address:

Download address on CSDN:

http://download.csdn.net/detail/fanxiushu/9719017

Download address on GitHub:

Https://github.com/fanxiushu/xFsRedir/raw/master/xFsRedir-1.0.0.1.zip

This is version 1.0.0.1, if you are looking for a new version, please pay attention to:

Https://github.com/fanxiushu/xFsRedir or send a message fanxiushu@sohu.com If a bug is found, it can be raised on csdn or GitHub, or send a message fanxiushu@sohu.com

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.