- 浏览: 809684 次
- 性别:
- 来自: 广州
最新评论
-
mixture:
语句int num1, num2;的频度为1;语句i=0;的频 ...
算法时间复杂度的计算 [整理] -
zxjlwt:
学习了。http://surenpi.com
[问题解决]Error: ShouldNotReachHere() [整理] -
Animal:
谢谢 楼主 好东西
算法时间复杂度的计算 [整理] -
univasity:
gaidandan 写道缓存失败,,模拟器上可以缓存,同样代码 ...
[开发总结]WebView使用中遇到的一些问题&解决 -
blucelee2:
那么麻烦干吗,而且这种方法会导致,当拉太小的时候样式会丢掉,整 ...
[SWT]SashForm中固定单侧大小(&实现面板隐藏)
续>>
/******************************************
2010.11.10更新了代码,调整了一处地方,lowUsn的设置。
******************************************/
第四步:获取 USN Journal 文件的基本信息
MSDN: http://msdn.microsoft.com/en-us/library/aa364583%28v=VS.85%29.aspx
[[
他是这么一个结构:
typedef struct {
DWORDLONG UsnJournalID;
USN FirstUsn;
USN NextUsn;
USN LowestValidUsn;
USN MaxUsn;
DWORDLONG MaximumSize;
DWORDLONG AllocationDelta;
} USN_JOURNAL_DATA, *PUSN_JOURNAL_DATA;
其中的 UsnJournalID ,FirstUsn ,NextUsn 是我们后续操作需要用到的。
获取他很简单,通过DeviceIoControl() 配合 FSCTL_QUERY_USN_JOURNAL 来实现。
]]
给出一个实现参考 :
bool getBasicInfoSuccess = false; /** * step 04. 获取USN日志基本信息(用于后续操作) * msdn:http://msdn.microsoft.com/en-us/library/aa364583%28v=VS.85%29.aspx */ DWORD br; status = DeviceIoControl(hVol, FSCTL_QUERY_USN_JOURNAL, NULL, 0, &UsnInfo, sizeof(UsnInfo), &br, NULL); if(0!=status){ getBasicInfoSuccess = true; }else{ printf("获取USN日志基本信息失败 —— status:%x error:%d\n", status, GetLastError()); }
第五步:列出 USN Journal 文件的数据
前面提到 USN 日志的数据是以 USN_RECORD 形式储存的,在 MSDN 的介绍:
http://msdn.microsoft.com/en-us/library/aa365722%28VS.85%29.aspx
[[
同时分享一个网上找到的带中文注释的 USN_RECORD : ( 原文链接 )
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;
其中 <> 是我补充上的,要实现类似 Everything 的搜索,我们主要关注下面几个参数:
FileReferenceNumber, ParentFileReferenceNumber -> 可以用来找回文件路径
FileNameLength, FileName[1] -> 储存了文件名
]]
需要枚举 USN 的数据,我们需要使用 DeviceIoControl() 和 FSCTL_ENUM_USN_DATA 配合。
MSDN : http://msdn.microsoft.com/en-us/library/aa364563%28v=VS.85%29.aspx
这里需要提供一个 MTF_ENUM_DATA 的结构作为参数 , 正如描述所指:
Enumerates the update sequence number (USN) data between two specified boundaries to obtain master file table (MFT) records.
这些 USN_RECORD 储存在一个叫 MFT 的表里, MTF_ENUM_DATA 的作用就是制定一个范围 。对这个我也不是很了解,不管他,把参数填上看看结果再说。
[[
关键就是如何构建一个 MFT_ENUM_DATA 的结构来指定获取数据的范围,我们来看一下这个结构:
typedef struct {
DWORDLONG StartFileReferenceNumber;
USN LowUsn;
USN HighUsn;
} MFT_ENUM_DATA, *PMFT_ENUM_DATA;
最后我在 MSDN 中找到关键的一段话:
The first call to FSCTL_ENUM_USN_DATA during an enumeration must have the StartFileReferenceNumber member set to (DWORDLONG)0. Each call to FSCTL_ENUM_USN_DATA retrieves the starting point for the subsequent call as the first entry in the output buffer. Subsequent calls must be made with StartFileReferenceNumber set to this value. For more information, see FSCTL_ENUM_USN_DATA .
大概意思是:
初始时将 StartFileReferenceNumber 设置为 0 ,然后每次进行枚举后获取起始点进行下一次操作,这个新的起始点包含在返回的 buffer 的开头。
我们不难发现,这里指的 buffer 就是 DeviceIoControl 函数中的:
BOOL DeviceIoControl(
(HANDLE) hDevice, // handle to volume
FSCTL_ENUM_USN_DATA, // dwIoControlCode
(LPVOID) lpInBuffer, // input buffer
(DWORD) nInBufferSize, // size of input buffer
(LPVOID) lpOutBuffer, // output buffer < 这里>
(DWORD) nOutBufferSize, // size of output buffer
(LPDWORD) lpBytesReturned, // number of bytes returned
(LPOVERLAPPED) lpOverlapped // OVERLAPPED structure
);
在 MFT_ENUM_DATA 中 还有另外两个参数:
LowUsn, HighUsn
分别制定范围的起止。
我们这里要获取所有USN 的数据,需要知道整个USN 的起止位置。可通过 DeviceIoControl() 配合 FSCTL_QUERY_USN_JOURNAL 来获取一个 USN_JOURNAL_DATA 结构体,里面包含我们需要的信息 ( 后续的删除操作也要用到这些信息 ) :
typedef struct {
DWORDLONG UsnJournalID;
USN FirstUsn;
USN NextUsn;
USN LowestValidUsn;
USN MaxUsn;
DWORDLONG MaximumSize;
DWORDLONG AllocationDelta;
} USN_JOURNAL_DATA, *PUSN_JOURNAL_DATA;
其中的FirstUsn 和NextUsn 就分别对应了LowUsn 和HighUsn.
]]
首先需要构建一个MFT_ENUM_DATA ,我们用上一步获取到的USN_JOURNAL_DATA 进行填充。
这里给出一个实现参考:
MFT_ENUM_DATA med; med.StartFileReferenceNumber = 0; med.LowUsn = 0;//UsnInfo.FirstUsn; 这里经测试发现,如果用FirstUsn有时候不正确,导致获取到不完整的数据,还是直接写0好. med.HighUsn = UsnInfo.NextUsn;
有了MFT_ENUM_DATA ,就可以获取到USN 的数据了。
MSDN上也提供了一个例子可做参考 ,虽然是FSCTL_READ_USN_JOURNAL,和我们要执行的ENUM是类似的。
枚举USN数据,这里给出实现参考:
#define BUF_LEN 4096 CHAR buffer[BUF_LEN]; // 用于储存记录的缓冲 , 尽量足够地大 DWORD usnDataSize; PUSN_RECORD UsnRecord; while (0!=DeviceIoControl(hVol, FSCTL_ENUM_USN_DATA, &med, sizeof (med), buffer, BUF_LEN, &usnDataSize, NULL)) { DWORD dwRetBytes = usnDataSize - sizeof (USN); // 找到第一个 USN 记录 // from MSDN(http://msdn.microsoft.com/en-us/library/aa365736%28v=VS.85%29.aspx ): // return a USN followed by zero or more change journal records, each in a USN_RECORD structure. UsnRecord = (PUSN_RECORD)(((PCHAR)buffer)+sizeof (USN)); printf(" ********************************** \n" ); while (dwRetBytes>0){ // 打印获取到的信息 const int strLen = UsnRecord->FileNameLength; char fileName[MAX_PATH] = {0}; WideCharToMultiByte(CP_OEMCP,NULL,UsnRecord->FileName,strLen/2,fileName,strLen,NULL,FALSE); printf("FileName: %s\n" , fileName); // 下面两个 file reference number 可以用来获取文件的路径信息 printf("FileReferenceNumber: %xI64\n" , UsnRecord->FileReferenceNumber); printf("ParentFileReferenceNumber: %xI64\n" , UsnRecord->ParentFileReferenceNumber); printf("\n" ); // 获取下一个记录 DWORD recordLen = UsnRecord->RecordLength; dwRetBytes -= recordLen; UsnRecord = (PUSN_RECORD)(((PCHAR)UsnRecord)+recordLen); } // 获取下一页数据, MTF 大概是分多页来储存的吧? // from MSDN(http://msdn.microsoft.com/en-us/library/aa365736%28v=VS.85%29.aspx ): // The USN returned as the first item in the output buffer is the USN of the next record number to be retrieved. // Use this value to continue reading records from the end boundary forward. med.StartFileReferenceNumber = *(USN *)&buffer; }
现在只要对列出的数据进行筛选,基本就可以实现 Everything 的快速搜索了。
还需要结合索引的建立,才能达到更快的速度。
下面再介绍下如何删除 USN Journal 文件,当你不再需要他的时候。
第六步:删除 USN Journal 文件
MSDN 参考: http://msdn.microsoft.com/en-us/library/aa363928%28v=VS.85%29.aspx
实现参考:
/** * step 06. 删除 USN 日志文件 ( 当然也可以不删除 ) */ DELETE_USN_JOURNAL_DATA dujd; dujd.UsnJournalID = UsnInfo.UsnJournalID; dujd.DeleteFlags = USN_DELETE_FLAG_DELETE; int status = DeviceIoControl(hVol, FSCTL_DELETE_USN_JOURNAL, &dujd, sizeof (dujd), NULL, 0, &br, NULL); if (0!=status){ printf(" 成功删除 USN 日志文件 !\n" ); }else { printf(" 删除 USN 日志文件失败 —— status:%x error:%d\n" , status, GetLastError()); }
拓展实现:通过 File Reference Number 获取文件路径
这个这里暂时不讲了,感兴趣的可以参考文章最后给出的链接的实现。
C++上可以通过使用NtCreateFile()和NtQueryFileInformation()来实现路径获取。
基本MSDN上有比较详细的说明了。
===================================================================================================================
>>最后
附上一个完整的C++实现的例子:
NftsUsnJournalDemo_2010.11.10_.rar
另外,还有一个在国外BLOG找到的C#实现的例子,比较完成,注释也很清晰。我也参考了不少。
原BLOG上是以文本贴出代码的,我这里整理成可编译的项目提供下载。
原文BLOG:http://www.dreamincode.net/forums/blog/1017-stcroixskippers-blog/
整理的项目:
UsnJournalProject_v1.3.rar
===================================================================================================================
以上都是出于个人兴趣的研究,接触C++实在迫不得已……Java某些部分的局限性太大了。
上面很多东西都是GOOGLE+MSDN完成的,若有疏忽请指教。
下一步准备将这些基本操作封装成DLL,再通过JNI供JAVA使用。欢迎交流。
- UsnJournalProject_v1.3.rar (169 KB)
- 下载次数: 689
- NftsUsnJournalDemo_2010.11.10_.rar (25.5 KB)
- 下载次数: 737
评论
一直都在使用Everything,实在是太赞了。以前知道Everything的大概原理,但是自己却不回实现,看了博主的介绍后对受益匪浅。
不过,在初始化USN日记的时候,我遇到了以下问题(我用的是VC++6.0编译器):
error C2065: 'CREATE_USN_JOURNAL_DATA' : undeclared identifier
error C2146: syntax error : missing ';' before identifier 'cujd'
error C2065: 'cujd' : undeclared identifier
error C2228: left of '.MaximumSize' must have class/struct/union type
error C2228: left of '.AllocationDelta' must have class/struct/union type
error C2065: 'FSCTL_CREATE_USN_JOURNAL' : undeclared identifier
我已经在原文件中加入了以下语句:
#include <winioctl.h>
请问博主知道是怎么回事吗?
我看了一下你提供的源代码,发现你只是include了Windows.h,这样也可以使用'CREATE_USN_JOURNAL_DATA' 这个结构体吗?
谢谢!
提示未定义的错误。我用2010的,可能版本问题。
这些结构体如果没有可以自己定义,具体参考MSDN,直接将结构体代码拷贝到使用前的位置就可以。
我引用的这些是被定义在一个叫WinIoCtl.h的头文件。你需要的结构体如下:
#define FSCTL_CREATE_USN_JOURNAL CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 57, METHOD_NEITHER, FILE_ANY_ACCESS) // CREATE_USN_JOURNAL_DATA,
typedef struct {
DWORDLONG MaximumSize;
DWORDLONG AllocationDelta;
} CREATE_USN_JOURNAL_DATA, *PCREATE_USN_JOURNAL_DATA;
VC++6下我暂时无法测试,希望能帮到你。
一直都在使用Everything,实在是太赞了。以前知道Everything的大概原理,但是自己却不回实现,看了博主的介绍后对受益匪浅。
不过,在初始化USN日记的时候,我遇到了以下问题(我用的是VC++6.0编译器):
error C2065: 'CREATE_USN_JOURNAL_DATA' : undeclared identifier
error C2146: syntax error : missing ';' before identifier 'cujd'
error C2065: 'cujd' : undeclared identifier
error C2228: left of '.MaximumSize' must have class/struct/union type
error C2228: left of '.AllocationDelta' must have class/struct/union type
error C2065: 'FSCTL_CREATE_USN_JOURNAL' : undeclared identifier
我已经在原文件中加入了以下语句:
#include <winioctl.h>
请问博主知道是怎么回事吗?
我看了一下你提供的源代码,发现你只是include了Windows.h,这样也可以使用'CREATE_USN_JOURNAL_DATA' 这个结构体吗?
谢谢!
发表评论
-
[问题解决]个推SDK使用侧记 -- 多个账号注册导致的问题
2013-12-28 14:40 2251这是我们项目最近用到的东西,用来实现消息推送。 (还不了 ... -
[问题解决] 个推(igetui)SDK使用侧记 -- 多个账号注册同一应用导致的问题
2013-12-28 14:33 0这是我们项目最近用到的东西,用来实现消息推送。 (还不了解 ... -
[SWT]打开Windows文件夹的方法 [整理]
2012-10-24 21:03 2633参考论坛帖子:http://www.iteye.com/top ... -
[SWT]SashForm中固定单侧大小(&实现面板隐藏)
2012-09-20 16:06 7161<!-- 额,发觉写篇博客都不知怎么选分类了。。。名称太 ... -
[Everything模仿] 相关项目资源整理
2012-04-29 20:04 3804一段时间来,发觉还是 ... -
[问题解决]Ubuntu10.04安装出现的显示器“无信号”问题
2011-12-11 20:42 4370<!-- 旧帖转移,2010-09-25 --> ... -
9个主流的开源许可协议[整理]
2011-12-05 23:15 29398关于开源许可 现今存在的开源协议很多,而经过 ... -
电子邮件收发原理和实现(POP3, SMTP) [整理]
2011-09-16 11:12 28374<!-- 最近工作上接触到了邮箱的开发,整理一下学到的东 ... -
讲解极小极大 (Minimax Explained) [译]
2011-09-11 21:00 6917原文链接:Minimax Explaine ... -
理解极小极大算法 (Understanding The Minimax Algorithm) [译]
2011-09-11 20:45 27109原文链接:Understanding Th ... -
Maven In Android
2011-08-31 17:32 3485Maven 一个项目管理工具,类似于Ant。相比Ant, ... -
[基础回顾]基于Eclipse的J2me和Android开发环境搭建
2011-03-23 00:10 1893<!-- 越是基础的东西就容易被忽略和轻视...我是接触 ... -
[SVN]423 Locked problem (Solved)
2011-03-03 17:15 9029今天使用SVN上传代码,突然冒出了一行红字... Se ... -
Everything研究之快速获取USN记录的文件路径
2011-01-06 17:04 9012<!-- 发觉越是没事干,记忆越差,乘还记得点什么,记录 ... -
Everything研究之读取NTFS下的USN日志文件(1)
2010-11-08 01:02 33064我在第一次使用 Everything 时,对其速度确实感到 ... -
[Swing]Netbean中使用外部资源
2010-10-22 15:43 1641要在NetBean中使用外部资源,首先需要在项目目录下创建一个 ... -
[Swing]实现一个文本自动完成工具
2010-10-17 00:00 3644//------------------------- ... -
[图形算法]J2me上的凹凸拼图实现思路
2010-04-05 21:31 6147出于个人兴趣,简单研究了一下凹凸拼图的实现。以下为本人的实现思 ... -
[特效研究]j2medev论坛里提到的一个显示特效实现
2010-03-14 16:05 2480原贴链接:http://www.j2medev.com/ ... -
[LUA]在eclipse中使用luajava
2009-10-17 23:23 4324<!--StartFragment--> st ...
相关推荐
原理是读取ntfs的USN文件日志,然后内建索引加速文件搜索过程。 1、列表文件支持批量处理(删除、复制、复制文件名路径、打开、重命名),或者引用系统菜单。 2、支持拼音首字母缩写搜索,指定文件夹内搜索,多...
不同于 Windows 自带的搜索功能,Everything 不依赖于文件名中的关键词,而是直接读取 NTFS 文件系统的 USN 日志,这意味着即使文件内容发生变化,它也能快速更新索引。输入关键词后,搜索结果几乎是即时显示的,...
Everything在首次使用时会建立一个索引数据库,通过读取NTFS USN日志来建立文件索引树,生成的索引文件非常小。在搜索栏中输入要搜索的文件名,瞬间就能够帮助你找到要找的文件。支持使用搜索语法及正则表达式语法...
NTFS(New Technology File System)是Windows操作系统中广泛使用的文件系统,它支持多种高级功能,其中之一就是USN(Update Sequence Number)日志。USN日志是一个记录文件系统变化的系统,每次文件或目录发生更改...
原理是:Everything是靠读取NTFS文件系统中的USN日志来完成的,所以如果你的硬盘不是NTFS的,那就没有什么用了。 这是免安装版,解压使用时,默认是日文界面,要把那个.lng文件放到Everything的执行文件所在文件夹...
这个"Everything山寨版源码"显然是一款基于"Everything"的仿制品或修改版,其核心也是通过读取NTFS文件系统的USN(Update Sequence Number)日志来实现即时的文件索引和搜索功能。 NTFS USN日志是Windows操作系统为...
这种快速,是因为Everything的索引无需逐一扫描硬盘文件,而是直接读取NTFS磁盘USN日志。这当然是既省力,又合理的做法。 第二个快速体现在搜索速度。在搜索框中键入字符后,搜索结果——或许称为过滤结果更准确...
"Everything"的核心优势在于其利用了NTFS文件系统的USN(Update Sequence Number)日志。USN日志是NTFS文件系统的一个关键特性,它记录了文件系统中所有更改的历史。每当文件被创建、修改、删除或移动,USN日志都会...
在IT行业中,尤其是在系统开发和数据检索领域,"filesearch_everything.rar"这个压缩包可能包含了一个关于快速文件搜索工具的实现,特别是涉及到USN(Update Sequence Number)日志的利用。USN日志是Windows操作系统...
NTFS-Search通过读取和解析MFT,结合USN Journal的变化记录,能够在短时间内获取到最新的文件信息,为用户提供即时的文件搜索服务。 项目包含的文件中,UpgradeLog.htm可能是软件升级或更新的日志文件,LICENSE文件...
这是因为Everything通过读取NTFS文件系统的USN日志(Update Sequence Number Journal)和MFT(Master File Table)来构建索引,这两种数据结构记录了文件系统的所有变化,使得搜索结果始终保持最新。 《探索...
这种快速,是因为Everything的索引无需逐一扫描硬盘文件,而是直接读取NTFS文件系统的USN日志。这当然是既省力,又合理的做法。 第二个快速体现在搜索速度。在搜索框中键入字符后,搜索结果——或许称为过滤结果更...
这种快速,是因为Everything的索引无需逐一扫描硬盘文件,而是直接读取NTFS文件系统的USN日志。这当然是既省力,又合理的做法。 第二个快速体现在搜索速度。在搜索框中键入字符后,搜索结果——或许称为过滤结果更...
这款工具之所以能够实现如此高效的搜索,主要得益于对NTFS文件系统的深入理解和巧妙利用。 首先,我们来看NTFS文件系统的基础——Master File Table(MFT)。MFT是NTFS的核心组件,存储了文件和目录的所有元数据。...