- 浏览: 811700 次
- 性别:
- 来自: 广州
最新评论
-
mixture:
语句int num1, num2;的频度为1;语句i=0;的频 ...
算法时间复杂度的计算 [整理] -
zxjlwt:
学习了。http://surenpi.com
[问题解决]Error: ShouldNotReachHere() [整理] -
Animal:
谢谢 楼主 好东西
算法时间复杂度的计算 [整理] -
univasity:
gaidandan 写道缓存失败,,模拟器上可以缓存,同样代码 ...
[开发总结]WebView使用中遇到的一些问题&解决 -
blucelee2:
那么麻烦干吗,而且这种方法会导致,当拉太小的时候样式会丢掉,整 ...
[SWT]SashForm中固定单侧大小(&实现面板隐藏)
<!-- 发觉越是没事干,记忆越差,乘还记得点什么,记录下以备份 -->
继上一篇关于USN的探索,我们能对USN进行了简单的操作,但是有一样基本的东西却没有做到——我们还无法获取到USN记录的文件路径,而这恰恰是非常必要的。
<开始探索>
typedef struct {
DWORD RecordLength; // 记录长度
WORD MajorVersion; // 主版本
WORD MinorVersion; // 次版本
DWORDLONG FileReferenceNumber; // 文件引用数
DWORDLONG ParentFileReferenceNumber; // 父目录引用数
USN Usn; // USN
LARGE_INTEGER TimeStamp; // 时间戳
DWORD Reason; // 原因
DWORD SourceInfo; // 源信息
DWORD SecurityId; // 安全
ID DWORD FileAttributes; // 文件属性
WORD FileNameLength; // 文件长度
WORD FileNameOffset; // penultimate of original version 2.0 < 文件名偏移 >
DWORD ExtraInfo1; // Hypothetically added in version 2.1
DWORD ExtraInfo2; // Hypothetically added in version 2.2
DWORD ExtraInfo3; // Hypothetically added in version 2.3
WCHAR FileName[1]; // variable length always at the end < 文件名第一位的指针 >
} USN_RECORD, *PUSN_RECORD;
这是每个USN记录的结构,通过这个结构我们能获取到的文件名和其他一些信息,但并不包含其所在的路径。
前面的文章中曾稍微提到过其中的FileReferenceNumber和 ParentFileReferenceNumber是关键。
是有这么一种方法,通过微软提供的NtQueryInformationFile 函数获取,具体实现如下:
/// <summary> /// GetPathByFileReferenceNumber() 通过文件的映射ID获取文件路径. /// </summary> /// <param name="hVol">HANDLE对象,指向驱动盘 /// </param> /// <param name="frn">文件的映射ID,包含在USN_RECORD中 /// </param> /// <param name="pathBuffer">储存返回值的char* /// </param> /// <param name="bufferSize">指定返回值的长度 /// </param> /// <returns>BOOL /// </returns> /// <remarks> /// 只支持NTFS3.0及以上的驱动盘,并且在Win7下运行该方法需要获取管理员权限 /// </remarks> BOOL GetPathByFileReferenceNumber(__in HANDLE hVol, __in DWORDLONG frn, __out char* pathBuffer, __in int bufferSize) { BOOL result = FALSE; HANDLE hFile; //printf("frn: %I64x\n", frn); // 将FileReferenceNumber转为UNICODE_STR UNICODE_STRING fidstr; CoverFileReferenceNumberToFileIdStr(frn, &fidstr); //ULONG fid[2] = {0x00000892, 0x00020000};//{i.nFileIndexLow, i.nFileIndexHigh}; //UNICODE_STRING fidstr = {8, 8, (PWSTR) fid}; // 构建用于寻找的OBJECT_ATTRIBUTES OBJECT_ATTRIBUTES oa = {0}; oa.Length = sizeof(OBJECT_ATTRIBUTES); oa.ObjectName = &fidstr; oa.RootDirectory = hVol; oa.Attributes = OBJ_CASE_INSENSITIVE; //InitializeObjectAttributes (&oa, &fidstr, OBJ_CASE_INSENSITIVE, d, NULL); IO_STATUS_BLOCK ioStatusBlock = {0}; // 通过FILE_ID打开文件,获取文件句柄 ULONG status = NtCreatefile(&hFile, FILE_GENERIC_READ, &oa, &ioStatusBlock, NULL, FILE_ATTRIBUTE_READONLY, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_OPEN_BY_FILE_ID | FILE_OPEN_FOR_BACKUP_INTENT, NULL, 0); //printf("status: %X, handle: %x\n", status, hFile); //printf("error: %d, t: %x\n", GetLastError(), iosb); if(0==status){ //FILE_NAME_INFORMATION* info = (FILE_NAME_INFORMATION*)malloc(BUF_LEN); //int allocSize = BUF_LEN; // 获取文件名称信息 status = NtQueryInformationFile(hFile, &ioStatusBlock, info, allocSize, FileNameInformation); if(0==status){ // 获取到的名字是wchar*, 将其转为char* int dwMinSize = (*info).FileNameLength; WideCharToMultiByte(CP_OEMCP,NULL,(*info).FileName,dwMinSize/2,pathBuffer,dwMinSize,NULL,FALSE); result = TRUE; } //free(info); CloseHandle(hFile); } return result; }
于是我将手头所有的信息汇集起来,将信息都打印到文本上仔细地审查了一遍。
下面是一部分打印出来的信息:
***********************
<盘符>
文件名
FileReferenceNumber - 对应地址
ParentFileReferenceNumber - 对应地址
<C:\>
Program Files
frn:281474976710716 - C:\Program Files
pfrn:1407374883553285 - C:\
Common Files
frn:281474976710717 - C:\Program Files\Common Files
pfrn:281474976710716 - C:\Program Files
microsoft shared
frn:281474976710718 - C:\Program Files\Common Files\microsoft shared
pfrn:281474976710717 - C:\Program Files\Common Files
<D:\>
Program Files
frn:281474976710691 - D:\Program Files
pfrn:1407374883553285 - D:\
Thunder Network
frn:281474976710692 - D:\Program Files\Thunder Network
pfrn:281474976710691 - D:\Program Files
Thunder
frn:281474976710693 - D:\Program Files\Thunder Network\Thunder
pfrn:281474976710692 - D:\Program Files\Thunder Network
<E:\>
实况8中超风云秋风DIY版
frn:281474976710694 - E:\实况8中超风云秋风DIY版
pfrn:1407374883553285 - E:\
WE8.exe
frn:281474976710698 - E:\实况8中超风云秋风DIY版\WE8.exe
pfrn:281474976710694 - E:\实况8中超风云秋风DIY版
**********************
首先注意下加粗的地方,指向的路径是根目录(盘符),不难发现他们对应的ReferenceNumber都是一致的,经测试无论U盘,外置硬盘还是删了USN再建,我发现都是一致的,而且就是1407374883553285,不知会不会和机器本身有关,具体有待验证,不过我们还是得出一条结论:
<根目录的ReferenceNumber是一个与盘符无关的特定不变的数值——1407374883553285>
再具体看数据,以上面<E:\>的数据作为样例,整理如下:
name frn pfrn path
WE8.exe 281474976710698
281474976710694 E:\实况8中超风云秋风DIY版\WE8.exe
实况8中超风云秋风DIY版 281474976710694
1407374883553285 E:\实况8中超风云秋风DIY版
E: 1407374883553285
/ E:\
前面3个信息是我们能通过USN直接获取的,path是我们要获取的。
而最后一行(1407374883553285
->E:\
)是我们前面验证的。
基于这个,如果我们要获取"实况8中超风云秋风DIY版 "所在的路径,就可以根据他的pfrn(1407374883553285 )关联到E:\ ,然后一组合,“E:\ 实况8中超风云秋风DIY版 ”就出来了。如果是“WE8.exe ”呢?那就必须先获取“实况8中超风云秋风DIY版 ”的路径才能建立起来。
按这样的规律,只要我们能自上而下地建立起联系就能获取到所有文件的完整路径了。其实这就是一个树的结构。
<具体实现>
为了能自上而下地建立起来,在我们读取USN的时候就要先做一些处理。
1.按每个目录属性的记录的frn作为key值,每个以该key作为pfrn的记录作为内容,构建一个哈希表(Hashtable<Long, Vector>)。
这样,当我们读取完所有记录后就会得到一个这样的哈希表结构:
key value
(目录属性)记录的frn array{...}[pfrn为key值的记录]
2.给定一个首要条件,建立第一级关联
根据盘符名(如E:\)->1407374883553285,找到key=1407374883553285下的所有记录,将其路径逐一标记为"盘符+机身名字"
3.递归遍历,获取所有记录的路径
遍历已建立路径的每个记录,找到以该记录的frn为key值的元素,建立路径,如此来回反复。
最后就能建立起完整的路径表。当然这样的局限性就是需要先获取到所有的数据。
这里提供一个大概的参考:
static final long rootFileReferenceNumber = Long.parseLong("1407374883553285"); static final String EndSymbol = "\\"; private Hashtable<Long, Vector> hashByPfrn; // 根据pfrn作为key值对记录进行分类储存 private Hashtable<Long, String> hashPaths; // 用于辅助递归 public static main(String[] args){ for(所有USN记录){ addData(.frn, .fileName, .pfrn, .filePath, .fileAttribute); } buildPath(rootFileReferenceNumber, "E:\\"); } /** * 添加数据 * @param frn * @param fileName * @param pfrn * @param filePath * @param fileAttribute */ private void addData(long frn, String fileName, long pfrn, String filePath, int fileAttribute) { Vector<NtfsVolumeData> v = (Vector<NtfsVolumeData>) hashByPfrn.get(pfrn); NtfsVolumeData record = new NtfsVolumeData(frn, fileName, pfrn, filePath, fileAttribute); if (v == null) { v = new Vector<NtfsVolumeData>(); v.add(record); hashByPfrn.put(pfrn, v); } else { v.add(record); } fileCounter++; } /** * 建立路径 * @param rootKey * @param rootName */ private void buildPath(long rootKey, String rootName) { hashPaths.clear(); long key = rootKey; hashPaths.put(key, rootName); buildPath(key, hashPaths); } /** * 递归建立路径 * @param key * @param hashPaths */ private void buildPath(long key, Hashtable hashPaths) { // 获取到属于该key的记录 Vector<NtfsVolumeData> records = (Vector<NtfsVolumeData>) hashByPfrn.get(key); if (records == null || records.size() <= 0) { return; } // 获取该key对应的路径 String filePath = (String) hashPaths.get(key); // 设置路径 for (NtfsVolumeData record : records) { record.setParentPath(filePath); /** * 对带有目录属性的记录 */ if (0 != (record.getFileAttributes() & UsnRecordAttributeValues.FILE_ATTRIBUTE_DIRECTORY)) { // 记录当前记录路径为新路径 hashPaths.put(record.frn, record.getFullPath() + EndSymbol); // 再进一步搜索 buildPath(record.frn, hashPaths); } } }
评论
4.我记得有位老兄用C++实现了,或许可以参考下...我找找哈~~
找到了,哈哈,保存网页是个好习惯~~
http://hi.baidu.com/chenxiong0115/blog/item/b31e573a3d8bd6e715cecbb6.html
希望有帮助,我C++不太懂...
1、也就是说对于每个盘符,需要枚举usn一次是吗?
2、这样统计的话,逻辑分区与主分区是没有区别的吧?
3、路径还原的方法是?java代码我没看懂,自己是这样做的:两个容器(<文件名,父指针>, hash<当前指针,struct(父指针,文件名)>,但这样内存占用有点大了,有啥好办法吗?
4、同3,去掉第一个容器,直接在hash表找文件名,一是慢,二是加上模糊查找,哎,更慢……
1.对,每个盘的USN文件都是独立的;
2.具体细节没有研究过,但基本操作没区别;
3.我的思路是,通过pfrn(父级/上层目录ID)与frn(当前文件ID)的关系,建立一个树结构。确实是需要一定的内存,但数量是和你磁盘的文件条数对等的。暂时没有想到更好的方法,如果你不需要一次获取所有文件的完整路径的话,可以用微软提供的函数——获取单个文件的路径(文章一开始有说)。
4.我记得有位老兄用C++实现了,或许可以参考下...我找找哈~~
1、也就是说对于每个盘符,需要枚举usn一次是吗?
2、这样统计的话,逻辑分区与主分区是没有区别的吧?
3、路径还原的方法是?java代码我没看懂,自己是这样做的:两个容器(<文件名,父指针>, hash<当前指针,struct(父指针,文件名)>,但这样内存占用有点大了,有啥好办法吗?
4、同3,去掉第一个容器,直接在hash表找文件名,一是慢,二是加上模糊查找,哎,更慢……
不能区分,每个盘的USN数据要独立处理,因为系统只会确保不同盘的USN中的数据ID是唯一的(每个盘的USN数据都是独立的)。我这里说的是,不管是哪个分区,其根目录(如C:\, D:\)在USN中对应的ID值总是1407374883553285,用这个值找到根目录,在通过ParentFileReferenceNumber和FileReferenceNumber的关系进行递归遍历,最终构造出完整的目录树...
谢谢分享!
发表评论
-
[问题解决]个推SDK使用侧记 -- 多个账号注册导致的问题
2013-12-28 14:40 2291这是我们项目最近用到的东西,用来实现消息推送。 (还不了 ... -
[问题解决] 个推(igetui)SDK使用侧记 -- 多个账号注册同一应用导致的问题
2013-12-28 14:33 0这是我们项目最近用到的东西,用来实现消息推送。 (还不了解 ... -
[SWT]打开Windows文件夹的方法 [整理]
2012-10-24 21:03 2699参考论坛帖子:http://www.iteye.com/top ... -
[SWT]SashForm中固定单侧大小(&实现面板隐藏)
2012-09-20 16:06 7211<!-- 额,发觉写篇博客都不知怎么选分类了。。。名称太 ... -
[Everything模仿] 相关项目资源整理
2012-04-29 20:04 3841一段时间来,发觉还是 ... -
[问题解决]Ubuntu10.04安装出现的显示器“无信号”问题
2011-12-11 20:42 4385<!-- 旧帖转移,2010-09-25 --> ... -
9个主流的开源许可协议[整理]
2011-12-05 23:15 29432关于开源许可 现今存在的开源协议很多,而经过 ... -
电子邮件收发原理和实现(POP3, SMTP) [整理]
2011-09-16 11:12 28417<!-- 最近工作上接触到了邮箱的开发,整理一下学到的东 ... -
讲解极小极大 (Minimax Explained) [译]
2011-09-11 21:00 6946原文链接:Minimax Explaine ... -
理解极小极大算法 (Understanding The Minimax Algorithm) [译]
2011-09-11 20:45 27140原文链接:Understanding Th ... -
Maven In Android
2011-08-31 17:32 3493Maven 一个项目管理工具,类似于Ant。相比Ant, ... -
[基础回顾]基于Eclipse的J2me和Android开发环境搭建
2011-03-23 00:10 1897<!-- 越是基础的东西就容易被忽略和轻视...我是接触 ... -
[SVN]423 Locked problem (Solved)
2011-03-03 17:15 9038今天使用SVN上传代码,突然冒出了一行红字... Se ... -
Everything研究之读取NTFS下的USN日志文件(2)
2010-11-08 01:08 15887续>> /******************* ... -
Everything研究之读取NTFS下的USN日志文件(1)
2010-11-08 01:02 33139我在第一次使用 Everything 时,对其速度确实感到 ... -
[Swing]Netbean中使用外部资源
2010-10-22 15:43 1658要在NetBean中使用外部资源,首先需要在项目目录下创建一个 ... -
[Swing]实现一个文本自动完成工具
2010-10-17 00:00 3660//------------------------- ... -
[图形算法]J2me上的凹凸拼图实现思路
2010-04-05 21:31 6165出于个人兴趣,简单研究了一下凹凸拼图的实现。以下为本人的实现思 ... -
[特效研究]j2medev论坛里提到的一个显示特效实现
2010-03-14 16:05 2492原贴链接:http://www.j2medev.com/ ... -
[LUA]在eclipse中使用luajava
2009-10-17 23:23 4340<!--StartFragment--> st ...
相关推荐
原理是读取ntfs的USN文件日志,然后内建索引加速文件搜索过程。 1、列表文件支持批量处理(删除、复制、复制文件名路径、打开、重命名),或者引用系统菜单。 2、支持拼音首字母缩写搜索,指定文件夹内搜索,多...
关于获取USN基本日志信息的C++ code block 上运行,因为是自己参照网上VC版本改编的可能会有些许疏漏。
原理是读取USN文件日志,然后内建索引加快文件搜索速度。 1、列表文件支持批量处理(删除、复制、复制文件名路径、打开、重命名),或者引用系统菜单。 2、支持拼音首字母缩写搜索,指定文件夹内搜索,多关键词搜索...
USN日志是一个记录文件系统变化的系统,每次文件或目录发生更改,如创建、修改、删除等,都会在USN日志中留下记录。这个日志提供了实时更新索引的可能性,使得我们可以快速获取到文件系统的最新状态。 在模拟...
利用USN日志,开发者可以构建实时的文件索引,以便快速响应文件系统的变动。 在C#中实现NTFS硬盘文件索引,首先需要理解如何与USN日志交互。这通常涉及到使用Windows API,如`CreateFile`函数打开USN日志数据卷,...
这个项目可能是一个自研的解决方案,其目标是创建一个Java版的"Everything"工具,这是一个快速的文件搜索工具,但目前可能还处于未完成状态。 首先,让我们深入理解“不使用任何jar包读取docx文件”。docx文件本质...
这是因为Everything通过读取NTFS文件系统的USN日志(Update Sequence Number Journal)和MFT(Master File Table)来构建索引,这两种数据结构记录了文件系统的所有变化,使得搜索结果始终保持最新。 《探索...
这种快速,是因为Everything的索引无需逐一扫描硬盘文件,而是直接读取NTFS文件系统的USN日志。这当然是既省力,又合理的做法。 第二个快速体现在搜索速度。在搜索框中键入字符后,搜索结果——或许称为过滤结果更...
USN日志是Windows操作系统中一个重要的系统组件,它记录了文件系统中所有更改的序列号,用于跟踪文件和目录的变化。在Windows NTFS文件系统中,每当文件有变动,如创建、修改、删除等,USN日志都会更新一条记录。 ...
在日常使用中,"Everything"不仅可以帮助用户快速找到硬盘上的文件,还能在大量数据中定位特定信息,对于开发者查找代码、设计师寻找素材、文档工作者整理文件等都非常实用。而且,"Everything"的资源占用极低,即使...
Everything应用了Change Journal的特性,实现了快速获取磁盘上所有文件和文件夹名称的功能。它通过顺序遍历MFT中的每条数据,查找每个文件和目录的USN字段,这样就可以非常高效地列出卷上的所有文件。此外,通过监控...
这种快速,是因为Everything的索引无需逐一扫描硬盘文件,而是直接读取NTFS磁盘USN日志。这当然是既省力,又合理的做法。 第二个快速体现在搜索速度。在搜索框中键入字符后,搜索结果——或许称为过滤结果更准确...
"Everything"是一款高效快速的文件搜索工具,尤其在大量文件的环境下,它的性能表现非常出色。这个"Everything山寨版源码"显然是一款基于"Everything"的仿制品或修改版,其核心也是通过读取NTFS文件系统的USN...
华为USN9810是华为公司推出的一款高端核心路由器,主要应用于移动通信网络的核心层,特别在中国移动4G网络工程中扮演着重要角色。V900R011是该产品的某一版本,它在2019年7月进行了更新,体现了华为在技术研发上的...
通过直接访问MFT,可以快速获取文件系统的结构信息,提高搜索效率。 USN Journal(更新序列号日志)是NTFS文件系统用来跟踪文件系统变化的日志,记录了文件的创建、删除、修改等操作。利用USN Journal,程序可以...
华为MME USN9810硬件配置,最新架构的osta2.0介绍,基本的配置原则和步骤。
在IT行业中,尤其是在系统开发和数据检索领域,"filesearch_everything.rar"这个压缩包可能包含了一个关于快速文件搜索工具的实现,特别是涉及到USN(Update Sequence Number)日志的利用。USN日志是Windows操作系统...
不同于 Windows 自带的搜索功能,Everything 不依赖于文件名中的关键词,而是直接读取 NTFS 文件系统的 USN 日志,这意味着即使文件内容发生变化,它也能快速更新索引。输入关键词后,搜索结果几乎是即时显示的,...
这种快速,是因为Everything的索引无需逐一扫描硬盘文件,而是直接读取NTFS文件系统的USN日志。这当然是既省力,又合理的做法。 第二个快速体现在搜索速度。在搜索框中键入字符后,搜索结果——或许称为过滤结果更...
原理是:Everything是靠读取NTFS文件系统中的USN日志来完成的,所以如果你的硬盘不是NTFS的,那就没有什么用了。 这是免安装版,解压使用时,默认是日文界面,要把那个.lng文件放到Everything的执行文件所在文件夹...