有方法读取一个已被其他进程打开且dwSharemode = 0的文件吗?

有方法读取一个已被其他进程打开且dwSharemode = 0的文件吗?

最近有项目要打开一个已被其他进程打开,且其dwShareMode=0,即其它进程不得共享打开。该如何做呢?久思不得其解,于是去bbs.pediy.com询问[1],网友给出的方法是:

3)

我选用了第二种方法,果然能解决问题。但是中间也遇到了一些问题,本文来说说这中间遇到的问题。

既然是使用DuplicateHandle,那么必须知道原进程的PID,和文件在该进程中的句柄Handle。

所以程序的思路是先遍历系统中所有进程,然后或则进程中文件句柄,接着使用文件句柄获得文件名称——这样便可以得到PID和Handle了。

一.遍历系统所有进程

可以使用多种方法遍历系统中所有进程,一般使用ZwQuerySystemInformation(SystemProcessesAndThreadsInformation)或者CreateToolhelp32Snapshot来实现。

二.遍历句柄

句柄的遍历使用ZwQuerySystemInformation(SystemHandleInformation),该函数列出所有进程的所有句柄,然后使用TSYSTEM_HANDLE_INFORMATION结构体中的ProcessId来过滤出指定进程的句柄。

这里的句柄是各种类型。可以通过TSYSTEM_HANDLE_INFORMATION结构体中的ObjectTypeNumber来判断句柄类型。在程序中我使用File=28硬编码,因为我发现在Win7和XP下是成立的,

但是有网友[3]讨论说不是所有的系统都是这样的,于是我尝试遍历系统中所有的类型对象(type object),方法是使用ZwQueryObject(ObjectAllTypesInformation)。本想通过序号实时找出当前系统中的类型值,但是遗憾是序号值不对。

三.根据文件句柄获取文件名

只有获得句柄对应的文件名,通过比较才能知道是否是想要的文件句柄,所以当务之急是获得文件名。但是得先通过调用OpenProcess和DuplicateHandle来复制一个句柄。然后再使用下面两类方法中的一种:

1.使用ZwQueryInformationFile

该函数返回一个TFILE_NAME_INFORMATION结构,这个结构包括文件的名称,,但是不包括驱动器名,所以需要通过其他方法(见下)获得驱动器名,将上述两者相连方可获得整个文件名了。

这个方法有个问题,在某些进程(如qq.exe)在调用ZwQueryInformationFile时会使调用程序“死掉”。难道qq这些程序有什么保护方法,不让复制的句柄来使用ZwQueryInformationFile?

2.使用GetMappedFileName

这种方法使用CreateFileMapping、MapViewOfFile和GetMappedFileName获得文件名——同样没有驱动器名,所以也得通过其他方法(见下)获得驱动器名。

这种方法也有缺陷,不能调用CreateFileMapping打开没有访问权限目录中的文件。

3.获得驱动器名

有两种方法获得驱动器名:

1) GetFileInformationByHandle和GetLogicalDriveStringsA比较

2) GetLogicalDriveStrings和QueryDosDevice比较

GetFileInformationByHandle也会使程序“死掉”,所以慎用。

四.大功告成

知道了进程pid和句柄值,就可以通过复制句柄的方法访问文件了——这其实在前面已经这么做过一次了——获得文件名不正是复制句柄来实现的吗?

不过,在使用文件指针访问文件(如调用ReadFile和WriteFile)时要注意:因为原句柄和复制句柄共享一个文件指针,所以可能会造成指针位置的混乱。

五.参考文献

1.?t=198566

2.有关遍历进程中句柄的方法总结

3.?t=179951

4.[Delphi]从handle获得文件名

就是对虚怀若谷谦虚谨慎八个字真正理解的人,

有方法读取一个已被其他进程打开且dwSharemode = 0的文件吗?

相关文章:

你感兴趣的文章:

标签云: