NTFS Change Journal
NTFS卷上的变化日志,每个卷上都有自己的变化日志。
文件被隐藏
初始化的时候为空,文件或目录发生改变,写到日志的末尾
每条记录是一个USN(Update Sequence Number),64位的标示
USNs按增长顺序生成
每页大概包含30-40个记录,记录不可以跨页,所以页尾可能浪费一些
NTFS卷上文件,目录信息存储在MFT(Master File Table)上,
MFT上的记录描述了文件的名称,位置,大小,属性。。。
每个文件的MFT条目记录了这个文件的最新USN
文件系统更新变化文件的MFT的最新USN
日志文件增长过大,文件系统允许在文件的开始处,清除旧的记录
传统的方法,清除前面的要很多IO操作,后面的还要移到新的位置
但是日志十个稀疏文件,支持清除不需要的部分,保留部分的偏移量仍然可用
某卷的变化日志可以被禁用,防止系统为文件和目录写日志,默认情况下是关闭的,
应用程序需要激活它
任何应用程序都可以在任何时候,禁用,启用日志,所以当有程序使用的情况,要温柔的处理
当日志被禁用的时候,系统要清除日志的记录内容,防止程序读不可靠的信息,
日志仅保留持续活动期间的记录
目前的实现是,禁用时候删除变化日志,启用的时候创建一个新的日志,
虽然应用程序不关心删除和创建操作,但是平台编成却要使用
***************************************************************************
***************************************************************************
访问Change Journal要通过DeviceIoControl
BOOL DeviceIoControl(
(HANDLE) hDevice, // 文件,目录,设备,用CreateFile取得句柄
FSCTL_READ_USN_JOURNAL, // 请求
(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
);
HANDLE hcj = CreateFile("////.//C:", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL);
***************************************************************************
***************************************************************************
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;
应用程序不去填写这些信息,当程序读Change Journal时由系统返回。
PUSN_RECORD pNext;
pNext = (PUSN_RECORD) (((PBYTE) pRecord) + pRecord->RecordLength);
在网上突然发现了Everything这个程序对NTFS磁盘文件可以快速的进行搜索,而且搜素的速度之快,让你惊讶这个东西怎么工作的? 具介绍说是 采用了NTFS的 Change Journal这个特性进行开发的。总算对这个 USN的说法有了个了解,但是这个特性如何对他的检索怎么应用的还没有想清楚。不过看它的搜索速度真是让人惊奇! NTFS Change Journal NTFS卷上的变化日志,每个卷上都有自己的变化日志。 文件被隐藏 初始化的时候为空,文件或目录发生改变,写到日志的末尾 每条记录是一个USN(Update
Sequence Number),64位的标示 USNs按增长顺序生成 每页大概包含30-40个记录,记录不可以跨页,所以页尾可能浪费一些 NTFS卷上文件,目录信息存储在MFT(Master File Table)上, MFT上的记录描述了文件的名称,位置,大小,属性。。。 每个文件的MFT条目记录了这个文件的最新USN 文件系统更新变化文件的MFT的最新USN 日志文件增长过大,文件系统允许在文件的开始处,清除旧的记录传统的方法,清除前面的要很多IO操作,后面的还要移到新的位置但是日志十个稀疏文件,支持清除不需要的部分,保留部分的偏移量仍然可用
某卷的变化日志可以被禁用,防止系统为文件和目录写日志,默认情况下是关闭的, 应用程序需要激活它 任何应用程序都可以在任何时候,禁用,启用日志,所以当有程序使用的情况,要温柔的处理 当日志被禁用的时候,系统要清除日志的记录内容,防止程序读不可靠的信息, 日志仅保留持续活动期间的记录 目前的实现是,禁用时候删除变化日志,启用的时候创建一个新的日志, 虽然应用程序不关心删除和创建操作,但是平台编成却要使用 ***************************************************************************
*************************************************************************** 访问Change Journal要通过DeviceIoControl BOOL DeviceIoControl( (HANDLE) hDevice, // 文件,目录,设备,用CreateFile取得句柄 FSCTL_READ_USN_JOURNAL, // 请求 (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 ); HANDLE hcj = CreateFile("\\\\.\\C:",
GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); *************************************************************************** *************************************************************************** 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; 应用程序不去填写这些信息,当程序读Change Journal时由系统返回。 PUSN_RECORD pNext; pNext = (PUSN_RECORD) (((PBYTE) pRecord) + pRecord->RecordLength);
取得NTFS磁盘上的MTF信息
2010-10-28 06:33752人阅读评论(1)收藏举报 [cpp] view plaincopyprint? 01.#include "ntfs.h" 02.#include <iostream> 03.#include <fstream> 04.#include <map> 05.#include <vector> 06.using namespace std; 07.//管理员权限运行 08.typedef struct { 09. ULONGLONG index; 10. ULONGLONG parent; 11. WCHAR name[1024]; 12. int type; //0 file 1 dir 13.} FILE_INFO, *PFILE_INFO; 14. 15.//枚举盘符 16.void OpenNtfsVolume() 17.{ 18. WCHAR tDrivers[26*4+1] = {}; 19. GetLogicalDriveStrings(26*4+1,tDrivers); 20. WCHAR fileSysBuf[8]; 21. DWORD dwDri; //0~25 22. 23. WCHAR szRootName[40]; 24. WCHAR szVolumeName[32]; 25. int iFilterRoot=0; 26. for(WCHAR *p=tDrivers;*p!='\0';p+=4) 27. { 28. if(*p>=L'a') *p-=32;// 29. dwDri=*p-L'A'; 30. if(DRIVE_FIXED==GetDriveTypeW(p)) 31. { 32. DWORD dwMaxComLen,dwFileSysFlag; 33. GetVolumeInformationW(p,szVolumeName,32,NULL,&dwMaxComLen,&dwFileSysFlag,fileSysBuf,8); 34. if(fileSysBuf[0]==L'N' && fileSysBuf[1]==L'T' && fileSysBuf[2]==L'F' && fileSysBuf[3]==L'S') 35. { 36. swprintf(szRootName,L"%s (%c:)",szVolumeName,*p); 37. WCHAR szVolumePath[10]; 38. swprintf(szVolumePath,L"\\\\.\\%c:",*p); 39. wcout<<szVolumePath<<endl; 40. } 41. } 42. } 43.} 44. 45.int main() 46.{ 47. //wcout.imbue(locale(locale(),"",LC_CTYPE)); 48. char szACP[16]; 49. sprintf(szACP, ".%d", GetACP()); 50. //setlocale(LC_CTYPE, szACP); 51. wcout.imbue(locale(locale(),szACP,LC_CTYPE)); 52. OpenNtfsVolume(); 53. 54. WCHAR driveletter[] = L"\\\\.\\D:"; 55. HANDLE hVol = CreateFile(driveletter, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,NULL); 56. NTFS_VOLUME_DATA_BUFFER ntfsVolData; 57. DWORD dwWritten = 0; 58. 59. BOOL bDioControl = DeviceIoControl(hVol, FSCTL_GET_NTFS_VOLUME_DATA, NULL, 0, &ntfsVolData, sizeof(ntfsVolData), &dwWritten, NULL); 60. if (!bDioControl) {wcout<<L"error"<<endl; return 1;} 61. 62. LARGE_INTEGER num; 63. num.QuadPart = 1024; 64. LONGLONG total_file_count = (ntfsVolData.MftValidDataLength.QuadPart/num.QuadPart); 65. wcout<<L"total_file_count:"<<total_file_count<<endl; 66. 67. 68. PNTFS_FILE_RECORD_OUTPUT_BUFFER ntfsFileRecordOutput = (PNTFS_FILE_RECORD_OUTPUT_BUFFER)malloc(sizeof(NTFS_FILE_RECORD_OUTPUT_BUFFER)+ntfsVolData.BytesPerFileRecordSegment-1); 69. for( LONGLONG i = 0; i < total_file_count && i < 10;i++) 70. { 71. NTFS_FILE_RECORD_INPUT_BUFFER mftRecordInput; 72. mftRecordInput.FileReferenceNumber.QuadPart = i; 73. memset(ntfsFileRecordOutput, 0, sizeof(NTFS_FILE_RECORD_OUTPUT_BUFFER)+ntfsVolData.BytesPerFileRecordSegment-1); 74. DeviceIoControl(hVol, FSCTL_GET_NTFS_FILE_RECORD, &mftRecordInput, sizeof(mftRecordInput), ntfsFileRecordOutput, sizeof(NTFS_FILE_RECORD_OUTPUT_BUFFER)+ntfsVolData.BytesPerFileRecordSegment-1, &dwWritten, NULL); 75. PFILE_RECORD_HEADER pfileRecordheader=(PFILE_RECORD_HEADER)ntfsFileRecordOutput->FileRecordBuffer; 76. if(pfileRecordheader->Ntfs.Type != 'ELIF') 77. continue; 78. for(PATTRIBUTE pAttribute = (PATTRIBUTE)((PBYTE)pfileRecordheader +pfileRecordheader->AttributeOffset);pAttribute->AttributeType != -1;pAttribute=(PATTRIBUTE)((PBYTE)pAttribute +pAttribute->Length)) 79. { 80. switch (pAttribute->AttributeType) 81. { 82. case AttributeFileName: 83. { 84. if((0x0002 & pfileRecordheader->Flags) && (0x0001 & pfileRecordheader->Flags)); 85. PFILENAME_ATTRIBUTE pFileNameAttr=PFILENAME_ATTRIBUTE((PBYTE)pAttribute+PRESIDENT_ATTRIBUTE(pAttribute)->ValueOffset); 86. } 87. break; 88. case AttributeStandardInformation: 89. break; 90. case AttributeAttributeList: 91. break; 92. case AttributeObjectId: 93. break; 94. } 95. } 96. } 97. free(ntfsFileRecordOutput); 98. 99. USN_JOURNAL_DATA journalData; 100. READ_USN_JOURNAL_DATA readData = {0, 0xFFFFFFFF, FALSE, 0, 0}; 101. 102. PUSN_RECORD usnRecord; 103. DWORD dwBytes; 104. DWORD dwRetBytes; 105. char buffer[USN_PAGE_SIZE]; 106. bDioControl = DeviceIoControl(hVol, FSCTL_QUERY_USN_JOURNAL, NULL,0,&journalData,sizeof(journalData),&dwBytes,NULL); 107. if (!bDioControl) {wcout<<L"error"<<endl; return 1;} 108. readData.UsnJournalID = journalData.UsnJournalID; 109. wprintf(L"Journal ID: %I64x\n", journalData.UsnJournalID ); 110. wprintf(L"FirstUsn: %I64x\n\n", journalData.FirstUsn ); 111. 112. MFT_ENUM_DATA med; 113. med.StartFileReferenceNumber = 0; 114. med.LowUsn = 0; 115. med.HighUsn = journalData.NextUsn; 116. 117. map<ULONGLONG,wstring> namemap; 118. map<ULONGLONG,ULONGLONG> frnmap; 119. vector<FILE_INFO> fileVect; 120. for (;;) 121. { 122. memset(buffer, 0, sizeof(USN_PAGE_SIZE)); 123. //FSCTL_ENUM_USN_DATA FSCTL_READ_USN_JOURNAL 124. //DeviceIoControl( hVol, FSCTL_READ_USN_JOURNAL, &readData,sizeof(readData),&buffer,USN_PAGE_SIZE,&dwBytes,NULL); 125. bDioControl = DeviceIoControl( hVol, FSCTL_ENUM_USN_DATA, &med, sizeof(med),&buffer,USN_PAGE_SIZE,&dwBytes,NULL); 126. if (!bDioControl) {wcout<<L"error"<<endl; break;} 127. 128. if(dwBytes<=sizeof(USN)) break;//结束! 129. dwRetBytes = dwBytes - sizeof(USN);//跳过了1个USN,此USN是下一论查询起点 130. usnRecord = (PUSN_RECORD)(((PUCHAR)buffer) + sizeof(USN)); 131. while(dwRetBytes > 0) 132. { 133. FILE_INFO fi; 134. fi.index = usnRecord->FileReferenceNumber; 135. fi.parent = usnRecord->ParentFileReferenceNumber; 136. 137. //wprintf(L"USN: %I64x\n", usnRecord->Usn ); 138. //wprintf(L"File name: %.*s\n", (int)(usnRecord->FileNameLength/2),usnRecord->FileName ); 139. //wprintf(L"Reason: %x\n", usnRecord->Reason ); 140. 141. memset(fi.name,0,sizeof(fi.name)); 142. swprintf(fi.name,L"%.*ws", (int)(usnRecord->FileNameLength/2),usnRecord->FileName); 143. namemap[fi.index] = wstring(fi.name); 144. fileVect.push_back(fi); 145. frnmap[fi.index] = fi.parent; 146. 147. dwRetBytes -= usnRecord->RecordLength; 148. usnRecord = (PUSN_RECORD)(((PCHAR)usnRecord) + usnRecord->RecordLength); 149. } 150. med.StartFileReferenceNumber=*(DWORDLONG*)buffer; 151. //readData.StartUsn = *(USN *)&buffer; 152. } 153. wcout<<fileVect.size()<<endl; 154. map<ULONGLONG,wstring>::iterator it; 155. /*for ( it=namemap.begin() ; it != namemap.end(); it++ ) 156. { 157. wcout << (*it).first << " => " << ((*it).second).c_str() <<"==>"<<namemap[(*it).first].c_str()<< endl; 158. }*/ 159. 160. //wofstream ofs(L"data.txt"); 161. for (LONGLONG i = 0; i < fileVect.size(); i++) 162. { 163. FILE_INFO fi = fileVect[i]; 164. wcout<<i<<": "<<fi.name<<"===>"; 165. ULONGLONG parent = fi.parent; 166. while (namemap.find(parent) != namemap.end()) 167. { 168. wstring dir = namemap[parent]; 169. wcout<<L"\\"<<dir.c_str(); 170. 171. if (frnmap.find(parent) != frnmap.end()) 172. { 173. parent = frnmap[parent]; 174. } 175. else 176. { 177. break; 178. } 179. } 180. wcout<<endl; 181. } 182. wcout<<"done"<<endl; 183. CloseHandle(hVol); 184. return 0; 185.} 186. 187./*typedef struct { 188. 189.DWORD RecordLength; 190.WORD MajorVersion; 191.WORD MinorVersion; 192.DWORDLONG FileReferenceNumber; 193.DWORDLONG ParentFileReferenceNumber; 194.USN Usn; 195.LARGE_INTEGER TimeStamp; 196.DWORD Reason; 197.DWORD SourceInfo; 198.DWORD SecurityId; 199.DWORD FileAttributes; 200.WORD FileNameLength; 201.WORD FileNameOffset; 202.WCHAR FileName[1]; 203. 204.} USN_RECORD, *PUSN_RECORD;*/ 下面是ntfs.h的内容,编译使用UNICODE编码 [cpp] view plaincopyprint? 01.#include <Windows.h> 02.#include <WinIoCtl.h> 03. 04.typedef struct { 05. ULONG Type; //4B 'ELIF','XDNI','DAAB','ELOH','DKHC' 06. USHORT UsaOffset; //2B 更新序列号数组偏移,校验值地址 07. USHORT UsaCount; //1+n 1为校验值个数 n为待替换值个数 fixup 08. USN Usn; //8B 每次记录被修改 USN都变化 09.} NTFS_RECORD_HEADER, *PNTFS_RECORD_HEADER; 10. 11.typedef struct { //sizeof(FILE_RECORD_HEADER)==48 12. NTFS_RECORD_HEADER Ntfs; //16B Ntfs.Type总是'ELIF' 13. USHORT SequenceNumber; //File Reference Number的高16位 i是低48位 0~total_file_count-1 14. //用于记录主文件表记录被重复使用的次数 15. USHORT LinkCount; //记录硬连接的数目,只出现在基本文件记录中 16. USHORT AttributeOffset; //第一个属性的偏移 17. USHORT Flags; // 0x0001 = InUse, 0x0002 = Directory 18. ULONG BytesInUse; //记录头和属性的总长度,即文件记录的实际长度文件,即记录在磁盘上实际占用的字节空间。 19. ULONG BytesAllocated; //总共分配给记录的长度 20. ULONGLONG BaseFileRecord; //基本文件记录中的文件索引号, 21. //对于基本文件记录,其值为0,如果不为0,则是一个主文件表的文件索引号, 22. //指向所属的基本文件记录中的文件记录号, 23. //在基本文件记录中包含有扩展文件记录的信息,存储在“属性列表ATTRIBUTE_LIST”属性中。 24. USHORT NextAttributeNumber; //下一属性ID 25.} FILE_RECORD_HEADER, *PFILE_RECORD_HEADER; 26. 27. 28.//文件记录中按属性非降序(因为有时连续多个相同的属性)排列, 29.//属性的值即为 字节流 30.typedef enum { 31. //诸如只读、存档等文件属性; 32. //时间戳:文件创建时、最后一次修改时; 33. //多少目录指向该文件(硬链接计数hard link count) 34. AttributeStandardInformation = 0x10, //Resident_Attributes 常驻属性 35. 36. //????????????????????????????????? 37. //当一个文件要求多个MFT文件记录时 会有该属性 38. //属性列表,包括构成该文件的这些属性,以及每个属性所在的MFT文件记录的文件引用 39. //????????????????????????????????? 40. AttributeAttributeList = 0x20,//由于属性值可能会增长,可能是非驻留属性 41. 42. //文件名属性可以有多个: 43. //1.长文件名自动为其短文件名(以便MS-DOS和16位程序访问) 44. //2.当该文件存在硬链接时 45. AttributeFileName = 0x30, //常驻 46. 47. //一个文件或目录的64字节标识符,其中低16字节对于该卷来说是唯一的 48. //链接-跟踪服务将对象ID分配给外壳快捷方式和OLE链接源文件。 49. //NTFS提供了相应的API,因为文件和目录可以通过其对象ID,而不是通过其文件名打开 50. AttributeObjectId = 0x40, //常驻 51. 52. //为与NTFS以前版本保持向后兼容 53. //所有具有相同安全描述符的文件或目录共享同样的安全描述 54. //以前版本的NTFS将私有的安全描述符信息与每个文件和目录存储在一起 55. AttributeSecurityDescriptor = 0x50,//出现于$Secure元数据文件中 56. 57. //保存了该卷的版本和label信息 58. AttributeVolumeName = 0x60, //仅出现于$Volume元数据文件中 59. AttributeVolumeInformation = 0x70,//仅出现于$Volume元数据文件中 60. 61. //文件内容,一个文件仅有一个未命名的数据属性,但可有额外多个命名数据属性 62. //即一个文件可以有多个数据流,目录没有默认的数据属性,但可有多个可选的命名的数据属性 63. AttributeData = 0x80,//由于属性值可能会增长,可能是非驻留属性 64. 65. //以下三个用于实现大目录的文件名分配和位图索引 66. AttributeIndexRoot = 0x90,//常驻 67. AttributeIndexAllocation = 0xA0, 68. AttributeBitmap = 0xB0, 69. 70. //存储了一个文件的重解析点数据,NTFS的交接(junction)和挂载点包含此属性 71. AttributeReparsePoint = 0xC0, 72. 73. //以下两个为扩展属性,现已不再被主动使用,之所以提供是为与OS/2程序保持向后兼容 74. AttributeEAInformation = 0xD0, 75. AttributeEA = 0xE0, 76. 77. AttributePropertySet = 0xF0, 78. AttributeLoggedUtilityStream = 0x100, 79. AttributeEnd=0xFFFFFFFF 80.} ATTRIBUTE_TYPE, *PATTRIBUTE_TYPE; 81. 82.typedef struct { 83. ATTRIBUTE_TYPE AttributeType; 84. ULONG Length; //本属性长度(包含属性值) 85. BOOLEAN Nonresident; //本属性不是 驻留 属性么? 86. UCHAR NameLength; //属性名的名称长度 87. USHORT NameOffset;//属性名偏移 88. USHORT Flags; // 0x0001 压缩 0x4000 加密 0x8000稀疏文件 89. USHORT AttributeNumber; 90.} ATTRIBUTE, *PATTRIBUTE; 91. 92.typedef struct { 93. ATTRIBUTE Attribute; 94. ULONG ValueLength; //属性值长度 95. USHORT ValueOffset; //属性值偏移 96. USHORT Flags; // 索引标志 0x0001 = Indexed 97.} RESIDENT_ATTRIBUTE, *PRESIDENT_ATTRIBUTE; 98. 99.typedef struct { 100. ATTRIBUTE Attribute; 101. ULONGLONG LowVcn; 102. ULONGLONG HighVcn; 103. USHORT RunArrayOffset; 104. UCHAR CompressionUnit; 105. UCHAR AlignmentOrReserved[5]; 106. ULONGLONG AllocatedSize; 107. ULONGLONG DataSize; 108. ULONGLONG InitializedSize; 109. ULONGLONG CompressedSize; // Only when compressed 110.} NONRESIDENT_ATTRIBUTE, *PNONRESIDENT_ATTRIBUTE; 111. 112.typedef struct { //文件名属性的值区域 113. ULONGLONG DirectoryFileReferenceNumber; //父目录的FRN 114. ULONGLONG CreationTime; 115. ULONGLONG ChangeTime; 116. ULONGLONG LastWriteTime; // 最后一次MFT更新时间 117. ULONGLONG LastAccessTime; 118. ULONGLONG AllocatedSize; // 未明 119. ULONGLONG DataSize; // 偶尔与文件大小GetFileSize不同 120. ULONG FileAttributes; 121. ULONG AlignmentOrReserved; 122. UCHAR NameLength; 123. UCHAR NameType; //POSIX 0x0 WIN32 0x01 DOS 0x02 WIN32&DOS 0x3 124. WCHAR Name[1]; 125.} FILENAME_ATTRIBUTE, *PFILENAME_ATTRIBUTE; 126. 127.typedef struct { 128. ATTRIBUTE_TYPE AttributeType; //属性类型 129. USHORT Length; //本记录长度 130. UCHAR NameLength; //属性名长度 131. UCHAR NameOffset; //属性名偏移 132. ULONGLONG LowVcn; //起始VCN 133. ULONGLONG FileReferenceNumber; //属性的文件参考号 134. USHORT AttributeNumber; //标识 135. WCHAR Name[1]; 136.} ATTRIBUTE_LIST, *PATTRIBUTE_LIST; 137. 138.#pragma pack(push,1) 139.typedef struct { //512B 140. UCHAR Jump[3];//跳过3个字节 141. UCHAR Format[8]; //‘N’'T' 'F' 'S' 0x20 0x20 0x20 0x20 142. USHORT BytesPerSector;//每扇区有多少字节 一般为512B 0x200 143. UCHAR SectorsPerCluster;//每簇有多少个扇区 144. USHORT BootSectors;// 145. UCHAR Mbz1;//保留0 146. USHORT Mbz2;//保留0 147. USHORT Reserved1;//保留0 148. UCHAR MediaType;//介质描述符,硬盘为0xf8 149. USHORT Mbz3;//总为0 150. USHORT SectorsPerTrack;//每道扇区数,一般为0x3f 151. USHORT NumberOfHeads;//磁头数 152. ULONG PartitionOffset;//该分区的便宜(即该分区前的隐含扇区数 一般为磁道扇区数0x3f 63) 153. ULONG Reserved2[2]; 154. ULONGLONG TotalSectors;//该分区总扇区数 155. ULONGLONG MftStartLcn;//MFT表的起始簇号LCN 156. ULONGLONG Mft2StartLcn;//MFT备份表的起始簇号LCN 157. ULONG ClustersPerFileRecord;//每个MFT记录包含几个簇 记录的字节不一定为:ClustersPerFileRecord*SectorsPerCluster*BytesPerSector 158. ULONG ClustersPerIndexBlock;//每个索引块的簇数 159. ULONGLONG VolumeSerialNumber;//卷序列号 160. UCHAR Code[0x1AE]; 161. USHORT BootSignature; 162.} BOOT_BLOCK, *PBOOT_BLOCK; 163.#pragma pack(pop)