RmGetList() API fails when file is locked using Ez file locker but works with another file locking utility

…衆ロ難τιáo~ 提交于 2019-11-28 14:06:16
RbMm

Easy File Locker is "locking" the file only in the informal sense of the word, i.e., it protects the files from access, but it does not do so by obtaining a lock on the file. Instead, it uses a lower-level technology (a file system filter driver) that is broadly similar to the way that anti-virus software protects its files from any unauthorized access. The Restart Manager API is not intended to, and does not, deal with this sort of scenario.

Your application almost certainly doesn't need to deal with this sort of scenario either. This means that Easy File Locker is not an appropriate tool for your particular needs; throw it away.


Why would RmGetList() fail with one file locking utility but work with another?

To answer this we need to understand how RmGetList works internally. In your case, we provide it with a filename, and its output is an array of RM_PROCESS_INFO structures. In order to build this array, Windows must determine which processes are using the file. But how does Windows do this?

The function ZwQueryInformationFile (exported by ntdll.dll) can return a lot of information about a file. One of the options in the FILE_INFORMATION_CLASS enumeration is

FileProcessIdsUsingFileInformation

A FILE_PROCESS_IDS_USING_FILE_INFORMATION structure. This value is reserved for system use. This value is available starting with Windows Vista.

and in wdm.h (which is a well known file from the windows WDK) we find

typedef  struct _FILE_PROCESS_IDS_USING_FILE_INFORMATION {
    ULONG NumberOfProcessIdsInList;
    ULONG_PTR ProcessIdList[1];
} FILE_PROCESS_IDS_USING_FILE_INFORMATION, *PFILE_PROCESS_IDS_USING_FILE_INFORMATION;

so this option is exactly which we need!

The algorithm goes like this:

  1. open the file with FILE_READ_ATTRIBUTES access (which is sufficient for this information class)
  2. call ZwQueryInformationFile(..,FileProcessIdsUsingFileInformation); if NumberOfProcessIdsInList != 0 walk the ProcessIdList
  3. open process by ProcessId, query it with ProcessStartTime (see GetProcessTimes) and other properties to fill RM_PROCESS_INFO

So now that we know how that works, let's look at the two utilities you're using.

The second is a very simple app, which provides source code. All it does is to call CreateFile with dwShareMode = 0. That acquires an exclusive lock on the file, ensuring that any attempt to open the file with a dwDesiredAccess that contains FILE_READ_DATA or FILE_WRITE_DATA or DELETE will fail with ERROR_SHARING_VIOLATION. It does not, however, prevent us from opening the file with dwDesiredAccess = FILE_READ_ATTRIBUTES, so the call to RmGetList() will still work properly.

But the first tool, Easy File Locker from XOSLAB, is using a minifilter driver (HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\xlkfs) to restrict access to the file. This driver returns STATUS_ACCESS_DENIED (which is converted to the Win32 ERROR_ACCESS_DENIED) for any attempt to open the file. Because of this, you get an error ERROR_ACCESS_DENIED when RmGetList attempts to open the file at step (1) and (since the API has no idea what to do about this) this error code is returned to you.

That's all there is to it. The tool simply isn't doing what you were expecting it to.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!