https://github.com/flamecyclone/ntfs_search
A library for quickly searching files on an NTFS volume, file fast search, ntfs search, mft parse
https://github.com/flamecyclone/ntfs_search
files mft ntfs usn windows
Last synced: 21 days ago
JSON representation
A library for quickly searching files on an NTFS volume, file fast search, ntfs search, mft parse
- Host: GitHub
- URL: https://github.com/flamecyclone/ntfs_search
- Owner: flamecyclone
- Created: 2024-12-20T07:10:53.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2024-12-24T01:47:24.000Z (over 1 year ago)
- Last Synced: 2025-06-01T13:29:13.974Z (about 1 year ago)
- Topics: files, mft, ntfs, usn, windows
- Language: C++
- Homepage:
- Size: 43 MB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# NTFS File Search Library
[中文 ](README_cn.md) | English
A library for quickly searching files on an NTFS volume.


## Features
- Quickly scan all files on NTFS formatted drives
- Real-time quick synchronization of file changes (creation, renaming, deletion)
- Support for wildcard queries for file names or file paths
- Automatic file update upon restart, no need to perform a full disk scan again
## API Description
- Initialize and specify the drive you are concerned with.
```C++
//
// @brief: Initialize(Drive Mask)
// @param: dwDriveIndexMask Drive index mask.(Bit combination: C: 0x01 D: 0x02 E: 0x04...)
// @param: strDbPath Database file path
// @param: fRebuildDb Whether to rebuild the database
// @ret: BOOL Whether the operation was successful.
BOOL NTFS_Search_Initialize_By_Drive_Mask(
DWORD dwDriveIndexMask,
LPCTSTR lpDbPath,
bool fRebuildDb
);
//
// @brief: Initialize(Drive Letter)
// @param: strDriveList Drive list, Such as: "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
// @param: strDbPath Database file path
// @param: fRebuildDb Whether to rebuild the database
// @ret: BOOL Whether the operation was successful.
BOOL NTFS_Search_Initialize_By_Drive_Letter(
LPCTSTR lpDriveList,
LPCTSTR lpDbPath,
bool fRebuildDb
);
```
- Reset and specify the drive you are concerned with.
```C++
//
// @brief: Reset(Drive Mask)
// @param: dwDriveIndexMask Drive index mask.(Bit combination: C: 0x01 D: 0x02 E: 0x04...)
// @param: strDbPath Database file path
// @param: fRebuildDb Whether to rebuild the database
// @ret: BOOL Whether the operation was successful.
NTFSSEARCH_API BOOL NTFS_Search_Reset_By_Drive_Mask(
DWORD dwDriveIndexMask,
LPCTSTR lpDbPath,
bool fRebuildDb
);
//
// @brief: Reset(Drive Letter)
// @param: strDriveList Drive list, Such as: "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
// @param: strDbPath Database file path
// @param: fRebuildDb Whether to rebuild the database
// @ret: BOOL Whether the operation was successful.
NTFSSEARCH_API BOOL NTFS_Search_Reset_By_Drive_Letter(
LPCTSTR lpDriveList,
LPCTSTR lpDbPath,
bool fRebuildDb
);
```
- Get the current total number of files.
```C++
//
// @brief: Get the current total number of files.
// @ret: LONGLONG Current total number of files
NTFSSEARCH_API LONGLONG NTFS_Search_GetCount();
```
- Search for files, supporting wildcards (* matches 0 or more characters, ? matches 1 character).
```C++
//
// @brief: Query file path.
// @param: lpKeyword Keyword, such as: "C:\*.zip"
// @param: cb Query callback function (return FALSE to terminate result enumeration).
// @param: lpData Callback function additional parameters
// @ret: BOOL Whether the operation was successful.
NTFSSEARCH_API BOOL NTFS_Search_Query(
LPCTSTR lpKeyword,
NtfsSearchCallback cb,
LPVOID lpData
);
```
- Uninitialize
```C++
//
// @brief: Uninitialize
// @ret: void Whether the operation was successful.
NTFSSEARCH_API VOID NTFS_Search_Uninitialize();
```
## Performance Description
- Good performance
- Full disk scan of 770,000 files takes about 13 seconds
- Searching for * takes 1.3 seconds
- Searching for *.zip takes 0.2 seconds
- Low memory usage
- Memory usage for 770,000 files is only around 100MB
- Database file occupancy
- Database storage for 770,000 files occupies over 300MB of disk space
## Usage Examples
```c++
#include
#include
#include
#include
#include
#include "../NTFS_Search_Lib/include/NTFS_Search_Api.h"
#ifdef _UNICODE
using _tstring = std::wstring;
#else
using _tstring = std::string;
#endif
#ifndef _DEBUG
#ifndef _DEBUG
#ifdef _UNICODE
#ifdef _WIN64
#pragma comment(lib, "../NTFS_Search_lib/lib/NTFS_Search_Lib_x64_W.lib")
#else
#pragma comment(lib, "../NTFS_Search_lib/lib/NTFS_Search_Lib_x86_W.lib")
#endif
#else
#ifdef _WIN64
#pragma comment(lib, "../NTFS_Search_lib/lib/NTFS_Search_Lib_x64_A.lib")
#else
#pragma comment(lib, "../NTFS_Search_lib/lib/NTFS_Search_Lib_x86_A.lib")
#endif
#endif
#else
#ifdef _UNICODE
#ifdef _WIN64
#pragma comment(lib, "../NTFS_Search_lib/lib/NTFS_Search_Lib_x64_WD.lib")
#else
#pragma comment(lib, "../NTFS_Search_lib/lib/NTFS_Search_Lib_x86_WD.lib")
#endif
#else
#ifdef _WIN64
#pragma comment(lib, "../NTFS_Search_lib/lib/NTFS_Search_Lib_x64_AD.lib")
#else
#pragma comment(lib, "../NTFS_Search_lib/lib/NTFS_Search_Lib_x86_AD.lib")
#endif
#endif
#endif
std::wstring _MultiStrToWStr(UINT CodePage, const std::string& str)
{
int cchWideChar = ::MultiByteToWideChar(CodePage, 0, str.c_str(), -1, NULL, 0);
std::wstring strResult(cchWideChar, 0);
size_t nConverted = ::MultiByteToWideChar(CodePage, 0, str.c_str(), (int)str.size(), &strResult[0], (int)strResult.size());
strResult.resize(nConverted);
return strResult;
}
_tstring AStrToTStr(const std::string& str)
{
#ifdef _UNICODE
return _MultiStrToWStr(CP_ACP, str);
#else
return str;
#endif
}
int _tmain(int argc, LPCTSTR argv[])
{
setlocale(LC_ALL, "");
clock_t tmBegin = ::clock();
clock_t tmEnd = ::clock();
_tstring strDriveList = _T("");
_tstring strDbPath = _T("");
// Initialize
NTFS_Search_Initialize_By_Drive_Letter(strDriveList.c_str(), strDbPath.c_str(), false);
if (0 == NTFS_Search_GetCount())
{
_tprintf(_T("Scan the specified drive: %s\n"), strDriveList.c_str());
tmBegin = ::clock();
NTFS_Search_Reset_By_Drive_Letter(strDriveList.c_str(), strDbPath.c_str(), true);
tmEnd = ::clock();
_tprintf(_T("Scanning Time Taken: %dms\n"), tmEnd - tmBegin);
}
_tstring strKey;
while (true)
{
char szBuf[MAX_PATH] = { 0 };
_tprintf(_T("File count: %llu\n"), NTFS_Search_GetCount());
_tprintf(_T("Command: \n"));
_tprintf(_T(" :r Rescan, such as: :r\n"));
_tprintf(_T(" :: Rescan the specified drive, such as: ::CDEF\n"));
_tprintf(_T(" :q Quit, such as: :q\n"));
_tprintf(_T("Find keyword: "));
strKey.clear();
while (strKey.empty())
{
gets_s(szBuf, sizeof(szBuf));
strKey = AStrToTStr(szBuf);
}
if (0 == _strnicmp(szBuf, "::", 2))
{
strDriveList = strKey.substr(2);
_tprintf(_T("Rescan the specified drive: %s\n"), strDriveList.c_str());
tmBegin = ::clock();
NTFS_Search_Reset_By_Drive_Letter(strDriveList.c_str(), strDbPath.c_str(), true);
tmEnd = ::clock();
_tprintf(_T("Total time taken: %dms\n"), tmEnd - tmBegin);
continue;
}
if (0 == _stricmp(szBuf, ":r"))
{
_tprintf(_T("Rescan\n"));
tmBegin = ::clock();
NTFS_Search_Reset_By_Drive_Letter(strDriveList.c_str(), strDbPath.c_str(), true);
tmEnd = ::clock();
_tprintf(_T("Total time taken: %dms\n"), tmEnd - tmBegin);
continue;
}
if (0 == _stricmp(szBuf, ":q"))
{
_tprintf(_T("Quit\n"));
break;
}
_tprintf(_T(R"(Searching...)"));
_tprintf(_T("\n"));
std::vector<_tstring> fileList;
tmBegin = ::clock();
int nRes = NTFS_Search_Query(strKey.c_str(), [](LPVOID lpData, LPCTSTR lpPath) -> bool {
std::vector<_tstring>* pList = (std::vector<_tstring>*)lpData;
pList->push_back(lpPath);
return true;
},
&fileList
);
tmEnd = ::clock();
int nIndex = 0;
for (const auto& item : fileList)
{
_tprintf(_T("%d: %s\r\n"), ++nIndex, item.c_str());
if (nIndex >= 100)
{
break;
}
}
_tprintf(_T("\n"));
_tprintf(_T("Time taken: %gs Number of files: %d \n"), (double)((tmEnd - tmBegin)) / 1000.0f, (int)fileList.size());
}
// Uninitialize
NTFS_Search_Uninitialize();
return 0;
};
```