USN日志

转载:https://www.iteye.com/blog/univasity-805234    https://blog.51cto.com/velika/1440105

源码:https://files.cnblogs.com/files/Toya/USN.7z

本程序需要管理员权限

  1 #include<iostream>
  2 #include<stdio.h>
  3 #include<string>
  4 #include<tchar.h>
  5 #include<Windows.h>
  6 
  7 using namespace std;
  8 
  9 bool isNTFS(string path);
 10 HANDLE getHandle(string volName);
 11 bool createUSN(HANDLE hVol, CREATE_USN_JOURNAL_DATA& cujd);
 12 bool getUSNInfo(HANDLE hVol, USN_JOURNAL_DATA& ujd);
 13 bool getUSNJournal(HANDLE hVol, USN_JOURNAL_DATA& ujd);
 14 bool deleteUSN(HANDLE hVol, USN_JOURNAL_DATA& ujd);
 15 
 16 int main(){
 17     //isNTFS("C:/");
 18     CREATE_USN_JOURNAL_DATA* cujd = new CREATE_USN_JOURNAL_DATA;
 19     USN_JOURNAL_DATA* ujd = new USN_JOURNAL_DATA;
 20     HANDLE hVol = getHandle("C:");
 21     createUSN(hVol, *cujd);
 22     getUSNInfo(hVol, *ujd);
 23     getUSNJournal(hVol, *ujd);
 24     deleteUSN(hVol, *ujd);
 25     system("pause");
 26     return 0;
 27 }
 28 
 29 //判断是否是NTFS盘
 30 bool isNTFS(string path){//"C:/"
 31     char sysNameBuf[MAX_PATH];
 32     int status = GetVolumeInformationA(path.c_str(),
 33         NULL,
 34         0,
 35         NULL,
 36         NULL,
 37         NULL,
 38         sysNameBuf,
 39         MAX_PATH);
 40 
 41     if (0 != status){
 42         if (0 == strcmp(sysNameBuf, "NTFS")){
 43             //printf(" 文件系统名 : %s
", sysNameBuf);
 44             cout << "盘符:" << path << "
文件系统名:" << sysNameBuf << endl;
 45             return true;
 46         }
 47         else {
 48             printf(" 该驱动盘非 NTFS 格式 
");
 49             return false;
 50         }
 51 
 52     }
 53     return false;
 54 }
 55 
 56 /**
 57 * step 02. 获取驱动盘句柄
 58 */
 59 HANDLE getHandle(string volName){
 60 
 61     char fileName[MAX_PATH];
 62     fileName[0] = '';
 63 
 64     // 传入的文件名必须为\.C:的形式  
 65     strcpy_s(fileName, "\\.\");
 66     strcat_s(fileName, volName.c_str());
 67     // 为了方便操作,这里转为string进行去尾  
 68     string fileNameStr = (string)fileName;
 69     fileNameStr.erase(fileNameStr.find_last_of(":") + 1);
 70 
 71     printf("驱动盘地址: %s
", fileNameStr.data());
 72 
 73     // 调用该函数需要管理员权限  
 74     HANDLE hVol = CreateFileA(fileNameStr.data(),
 75         GENERIC_READ | GENERIC_WRITE, // 可以为0  
 76         FILE_SHARE_READ | FILE_SHARE_WRITE, // 必须包含有FILE_SHARE_WRITE  
 77         NULL, // 这里不需要  
 78         OPEN_EXISTING, // 必须包含OPEN_EXISTING, CREATE_ALWAYS可能会导致错误  
 79         FILE_ATTRIBUTE_READONLY, // FILE_ATTRIBUTE_NORMAL可能会导致错误  
 80         NULL); // 这里不需要  
 81 
 82     if (INVALID_HANDLE_VALUE != hVol){
 83         //getHandleSuccess = true;
 84         cout << "获取驱动盘句柄成功!
";
 85         return hVol;
 86     }
 87     else{
 88         printf("获取驱动盘句柄失败 —— handle:%x error:%d
", hVol, GetLastError());
 89         return 0;
 90     }
 91     return 0;
 92 }
 93 
 94 /**
 95 * step 03. 初始化USN日志文件
 96 */
 97 bool createUSN(HANDLE hVol, CREATE_USN_JOURNAL_DATA& cujd){
 98     DWORD br;    
 99     cujd.MaximumSize = 0; // 0表示使用默认值  
100     cujd.AllocationDelta = 0; // 0表示使用默认值  
101     bool status = DeviceIoControl(hVol,
102         FSCTL_CREATE_USN_JOURNAL,
103         &cujd,
104         sizeof(cujd),
105         NULL,
106         0,
107         &br,
108         NULL);
109 
110     if (0 != status){
111         //initUsnJournalSuccess = true;
112         return true;
113     }
114     else{
115         printf("初始化USN日志文件失败 —— status:%x error:%d
", status, GetLastError());
116         return false;
117     }
118     return false;
119 }
120 
121 /**
122 
123 * step 04. 获取USN日志基本信息(用于后续操作)
124 
125 * msdn:http://msdn.microsoft.com/en-us/library/aa364583%28v=VS.85%29.aspx
126 
127 */
128 bool getUSNInfo(HANDLE hVol, USN_JOURNAL_DATA& ujd){
129     bool getBasicInfoSuccess = false;
130     DWORD br;
131     bool status = DeviceIoControl(hVol,
132         FSCTL_QUERY_USN_JOURNAL,
133         NULL,
134         0,
135         &ujd,
136         sizeof(ujd),
137         &br,
138         NULL);
139     if (0 != status){
140         //getBasicInfoSuccess = true;
141         printf("获取USN日志基本信息成功
");
142         return true;
143     }
144     else{
145         printf("获取USN日志基本信息失败 —— status:%x error:%d
", status, GetLastError());
146         return false;
147     }
148     return false;
149 }
150 
151 bool getUSNJournal(HANDLE hVol, USN_JOURNAL_DATA& ujd){
152     MFT_ENUM_DATA_V0 med;
153     med.StartFileReferenceNumber = 0;
154     med.LowUsn = ujd.FirstUsn;
155     med.HighUsn = ujd.NextUsn;
156 #define BUF_LEN 4096  
157     CHAR buffer[BUF_LEN]; // 用于储存记录的缓冲 , 尽量足够地大  
158     DWORD usnDataSize = 0;
159     PUSN_RECORD UsnRecord;
160     while (0 != DeviceIoControl(hVol,
161         FSCTL_ENUM_USN_DATA,
162         &med,
163         sizeof (med),
164         buffer,
165         BUF_LEN,
166         &usnDataSize,
167         NULL))
168     {
169         DWORD dwRetBytes = usnDataSize - sizeof (USN);
170         // 找到第一个 USN 记录  
171         // from MSDN(http://msdn.microsoft.com/en-us/library/aa365736%28v=VS.85%29.aspx ):  
172         // return a USN followed by zero or more change journal records, each in a USN_RECORD structure.  
173         UsnRecord = (PUSN_RECORD)(((PCHAR)buffer) + sizeof (USN));
174         printf(" ********************************** 
");
175         while (dwRetBytes>0){
176             // 打印获取到的信息  
177             const int strLen = UsnRecord->FileNameLength;
178             char fileName[MAX_PATH] = { 0 };
179             WideCharToMultiByte(CP_OEMCP, NULL, UsnRecord->FileName, strLen / 2, fileName, strLen, NULL, FALSE);
180             printf("FileName: %s
", fileName);
181             // 下面两个 file reference number 可以用来获取文件的路径信息  
182             printf("FileReferenceNumber: %xI64
", UsnRecord->FileReferenceNumber);
183             printf("ParentFileReferenceNumber: %xI64
", UsnRecord->ParentFileReferenceNumber);
184             printf("
");
185             // 获取下一个记录  
186             DWORD recordLen = UsnRecord->RecordLength;
187             dwRetBytes -= recordLen;
188             UsnRecord = (PUSN_RECORD)(((PCHAR)UsnRecord) + recordLen);
189         }
190         // 获取下一页数据, MTF 大概是分多页来储存的吧?  
191         // from MSDN(http://msdn.microsoft.com/en-us/library/aa365736%28v=VS.85%29.aspx ):  
192         // The USN returned as the first item in the output buffer is the USN of the next record number to be retrieved.  
193         // Use this value to continue reading records from the end boundary forward.  
194         med.StartFileReferenceNumber = *(USN *)&buffer;
195     }
196     return true;
197 }
198 
199 /**
200 * step 06. 删除 USN 日志文件 ( 当然也可以不删除 )
201 */
202 bool deleteUSN(HANDLE hVol, USN_JOURNAL_DATA& ujd){
203     DELETE_USN_JOURNAL_DATA dujd;
204     dujd.UsnJournalID = ujd.UsnJournalID;
205     dujd.DeleteFlags = USN_DELETE_FLAG_DELETE;
206     DWORD br;
207     int status = DeviceIoControl(hVol,
208         FSCTL_DELETE_USN_JOURNAL,
209         &dujd,
210         sizeof (dujd),
211         NULL,
212         0,
213         &br,
214         NULL);
215     if (0 != status){
216         CloseHandle(hVol);
217         printf(" 成功删除 USN 日志文件 !
");
218         return true;
219     }
220     else {
221         CloseHandle(hVol);
222         printf(" 删除 USN 日志文件失败 —— status:%x error:%d
", status, GetLastError());
223         return false;
224     }
225     return false;
226 }

运行结果:

原文地址:https://www.cnblogs.com/Toya/p/11398817.html