1*f6dc9357SAndroid Build Coastguard Worker // NtfsHandler.cpp
2*f6dc9357SAndroid Build Coastguard Worker
3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
4*f6dc9357SAndroid Build Coastguard Worker
5*f6dc9357SAndroid Build Coastguard Worker // #define SHOW_DEBUG_INFO
6*f6dc9357SAndroid Build Coastguard Worker // #define SHOW_DEBUG_INFO2
7*f6dc9357SAndroid Build Coastguard Worker
8*f6dc9357SAndroid Build Coastguard Worker #if defined(SHOW_DEBUG_INFO) || defined(SHOW_DEBUG_INFO2)
9*f6dc9357SAndroid Build Coastguard Worker #include <stdio.h>
10*f6dc9357SAndroid Build Coastguard Worker #endif
11*f6dc9357SAndroid Build Coastguard Worker
12*f6dc9357SAndroid Build Coastguard Worker #include "../../../C/CpuArch.h"
13*f6dc9357SAndroid Build Coastguard Worker
14*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/ComTry.h"
15*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/IntToString.h"
16*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/MyBuffer.h"
17*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/MyCom.h"
18*f6dc9357SAndroid Build Coastguard Worker
19*f6dc9357SAndroid Build Coastguard Worker #include "../../Windows/PropVariant.h"
20*f6dc9357SAndroid Build Coastguard Worker #include "../../Windows/TimeUtils.h"
21*f6dc9357SAndroid Build Coastguard Worker
22*f6dc9357SAndroid Build Coastguard Worker #include "../Common/MethodProps.h"
23*f6dc9357SAndroid Build Coastguard Worker #include "../Common/ProgressUtils.h"
24*f6dc9357SAndroid Build Coastguard Worker #include "../Common/RegisterArc.h"
25*f6dc9357SAndroid Build Coastguard Worker #include "../Common/StreamObjects.h"
26*f6dc9357SAndroid Build Coastguard Worker #include "../Common/StreamUtils.h"
27*f6dc9357SAndroid Build Coastguard Worker
28*f6dc9357SAndroid Build Coastguard Worker #include "../Compress/CopyCoder.h"
29*f6dc9357SAndroid Build Coastguard Worker
30*f6dc9357SAndroid Build Coastguard Worker #include "Common/DummyOutStream.h"
31*f6dc9357SAndroid Build Coastguard Worker
32*f6dc9357SAndroid Build Coastguard Worker #ifdef SHOW_DEBUG_INFO
33*f6dc9357SAndroid Build Coastguard Worker #define PRF(x) x
34*f6dc9357SAndroid Build Coastguard Worker #define PRF_UTF16(x) PRF(printf("%S", x))
35*f6dc9357SAndroid Build Coastguard Worker #else
36*f6dc9357SAndroid Build Coastguard Worker #define PRF(x)
37*f6dc9357SAndroid Build Coastguard Worker #define PRF_UTF16(x)
38*f6dc9357SAndroid Build Coastguard Worker #endif
39*f6dc9357SAndroid Build Coastguard Worker
40*f6dc9357SAndroid Build Coastguard Worker #ifdef SHOW_DEBUG_INFO2
41*f6dc9357SAndroid Build Coastguard Worker #define PRF2(x) x
42*f6dc9357SAndroid Build Coastguard Worker #else
43*f6dc9357SAndroid Build Coastguard Worker #define PRF2(x)
44*f6dc9357SAndroid Build Coastguard Worker #endif
45*f6dc9357SAndroid Build Coastguard Worker
46*f6dc9357SAndroid Build Coastguard Worker #define Get16(p) GetUi16(p)
47*f6dc9357SAndroid Build Coastguard Worker #define Get32(p) GetUi32(p)
48*f6dc9357SAndroid Build Coastguard Worker #define Get64(p) GetUi64(p)
49*f6dc9357SAndroid Build Coastguard Worker
50*f6dc9357SAndroid Build Coastguard Worker #define G16(p, dest) dest = Get16(p)
51*f6dc9357SAndroid Build Coastguard Worker #define G32(p, dest) dest = Get32(p)
52*f6dc9357SAndroid Build Coastguard Worker #define G64(p, dest) dest = Get64(p)
53*f6dc9357SAndroid Build Coastguard Worker
54*f6dc9357SAndroid Build Coastguard Worker using namespace NWindows;
55*f6dc9357SAndroid Build Coastguard Worker
56*f6dc9357SAndroid Build Coastguard Worker namespace NArchive {
57*f6dc9357SAndroid Build Coastguard Worker namespace Ntfs {
58*f6dc9357SAndroid Build Coastguard Worker
59*f6dc9357SAndroid Build Coastguard Worker static const wchar_t * const kVirtualFolder_System = L"[SYSTEM]";
60*f6dc9357SAndroid Build Coastguard Worker static const wchar_t * const kVirtualFolder_Lost_Normal = L"[LOST]";
61*f6dc9357SAndroid Build Coastguard Worker static const wchar_t * const kVirtualFolder_Lost_Deleted = L"[UNKNOWN]";
62*f6dc9357SAndroid Build Coastguard Worker
63*f6dc9357SAndroid Build Coastguard Worker static const unsigned kNumSysRecs = 16;
64*f6dc9357SAndroid Build Coastguard Worker
65*f6dc9357SAndroid Build Coastguard Worker static const unsigned kRecIndex_Volume = 3;
66*f6dc9357SAndroid Build Coastguard Worker static const unsigned kRecIndex_RootDir = 5;
67*f6dc9357SAndroid Build Coastguard Worker static const unsigned kRecIndex_BadClus = 8;
68*f6dc9357SAndroid Build Coastguard Worker static const unsigned kRecIndex_Security = 9;
69*f6dc9357SAndroid Build Coastguard Worker
70*f6dc9357SAndroid Build Coastguard Worker struct CHeader
71*f6dc9357SAndroid Build Coastguard Worker {
72*f6dc9357SAndroid Build Coastguard Worker unsigned SectorSizeLog;
73*f6dc9357SAndroid Build Coastguard Worker unsigned ClusterSizeLog;
74*f6dc9357SAndroid Build Coastguard Worker unsigned MftRecordSizeLog;
75*f6dc9357SAndroid Build Coastguard Worker // Byte MediaType;
76*f6dc9357SAndroid Build Coastguard Worker // UInt32 NumHiddenSectors;
77*f6dc9357SAndroid Build Coastguard Worker UInt64 NumSectors;
78*f6dc9357SAndroid Build Coastguard Worker UInt64 NumClusters;
79*f6dc9357SAndroid Build Coastguard Worker UInt64 MftCluster;
80*f6dc9357SAndroid Build Coastguard Worker UInt64 SerialNumber;
81*f6dc9357SAndroid Build Coastguard Worker // UInt16 SectorsPerTrack;
82*f6dc9357SAndroid Build Coastguard Worker // UInt16 NumHeads;
83*f6dc9357SAndroid Build Coastguard Worker
GetPhySize_ClustersNArchive::Ntfs::CHeader84*f6dc9357SAndroid Build Coastguard Worker UInt64 GetPhySize_Clusters() const { return NumClusters << ClusterSizeLog; }
GetPhySize_MaxNArchive::Ntfs::CHeader85*f6dc9357SAndroid Build Coastguard Worker UInt64 GetPhySize_Max() const { return (NumSectors + 1) << SectorSizeLog; }
ClusterSizeNArchive::Ntfs::CHeader86*f6dc9357SAndroid Build Coastguard Worker UInt32 ClusterSize() const { return (UInt32)1 << ClusterSizeLog; }
87*f6dc9357SAndroid Build Coastguard Worker bool Parse(const Byte *p);
88*f6dc9357SAndroid Build Coastguard Worker };
89*f6dc9357SAndroid Build Coastguard Worker
GetLog(UInt32 num)90*f6dc9357SAndroid Build Coastguard Worker static int GetLog(UInt32 num)
91*f6dc9357SAndroid Build Coastguard Worker {
92*f6dc9357SAndroid Build Coastguard Worker for (int i = 0; i < 31; i++)
93*f6dc9357SAndroid Build Coastguard Worker if (((UInt32)1 << i) == num)
94*f6dc9357SAndroid Build Coastguard Worker return i;
95*f6dc9357SAndroid Build Coastguard Worker return -1;
96*f6dc9357SAndroid Build Coastguard Worker }
97*f6dc9357SAndroid Build Coastguard Worker
Parse(const Byte * p)98*f6dc9357SAndroid Build Coastguard Worker bool CHeader::Parse(const Byte *p)
99*f6dc9357SAndroid Build Coastguard Worker {
100*f6dc9357SAndroid Build Coastguard Worker if (p[0x1FE] != 0x55 || p[0x1FF] != 0xAA)
101*f6dc9357SAndroid Build Coastguard Worker return false;
102*f6dc9357SAndroid Build Coastguard Worker
103*f6dc9357SAndroid Build Coastguard Worker // int codeOffset = 0;
104*f6dc9357SAndroid Build Coastguard Worker switch (p[0])
105*f6dc9357SAndroid Build Coastguard Worker {
106*f6dc9357SAndroid Build Coastguard Worker case 0xE9: /* codeOffset = 3 + (Int16)Get16(p + 1); */ break;
107*f6dc9357SAndroid Build Coastguard Worker case 0xEB: if (p[2] != 0x90) return false; /* codeOffset = 2 + (int)(signed char)p[1]; */ break;
108*f6dc9357SAndroid Build Coastguard Worker default: return false;
109*f6dc9357SAndroid Build Coastguard Worker }
110*f6dc9357SAndroid Build Coastguard Worker unsigned sectorsPerClusterLog;
111*f6dc9357SAndroid Build Coastguard Worker
112*f6dc9357SAndroid Build Coastguard Worker if (memcmp(p + 3, "NTFS ", 8) != 0)
113*f6dc9357SAndroid Build Coastguard Worker return false;
114*f6dc9357SAndroid Build Coastguard Worker {
115*f6dc9357SAndroid Build Coastguard Worker {
116*f6dc9357SAndroid Build Coastguard Worker const int t = GetLog(Get16(p + 11));
117*f6dc9357SAndroid Build Coastguard Worker if (t < 9 || t > 12)
118*f6dc9357SAndroid Build Coastguard Worker return false;
119*f6dc9357SAndroid Build Coastguard Worker SectorSizeLog = (unsigned)t;
120*f6dc9357SAndroid Build Coastguard Worker }
121*f6dc9357SAndroid Build Coastguard Worker {
122*f6dc9357SAndroid Build Coastguard Worker const unsigned v = p[13];
123*f6dc9357SAndroid Build Coastguard Worker if (v <= 0x80)
124*f6dc9357SAndroid Build Coastguard Worker {
125*f6dc9357SAndroid Build Coastguard Worker const int t = GetLog(v);
126*f6dc9357SAndroid Build Coastguard Worker if (t < 0)
127*f6dc9357SAndroid Build Coastguard Worker return false;
128*f6dc9357SAndroid Build Coastguard Worker sectorsPerClusterLog = (unsigned)t;
129*f6dc9357SAndroid Build Coastguard Worker }
130*f6dc9357SAndroid Build Coastguard Worker else
131*f6dc9357SAndroid Build Coastguard Worker sectorsPerClusterLog = 0x100 - v;
132*f6dc9357SAndroid Build Coastguard Worker ClusterSizeLog = SectorSizeLog + sectorsPerClusterLog;
133*f6dc9357SAndroid Build Coastguard Worker if (ClusterSizeLog > 30)
134*f6dc9357SAndroid Build Coastguard Worker return false;
135*f6dc9357SAndroid Build Coastguard Worker }
136*f6dc9357SAndroid Build Coastguard Worker }
137*f6dc9357SAndroid Build Coastguard Worker
138*f6dc9357SAndroid Build Coastguard Worker for (int i = 14; i < 21; i++)
139*f6dc9357SAndroid Build Coastguard Worker if (p[i] != 0)
140*f6dc9357SAndroid Build Coastguard Worker return false;
141*f6dc9357SAndroid Build Coastguard Worker
142*f6dc9357SAndroid Build Coastguard Worker // F8 : a hard disk
143*f6dc9357SAndroid Build Coastguard Worker // F0 : high-density 3.5-inch floppy disk
144*f6dc9357SAndroid Build Coastguard Worker if (p[21] != 0xF8) // MediaType = Fixed_Disk
145*f6dc9357SAndroid Build Coastguard Worker return false;
146*f6dc9357SAndroid Build Coastguard Worker if (Get16(p + 22) != 0) // NumFatSectors
147*f6dc9357SAndroid Build Coastguard Worker return false;
148*f6dc9357SAndroid Build Coastguard Worker // G16(p + 24, SectorsPerTrack); // 63 usually
149*f6dc9357SAndroid Build Coastguard Worker // G16(p + 26, NumHeads); // 255
150*f6dc9357SAndroid Build Coastguard Worker // G32(p + 28, NumHiddenSectors); // 63 (XP) / 2048 (Vista and win7) / (0 on media that are not partitioned ?)
151*f6dc9357SAndroid Build Coastguard Worker if (Get32(p + 32) != 0) // NumSectors32
152*f6dc9357SAndroid Build Coastguard Worker return false;
153*f6dc9357SAndroid Build Coastguard Worker
154*f6dc9357SAndroid Build Coastguard Worker // DriveNumber = p[0x24];
155*f6dc9357SAndroid Build Coastguard Worker if (p[0x25] != 0) // CurrentHead
156*f6dc9357SAndroid Build Coastguard Worker return false;
157*f6dc9357SAndroid Build Coastguard Worker /*
158*f6dc9357SAndroid Build Coastguard Worker NTFS-HDD: p[0x26] = 0x80
159*f6dc9357SAndroid Build Coastguard Worker NTFS-FLASH: p[0x26] = 0
160*f6dc9357SAndroid Build Coastguard Worker */
161*f6dc9357SAndroid Build Coastguard Worker if (p[0x26] != 0x80 && p[0x26] != 0) // ExtendedBootSig
162*f6dc9357SAndroid Build Coastguard Worker return false;
163*f6dc9357SAndroid Build Coastguard Worker if (p[0x27] != 0) // reserved
164*f6dc9357SAndroid Build Coastguard Worker return false;
165*f6dc9357SAndroid Build Coastguard Worker
166*f6dc9357SAndroid Build Coastguard Worker NumSectors = Get64(p + 0x28);
167*f6dc9357SAndroid Build Coastguard Worker if (NumSectors >= ((UInt64)1 << (62 - SectorSizeLog)))
168*f6dc9357SAndroid Build Coastguard Worker return false;
169*f6dc9357SAndroid Build Coastguard Worker
170*f6dc9357SAndroid Build Coastguard Worker NumClusters = NumSectors >> sectorsPerClusterLog;
171*f6dc9357SAndroid Build Coastguard Worker
172*f6dc9357SAndroid Build Coastguard Worker G64(p + 0x30, MftCluster); // $MFT.
173*f6dc9357SAndroid Build Coastguard Worker // G64(p + 0x38, Mft2Cluster);
174*f6dc9357SAndroid Build Coastguard Worker G64(p + 0x48, SerialNumber); // $MFTMirr
175*f6dc9357SAndroid Build Coastguard Worker
176*f6dc9357SAndroid Build Coastguard Worker /*
177*f6dc9357SAndroid Build Coastguard Worker numClusters_per_MftRecord:
178*f6dc9357SAndroid Build Coastguard Worker numClusters_per_IndexBlock:
179*f6dc9357SAndroid Build Coastguard Worker only low byte from 4 bytes is used. Another 3 high bytes are zeros.
180*f6dc9357SAndroid Build Coastguard Worker If the number is positive (number < 0x80),
181*f6dc9357SAndroid Build Coastguard Worker then it represents the number of clusters.
182*f6dc9357SAndroid Build Coastguard Worker If the number is negative (number >= 0x80),
183*f6dc9357SAndroid Build Coastguard Worker then the size of the file record is 2 raised to the absolute value of this number.
184*f6dc9357SAndroid Build Coastguard Worker example: (0xF6 == -10) means 2^10 = 1024 bytes.
185*f6dc9357SAndroid Build Coastguard Worker */
186*f6dc9357SAndroid Build Coastguard Worker {
187*f6dc9357SAndroid Build Coastguard Worker UInt32 numClusters_per_MftRecord;
188*f6dc9357SAndroid Build Coastguard Worker G32(p + 0x40, numClusters_per_MftRecord);
189*f6dc9357SAndroid Build Coastguard Worker if (numClusters_per_MftRecord >= 0x100 || numClusters_per_MftRecord == 0)
190*f6dc9357SAndroid Build Coastguard Worker return false;
191*f6dc9357SAndroid Build Coastguard Worker if (numClusters_per_MftRecord < 0x80)
192*f6dc9357SAndroid Build Coastguard Worker {
193*f6dc9357SAndroid Build Coastguard Worker const int t = GetLog(numClusters_per_MftRecord);
194*f6dc9357SAndroid Build Coastguard Worker if (t < 0)
195*f6dc9357SAndroid Build Coastguard Worker return false;
196*f6dc9357SAndroid Build Coastguard Worker MftRecordSizeLog = (unsigned)t + ClusterSizeLog;
197*f6dc9357SAndroid Build Coastguard Worker }
198*f6dc9357SAndroid Build Coastguard Worker else
199*f6dc9357SAndroid Build Coastguard Worker MftRecordSizeLog = 0x100 - numClusters_per_MftRecord;
200*f6dc9357SAndroid Build Coastguard Worker // what exact MFT record sizes are possible and supported by Windows?
201*f6dc9357SAndroid Build Coastguard Worker // do we need to change this limit here?
202*f6dc9357SAndroid Build Coastguard Worker const unsigned k_MftRecordSizeLog_MAX = 12;
203*f6dc9357SAndroid Build Coastguard Worker if (MftRecordSizeLog > k_MftRecordSizeLog_MAX)
204*f6dc9357SAndroid Build Coastguard Worker return false;
205*f6dc9357SAndroid Build Coastguard Worker if (MftRecordSizeLog < SectorSizeLog)
206*f6dc9357SAndroid Build Coastguard Worker return false;
207*f6dc9357SAndroid Build Coastguard Worker }
208*f6dc9357SAndroid Build Coastguard Worker {
209*f6dc9357SAndroid Build Coastguard Worker UInt32 numClusters_per_IndexBlock;
210*f6dc9357SAndroid Build Coastguard Worker G32(p + 0x44, numClusters_per_IndexBlock);
211*f6dc9357SAndroid Build Coastguard Worker return (numClusters_per_IndexBlock < 0x100);
212*f6dc9357SAndroid Build Coastguard Worker }
213*f6dc9357SAndroid Build Coastguard Worker }
214*f6dc9357SAndroid Build Coastguard Worker
215*f6dc9357SAndroid Build Coastguard Worker struct CMftRef
216*f6dc9357SAndroid Build Coastguard Worker {
217*f6dc9357SAndroid Build Coastguard Worker UInt64 Val;
218*f6dc9357SAndroid Build Coastguard Worker
GetIndexNArchive::Ntfs::CMftRef219*f6dc9357SAndroid Build Coastguard Worker UInt64 GetIndex() const { return Val & (((UInt64)1 << 48) - 1); }
GetNumberNArchive::Ntfs::CMftRef220*f6dc9357SAndroid Build Coastguard Worker UInt16 GetNumber() const { return (UInt16)(Val >> 48); }
IsBaseItselfNArchive::Ntfs::CMftRef221*f6dc9357SAndroid Build Coastguard Worker bool IsBaseItself() const { return Val == 0; }
222*f6dc9357SAndroid Build Coastguard Worker
CMftRefNArchive::Ntfs::CMftRef223*f6dc9357SAndroid Build Coastguard Worker CMftRef(): Val(0) {}
224*f6dc9357SAndroid Build Coastguard Worker };
225*f6dc9357SAndroid Build Coastguard Worker
226*f6dc9357SAndroid Build Coastguard Worker #define ATNAME(n) ATTR_TYPE_ ## n
227*f6dc9357SAndroid Build Coastguard Worker #define DEF_ATTR_TYPE(v, n) ATNAME(n) = v
228*f6dc9357SAndroid Build Coastguard Worker
229*f6dc9357SAndroid Build Coastguard Worker enum
230*f6dc9357SAndroid Build Coastguard Worker {
231*f6dc9357SAndroid Build Coastguard Worker DEF_ATTR_TYPE(0x00, UNUSED),
232*f6dc9357SAndroid Build Coastguard Worker DEF_ATTR_TYPE(0x10, STANDARD_INFO),
233*f6dc9357SAndroid Build Coastguard Worker DEF_ATTR_TYPE(0x20, ATTRIBUTE_LIST),
234*f6dc9357SAndroid Build Coastguard Worker DEF_ATTR_TYPE(0x30, FILE_NAME),
235*f6dc9357SAndroid Build Coastguard Worker DEF_ATTR_TYPE(0x40, OBJECT_ID),
236*f6dc9357SAndroid Build Coastguard Worker DEF_ATTR_TYPE(0x50, SECURITY_DESCRIPTOR),
237*f6dc9357SAndroid Build Coastguard Worker DEF_ATTR_TYPE(0x60, VOLUME_NAME),
238*f6dc9357SAndroid Build Coastguard Worker DEF_ATTR_TYPE(0x70, VOLUME_INFO),
239*f6dc9357SAndroid Build Coastguard Worker DEF_ATTR_TYPE(0x80, DATA),
240*f6dc9357SAndroid Build Coastguard Worker DEF_ATTR_TYPE(0x90, INDEX_ROOT),
241*f6dc9357SAndroid Build Coastguard Worker DEF_ATTR_TYPE(0xA0, INDEX_ALLOCATION),
242*f6dc9357SAndroid Build Coastguard Worker DEF_ATTR_TYPE(0xB0, BITMAP),
243*f6dc9357SAndroid Build Coastguard Worker DEF_ATTR_TYPE(0xC0, REPARSE_POINT),
244*f6dc9357SAndroid Build Coastguard Worker DEF_ATTR_TYPE(0xD0, EA_INFO),
245*f6dc9357SAndroid Build Coastguard Worker DEF_ATTR_TYPE(0xE0, EA),
246*f6dc9357SAndroid Build Coastguard Worker DEF_ATTR_TYPE(0xF0, PROPERTY_SET),
247*f6dc9357SAndroid Build Coastguard Worker DEF_ATTR_TYPE(0x100, LOGGED_UTILITY_STREAM),
248*f6dc9357SAndroid Build Coastguard Worker DEF_ATTR_TYPE(0x1000, FIRST_USER_DEFINED_ATTRIBUTE)
249*f6dc9357SAndroid Build Coastguard Worker };
250*f6dc9357SAndroid Build Coastguard Worker
251*f6dc9357SAndroid Build Coastguard Worker
252*f6dc9357SAndroid Build Coastguard Worker /* WinXP-64:
253*f6dc9357SAndroid Build Coastguard Worker Probably only one short name (dos name) per record is allowed.
254*f6dc9357SAndroid Build Coastguard Worker There are no short names for hard links.
255*f6dc9357SAndroid Build Coastguard Worker The pair (Win32,Dos) can be in any order.
256*f6dc9357SAndroid Build Coastguard Worker Posix name can be after or before Win32 name
257*f6dc9357SAndroid Build Coastguard Worker */
258*f6dc9357SAndroid Build Coastguard Worker
259*f6dc9357SAndroid Build Coastguard Worker // static const Byte kFileNameType_Posix = 0; // for hard links
260*f6dc9357SAndroid Build Coastguard Worker static const Byte kFileNameType_Win32 = 1; // after Dos name
261*f6dc9357SAndroid Build Coastguard Worker static const Byte kFileNameType_Dos = 2; // short name
262*f6dc9357SAndroid Build Coastguard Worker static const Byte kFileNameType_Win32Dos = 3; // short and full name are same
263*f6dc9357SAndroid Build Coastguard Worker
264*f6dc9357SAndroid Build Coastguard Worker struct CFileNameAttr
265*f6dc9357SAndroid Build Coastguard Worker {
266*f6dc9357SAndroid Build Coastguard Worker CMftRef ParentDirRef;
267*f6dc9357SAndroid Build Coastguard Worker
268*f6dc9357SAndroid Build Coastguard Worker // Probably these timestamps don't contain some useful timestamps. So we don't use them
269*f6dc9357SAndroid Build Coastguard Worker // UInt64 CTime;
270*f6dc9357SAndroid Build Coastguard Worker // UInt64 MTime;
271*f6dc9357SAndroid Build Coastguard Worker // UInt64 ThisRecMTime; // xp-64: the time of previous name change (not last name change. why?)
272*f6dc9357SAndroid Build Coastguard Worker // UInt64 ATime;
273*f6dc9357SAndroid Build Coastguard Worker // UInt64 AllocatedSize;
274*f6dc9357SAndroid Build Coastguard Worker // UInt64 DataSize;
275*f6dc9357SAndroid Build Coastguard Worker // UInt16 PackedEaSize;
276*f6dc9357SAndroid Build Coastguard Worker UString2 Name;
277*f6dc9357SAndroid Build Coastguard Worker UInt32 Attrib;
278*f6dc9357SAndroid Build Coastguard Worker Byte NameType;
279*f6dc9357SAndroid Build Coastguard Worker
IsDosNArchive::Ntfs::CFileNameAttr280*f6dc9357SAndroid Build Coastguard Worker bool IsDos() const { return NameType == kFileNameType_Dos; }
IsWin32NArchive::Ntfs::CFileNameAttr281*f6dc9357SAndroid Build Coastguard Worker bool IsWin32() const { return (NameType == kFileNameType_Win32); }
282*f6dc9357SAndroid Build Coastguard Worker
283*f6dc9357SAndroid Build Coastguard Worker bool Parse(const Byte *p, unsigned size);
284*f6dc9357SAndroid Build Coastguard Worker
CFileNameAttrNArchive::Ntfs::CFileNameAttr285*f6dc9357SAndroid Build Coastguard Worker CFileNameAttr():
286*f6dc9357SAndroid Build Coastguard Worker Attrib(0),
287*f6dc9357SAndroid Build Coastguard Worker NameType(0)
288*f6dc9357SAndroid Build Coastguard Worker {}
289*f6dc9357SAndroid Build Coastguard Worker };
290*f6dc9357SAndroid Build Coastguard Worker
GetString(const Byte * p,const unsigned len,UString2 & res)291*f6dc9357SAndroid Build Coastguard Worker static void GetString(const Byte *p, const unsigned len, UString2 &res)
292*f6dc9357SAndroid Build Coastguard Worker {
293*f6dc9357SAndroid Build Coastguard Worker if (len == 0 && res.IsEmpty())
294*f6dc9357SAndroid Build Coastguard Worker return;
295*f6dc9357SAndroid Build Coastguard Worker wchar_t *s = res.GetBuf(len);
296*f6dc9357SAndroid Build Coastguard Worker unsigned i;
297*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < len; i++)
298*f6dc9357SAndroid Build Coastguard Worker {
299*f6dc9357SAndroid Build Coastguard Worker const wchar_t c = Get16(p + i * 2);
300*f6dc9357SAndroid Build Coastguard Worker if (c == 0)
301*f6dc9357SAndroid Build Coastguard Worker break;
302*f6dc9357SAndroid Build Coastguard Worker s[i] = c;
303*f6dc9357SAndroid Build Coastguard Worker }
304*f6dc9357SAndroid Build Coastguard Worker s[i] = 0;
305*f6dc9357SAndroid Build Coastguard Worker res.ReleaseBuf_SetLen(i);
306*f6dc9357SAndroid Build Coastguard Worker }
307*f6dc9357SAndroid Build Coastguard Worker
Parse(const Byte * p,unsigned size)308*f6dc9357SAndroid Build Coastguard Worker bool CFileNameAttr::Parse(const Byte *p, unsigned size)
309*f6dc9357SAndroid Build Coastguard Worker {
310*f6dc9357SAndroid Build Coastguard Worker if (size < 0x42)
311*f6dc9357SAndroid Build Coastguard Worker return false;
312*f6dc9357SAndroid Build Coastguard Worker G64(p + 0x00, ParentDirRef.Val);
313*f6dc9357SAndroid Build Coastguard Worker // G64(p + 0x08, CTime);
314*f6dc9357SAndroid Build Coastguard Worker // G64(p + 0x10, MTime);
315*f6dc9357SAndroid Build Coastguard Worker // G64(p + 0x18, ThisRecMTime);
316*f6dc9357SAndroid Build Coastguard Worker // G64(p + 0x20, ATime);
317*f6dc9357SAndroid Build Coastguard Worker // G64(p + 0x28, AllocatedSize);
318*f6dc9357SAndroid Build Coastguard Worker // G64(p + 0x30, DataSize);
319*f6dc9357SAndroid Build Coastguard Worker G32(p + 0x38, Attrib);
320*f6dc9357SAndroid Build Coastguard Worker // G16(p + 0x3C, PackedEaSize);
321*f6dc9357SAndroid Build Coastguard Worker NameType = p[0x41];
322*f6dc9357SAndroid Build Coastguard Worker const unsigned len = p[0x40];
323*f6dc9357SAndroid Build Coastguard Worker if (0x42 + len * 2 > size)
324*f6dc9357SAndroid Build Coastguard Worker return false;
325*f6dc9357SAndroid Build Coastguard Worker if (len != 0)
326*f6dc9357SAndroid Build Coastguard Worker GetString(p + 0x42, len, Name);
327*f6dc9357SAndroid Build Coastguard Worker return true;
328*f6dc9357SAndroid Build Coastguard Worker }
329*f6dc9357SAndroid Build Coastguard Worker
330*f6dc9357SAndroid Build Coastguard Worker struct CSiAttr
331*f6dc9357SAndroid Build Coastguard Worker {
332*f6dc9357SAndroid Build Coastguard Worker UInt64 CTime;
333*f6dc9357SAndroid Build Coastguard Worker UInt64 MTime;
334*f6dc9357SAndroid Build Coastguard Worker UInt64 ThisRecMTime;
335*f6dc9357SAndroid Build Coastguard Worker UInt64 ATime;
336*f6dc9357SAndroid Build Coastguard Worker UInt32 Attrib;
337*f6dc9357SAndroid Build Coastguard Worker
338*f6dc9357SAndroid Build Coastguard Worker /*
339*f6dc9357SAndroid Build Coastguard Worker UInt32 MaxVersions;
340*f6dc9357SAndroid Build Coastguard Worker UInt32 Version;
341*f6dc9357SAndroid Build Coastguard Worker UInt32 ClassId;
342*f6dc9357SAndroid Build Coastguard Worker UInt32 OwnerId;
343*f6dc9357SAndroid Build Coastguard Worker */
344*f6dc9357SAndroid Build Coastguard Worker UInt32 SecurityId; // SecurityId = 0 is possible ?
345*f6dc9357SAndroid Build Coastguard Worker // UInt64 QuotaCharged;
346*f6dc9357SAndroid Build Coastguard Worker
347*f6dc9357SAndroid Build Coastguard Worker bool Parse(const Byte *p, unsigned size);
348*f6dc9357SAndroid Build Coastguard Worker
CSiAttrNArchive::Ntfs::CSiAttr349*f6dc9357SAndroid Build Coastguard Worker CSiAttr():
350*f6dc9357SAndroid Build Coastguard Worker CTime(0),
351*f6dc9357SAndroid Build Coastguard Worker MTime(0),
352*f6dc9357SAndroid Build Coastguard Worker ThisRecMTime(0),
353*f6dc9357SAndroid Build Coastguard Worker ATime(0),
354*f6dc9357SAndroid Build Coastguard Worker Attrib(0),
355*f6dc9357SAndroid Build Coastguard Worker SecurityId(0)
356*f6dc9357SAndroid Build Coastguard Worker {}
357*f6dc9357SAndroid Build Coastguard Worker };
358*f6dc9357SAndroid Build Coastguard Worker
359*f6dc9357SAndroid Build Coastguard Worker
Parse(const Byte * p,unsigned size)360*f6dc9357SAndroid Build Coastguard Worker bool CSiAttr::Parse(const Byte *p, unsigned size)
361*f6dc9357SAndroid Build Coastguard Worker {
362*f6dc9357SAndroid Build Coastguard Worker if (size < 0x24)
363*f6dc9357SAndroid Build Coastguard Worker return false;
364*f6dc9357SAndroid Build Coastguard Worker G64(p + 0x00, CTime);
365*f6dc9357SAndroid Build Coastguard Worker G64(p + 0x08, MTime);
366*f6dc9357SAndroid Build Coastguard Worker G64(p + 0x10, ThisRecMTime);
367*f6dc9357SAndroid Build Coastguard Worker G64(p + 0x18, ATime);
368*f6dc9357SAndroid Build Coastguard Worker G32(p + 0x20, Attrib);
369*f6dc9357SAndroid Build Coastguard Worker SecurityId = 0;
370*f6dc9357SAndroid Build Coastguard Worker if (size >= 0x38)
371*f6dc9357SAndroid Build Coastguard Worker G32(p + 0x34, SecurityId);
372*f6dc9357SAndroid Build Coastguard Worker return true;
373*f6dc9357SAndroid Build Coastguard Worker }
374*f6dc9357SAndroid Build Coastguard Worker
375*f6dc9357SAndroid Build Coastguard Worker static const UInt64 kEmptyExtent = (UInt64)(Int64)-1;
376*f6dc9357SAndroid Build Coastguard Worker
377*f6dc9357SAndroid Build Coastguard Worker struct CExtent
378*f6dc9357SAndroid Build Coastguard Worker {
379*f6dc9357SAndroid Build Coastguard Worker UInt64 Virt;
380*f6dc9357SAndroid Build Coastguard Worker UInt64 Phy;
381*f6dc9357SAndroid Build Coastguard Worker
IsEmptyNArchive::Ntfs::CExtent382*f6dc9357SAndroid Build Coastguard Worker bool IsEmpty() const { return Phy == kEmptyExtent; }
383*f6dc9357SAndroid Build Coastguard Worker };
384*f6dc9357SAndroid Build Coastguard Worker
385*f6dc9357SAndroid Build Coastguard Worker struct CVolInfo
386*f6dc9357SAndroid Build Coastguard Worker {
387*f6dc9357SAndroid Build Coastguard Worker Byte MajorVer;
388*f6dc9357SAndroid Build Coastguard Worker Byte MinorVer;
389*f6dc9357SAndroid Build Coastguard Worker // UInt16 Flags;
390*f6dc9357SAndroid Build Coastguard Worker
391*f6dc9357SAndroid Build Coastguard Worker bool Parse(const Byte *p, unsigned size);
392*f6dc9357SAndroid Build Coastguard Worker };
393*f6dc9357SAndroid Build Coastguard Worker
Parse(const Byte * p,unsigned size)394*f6dc9357SAndroid Build Coastguard Worker bool CVolInfo::Parse(const Byte *p, unsigned size)
395*f6dc9357SAndroid Build Coastguard Worker {
396*f6dc9357SAndroid Build Coastguard Worker if (size < 12)
397*f6dc9357SAndroid Build Coastguard Worker return false;
398*f6dc9357SAndroid Build Coastguard Worker MajorVer = p[8];
399*f6dc9357SAndroid Build Coastguard Worker MinorVer = p[9];
400*f6dc9357SAndroid Build Coastguard Worker // Flags = Get16(p + 10);
401*f6dc9357SAndroid Build Coastguard Worker return true;
402*f6dc9357SAndroid Build Coastguard Worker }
403*f6dc9357SAndroid Build Coastguard Worker
404*f6dc9357SAndroid Build Coastguard Worker struct CAttr
405*f6dc9357SAndroid Build Coastguard Worker {
406*f6dc9357SAndroid Build Coastguard Worker UInt32 Type;
407*f6dc9357SAndroid Build Coastguard Worker
408*f6dc9357SAndroid Build Coastguard Worker Byte NonResident;
409*f6dc9357SAndroid Build Coastguard Worker
410*f6dc9357SAndroid Build Coastguard Worker // Non-Resident
411*f6dc9357SAndroid Build Coastguard Worker Byte CompressionUnit;
412*f6dc9357SAndroid Build Coastguard Worker
413*f6dc9357SAndroid Build Coastguard Worker // UInt32 Len;
414*f6dc9357SAndroid Build Coastguard Worker UString2 Name;
415*f6dc9357SAndroid Build Coastguard Worker // UInt16 Flags;
416*f6dc9357SAndroid Build Coastguard Worker // UInt16 Instance;
417*f6dc9357SAndroid Build Coastguard Worker CByteBuffer Data;
418*f6dc9357SAndroid Build Coastguard Worker
419*f6dc9357SAndroid Build Coastguard Worker // Non-Resident
420*f6dc9357SAndroid Build Coastguard Worker UInt64 LowVcn;
421*f6dc9357SAndroid Build Coastguard Worker UInt64 HighVcn;
422*f6dc9357SAndroid Build Coastguard Worker UInt64 AllocatedSize;
423*f6dc9357SAndroid Build Coastguard Worker UInt64 Size;
424*f6dc9357SAndroid Build Coastguard Worker UInt64 PackSize;
425*f6dc9357SAndroid Build Coastguard Worker UInt64 InitializedSize;
426*f6dc9357SAndroid Build Coastguard Worker
427*f6dc9357SAndroid Build Coastguard Worker // Resident
428*f6dc9357SAndroid Build Coastguard Worker // UInt16 ResidentFlags;
429*f6dc9357SAndroid Build Coastguard Worker
IsCompressionUnitSupportedNArchive::Ntfs::CAttr430*f6dc9357SAndroid Build Coastguard Worker bool IsCompressionUnitSupported() const { return CompressionUnit == 0 || CompressionUnit == 4; }
431*f6dc9357SAndroid Build Coastguard Worker
432*f6dc9357SAndroid Build Coastguard Worker UInt32 Parse(const Byte *p, unsigned size);
ParseFileNameNArchive::Ntfs::CAttr433*f6dc9357SAndroid Build Coastguard Worker bool ParseFileName(CFileNameAttr &a) const { return a.Parse(Data, (unsigned)Data.Size()); }
ParseSiNArchive::Ntfs::CAttr434*f6dc9357SAndroid Build Coastguard Worker bool ParseSi(CSiAttr &a) const { return a.Parse(Data, (unsigned)Data.Size()); }
ParseVolInfoNArchive::Ntfs::CAttr435*f6dc9357SAndroid Build Coastguard Worker bool ParseVolInfo(CVolInfo &a) const { return a.Parse(Data, (unsigned)Data.Size()); }
436*f6dc9357SAndroid Build Coastguard Worker bool ParseExtents(CRecordVector<CExtent> &extents, UInt64 numClustersMax, unsigned compressionUnit) const;
GetSizeNArchive::Ntfs::CAttr437*f6dc9357SAndroid Build Coastguard Worker UInt64 GetSize() const { return NonResident ? Size : Data.Size(); }
GetPackSizeNArchive::Ntfs::CAttr438*f6dc9357SAndroid Build Coastguard Worker UInt64 GetPackSize() const
439*f6dc9357SAndroid Build Coastguard Worker {
440*f6dc9357SAndroid Build Coastguard Worker if (!NonResident)
441*f6dc9357SAndroid Build Coastguard Worker return Data.Size();
442*f6dc9357SAndroid Build Coastguard Worker if (CompressionUnit != 0)
443*f6dc9357SAndroid Build Coastguard Worker return PackSize;
444*f6dc9357SAndroid Build Coastguard Worker return AllocatedSize;
445*f6dc9357SAndroid Build Coastguard Worker }
446*f6dc9357SAndroid Build Coastguard Worker };
447*f6dc9357SAndroid Build Coastguard Worker
448*f6dc9357SAndroid Build Coastguard Worker #define RINOZ(x) { int _tt_ = (x); if (_tt_ != 0) return _tt_; }
449*f6dc9357SAndroid Build Coastguard Worker
CompareAttr(void * const * elem1,void * const * elem2,void *)450*f6dc9357SAndroid Build Coastguard Worker static int CompareAttr(void *const *elem1, void *const *elem2, void *)
451*f6dc9357SAndroid Build Coastguard Worker {
452*f6dc9357SAndroid Build Coastguard Worker const CAttr &a1 = *(*((const CAttr *const *)elem1));
453*f6dc9357SAndroid Build Coastguard Worker const CAttr &a2 = *(*((const CAttr *const *)elem2));
454*f6dc9357SAndroid Build Coastguard Worker RINOZ(MyCompare(a1.Type, a2.Type))
455*f6dc9357SAndroid Build Coastguard Worker if (a1.Name.IsEmpty())
456*f6dc9357SAndroid Build Coastguard Worker {
457*f6dc9357SAndroid Build Coastguard Worker if (!a2.Name.IsEmpty())
458*f6dc9357SAndroid Build Coastguard Worker return -1;
459*f6dc9357SAndroid Build Coastguard Worker }
460*f6dc9357SAndroid Build Coastguard Worker else if (a2.Name.IsEmpty())
461*f6dc9357SAndroid Build Coastguard Worker return 1;
462*f6dc9357SAndroid Build Coastguard Worker else
463*f6dc9357SAndroid Build Coastguard Worker {
464*f6dc9357SAndroid Build Coastguard Worker RINOZ(a1.Name.Compare(a2.Name.GetRawPtr()))
465*f6dc9357SAndroid Build Coastguard Worker }
466*f6dc9357SAndroid Build Coastguard Worker return MyCompare(a1.LowVcn, a2.LowVcn);
467*f6dc9357SAndroid Build Coastguard Worker }
468*f6dc9357SAndroid Build Coastguard Worker
Parse(const Byte * p,unsigned size)469*f6dc9357SAndroid Build Coastguard Worker UInt32 CAttr::Parse(const Byte *p, unsigned size)
470*f6dc9357SAndroid Build Coastguard Worker {
471*f6dc9357SAndroid Build Coastguard Worker if (size < 4)
472*f6dc9357SAndroid Build Coastguard Worker return 0;
473*f6dc9357SAndroid Build Coastguard Worker G32(p, Type);
474*f6dc9357SAndroid Build Coastguard Worker if (Type == 0xFFFFFFFF)
475*f6dc9357SAndroid Build Coastguard Worker return 8; // required size is 4, but attributes are 8 bytes aligned. So we return 8
476*f6dc9357SAndroid Build Coastguard Worker if (size < 0x18)
477*f6dc9357SAndroid Build Coastguard Worker return 0;
478*f6dc9357SAndroid Build Coastguard Worker
479*f6dc9357SAndroid Build Coastguard Worker PRF(printf(" T=%2X", Type));
480*f6dc9357SAndroid Build Coastguard Worker
481*f6dc9357SAndroid Build Coastguard Worker UInt32 len = Get32(p + 4);
482*f6dc9357SAndroid Build Coastguard Worker PRF(printf(" L=%3d", len));
483*f6dc9357SAndroid Build Coastguard Worker if (len > size)
484*f6dc9357SAndroid Build Coastguard Worker return 0;
485*f6dc9357SAndroid Build Coastguard Worker if ((len & 7) != 0)
486*f6dc9357SAndroid Build Coastguard Worker return 0;
487*f6dc9357SAndroid Build Coastguard Worker NonResident = p[8];
488*f6dc9357SAndroid Build Coastguard Worker {
489*f6dc9357SAndroid Build Coastguard Worker unsigned nameLen = p[9];
490*f6dc9357SAndroid Build Coastguard Worker UInt32 nameOffset = Get16(p + 0x0A);
491*f6dc9357SAndroid Build Coastguard Worker if (nameLen != 0)
492*f6dc9357SAndroid Build Coastguard Worker {
493*f6dc9357SAndroid Build Coastguard Worker if (nameOffset + nameLen * 2 > len)
494*f6dc9357SAndroid Build Coastguard Worker return 0;
495*f6dc9357SAndroid Build Coastguard Worker GetString(p + nameOffset, nameLen, Name);
496*f6dc9357SAndroid Build Coastguard Worker PRF(printf(" N="));
497*f6dc9357SAndroid Build Coastguard Worker PRF_UTF16(Name);
498*f6dc9357SAndroid Build Coastguard Worker }
499*f6dc9357SAndroid Build Coastguard Worker }
500*f6dc9357SAndroid Build Coastguard Worker
501*f6dc9357SAndroid Build Coastguard Worker // G16(p + 0x0C, Flags);
502*f6dc9357SAndroid Build Coastguard Worker // G16(p + 0x0E, Instance);
503*f6dc9357SAndroid Build Coastguard Worker // PRF(printf(" F=%4X", Flags));
504*f6dc9357SAndroid Build Coastguard Worker // PRF(printf(" Inst=%d", Instance));
505*f6dc9357SAndroid Build Coastguard Worker
506*f6dc9357SAndroid Build Coastguard Worker UInt32 dataSize;
507*f6dc9357SAndroid Build Coastguard Worker UInt32 offs;
508*f6dc9357SAndroid Build Coastguard Worker
509*f6dc9357SAndroid Build Coastguard Worker if (NonResident)
510*f6dc9357SAndroid Build Coastguard Worker {
511*f6dc9357SAndroid Build Coastguard Worker if (len < 0x40)
512*f6dc9357SAndroid Build Coastguard Worker return 0;
513*f6dc9357SAndroid Build Coastguard Worker PRF(printf(" NR"));
514*f6dc9357SAndroid Build Coastguard Worker G64(p + 0x10, LowVcn);
515*f6dc9357SAndroid Build Coastguard Worker G64(p + 0x18, HighVcn);
516*f6dc9357SAndroid Build Coastguard Worker G64(p + 0x28, AllocatedSize);
517*f6dc9357SAndroid Build Coastguard Worker G64(p + 0x30, Size);
518*f6dc9357SAndroid Build Coastguard Worker G64(p + 0x38, InitializedSize);
519*f6dc9357SAndroid Build Coastguard Worker G16(p + 0x20, offs);
520*f6dc9357SAndroid Build Coastguard Worker CompressionUnit = p[0x22];
521*f6dc9357SAndroid Build Coastguard Worker
522*f6dc9357SAndroid Build Coastguard Worker PackSize = Size;
523*f6dc9357SAndroid Build Coastguard Worker if (CompressionUnit != 0)
524*f6dc9357SAndroid Build Coastguard Worker {
525*f6dc9357SAndroid Build Coastguard Worker if (len < 0x48)
526*f6dc9357SAndroid Build Coastguard Worker return 0;
527*f6dc9357SAndroid Build Coastguard Worker G64(p + 0x40, PackSize);
528*f6dc9357SAndroid Build Coastguard Worker PRF(printf(" PS=%I64x", PackSize));
529*f6dc9357SAndroid Build Coastguard Worker }
530*f6dc9357SAndroid Build Coastguard Worker
531*f6dc9357SAndroid Build Coastguard Worker // PRF(printf("\n"));
532*f6dc9357SAndroid Build Coastguard Worker PRF(printf(" ASize=%4I64d", AllocatedSize));
533*f6dc9357SAndroid Build Coastguard Worker PRF(printf(" Size=%I64d", Size));
534*f6dc9357SAndroid Build Coastguard Worker PRF(printf(" IS=%I64d", InitializedSize));
535*f6dc9357SAndroid Build Coastguard Worker PRF(printf(" Low=%I64d", LowVcn));
536*f6dc9357SAndroid Build Coastguard Worker PRF(printf(" High=%I64d", HighVcn));
537*f6dc9357SAndroid Build Coastguard Worker PRF(printf(" CU=%d", (unsigned)CompressionUnit));
538*f6dc9357SAndroid Build Coastguard Worker dataSize = len - offs;
539*f6dc9357SAndroid Build Coastguard Worker }
540*f6dc9357SAndroid Build Coastguard Worker else
541*f6dc9357SAndroid Build Coastguard Worker {
542*f6dc9357SAndroid Build Coastguard Worker if (len < 0x18)
543*f6dc9357SAndroid Build Coastguard Worker return 0;
544*f6dc9357SAndroid Build Coastguard Worker G32(p + 0x10, dataSize);
545*f6dc9357SAndroid Build Coastguard Worker G16(p + 0x14, offs);
546*f6dc9357SAndroid Build Coastguard Worker // G16(p + 0x16, ResidentFlags);
547*f6dc9357SAndroid Build Coastguard Worker PRF(printf(" RES"));
548*f6dc9357SAndroid Build Coastguard Worker PRF(printf(" dataSize=%3d", dataSize));
549*f6dc9357SAndroid Build Coastguard Worker // PRF(printf(" ResFlags=%4X", ResidentFlags));
550*f6dc9357SAndroid Build Coastguard Worker }
551*f6dc9357SAndroid Build Coastguard Worker
552*f6dc9357SAndroid Build Coastguard Worker if (offs > len || dataSize > len || len - dataSize < offs)
553*f6dc9357SAndroid Build Coastguard Worker return 0;
554*f6dc9357SAndroid Build Coastguard Worker
555*f6dc9357SAndroid Build Coastguard Worker Data.CopyFrom(p + offs, dataSize);
556*f6dc9357SAndroid Build Coastguard Worker
557*f6dc9357SAndroid Build Coastguard Worker #ifdef SHOW_DEBUG_INFO
558*f6dc9357SAndroid Build Coastguard Worker PRF(printf(" : "));
559*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < Data.Size(); i++)
560*f6dc9357SAndroid Build Coastguard Worker {
561*f6dc9357SAndroid Build Coastguard Worker PRF(printf(" %02X", (unsigned)Data[i]));
562*f6dc9357SAndroid Build Coastguard Worker }
563*f6dc9357SAndroid Build Coastguard Worker #endif
564*f6dc9357SAndroid Build Coastguard Worker
565*f6dc9357SAndroid Build Coastguard Worker return len;
566*f6dc9357SAndroid Build Coastguard Worker }
567*f6dc9357SAndroid Build Coastguard Worker
568*f6dc9357SAndroid Build Coastguard Worker
ParseExtents(CRecordVector<CExtent> & extents,UInt64 numClustersMax,unsigned compressionUnit) const569*f6dc9357SAndroid Build Coastguard Worker bool CAttr::ParseExtents(CRecordVector<CExtent> &extents, UInt64 numClustersMax, unsigned compressionUnit) const
570*f6dc9357SAndroid Build Coastguard Worker {
571*f6dc9357SAndroid Build Coastguard Worker const Byte *p = Data;
572*f6dc9357SAndroid Build Coastguard Worker unsigned size = (unsigned)Data.Size();
573*f6dc9357SAndroid Build Coastguard Worker UInt64 vcn = LowVcn;
574*f6dc9357SAndroid Build Coastguard Worker UInt64 lcn = 0;
575*f6dc9357SAndroid Build Coastguard Worker const UInt64 highVcn1 = HighVcn + 1;
576*f6dc9357SAndroid Build Coastguard Worker
577*f6dc9357SAndroid Build Coastguard Worker if (LowVcn != extents.Back().Virt || highVcn1 > (UInt64)1 << 63)
578*f6dc9357SAndroid Build Coastguard Worker return false;
579*f6dc9357SAndroid Build Coastguard Worker
580*f6dc9357SAndroid Build Coastguard Worker extents.DeleteBack();
581*f6dc9357SAndroid Build Coastguard Worker
582*f6dc9357SAndroid Build Coastguard Worker PRF2(printf("\n# ParseExtents # LowVcn = %4I64X # HighVcn = %4I64X", LowVcn, HighVcn));
583*f6dc9357SAndroid Build Coastguard Worker
584*f6dc9357SAndroid Build Coastguard Worker while (size > 0)
585*f6dc9357SAndroid Build Coastguard Worker {
586*f6dc9357SAndroid Build Coastguard Worker const unsigned b = *p++;
587*f6dc9357SAndroid Build Coastguard Worker size--;
588*f6dc9357SAndroid Build Coastguard Worker if (b == 0)
589*f6dc9357SAndroid Build Coastguard Worker break;
590*f6dc9357SAndroid Build Coastguard Worker unsigned num = b & 0xF;
591*f6dc9357SAndroid Build Coastguard Worker if (num == 0 || num > 8 || num > size)
592*f6dc9357SAndroid Build Coastguard Worker return false;
593*f6dc9357SAndroid Build Coastguard Worker
594*f6dc9357SAndroid Build Coastguard Worker UInt64 vSize = 0;
595*f6dc9357SAndroid Build Coastguard Worker {
596*f6dc9357SAndroid Build Coastguard Worker unsigned i = num;
597*f6dc9357SAndroid Build Coastguard Worker do vSize = (vSize << 8) | p[--i]; while (i);
598*f6dc9357SAndroid Build Coastguard Worker }
599*f6dc9357SAndroid Build Coastguard Worker if (vSize == 0)
600*f6dc9357SAndroid Build Coastguard Worker return false;
601*f6dc9357SAndroid Build Coastguard Worker p += num;
602*f6dc9357SAndroid Build Coastguard Worker size -= num;
603*f6dc9357SAndroid Build Coastguard Worker if ((highVcn1 - vcn) < vSize)
604*f6dc9357SAndroid Build Coastguard Worker return false;
605*f6dc9357SAndroid Build Coastguard Worker
606*f6dc9357SAndroid Build Coastguard Worker CExtent e;
607*f6dc9357SAndroid Build Coastguard Worker e.Virt = vcn;
608*f6dc9357SAndroid Build Coastguard Worker vcn += vSize;
609*f6dc9357SAndroid Build Coastguard Worker
610*f6dc9357SAndroid Build Coastguard Worker num = b >> 4;
611*f6dc9357SAndroid Build Coastguard Worker if (num > 8 || num > size)
612*f6dc9357SAndroid Build Coastguard Worker return false;
613*f6dc9357SAndroid Build Coastguard Worker
614*f6dc9357SAndroid Build Coastguard Worker if (num == 0)
615*f6dc9357SAndroid Build Coastguard Worker {
616*f6dc9357SAndroid Build Coastguard Worker // Sparse
617*f6dc9357SAndroid Build Coastguard Worker
618*f6dc9357SAndroid Build Coastguard Worker /* if Unit is compressed, it can have many Elements for each compressed Unit:
619*f6dc9357SAndroid Build Coastguard Worker and last Element for unit MUST be without LCN.
620*f6dc9357SAndroid Build Coastguard Worker Element 0: numCompressedClusters2, LCN_0
621*f6dc9357SAndroid Build Coastguard Worker Element 1: numCompressedClusters2, LCN_1
622*f6dc9357SAndroid Build Coastguard Worker ...
623*f6dc9357SAndroid Build Coastguard Worker Last Element : (16 - total_clusters_in_previous_elements), no LCN
624*f6dc9357SAndroid Build Coastguard Worker */
625*f6dc9357SAndroid Build Coastguard Worker
626*f6dc9357SAndroid Build Coastguard Worker // sparse is not allowed for (compressionUnit == 0) ? Why ?
627*f6dc9357SAndroid Build Coastguard Worker if (compressionUnit == 0)
628*f6dc9357SAndroid Build Coastguard Worker return false;
629*f6dc9357SAndroid Build Coastguard Worker
630*f6dc9357SAndroid Build Coastguard Worker e.Phy = kEmptyExtent;
631*f6dc9357SAndroid Build Coastguard Worker }
632*f6dc9357SAndroid Build Coastguard Worker else
633*f6dc9357SAndroid Build Coastguard Worker {
634*f6dc9357SAndroid Build Coastguard Worker Int64 v = (signed char)p[num - 1];
635*f6dc9357SAndroid Build Coastguard Worker {
636*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = num - 1; i != 0;)
637*f6dc9357SAndroid Build Coastguard Worker v = (v << 8) | p[--i];
638*f6dc9357SAndroid Build Coastguard Worker }
639*f6dc9357SAndroid Build Coastguard Worker p += num;
640*f6dc9357SAndroid Build Coastguard Worker size -= num;
641*f6dc9357SAndroid Build Coastguard Worker lcn = (UInt64)((Int64)lcn + v);
642*f6dc9357SAndroid Build Coastguard Worker if (lcn > numClustersMax)
643*f6dc9357SAndroid Build Coastguard Worker return false;
644*f6dc9357SAndroid Build Coastguard Worker e.Phy = lcn;
645*f6dc9357SAndroid Build Coastguard Worker }
646*f6dc9357SAndroid Build Coastguard Worker
647*f6dc9357SAndroid Build Coastguard Worker extents.Add(e);
648*f6dc9357SAndroid Build Coastguard Worker }
649*f6dc9357SAndroid Build Coastguard Worker
650*f6dc9357SAndroid Build Coastguard Worker CExtent e;
651*f6dc9357SAndroid Build Coastguard Worker e.Phy = kEmptyExtent;
652*f6dc9357SAndroid Build Coastguard Worker e.Virt = vcn;
653*f6dc9357SAndroid Build Coastguard Worker extents.Add(e);
654*f6dc9357SAndroid Build Coastguard Worker return (highVcn1 == vcn);
655*f6dc9357SAndroid Build Coastguard Worker }
656*f6dc9357SAndroid Build Coastguard Worker
657*f6dc9357SAndroid Build Coastguard Worker
658*f6dc9357SAndroid Build Coastguard Worker static const UInt64 kEmptyTag = (UInt64)(Int64)-1;
659*f6dc9357SAndroid Build Coastguard Worker
660*f6dc9357SAndroid Build Coastguard Worker static const unsigned kNumCacheChunksLog = 1;
661*f6dc9357SAndroid Build Coastguard Worker static const size_t kNumCacheChunks = (size_t)1 << kNumCacheChunksLog;
662*f6dc9357SAndroid Build Coastguard Worker
663*f6dc9357SAndroid Build Coastguard Worker Z7_CLASS_IMP_IInStream(
664*f6dc9357SAndroid Build Coastguard Worker CInStream
665*f6dc9357SAndroid Build Coastguard Worker )
666*f6dc9357SAndroid Build Coastguard Worker UInt64 _virtPos;
667*f6dc9357SAndroid Build Coastguard Worker UInt64 _physPos;
668*f6dc9357SAndroid Build Coastguard Worker UInt64 _curRem;
669*f6dc9357SAndroid Build Coastguard Worker bool _sparseMode;
670*f6dc9357SAndroid Build Coastguard Worker public:
671*f6dc9357SAndroid Build Coastguard Worker bool InUse;
672*f6dc9357SAndroid Build Coastguard Worker private:
673*f6dc9357SAndroid Build Coastguard Worker unsigned _chunkSizeLog;
674*f6dc9357SAndroid Build Coastguard Worker CByteBuffer _inBuf;
675*f6dc9357SAndroid Build Coastguard Worker CByteBuffer _outBuf;
676*f6dc9357SAndroid Build Coastguard Worker public:
677*f6dc9357SAndroid Build Coastguard Worker UInt64 Size;
678*f6dc9357SAndroid Build Coastguard Worker UInt64 InitializedSize;
679*f6dc9357SAndroid Build Coastguard Worker unsigned BlockSizeLog;
680*f6dc9357SAndroid Build Coastguard Worker unsigned CompressionUnit;
681*f6dc9357SAndroid Build Coastguard Worker CRecordVector<CExtent> Extents;
682*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<IInStream> Stream;
683*f6dc9357SAndroid Build Coastguard Worker private:
684*f6dc9357SAndroid Build Coastguard Worker UInt64 _tags[kNumCacheChunks];
685*f6dc9357SAndroid Build Coastguard Worker
686*f6dc9357SAndroid Build Coastguard Worker HRESULT SeekToPhys() { return InStream_SeekSet(Stream, _physPos); }
687*f6dc9357SAndroid Build Coastguard Worker UInt32 GetCuSize() const { return (UInt32)1 << (BlockSizeLog + CompressionUnit); }
688*f6dc9357SAndroid Build Coastguard Worker public:
689*f6dc9357SAndroid Build Coastguard Worker HRESULT InitAndSeek(unsigned compressionUnit)
690*f6dc9357SAndroid Build Coastguard Worker {
691*f6dc9357SAndroid Build Coastguard Worker CompressionUnit = compressionUnit;
692*f6dc9357SAndroid Build Coastguard Worker _chunkSizeLog = BlockSizeLog + CompressionUnit;
693*f6dc9357SAndroid Build Coastguard Worker if (compressionUnit != 0)
694*f6dc9357SAndroid Build Coastguard Worker {
695*f6dc9357SAndroid Build Coastguard Worker UInt32 cuSize = GetCuSize();
696*f6dc9357SAndroid Build Coastguard Worker _inBuf.Alloc(cuSize);
697*f6dc9357SAndroid Build Coastguard Worker _outBuf.Alloc(kNumCacheChunks << _chunkSizeLog);
698*f6dc9357SAndroid Build Coastguard Worker }
699*f6dc9357SAndroid Build Coastguard Worker for (size_t i = 0; i < kNumCacheChunks; i++)
700*f6dc9357SAndroid Build Coastguard Worker _tags[i] = kEmptyTag;
701*f6dc9357SAndroid Build Coastguard Worker
702*f6dc9357SAndroid Build Coastguard Worker _sparseMode = false;
703*f6dc9357SAndroid Build Coastguard Worker _curRem = 0;
704*f6dc9357SAndroid Build Coastguard Worker _virtPos = 0;
705*f6dc9357SAndroid Build Coastguard Worker _physPos = 0;
706*f6dc9357SAndroid Build Coastguard Worker const CExtent &e = Extents[0];
707*f6dc9357SAndroid Build Coastguard Worker if (!e.IsEmpty())
708*f6dc9357SAndroid Build Coastguard Worker _physPos = e.Phy << BlockSizeLog;
709*f6dc9357SAndroid Build Coastguard Worker return SeekToPhys();
710*f6dc9357SAndroid Build Coastguard Worker }
711*f6dc9357SAndroid Build Coastguard Worker };
712*f6dc9357SAndroid Build Coastguard Worker
713*f6dc9357SAndroid Build Coastguard Worker static size_t Lznt1Dec(Byte *dest, size_t outBufLim, size_t destLen, const Byte *src, size_t srcLen)
714*f6dc9357SAndroid Build Coastguard Worker {
715*f6dc9357SAndroid Build Coastguard Worker size_t destSize = 0;
716*f6dc9357SAndroid Build Coastguard Worker while (destSize < destLen)
717*f6dc9357SAndroid Build Coastguard Worker {
718*f6dc9357SAndroid Build Coastguard Worker if (srcLen < 2 || (destSize & 0xFFF) != 0)
719*f6dc9357SAndroid Build Coastguard Worker break;
720*f6dc9357SAndroid Build Coastguard Worker UInt32 comprSize;
721*f6dc9357SAndroid Build Coastguard Worker {
722*f6dc9357SAndroid Build Coastguard Worker const UInt32 v = Get16(src);
723*f6dc9357SAndroid Build Coastguard Worker if (v == 0)
724*f6dc9357SAndroid Build Coastguard Worker break;
725*f6dc9357SAndroid Build Coastguard Worker src += 2;
726*f6dc9357SAndroid Build Coastguard Worker srcLen -= 2;
727*f6dc9357SAndroid Build Coastguard Worker comprSize = (v & 0xFFF) + 1;
728*f6dc9357SAndroid Build Coastguard Worker if (comprSize > srcLen)
729*f6dc9357SAndroid Build Coastguard Worker break;
730*f6dc9357SAndroid Build Coastguard Worker srcLen -= comprSize;
731*f6dc9357SAndroid Build Coastguard Worker if ((v & 0x8000) == 0)
732*f6dc9357SAndroid Build Coastguard Worker {
733*f6dc9357SAndroid Build Coastguard Worker if (comprSize != (1 << 12))
734*f6dc9357SAndroid Build Coastguard Worker break;
735*f6dc9357SAndroid Build Coastguard Worker memcpy(dest + destSize, src, comprSize);
736*f6dc9357SAndroid Build Coastguard Worker src += comprSize;
737*f6dc9357SAndroid Build Coastguard Worker destSize += comprSize;
738*f6dc9357SAndroid Build Coastguard Worker continue;
739*f6dc9357SAndroid Build Coastguard Worker }
740*f6dc9357SAndroid Build Coastguard Worker }
741*f6dc9357SAndroid Build Coastguard Worker {
742*f6dc9357SAndroid Build Coastguard Worker if (destSize + (1 << 12) > outBufLim || (src[0] & 1) != 0)
743*f6dc9357SAndroid Build Coastguard Worker return 0;
744*f6dc9357SAndroid Build Coastguard Worker unsigned numDistBits = 4;
745*f6dc9357SAndroid Build Coastguard Worker UInt32 sbOffset = 0;
746*f6dc9357SAndroid Build Coastguard Worker UInt32 pos = 0;
747*f6dc9357SAndroid Build Coastguard Worker
748*f6dc9357SAndroid Build Coastguard Worker do
749*f6dc9357SAndroid Build Coastguard Worker {
750*f6dc9357SAndroid Build Coastguard Worker comprSize--;
751*f6dc9357SAndroid Build Coastguard Worker for (UInt32 mask = src[pos++] | 0x100; mask > 1 && comprSize > 0; mask >>= 1)
752*f6dc9357SAndroid Build Coastguard Worker {
753*f6dc9357SAndroid Build Coastguard Worker if ((mask & 1) == 0)
754*f6dc9357SAndroid Build Coastguard Worker {
755*f6dc9357SAndroid Build Coastguard Worker if (sbOffset >= (1 << 12))
756*f6dc9357SAndroid Build Coastguard Worker return 0;
757*f6dc9357SAndroid Build Coastguard Worker dest[destSize++] = src[pos++];
758*f6dc9357SAndroid Build Coastguard Worker sbOffset++;
759*f6dc9357SAndroid Build Coastguard Worker comprSize--;
760*f6dc9357SAndroid Build Coastguard Worker }
761*f6dc9357SAndroid Build Coastguard Worker else
762*f6dc9357SAndroid Build Coastguard Worker {
763*f6dc9357SAndroid Build Coastguard Worker if (comprSize < 2)
764*f6dc9357SAndroid Build Coastguard Worker return 0;
765*f6dc9357SAndroid Build Coastguard Worker const UInt32 v = Get16(src + pos);
766*f6dc9357SAndroid Build Coastguard Worker pos += 2;
767*f6dc9357SAndroid Build Coastguard Worker comprSize -= 2;
768*f6dc9357SAndroid Build Coastguard Worker
769*f6dc9357SAndroid Build Coastguard Worker while (((sbOffset - 1) >> numDistBits) != 0)
770*f6dc9357SAndroid Build Coastguard Worker numDistBits++;
771*f6dc9357SAndroid Build Coastguard Worker
772*f6dc9357SAndroid Build Coastguard Worker UInt32 len = (v & (0xFFFF >> numDistBits)) + 3;
773*f6dc9357SAndroid Build Coastguard Worker if (sbOffset + len > (1 << 12))
774*f6dc9357SAndroid Build Coastguard Worker return 0;
775*f6dc9357SAndroid Build Coastguard Worker UInt32 dist = (v >> (16 - numDistBits));
776*f6dc9357SAndroid Build Coastguard Worker if (dist >= sbOffset)
777*f6dc9357SAndroid Build Coastguard Worker return 0;
778*f6dc9357SAndroid Build Coastguard Worker const size_t offs = 1 + dist;
779*f6dc9357SAndroid Build Coastguard Worker Byte *p = dest + destSize - offs;
780*f6dc9357SAndroid Build Coastguard Worker destSize += len;
781*f6dc9357SAndroid Build Coastguard Worker sbOffset += len;
782*f6dc9357SAndroid Build Coastguard Worker const Byte *lim = p + len;
783*f6dc9357SAndroid Build Coastguard Worker p[offs] = *p; ++p;
784*f6dc9357SAndroid Build Coastguard Worker p[offs] = *p; ++p;
785*f6dc9357SAndroid Build Coastguard Worker do
786*f6dc9357SAndroid Build Coastguard Worker p[offs] = *p;
787*f6dc9357SAndroid Build Coastguard Worker while (++p != lim);
788*f6dc9357SAndroid Build Coastguard Worker }
789*f6dc9357SAndroid Build Coastguard Worker }
790*f6dc9357SAndroid Build Coastguard Worker }
791*f6dc9357SAndroid Build Coastguard Worker while (comprSize > 0);
792*f6dc9357SAndroid Build Coastguard Worker src += pos;
793*f6dc9357SAndroid Build Coastguard Worker }
794*f6dc9357SAndroid Build Coastguard Worker }
795*f6dc9357SAndroid Build Coastguard Worker return destSize;
796*f6dc9357SAndroid Build Coastguard Worker }
797*f6dc9357SAndroid Build Coastguard Worker
798*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CInStream::Read(void *data, UInt32 size, UInt32 *processedSize))
799*f6dc9357SAndroid Build Coastguard Worker {
800*f6dc9357SAndroid Build Coastguard Worker if (processedSize)
801*f6dc9357SAndroid Build Coastguard Worker *processedSize = 0;
802*f6dc9357SAndroid Build Coastguard Worker if (_virtPos >= Size)
803*f6dc9357SAndroid Build Coastguard Worker return (Size == _virtPos) ? S_OK: E_FAIL;
804*f6dc9357SAndroid Build Coastguard Worker if (size == 0)
805*f6dc9357SAndroid Build Coastguard Worker return S_OK;
806*f6dc9357SAndroid Build Coastguard Worker {
807*f6dc9357SAndroid Build Coastguard Worker const UInt64 rem = Size - _virtPos;
808*f6dc9357SAndroid Build Coastguard Worker if (size > rem)
809*f6dc9357SAndroid Build Coastguard Worker size = (UInt32)rem;
810*f6dc9357SAndroid Build Coastguard Worker }
811*f6dc9357SAndroid Build Coastguard Worker
812*f6dc9357SAndroid Build Coastguard Worker if (_virtPos >= InitializedSize)
813*f6dc9357SAndroid Build Coastguard Worker {
814*f6dc9357SAndroid Build Coastguard Worker memset((Byte *)data, 0, size);
815*f6dc9357SAndroid Build Coastguard Worker _virtPos += size;
816*f6dc9357SAndroid Build Coastguard Worker *processedSize = size;
817*f6dc9357SAndroid Build Coastguard Worker return S_OK;
818*f6dc9357SAndroid Build Coastguard Worker }
819*f6dc9357SAndroid Build Coastguard Worker
820*f6dc9357SAndroid Build Coastguard Worker {
821*f6dc9357SAndroid Build Coastguard Worker const UInt64 rem = InitializedSize - _virtPos;
822*f6dc9357SAndroid Build Coastguard Worker if (size > rem)
823*f6dc9357SAndroid Build Coastguard Worker size = (UInt32)rem;
824*f6dc9357SAndroid Build Coastguard Worker }
825*f6dc9357SAndroid Build Coastguard Worker
826*f6dc9357SAndroid Build Coastguard Worker while (_curRem == 0)
827*f6dc9357SAndroid Build Coastguard Worker {
828*f6dc9357SAndroid Build Coastguard Worker const UInt64 cacheTag = _virtPos >> _chunkSizeLog;
829*f6dc9357SAndroid Build Coastguard Worker const size_t cacheIndex = (size_t)cacheTag & (kNumCacheChunks - 1);
830*f6dc9357SAndroid Build Coastguard Worker
831*f6dc9357SAndroid Build Coastguard Worker if (_tags[cacheIndex] == cacheTag)
832*f6dc9357SAndroid Build Coastguard Worker {
833*f6dc9357SAndroid Build Coastguard Worker const size_t chunkSize = (size_t)1 << _chunkSizeLog;
834*f6dc9357SAndroid Build Coastguard Worker const size_t offset = (size_t)_virtPos & (chunkSize - 1);
835*f6dc9357SAndroid Build Coastguard Worker size_t cur = chunkSize - offset;
836*f6dc9357SAndroid Build Coastguard Worker if (cur > size)
837*f6dc9357SAndroid Build Coastguard Worker cur = size;
838*f6dc9357SAndroid Build Coastguard Worker memcpy(data, _outBuf + (cacheIndex << _chunkSizeLog) + offset, cur);
839*f6dc9357SAndroid Build Coastguard Worker *processedSize = (UInt32)cur;
840*f6dc9357SAndroid Build Coastguard Worker _virtPos += cur;
841*f6dc9357SAndroid Build Coastguard Worker return S_OK;
842*f6dc9357SAndroid Build Coastguard Worker }
843*f6dc9357SAndroid Build Coastguard Worker
844*f6dc9357SAndroid Build Coastguard Worker PRF2(printf("\nVirtPos = %6d", _virtPos));
845*f6dc9357SAndroid Build Coastguard Worker
846*f6dc9357SAndroid Build Coastguard Worker const UInt32 comprUnitSize = (UInt32)1 << CompressionUnit;
847*f6dc9357SAndroid Build Coastguard Worker const UInt64 virtBlock = _virtPos >> BlockSizeLog;
848*f6dc9357SAndroid Build Coastguard Worker const UInt64 virtBlock2 = virtBlock & ~((UInt64)comprUnitSize - 1);
849*f6dc9357SAndroid Build Coastguard Worker
850*f6dc9357SAndroid Build Coastguard Worker unsigned left = 0, right = Extents.Size();
851*f6dc9357SAndroid Build Coastguard Worker for (;;)
852*f6dc9357SAndroid Build Coastguard Worker {
853*f6dc9357SAndroid Build Coastguard Worker unsigned mid = (left + right) / 2;
854*f6dc9357SAndroid Build Coastguard Worker if (mid == left)
855*f6dc9357SAndroid Build Coastguard Worker break;
856*f6dc9357SAndroid Build Coastguard Worker if (virtBlock2 < Extents[mid].Virt)
857*f6dc9357SAndroid Build Coastguard Worker right = mid;
858*f6dc9357SAndroid Build Coastguard Worker else
859*f6dc9357SAndroid Build Coastguard Worker left = mid;
860*f6dc9357SAndroid Build Coastguard Worker }
861*f6dc9357SAndroid Build Coastguard Worker
862*f6dc9357SAndroid Build Coastguard Worker bool isCompressed = false;
863*f6dc9357SAndroid Build Coastguard Worker const UInt64 virtBlock2End = virtBlock2 + comprUnitSize;
864*f6dc9357SAndroid Build Coastguard Worker if (CompressionUnit != 0)
865*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = left; i < Extents.Size(); i++)
866*f6dc9357SAndroid Build Coastguard Worker {
867*f6dc9357SAndroid Build Coastguard Worker const CExtent &e = Extents[i];
868*f6dc9357SAndroid Build Coastguard Worker if (e.Virt >= virtBlock2End)
869*f6dc9357SAndroid Build Coastguard Worker break;
870*f6dc9357SAndroid Build Coastguard Worker if (e.IsEmpty())
871*f6dc9357SAndroid Build Coastguard Worker {
872*f6dc9357SAndroid Build Coastguard Worker isCompressed = true;
873*f6dc9357SAndroid Build Coastguard Worker break;
874*f6dc9357SAndroid Build Coastguard Worker }
875*f6dc9357SAndroid Build Coastguard Worker }
876*f6dc9357SAndroid Build Coastguard Worker
877*f6dc9357SAndroid Build Coastguard Worker unsigned i;
878*f6dc9357SAndroid Build Coastguard Worker for (i = left; Extents[i + 1].Virt <= virtBlock; i++);
879*f6dc9357SAndroid Build Coastguard Worker
880*f6dc9357SAndroid Build Coastguard Worker _sparseMode = false;
881*f6dc9357SAndroid Build Coastguard Worker if (!isCompressed)
882*f6dc9357SAndroid Build Coastguard Worker {
883*f6dc9357SAndroid Build Coastguard Worker const CExtent &e = Extents[i];
884*f6dc9357SAndroid Build Coastguard Worker UInt64 newPos = (e.Phy << BlockSizeLog) + _virtPos - (e.Virt << BlockSizeLog);
885*f6dc9357SAndroid Build Coastguard Worker if (newPos != _physPos)
886*f6dc9357SAndroid Build Coastguard Worker {
887*f6dc9357SAndroid Build Coastguard Worker _physPos = newPos;
888*f6dc9357SAndroid Build Coastguard Worker RINOK(SeekToPhys())
889*f6dc9357SAndroid Build Coastguard Worker }
890*f6dc9357SAndroid Build Coastguard Worker UInt64 next = Extents[i + 1].Virt;
891*f6dc9357SAndroid Build Coastguard Worker if (next > virtBlock2End)
892*f6dc9357SAndroid Build Coastguard Worker next &= ~((UInt64)comprUnitSize - 1);
893*f6dc9357SAndroid Build Coastguard Worker next <<= BlockSizeLog;
894*f6dc9357SAndroid Build Coastguard Worker if (next > Size)
895*f6dc9357SAndroid Build Coastguard Worker next = Size;
896*f6dc9357SAndroid Build Coastguard Worker _curRem = next - _virtPos;
897*f6dc9357SAndroid Build Coastguard Worker break;
898*f6dc9357SAndroid Build Coastguard Worker }
899*f6dc9357SAndroid Build Coastguard Worker
900*f6dc9357SAndroid Build Coastguard Worker bool thereArePhy = false;
901*f6dc9357SAndroid Build Coastguard Worker
902*f6dc9357SAndroid Build Coastguard Worker for (unsigned i2 = left; i2 < Extents.Size(); i2++)
903*f6dc9357SAndroid Build Coastguard Worker {
904*f6dc9357SAndroid Build Coastguard Worker const CExtent &e = Extents[i2];
905*f6dc9357SAndroid Build Coastguard Worker if (e.Virt >= virtBlock2End)
906*f6dc9357SAndroid Build Coastguard Worker break;
907*f6dc9357SAndroid Build Coastguard Worker if (!e.IsEmpty())
908*f6dc9357SAndroid Build Coastguard Worker {
909*f6dc9357SAndroid Build Coastguard Worker thereArePhy = true;
910*f6dc9357SAndroid Build Coastguard Worker break;
911*f6dc9357SAndroid Build Coastguard Worker }
912*f6dc9357SAndroid Build Coastguard Worker }
913*f6dc9357SAndroid Build Coastguard Worker
914*f6dc9357SAndroid Build Coastguard Worker if (!thereArePhy)
915*f6dc9357SAndroid Build Coastguard Worker {
916*f6dc9357SAndroid Build Coastguard Worker _curRem = (Extents[i + 1].Virt << BlockSizeLog) - _virtPos;
917*f6dc9357SAndroid Build Coastguard Worker _sparseMode = true;
918*f6dc9357SAndroid Build Coastguard Worker break;
919*f6dc9357SAndroid Build Coastguard Worker }
920*f6dc9357SAndroid Build Coastguard Worker
921*f6dc9357SAndroid Build Coastguard Worker size_t offs = 0;
922*f6dc9357SAndroid Build Coastguard Worker UInt64 curVirt = virtBlock2;
923*f6dc9357SAndroid Build Coastguard Worker
924*f6dc9357SAndroid Build Coastguard Worker for (i = left; i < Extents.Size(); i++)
925*f6dc9357SAndroid Build Coastguard Worker {
926*f6dc9357SAndroid Build Coastguard Worker const CExtent &e = Extents[i];
927*f6dc9357SAndroid Build Coastguard Worker if (e.IsEmpty())
928*f6dc9357SAndroid Build Coastguard Worker break;
929*f6dc9357SAndroid Build Coastguard Worker if (e.Virt >= virtBlock2End)
930*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
931*f6dc9357SAndroid Build Coastguard Worker const UInt64 newPos = (e.Phy + (curVirt - e.Virt)) << BlockSizeLog;
932*f6dc9357SAndroid Build Coastguard Worker if (newPos != _physPos)
933*f6dc9357SAndroid Build Coastguard Worker {
934*f6dc9357SAndroid Build Coastguard Worker _physPos = newPos;
935*f6dc9357SAndroid Build Coastguard Worker RINOK(SeekToPhys())
936*f6dc9357SAndroid Build Coastguard Worker }
937*f6dc9357SAndroid Build Coastguard Worker UInt64 numChunks = Extents[i + 1].Virt - curVirt;
938*f6dc9357SAndroid Build Coastguard Worker if (curVirt + numChunks > virtBlock2End)
939*f6dc9357SAndroid Build Coastguard Worker numChunks = virtBlock2End - curVirt;
940*f6dc9357SAndroid Build Coastguard Worker const size_t compressed = (size_t)numChunks << BlockSizeLog;
941*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(Stream, _inBuf + offs, compressed))
942*f6dc9357SAndroid Build Coastguard Worker curVirt += numChunks;
943*f6dc9357SAndroid Build Coastguard Worker _physPos += compressed;
944*f6dc9357SAndroid Build Coastguard Worker offs += compressed;
945*f6dc9357SAndroid Build Coastguard Worker }
946*f6dc9357SAndroid Build Coastguard Worker
947*f6dc9357SAndroid Build Coastguard Worker const size_t destLenMax = GetCuSize();
948*f6dc9357SAndroid Build Coastguard Worker size_t destLen = destLenMax;
949*f6dc9357SAndroid Build Coastguard Worker const UInt64 rem = Size - (virtBlock2 << BlockSizeLog);
950*f6dc9357SAndroid Build Coastguard Worker if (destLen > rem)
951*f6dc9357SAndroid Build Coastguard Worker destLen = (size_t)rem;
952*f6dc9357SAndroid Build Coastguard Worker
953*f6dc9357SAndroid Build Coastguard Worker Byte *dest = _outBuf + (cacheIndex << _chunkSizeLog);
954*f6dc9357SAndroid Build Coastguard Worker const size_t destSizeRes = Lznt1Dec(dest, destLenMax, destLen, _inBuf, offs);
955*f6dc9357SAndroid Build Coastguard Worker _tags[cacheIndex] = cacheTag;
956*f6dc9357SAndroid Build Coastguard Worker
957*f6dc9357SAndroid Build Coastguard Worker // some files in Vista have destSize > destLen
958*f6dc9357SAndroid Build Coastguard Worker if (destSizeRes < destLen)
959*f6dc9357SAndroid Build Coastguard Worker {
960*f6dc9357SAndroid Build Coastguard Worker memset(dest, 0, destLenMax);
961*f6dc9357SAndroid Build Coastguard Worker if (InUse)
962*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
963*f6dc9357SAndroid Build Coastguard Worker }
964*f6dc9357SAndroid Build Coastguard Worker }
965*f6dc9357SAndroid Build Coastguard Worker
966*f6dc9357SAndroid Build Coastguard Worker if (size > _curRem)
967*f6dc9357SAndroid Build Coastguard Worker size = (UInt32)_curRem;
968*f6dc9357SAndroid Build Coastguard Worker HRESULT res = S_OK;
969*f6dc9357SAndroid Build Coastguard Worker if (_sparseMode)
970*f6dc9357SAndroid Build Coastguard Worker memset(data, 0, size);
971*f6dc9357SAndroid Build Coastguard Worker else
972*f6dc9357SAndroid Build Coastguard Worker {
973*f6dc9357SAndroid Build Coastguard Worker res = Stream->Read(data, size, &size);
974*f6dc9357SAndroid Build Coastguard Worker _physPos += size;
975*f6dc9357SAndroid Build Coastguard Worker }
976*f6dc9357SAndroid Build Coastguard Worker if (processedSize)
977*f6dc9357SAndroid Build Coastguard Worker *processedSize = size;
978*f6dc9357SAndroid Build Coastguard Worker _virtPos += size;
979*f6dc9357SAndroid Build Coastguard Worker _curRem -= size;
980*f6dc9357SAndroid Build Coastguard Worker return res;
981*f6dc9357SAndroid Build Coastguard Worker }
982*f6dc9357SAndroid Build Coastguard Worker
983*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))
984*f6dc9357SAndroid Build Coastguard Worker {
985*f6dc9357SAndroid Build Coastguard Worker switch (seekOrigin)
986*f6dc9357SAndroid Build Coastguard Worker {
987*f6dc9357SAndroid Build Coastguard Worker case STREAM_SEEK_SET: break;
988*f6dc9357SAndroid Build Coastguard Worker case STREAM_SEEK_CUR: offset += _virtPos; break;
989*f6dc9357SAndroid Build Coastguard Worker case STREAM_SEEK_END: offset += Size; break;
990*f6dc9357SAndroid Build Coastguard Worker default: return STG_E_INVALIDFUNCTION;
991*f6dc9357SAndroid Build Coastguard Worker }
992*f6dc9357SAndroid Build Coastguard Worker if (offset < 0)
993*f6dc9357SAndroid Build Coastguard Worker return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
994*f6dc9357SAndroid Build Coastguard Worker if (_virtPos != (UInt64)offset)
995*f6dc9357SAndroid Build Coastguard Worker {
996*f6dc9357SAndroid Build Coastguard Worker _curRem = 0;
997*f6dc9357SAndroid Build Coastguard Worker _virtPos = (UInt64)offset;
998*f6dc9357SAndroid Build Coastguard Worker }
999*f6dc9357SAndroid Build Coastguard Worker if (newPosition)
1000*f6dc9357SAndroid Build Coastguard Worker *newPosition = (UInt64)offset;
1001*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1002*f6dc9357SAndroid Build Coastguard Worker }
1003*f6dc9357SAndroid Build Coastguard Worker
1004*f6dc9357SAndroid Build Coastguard Worker static HRESULT DataParseExtents(unsigned clusterSizeLog, const CObjectVector<CAttr> &attrs,
1005*f6dc9357SAndroid Build Coastguard Worker unsigned attrIndex, unsigned attrIndexLim, UInt64 numPhysClusters, CRecordVector<CExtent> &Extents)
1006*f6dc9357SAndroid Build Coastguard Worker {
1007*f6dc9357SAndroid Build Coastguard Worker {
1008*f6dc9357SAndroid Build Coastguard Worker CExtent e;
1009*f6dc9357SAndroid Build Coastguard Worker e.Virt = 0;
1010*f6dc9357SAndroid Build Coastguard Worker e.Phy = kEmptyExtent;
1011*f6dc9357SAndroid Build Coastguard Worker Extents.Add(e);
1012*f6dc9357SAndroid Build Coastguard Worker }
1013*f6dc9357SAndroid Build Coastguard Worker
1014*f6dc9357SAndroid Build Coastguard Worker const CAttr &attr0 = attrs[attrIndex];
1015*f6dc9357SAndroid Build Coastguard Worker
1016*f6dc9357SAndroid Build Coastguard Worker /*
1017*f6dc9357SAndroid Build Coastguard Worker if (attrs[attrIndexLim - 1].HighVcn + 1 != (attr0.AllocatedSize >> clusterSizeLog))
1018*f6dc9357SAndroid Build Coastguard Worker {
1019*f6dc9357SAndroid Build Coastguard Worker }
1020*f6dc9357SAndroid Build Coastguard Worker */
1021*f6dc9357SAndroid Build Coastguard Worker
1022*f6dc9357SAndroid Build Coastguard Worker if (attr0.AllocatedSize < attr0.Size ||
1023*f6dc9357SAndroid Build Coastguard Worker (attrs[attrIndexLim - 1].HighVcn + 1) != (attr0.AllocatedSize >> clusterSizeLog) ||
1024*f6dc9357SAndroid Build Coastguard Worker (attr0.AllocatedSize & ((1 << clusterSizeLog) - 1)) != 0)
1025*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1026*f6dc9357SAndroid Build Coastguard Worker
1027*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = attrIndex; i < attrIndexLim; i++)
1028*f6dc9357SAndroid Build Coastguard Worker if (!attrs[i].ParseExtents(Extents, numPhysClusters, attr0.CompressionUnit))
1029*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1030*f6dc9357SAndroid Build Coastguard Worker
1031*f6dc9357SAndroid Build Coastguard Worker UInt64 packSizeCalc = 0;
1032*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (k, Extents)
1033*f6dc9357SAndroid Build Coastguard Worker {
1034*f6dc9357SAndroid Build Coastguard Worker CExtent &e = Extents[k];
1035*f6dc9357SAndroid Build Coastguard Worker if (!e.IsEmpty())
1036*f6dc9357SAndroid Build Coastguard Worker packSizeCalc += (Extents[k + 1].Virt - e.Virt) << clusterSizeLog;
1037*f6dc9357SAndroid Build Coastguard Worker PRF2(printf("\nSize = %4I64X", Extents[k + 1].Virt - e.Virt));
1038*f6dc9357SAndroid Build Coastguard Worker PRF2(printf(" Pos = %4I64X", e.Phy));
1039*f6dc9357SAndroid Build Coastguard Worker }
1040*f6dc9357SAndroid Build Coastguard Worker
1041*f6dc9357SAndroid Build Coastguard Worker if (attr0.CompressionUnit != 0)
1042*f6dc9357SAndroid Build Coastguard Worker {
1043*f6dc9357SAndroid Build Coastguard Worker if (packSizeCalc != attr0.PackSize)
1044*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1045*f6dc9357SAndroid Build Coastguard Worker }
1046*f6dc9357SAndroid Build Coastguard Worker else
1047*f6dc9357SAndroid Build Coastguard Worker {
1048*f6dc9357SAndroid Build Coastguard Worker if (packSizeCalc != attr0.AllocatedSize)
1049*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1050*f6dc9357SAndroid Build Coastguard Worker }
1051*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1052*f6dc9357SAndroid Build Coastguard Worker }
1053*f6dc9357SAndroid Build Coastguard Worker
1054*f6dc9357SAndroid Build Coastguard Worker struct CDataRef
1055*f6dc9357SAndroid Build Coastguard Worker {
1056*f6dc9357SAndroid Build Coastguard Worker unsigned Start;
1057*f6dc9357SAndroid Build Coastguard Worker unsigned Num;
1058*f6dc9357SAndroid Build Coastguard Worker };
1059*f6dc9357SAndroid Build Coastguard Worker
1060*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kMagic_FILE = 0x454C4946;
1061*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kMagic_BAAD = 0x44414142;
1062*f6dc9357SAndroid Build Coastguard Worker
1063*f6dc9357SAndroid Build Coastguard Worker // 22.02: we support some rare case magic values:
1064*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kMagic_INDX = 0x58444e49;
1065*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kMagic_HOLE = 0x454c4f48;
1066*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kMagic_RSTR = 0x52545352;
1067*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kMagic_RCRD = 0x44524352;
1068*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kMagic_CHKD = 0x444b4843;
1069*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kMagic_FFFFFFFF = 0xFFFFFFFF;
1070*f6dc9357SAndroid Build Coastguard Worker
1071*f6dc9357SAndroid Build Coastguard Worker
1072*f6dc9357SAndroid Build Coastguard Worker struct CMftRec
1073*f6dc9357SAndroid Build Coastguard Worker {
1074*f6dc9357SAndroid Build Coastguard Worker UInt32 Magic;
1075*f6dc9357SAndroid Build Coastguard Worker // UInt64 Lsn;
1076*f6dc9357SAndroid Build Coastguard Worker UInt16 SeqNumber; // Number of times this mft record has been reused
1077*f6dc9357SAndroid Build Coastguard Worker UInt16 Flags;
1078*f6dc9357SAndroid Build Coastguard Worker // UInt16 LinkCount;
1079*f6dc9357SAndroid Build Coastguard Worker // UInt16 NextAttrInstance;
1080*f6dc9357SAndroid Build Coastguard Worker CMftRef BaseMftRef;
1081*f6dc9357SAndroid Build Coastguard Worker // UInt32 ThisRecNumber;
1082*f6dc9357SAndroid Build Coastguard Worker
1083*f6dc9357SAndroid Build Coastguard Worker UInt32 MyNumNameLinks;
1084*f6dc9357SAndroid Build Coastguard Worker int MyItemIndex; // index in Items[] of main item for that record, or -1 if there is no item for that record
1085*f6dc9357SAndroid Build Coastguard Worker
1086*f6dc9357SAndroid Build Coastguard Worker CObjectVector<CAttr> DataAttrs;
1087*f6dc9357SAndroid Build Coastguard Worker CObjectVector<CFileNameAttr> FileNames;
1088*f6dc9357SAndroid Build Coastguard Worker CRecordVector<CDataRef> DataRefs;
1089*f6dc9357SAndroid Build Coastguard Worker // CAttr SecurityAttr;
1090*f6dc9357SAndroid Build Coastguard Worker
1091*f6dc9357SAndroid Build Coastguard Worker CSiAttr SiAttr;
1092*f6dc9357SAndroid Build Coastguard Worker
1093*f6dc9357SAndroid Build Coastguard Worker CByteBuffer ReparseData;
1094*f6dc9357SAndroid Build Coastguard Worker
1095*f6dc9357SAndroid Build Coastguard Worker int FindWin32Name_for_DosName(unsigned dosNameIndex) const
1096*f6dc9357SAndroid Build Coastguard Worker {
1097*f6dc9357SAndroid Build Coastguard Worker const CFileNameAttr &cur = FileNames[dosNameIndex];
1098*f6dc9357SAndroid Build Coastguard Worker if (cur.IsDos())
1099*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < FileNames.Size(); i++)
1100*f6dc9357SAndroid Build Coastguard Worker {
1101*f6dc9357SAndroid Build Coastguard Worker const CFileNameAttr &next = FileNames[i];
1102*f6dc9357SAndroid Build Coastguard Worker if (next.IsWin32() && cur.ParentDirRef.Val == next.ParentDirRef.Val)
1103*f6dc9357SAndroid Build Coastguard Worker return (int)i;
1104*f6dc9357SAndroid Build Coastguard Worker }
1105*f6dc9357SAndroid Build Coastguard Worker return -1;
1106*f6dc9357SAndroid Build Coastguard Worker }
1107*f6dc9357SAndroid Build Coastguard Worker
1108*f6dc9357SAndroid Build Coastguard Worker int FindDosName(unsigned nameIndex) const
1109*f6dc9357SAndroid Build Coastguard Worker {
1110*f6dc9357SAndroid Build Coastguard Worker const CFileNameAttr &cur = FileNames[nameIndex];
1111*f6dc9357SAndroid Build Coastguard Worker if (cur.IsWin32())
1112*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < FileNames.Size(); i++)
1113*f6dc9357SAndroid Build Coastguard Worker {
1114*f6dc9357SAndroid Build Coastguard Worker const CFileNameAttr &next = FileNames[i];
1115*f6dc9357SAndroid Build Coastguard Worker if (next.IsDos() && cur.ParentDirRef.Val == next.ParentDirRef.Val)
1116*f6dc9357SAndroid Build Coastguard Worker return (int)i;
1117*f6dc9357SAndroid Build Coastguard Worker }
1118*f6dc9357SAndroid Build Coastguard Worker return -1;
1119*f6dc9357SAndroid Build Coastguard Worker }
1120*f6dc9357SAndroid Build Coastguard Worker
1121*f6dc9357SAndroid Build Coastguard Worker /*
1122*f6dc9357SAndroid Build Coastguard Worker bool IsAltStream(int dataIndex) const
1123*f6dc9357SAndroid Build Coastguard Worker {
1124*f6dc9357SAndroid Build Coastguard Worker return dataIndex >= 0 && (
1125*f6dc9357SAndroid Build Coastguard Worker (IsDir() ||
1126*f6dc9357SAndroid Build Coastguard Worker !DataAttrs[DataRefs[dataIndex].Start].Name.IsEmpty()));
1127*f6dc9357SAndroid Build Coastguard Worker }
1128*f6dc9357SAndroid Build Coastguard Worker */
1129*f6dc9357SAndroid Build Coastguard Worker
1130*f6dc9357SAndroid Build Coastguard Worker void MoveAttrsFrom(CMftRec &src)
1131*f6dc9357SAndroid Build Coastguard Worker {
1132*f6dc9357SAndroid Build Coastguard Worker DataAttrs += src.DataAttrs;
1133*f6dc9357SAndroid Build Coastguard Worker FileNames += src.FileNames;
1134*f6dc9357SAndroid Build Coastguard Worker src.DataAttrs.ClearAndFree();
1135*f6dc9357SAndroid Build Coastguard Worker src.FileNames.ClearAndFree();
1136*f6dc9357SAndroid Build Coastguard Worker }
1137*f6dc9357SAndroid Build Coastguard Worker
1138*f6dc9357SAndroid Build Coastguard Worker UInt64 GetPackSize() const
1139*f6dc9357SAndroid Build Coastguard Worker {
1140*f6dc9357SAndroid Build Coastguard Worker UInt64 res = 0;
1141*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (i, DataRefs)
1142*f6dc9357SAndroid Build Coastguard Worker res += DataAttrs[DataRefs[i].Start].GetPackSize();
1143*f6dc9357SAndroid Build Coastguard Worker return res;
1144*f6dc9357SAndroid Build Coastguard Worker }
1145*f6dc9357SAndroid Build Coastguard Worker
1146*f6dc9357SAndroid Build Coastguard Worker bool Parse(Byte *p, unsigned sectorSizeLog, UInt32 numSectors, UInt32 recNumber, CObjectVector<CAttr> *attrs);
1147*f6dc9357SAndroid Build Coastguard Worker
1148*f6dc9357SAndroid Build Coastguard Worker bool Is_Magic_Empty() const
1149*f6dc9357SAndroid Build Coastguard Worker {
1150*f6dc9357SAndroid Build Coastguard Worker // what exact Magic values are possible for empty and unused records?
1151*f6dc9357SAndroid Build Coastguard Worker const UInt32 k_Magic_Unused_MAX = 5; // 22.02
1152*f6dc9357SAndroid Build Coastguard Worker return (Magic <= k_Magic_Unused_MAX);
1153*f6dc9357SAndroid Build Coastguard Worker }
1154*f6dc9357SAndroid Build Coastguard Worker bool Is_Magic_FILE() const { return (Magic == kMagic_FILE); }
1155*f6dc9357SAndroid Build Coastguard Worker // bool Is_Magic_BAAD() const { return (Magic == kMagic_BAAD); }
1156*f6dc9357SAndroid Build Coastguard Worker bool Is_Magic_CanIgnore() const
1157*f6dc9357SAndroid Build Coastguard Worker {
1158*f6dc9357SAndroid Build Coastguard Worker return Is_Magic_Empty()
1159*f6dc9357SAndroid Build Coastguard Worker || Magic == kMagic_BAAD
1160*f6dc9357SAndroid Build Coastguard Worker || Magic == kMagic_INDX
1161*f6dc9357SAndroid Build Coastguard Worker || Magic == kMagic_HOLE
1162*f6dc9357SAndroid Build Coastguard Worker || Magic == kMagic_RSTR
1163*f6dc9357SAndroid Build Coastguard Worker || Magic == kMagic_RCRD
1164*f6dc9357SAndroid Build Coastguard Worker || Magic == kMagic_CHKD
1165*f6dc9357SAndroid Build Coastguard Worker || Magic == kMagic_FFFFFFFF;
1166*f6dc9357SAndroid Build Coastguard Worker }
1167*f6dc9357SAndroid Build Coastguard Worker
1168*f6dc9357SAndroid Build Coastguard Worker bool InUse() const { return (Flags & 1) != 0; }
1169*f6dc9357SAndroid Build Coastguard Worker bool IsDir() const { return (Flags & 2) != 0; }
1170*f6dc9357SAndroid Build Coastguard Worker
1171*f6dc9357SAndroid Build Coastguard Worker void ParseDataNames();
1172*f6dc9357SAndroid Build Coastguard Worker HRESULT GetStream(IInStream *mainStream, int dataIndex,
1173*f6dc9357SAndroid Build Coastguard Worker unsigned clusterSizeLog, UInt64 numPhysClusters, IInStream **stream) const;
1174*f6dc9357SAndroid Build Coastguard Worker unsigned GetNumExtents(int dataIndex, unsigned clusterSizeLog, UInt64 numPhysClusters) const;
1175*f6dc9357SAndroid Build Coastguard Worker
1176*f6dc9357SAndroid Build Coastguard Worker UInt64 GetSize(unsigned dataIndex) const { return DataAttrs[DataRefs[dataIndex].Start].GetSize(); }
1177*f6dc9357SAndroid Build Coastguard Worker
1178*f6dc9357SAndroid Build Coastguard Worker CMftRec():
1179*f6dc9357SAndroid Build Coastguard Worker SeqNumber(0),
1180*f6dc9357SAndroid Build Coastguard Worker Flags(0),
1181*f6dc9357SAndroid Build Coastguard Worker MyNumNameLinks(0),
1182*f6dc9357SAndroid Build Coastguard Worker MyItemIndex(-1) {}
1183*f6dc9357SAndroid Build Coastguard Worker };
1184*f6dc9357SAndroid Build Coastguard Worker
1185*f6dc9357SAndroid Build Coastguard Worker void CMftRec::ParseDataNames()
1186*f6dc9357SAndroid Build Coastguard Worker {
1187*f6dc9357SAndroid Build Coastguard Worker DataRefs.Clear();
1188*f6dc9357SAndroid Build Coastguard Worker DataAttrs.Sort(CompareAttr, NULL);
1189*f6dc9357SAndroid Build Coastguard Worker
1190*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < DataAttrs.Size();)
1191*f6dc9357SAndroid Build Coastguard Worker {
1192*f6dc9357SAndroid Build Coastguard Worker CDataRef ref;
1193*f6dc9357SAndroid Build Coastguard Worker ref.Start = i;
1194*f6dc9357SAndroid Build Coastguard Worker for (i++; i < DataAttrs.Size(); i++)
1195*f6dc9357SAndroid Build Coastguard Worker if (DataAttrs[ref.Start].Name != DataAttrs[i].Name)
1196*f6dc9357SAndroid Build Coastguard Worker break;
1197*f6dc9357SAndroid Build Coastguard Worker ref.Num = i - ref.Start;
1198*f6dc9357SAndroid Build Coastguard Worker DataRefs.Add(ref);
1199*f6dc9357SAndroid Build Coastguard Worker }
1200*f6dc9357SAndroid Build Coastguard Worker }
1201*f6dc9357SAndroid Build Coastguard Worker
1202*f6dc9357SAndroid Build Coastguard Worker HRESULT CMftRec::GetStream(IInStream *mainStream, int dataIndex,
1203*f6dc9357SAndroid Build Coastguard Worker unsigned clusterSizeLog, UInt64 numPhysClusters, IInStream **destStream) const
1204*f6dc9357SAndroid Build Coastguard Worker {
1205*f6dc9357SAndroid Build Coastguard Worker *destStream = NULL;
1206*f6dc9357SAndroid Build Coastguard Worker CBufferInStream *streamSpec = new CBufferInStream;
1207*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<IInStream> streamTemp = streamSpec;
1208*f6dc9357SAndroid Build Coastguard Worker
1209*f6dc9357SAndroid Build Coastguard Worker if (dataIndex >= 0)
1210*f6dc9357SAndroid Build Coastguard Worker if ((unsigned)dataIndex < DataRefs.Size())
1211*f6dc9357SAndroid Build Coastguard Worker {
1212*f6dc9357SAndroid Build Coastguard Worker const CDataRef &ref = DataRefs[dataIndex];
1213*f6dc9357SAndroid Build Coastguard Worker unsigned numNonResident = 0;
1214*f6dc9357SAndroid Build Coastguard Worker unsigned i;
1215*f6dc9357SAndroid Build Coastguard Worker for (i = ref.Start; i < ref.Start + ref.Num; i++)
1216*f6dc9357SAndroid Build Coastguard Worker if (DataAttrs[i].NonResident)
1217*f6dc9357SAndroid Build Coastguard Worker numNonResident++;
1218*f6dc9357SAndroid Build Coastguard Worker
1219*f6dc9357SAndroid Build Coastguard Worker const CAttr &attr0 = DataAttrs[ref.Start];
1220*f6dc9357SAndroid Build Coastguard Worker
1221*f6dc9357SAndroid Build Coastguard Worker if (numNonResident != 0 || ref.Num != 1)
1222*f6dc9357SAndroid Build Coastguard Worker {
1223*f6dc9357SAndroid Build Coastguard Worker if (numNonResident != ref.Num || !attr0.IsCompressionUnitSupported())
1224*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1225*f6dc9357SAndroid Build Coastguard Worker CInStream *ss = new CInStream;
1226*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<IInStream> streamTemp2 = ss;
1227*f6dc9357SAndroid Build Coastguard Worker RINOK(DataParseExtents(clusterSizeLog, DataAttrs, ref.Start, ref.Start + ref.Num, numPhysClusters, ss->Extents))
1228*f6dc9357SAndroid Build Coastguard Worker ss->Size = attr0.Size;
1229*f6dc9357SAndroid Build Coastguard Worker ss->InitializedSize = attr0.InitializedSize;
1230*f6dc9357SAndroid Build Coastguard Worker ss->Stream = mainStream;
1231*f6dc9357SAndroid Build Coastguard Worker ss->BlockSizeLog = clusterSizeLog;
1232*f6dc9357SAndroid Build Coastguard Worker ss->InUse = InUse();
1233*f6dc9357SAndroid Build Coastguard Worker RINOK(ss->InitAndSeek(attr0.CompressionUnit))
1234*f6dc9357SAndroid Build Coastguard Worker *destStream = streamTemp2.Detach();
1235*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1236*f6dc9357SAndroid Build Coastguard Worker }
1237*f6dc9357SAndroid Build Coastguard Worker
1238*f6dc9357SAndroid Build Coastguard Worker streamSpec->Buf = attr0.Data;
1239*f6dc9357SAndroid Build Coastguard Worker }
1240*f6dc9357SAndroid Build Coastguard Worker
1241*f6dc9357SAndroid Build Coastguard Worker streamSpec->Init();
1242*f6dc9357SAndroid Build Coastguard Worker *destStream = streamTemp.Detach();
1243*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1244*f6dc9357SAndroid Build Coastguard Worker }
1245*f6dc9357SAndroid Build Coastguard Worker
1246*f6dc9357SAndroid Build Coastguard Worker unsigned CMftRec::GetNumExtents(int dataIndex, unsigned clusterSizeLog, UInt64 numPhysClusters) const
1247*f6dc9357SAndroid Build Coastguard Worker {
1248*f6dc9357SAndroid Build Coastguard Worker if (dataIndex < 0)
1249*f6dc9357SAndroid Build Coastguard Worker return 0;
1250*f6dc9357SAndroid Build Coastguard Worker {
1251*f6dc9357SAndroid Build Coastguard Worker const CDataRef &ref = DataRefs[dataIndex];
1252*f6dc9357SAndroid Build Coastguard Worker unsigned numNonResident = 0;
1253*f6dc9357SAndroid Build Coastguard Worker unsigned i;
1254*f6dc9357SAndroid Build Coastguard Worker for (i = ref.Start; i < ref.Start + ref.Num; i++)
1255*f6dc9357SAndroid Build Coastguard Worker if (DataAttrs[i].NonResident)
1256*f6dc9357SAndroid Build Coastguard Worker numNonResident++;
1257*f6dc9357SAndroid Build Coastguard Worker
1258*f6dc9357SAndroid Build Coastguard Worker const CAttr &attr0 = DataAttrs[ref.Start];
1259*f6dc9357SAndroid Build Coastguard Worker
1260*f6dc9357SAndroid Build Coastguard Worker if (numNonResident != 0 || ref.Num != 1)
1261*f6dc9357SAndroid Build Coastguard Worker {
1262*f6dc9357SAndroid Build Coastguard Worker if (numNonResident != ref.Num || !attr0.IsCompressionUnitSupported())
1263*f6dc9357SAndroid Build Coastguard Worker return 0; // error;
1264*f6dc9357SAndroid Build Coastguard Worker CRecordVector<CExtent> extents;
1265*f6dc9357SAndroid Build Coastguard Worker if (DataParseExtents(clusterSizeLog, DataAttrs, ref.Start, ref.Start + ref.Num, numPhysClusters, extents) != S_OK)
1266*f6dc9357SAndroid Build Coastguard Worker return 0; // error;
1267*f6dc9357SAndroid Build Coastguard Worker return extents.Size() - 1;
1268*f6dc9357SAndroid Build Coastguard Worker }
1269*f6dc9357SAndroid Build Coastguard Worker // if (attr0.Data.Size() != 0)
1270*f6dc9357SAndroid Build Coastguard Worker // return 1;
1271*f6dc9357SAndroid Build Coastguard Worker return 0;
1272*f6dc9357SAndroid Build Coastguard Worker }
1273*f6dc9357SAndroid Build Coastguard Worker }
1274*f6dc9357SAndroid Build Coastguard Worker
1275*f6dc9357SAndroid Build Coastguard Worker bool CMftRec::Parse(Byte *p, unsigned sectorSizeLog, UInt32 numSectors, UInt32 recNumber,
1276*f6dc9357SAndroid Build Coastguard Worker CObjectVector<CAttr> *attrs)
1277*f6dc9357SAndroid Build Coastguard Worker {
1278*f6dc9357SAndroid Build Coastguard Worker G32(p, Magic);
1279*f6dc9357SAndroid Build Coastguard Worker if (!Is_Magic_FILE())
1280*f6dc9357SAndroid Build Coastguard Worker return Is_Magic_CanIgnore();
1281*f6dc9357SAndroid Build Coastguard Worker
1282*f6dc9357SAndroid Build Coastguard Worker {
1283*f6dc9357SAndroid Build Coastguard Worker UInt32 usaOffset;
1284*f6dc9357SAndroid Build Coastguard Worker UInt32 numUsaItems;
1285*f6dc9357SAndroid Build Coastguard Worker G16(p + 0x04, usaOffset);
1286*f6dc9357SAndroid Build Coastguard Worker G16(p + 0x06, numUsaItems);
1287*f6dc9357SAndroid Build Coastguard Worker
1288*f6dc9357SAndroid Build Coastguard Worker /* NTFS stores (usn) to 2 last bytes in each sector (before writing record to disk).
1289*f6dc9357SAndroid Build Coastguard Worker Original values of these two bytes are stored in table.
1290*f6dc9357SAndroid Build Coastguard Worker So we restore original data from table */
1291*f6dc9357SAndroid Build Coastguard Worker
1292*f6dc9357SAndroid Build Coastguard Worker if ((usaOffset & 1) != 0
1293*f6dc9357SAndroid Build Coastguard Worker || usaOffset + numUsaItems * 2 > ((UInt32)1 << sectorSizeLog) - 2
1294*f6dc9357SAndroid Build Coastguard Worker || numUsaItems == 0
1295*f6dc9357SAndroid Build Coastguard Worker || numUsaItems - 1 != numSectors)
1296*f6dc9357SAndroid Build Coastguard Worker return false;
1297*f6dc9357SAndroid Build Coastguard Worker
1298*f6dc9357SAndroid Build Coastguard Worker if (usaOffset >= 0x30) // NTFS 3.1+
1299*f6dc9357SAndroid Build Coastguard Worker {
1300*f6dc9357SAndroid Build Coastguard Worker UInt32 iii = Get32(p + 0x2C);
1301*f6dc9357SAndroid Build Coastguard Worker if (iii != recNumber)
1302*f6dc9357SAndroid Build Coastguard Worker {
1303*f6dc9357SAndroid Build Coastguard Worker // ntfs-3g probably writes 0 (that probably is incorrect value) to this field for unused records.
1304*f6dc9357SAndroid Build Coastguard Worker // so we support that "bad" case.
1305*f6dc9357SAndroid Build Coastguard Worker if (iii != 0)
1306*f6dc9357SAndroid Build Coastguard Worker return false;
1307*f6dc9357SAndroid Build Coastguard Worker }
1308*f6dc9357SAndroid Build Coastguard Worker }
1309*f6dc9357SAndroid Build Coastguard Worker
1310*f6dc9357SAndroid Build Coastguard Worker UInt16 usn = Get16(p + usaOffset);
1311*f6dc9357SAndroid Build Coastguard Worker // PRF(printf("\nusn = %d", usn));
1312*f6dc9357SAndroid Build Coastguard Worker for (UInt32 i = 1; i < numUsaItems; i++)
1313*f6dc9357SAndroid Build Coastguard Worker {
1314*f6dc9357SAndroid Build Coastguard Worker void *pp = p + (i << sectorSizeLog) - 2;
1315*f6dc9357SAndroid Build Coastguard Worker if (Get16(pp) != usn)
1316*f6dc9357SAndroid Build Coastguard Worker return false;
1317*f6dc9357SAndroid Build Coastguard Worker SetUi16(pp, Get16(p + usaOffset + i * 2))
1318*f6dc9357SAndroid Build Coastguard Worker }
1319*f6dc9357SAndroid Build Coastguard Worker }
1320*f6dc9357SAndroid Build Coastguard Worker
1321*f6dc9357SAndroid Build Coastguard Worker // G64(p + 0x08, Lsn);
1322*f6dc9357SAndroid Build Coastguard Worker G16(p + 0x10, SeqNumber);
1323*f6dc9357SAndroid Build Coastguard Worker // G16(p + 0x12, LinkCount);
1324*f6dc9357SAndroid Build Coastguard Worker // PRF(printf(" L=%d", LinkCount));
1325*f6dc9357SAndroid Build Coastguard Worker const UInt32 attrOffs = Get16(p + 0x14);
1326*f6dc9357SAndroid Build Coastguard Worker G16(p + 0x16, Flags);
1327*f6dc9357SAndroid Build Coastguard Worker PRF(printf(" F=%4X", Flags));
1328*f6dc9357SAndroid Build Coastguard Worker
1329*f6dc9357SAndroid Build Coastguard Worker const UInt32 bytesInUse = Get32(p + 0x18);
1330*f6dc9357SAndroid Build Coastguard Worker const UInt32 bytesAlloc = Get32(p + 0x1C);
1331*f6dc9357SAndroid Build Coastguard Worker G64(p + 0x20, BaseMftRef.Val);
1332*f6dc9357SAndroid Build Coastguard Worker if (BaseMftRef.Val != 0)
1333*f6dc9357SAndroid Build Coastguard Worker {
1334*f6dc9357SAndroid Build Coastguard Worker PRF(printf(" BaseRef=%d", (int)BaseMftRef.Val));
1335*f6dc9357SAndroid Build Coastguard Worker // return false; // Check it;
1336*f6dc9357SAndroid Build Coastguard Worker }
1337*f6dc9357SAndroid Build Coastguard Worker // G16(p + 0x28, NextAttrInstance);
1338*f6dc9357SAndroid Build Coastguard Worker
1339*f6dc9357SAndroid Build Coastguard Worker UInt32 limit = numSectors << sectorSizeLog;
1340*f6dc9357SAndroid Build Coastguard Worker if (attrOffs >= limit
1341*f6dc9357SAndroid Build Coastguard Worker || (attrOffs & 7) != 0
1342*f6dc9357SAndroid Build Coastguard Worker || (bytesInUse & 7) != 0
1343*f6dc9357SAndroid Build Coastguard Worker || bytesInUse > limit
1344*f6dc9357SAndroid Build Coastguard Worker || bytesAlloc != limit)
1345*f6dc9357SAndroid Build Coastguard Worker return false;
1346*f6dc9357SAndroid Build Coastguard Worker
1347*f6dc9357SAndroid Build Coastguard Worker limit = bytesInUse;
1348*f6dc9357SAndroid Build Coastguard Worker
1349*f6dc9357SAndroid Build Coastguard Worker for (UInt32 t = attrOffs;;)
1350*f6dc9357SAndroid Build Coastguard Worker {
1351*f6dc9357SAndroid Build Coastguard Worker if (t >= limit)
1352*f6dc9357SAndroid Build Coastguard Worker return false;
1353*f6dc9357SAndroid Build Coastguard Worker
1354*f6dc9357SAndroid Build Coastguard Worker CAttr attr;
1355*f6dc9357SAndroid Build Coastguard Worker // PRF(printf("\n %2d:", Attrs.Size()));
1356*f6dc9357SAndroid Build Coastguard Worker PRF(printf("\n"));
1357*f6dc9357SAndroid Build Coastguard Worker UInt32 len = attr.Parse(p + t, limit - t);
1358*f6dc9357SAndroid Build Coastguard Worker if (len == 0 || limit - t < len)
1359*f6dc9357SAndroid Build Coastguard Worker return false;
1360*f6dc9357SAndroid Build Coastguard Worker t += len;
1361*f6dc9357SAndroid Build Coastguard Worker if (attr.Type == 0xFFFFFFFF)
1362*f6dc9357SAndroid Build Coastguard Worker {
1363*f6dc9357SAndroid Build Coastguard Worker if (t != limit)
1364*f6dc9357SAndroid Build Coastguard Worker return false;
1365*f6dc9357SAndroid Build Coastguard Worker break;
1366*f6dc9357SAndroid Build Coastguard Worker }
1367*f6dc9357SAndroid Build Coastguard Worker switch (attr.Type)
1368*f6dc9357SAndroid Build Coastguard Worker {
1369*f6dc9357SAndroid Build Coastguard Worker case ATTR_TYPE_FILE_NAME:
1370*f6dc9357SAndroid Build Coastguard Worker {
1371*f6dc9357SAndroid Build Coastguard Worker CFileNameAttr fna;
1372*f6dc9357SAndroid Build Coastguard Worker if (!attr.ParseFileName(fna))
1373*f6dc9357SAndroid Build Coastguard Worker return false;
1374*f6dc9357SAndroid Build Coastguard Worker FileNames.Add(fna);
1375*f6dc9357SAndroid Build Coastguard Worker PRF(printf(" flags = %4x\n ", (int)fna.NameType));
1376*f6dc9357SAndroid Build Coastguard Worker PRF_UTF16(fna.Name);
1377*f6dc9357SAndroid Build Coastguard Worker break;
1378*f6dc9357SAndroid Build Coastguard Worker }
1379*f6dc9357SAndroid Build Coastguard Worker case ATTR_TYPE_STANDARD_INFO:
1380*f6dc9357SAndroid Build Coastguard Worker if (!attr.ParseSi(SiAttr))
1381*f6dc9357SAndroid Build Coastguard Worker return false;
1382*f6dc9357SAndroid Build Coastguard Worker break;
1383*f6dc9357SAndroid Build Coastguard Worker case ATTR_TYPE_DATA:
1384*f6dc9357SAndroid Build Coastguard Worker DataAttrs.Add(attr);
1385*f6dc9357SAndroid Build Coastguard Worker break;
1386*f6dc9357SAndroid Build Coastguard Worker case ATTR_TYPE_REPARSE_POINT:
1387*f6dc9357SAndroid Build Coastguard Worker ReparseData = attr.Data;
1388*f6dc9357SAndroid Build Coastguard Worker break;
1389*f6dc9357SAndroid Build Coastguard Worker /*
1390*f6dc9357SAndroid Build Coastguard Worker case ATTR_TYPE_SECURITY_DESCRIPTOR:
1391*f6dc9357SAndroid Build Coastguard Worker SecurityAttr = attr;
1392*f6dc9357SAndroid Build Coastguard Worker break;
1393*f6dc9357SAndroid Build Coastguard Worker */
1394*f6dc9357SAndroid Build Coastguard Worker default:
1395*f6dc9357SAndroid Build Coastguard Worker if (attrs)
1396*f6dc9357SAndroid Build Coastguard Worker attrs->Add(attr);
1397*f6dc9357SAndroid Build Coastguard Worker break;
1398*f6dc9357SAndroid Build Coastguard Worker }
1399*f6dc9357SAndroid Build Coastguard Worker }
1400*f6dc9357SAndroid Build Coastguard Worker
1401*f6dc9357SAndroid Build Coastguard Worker return true;
1402*f6dc9357SAndroid Build Coastguard Worker }
1403*f6dc9357SAndroid Build Coastguard Worker
1404*f6dc9357SAndroid Build Coastguard Worker /*
1405*f6dc9357SAndroid Build Coastguard Worker NTFS probably creates empty DATA_ATTRIBUTE for empty file,
1406*f6dc9357SAndroid Build Coastguard Worker But it doesn't do it for
1407*f6dc9357SAndroid Build Coastguard Worker $Secure (:$SDS),
1408*f6dc9357SAndroid Build Coastguard Worker $Extend\$Quota
1409*f6dc9357SAndroid Build Coastguard Worker $Extend\$ObjId
1410*f6dc9357SAndroid Build Coastguard Worker $Extend\$Reparse
1411*f6dc9357SAndroid Build Coastguard Worker */
1412*f6dc9357SAndroid Build Coastguard Worker
1413*f6dc9357SAndroid Build Coastguard Worker static const int k_Item_DataIndex_IsEmptyFile = -1; // file without unnamed data stream
1414*f6dc9357SAndroid Build Coastguard Worker static const int k_Item_DataIndex_IsDir = -2;
1415*f6dc9357SAndroid Build Coastguard Worker
1416*f6dc9357SAndroid Build Coastguard Worker // static const int k_ParentFolderIndex_Root = -1;
1417*f6dc9357SAndroid Build Coastguard Worker static const int k_ParentFolderIndex_Lost = -2;
1418*f6dc9357SAndroid Build Coastguard Worker static const int k_ParentFolderIndex_Deleted = -3;
1419*f6dc9357SAndroid Build Coastguard Worker
1420*f6dc9357SAndroid Build Coastguard Worker struct CItem
1421*f6dc9357SAndroid Build Coastguard Worker {
1422*f6dc9357SAndroid Build Coastguard Worker unsigned RecIndex; // index in Recs array
1423*f6dc9357SAndroid Build Coastguard Worker unsigned NameIndex; // index in CMftRec::FileNames
1424*f6dc9357SAndroid Build Coastguard Worker
1425*f6dc9357SAndroid Build Coastguard Worker int DataIndex; /* index in CMftRec::DataRefs
1426*f6dc9357SAndroid Build Coastguard Worker -1: file without unnamed data stream
1427*f6dc9357SAndroid Build Coastguard Worker -2: for directories */
1428*f6dc9357SAndroid Build Coastguard Worker
1429*f6dc9357SAndroid Build Coastguard Worker int ParentFolder; /* index in Items array
1430*f6dc9357SAndroid Build Coastguard Worker -1: for root items
1431*f6dc9357SAndroid Build Coastguard Worker -2: [LOST] folder
1432*f6dc9357SAndroid Build Coastguard Worker -3: [UNKNOWN] folder (deleted lost) */
1433*f6dc9357SAndroid Build Coastguard Worker int ParentHost; /* index in Items array, if it's AltStream
1434*f6dc9357SAndroid Build Coastguard Worker -1: if it's not AltStream */
1435*f6dc9357SAndroid Build Coastguard Worker
1436*f6dc9357SAndroid Build Coastguard Worker CItem(): DataIndex(k_Item_DataIndex_IsDir), ParentFolder(-1), ParentHost(-1) {}
1437*f6dc9357SAndroid Build Coastguard Worker
1438*f6dc9357SAndroid Build Coastguard Worker bool IsAltStream() const { return ParentHost != -1; }
1439*f6dc9357SAndroid Build Coastguard Worker bool IsDir() const { return DataIndex == k_Item_DataIndex_IsDir; }
1440*f6dc9357SAndroid Build Coastguard Worker // check it !!!
1441*f6dc9357SAndroid Build Coastguard Worker // probably NTFS for empty file still creates empty DATA_ATTRIBUTE
1442*f6dc9357SAndroid Build Coastguard Worker // But it doesn't do it for $Secure:$SDS
1443*f6dc9357SAndroid Build Coastguard Worker };
1444*f6dc9357SAndroid Build Coastguard Worker
1445*f6dc9357SAndroid Build Coastguard Worker struct CDatabase
1446*f6dc9357SAndroid Build Coastguard Worker {
1447*f6dc9357SAndroid Build Coastguard Worker CRecordVector<CItem> Items;
1448*f6dc9357SAndroid Build Coastguard Worker CObjectVector<CMftRec> Recs;
1449*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<IInStream> InStream;
1450*f6dc9357SAndroid Build Coastguard Worker CHeader Header;
1451*f6dc9357SAndroid Build Coastguard Worker UInt64 PhySize;
1452*f6dc9357SAndroid Build Coastguard Worker
1453*f6dc9357SAndroid Build Coastguard Worker IArchiveOpenCallback *OpenCallback;
1454*f6dc9357SAndroid Build Coastguard Worker
1455*f6dc9357SAndroid Build Coastguard Worker CByteBuffer ByteBuf;
1456*f6dc9357SAndroid Build Coastguard Worker
1457*f6dc9357SAndroid Build Coastguard Worker CObjectVector<CAttr> VolAttrs;
1458*f6dc9357SAndroid Build Coastguard Worker
1459*f6dc9357SAndroid Build Coastguard Worker CByteBuffer SecurData;
1460*f6dc9357SAndroid Build Coastguard Worker CRecordVector<size_t> SecurOffsets;
1461*f6dc9357SAndroid Build Coastguard Worker
1462*f6dc9357SAndroid Build Coastguard Worker // bool _headerWarning;
1463*f6dc9357SAndroid Build Coastguard Worker bool ThereAreAltStreams;
1464*f6dc9357SAndroid Build Coastguard Worker
1465*f6dc9357SAndroid Build Coastguard Worker bool _showSystemFiles;
1466*f6dc9357SAndroid Build Coastguard Worker bool _showDeletedFiles;
1467*f6dc9357SAndroid Build Coastguard Worker CObjectVector<UString2> VirtFolderNames;
1468*f6dc9357SAndroid Build Coastguard Worker UString EmptyString;
1469*f6dc9357SAndroid Build Coastguard Worker
1470*f6dc9357SAndroid Build Coastguard Worker int _systemFolderIndex;
1471*f6dc9357SAndroid Build Coastguard Worker int _lostFolderIndex_Normal;
1472*f6dc9357SAndroid Build Coastguard Worker int _lostFolderIndex_Deleted;
1473*f6dc9357SAndroid Build Coastguard Worker
1474*f6dc9357SAndroid Build Coastguard Worker void InitProps()
1475*f6dc9357SAndroid Build Coastguard Worker {
1476*f6dc9357SAndroid Build Coastguard Worker _showSystemFiles = true;
1477*f6dc9357SAndroid Build Coastguard Worker // we show SystemFiles by default since it's difficult to track $Extend\* system files
1478*f6dc9357SAndroid Build Coastguard Worker // it must be fixed later
1479*f6dc9357SAndroid Build Coastguard Worker _showDeletedFiles = false;
1480*f6dc9357SAndroid Build Coastguard Worker }
1481*f6dc9357SAndroid Build Coastguard Worker
1482*f6dc9357SAndroid Build Coastguard Worker CDatabase() { InitProps(); }
1483*f6dc9357SAndroid Build Coastguard Worker ~CDatabase() { ClearAndClose(); }
1484*f6dc9357SAndroid Build Coastguard Worker
1485*f6dc9357SAndroid Build Coastguard Worker void Clear();
1486*f6dc9357SAndroid Build Coastguard Worker void ClearAndClose();
1487*f6dc9357SAndroid Build Coastguard Worker
1488*f6dc9357SAndroid Build Coastguard Worker void GetItemPath(unsigned index, NCOM::CPropVariant &path) const;
1489*f6dc9357SAndroid Build Coastguard Worker HRESULT Open();
1490*f6dc9357SAndroid Build Coastguard Worker
1491*f6dc9357SAndroid Build Coastguard Worker HRESULT SeekToCluster(UInt64 cluster);
1492*f6dc9357SAndroid Build Coastguard Worker
1493*f6dc9357SAndroid Build Coastguard Worker int Find_DirItem_For_MftRec(UInt64 recIndex) const
1494*f6dc9357SAndroid Build Coastguard Worker {
1495*f6dc9357SAndroid Build Coastguard Worker if (recIndex >= Recs.Size())
1496*f6dc9357SAndroid Build Coastguard Worker return -1;
1497*f6dc9357SAndroid Build Coastguard Worker const CMftRec &rec = Recs[(unsigned)recIndex];
1498*f6dc9357SAndroid Build Coastguard Worker if (!rec.IsDir())
1499*f6dc9357SAndroid Build Coastguard Worker return -1;
1500*f6dc9357SAndroid Build Coastguard Worker return rec.MyItemIndex;
1501*f6dc9357SAndroid Build Coastguard Worker /*
1502*f6dc9357SAndroid Build Coastguard Worker unsigned left = 0, right = Items.Size();
1503*f6dc9357SAndroid Build Coastguard Worker while (left != right)
1504*f6dc9357SAndroid Build Coastguard Worker {
1505*f6dc9357SAndroid Build Coastguard Worker unsigned mid = (left + right) / 2;
1506*f6dc9357SAndroid Build Coastguard Worker const CItem &item = Items[mid];
1507*f6dc9357SAndroid Build Coastguard Worker UInt64 midValue = item.RecIndex;
1508*f6dc9357SAndroid Build Coastguard Worker if (recIndex == midValue)
1509*f6dc9357SAndroid Build Coastguard Worker {
1510*f6dc9357SAndroid Build Coastguard Worker // if item is not dir (file or alt stream we don't return it)
1511*f6dc9357SAndroid Build Coastguard Worker // if (item.DataIndex < 0)
1512*f6dc9357SAndroid Build Coastguard Worker if (item.IsDir())
1513*f6dc9357SAndroid Build Coastguard Worker return mid;
1514*f6dc9357SAndroid Build Coastguard Worker right = mid;
1515*f6dc9357SAndroid Build Coastguard Worker }
1516*f6dc9357SAndroid Build Coastguard Worker else if (recIndex < midValue)
1517*f6dc9357SAndroid Build Coastguard Worker right = mid;
1518*f6dc9357SAndroid Build Coastguard Worker else
1519*f6dc9357SAndroid Build Coastguard Worker left = mid + 1;
1520*f6dc9357SAndroid Build Coastguard Worker }
1521*f6dc9357SAndroid Build Coastguard Worker return -1;
1522*f6dc9357SAndroid Build Coastguard Worker */
1523*f6dc9357SAndroid Build Coastguard Worker }
1524*f6dc9357SAndroid Build Coastguard Worker
1525*f6dc9357SAndroid Build Coastguard Worker bool FindSecurityDescritor(UInt32 id, UInt64 &offset, UInt32 &size) const;
1526*f6dc9357SAndroid Build Coastguard Worker
1527*f6dc9357SAndroid Build Coastguard Worker HRESULT ParseSecuritySDS_2();
1528*f6dc9357SAndroid Build Coastguard Worker void ParseSecuritySDS()
1529*f6dc9357SAndroid Build Coastguard Worker {
1530*f6dc9357SAndroid Build Coastguard Worker HRESULT res = ParseSecuritySDS_2();
1531*f6dc9357SAndroid Build Coastguard Worker if (res != S_OK)
1532*f6dc9357SAndroid Build Coastguard Worker {
1533*f6dc9357SAndroid Build Coastguard Worker SecurOffsets.Clear();
1534*f6dc9357SAndroid Build Coastguard Worker SecurData.Free();
1535*f6dc9357SAndroid Build Coastguard Worker }
1536*f6dc9357SAndroid Build Coastguard Worker }
1537*f6dc9357SAndroid Build Coastguard Worker
1538*f6dc9357SAndroid Build Coastguard Worker };
1539*f6dc9357SAndroid Build Coastguard Worker
1540*f6dc9357SAndroid Build Coastguard Worker HRESULT CDatabase::SeekToCluster(UInt64 cluster)
1541*f6dc9357SAndroid Build Coastguard Worker {
1542*f6dc9357SAndroid Build Coastguard Worker return InStream_SeekSet(InStream, cluster << Header.ClusterSizeLog);
1543*f6dc9357SAndroid Build Coastguard Worker }
1544*f6dc9357SAndroid Build Coastguard Worker
1545*f6dc9357SAndroid Build Coastguard Worker void CDatabase::Clear()
1546*f6dc9357SAndroid Build Coastguard Worker {
1547*f6dc9357SAndroid Build Coastguard Worker Items.Clear();
1548*f6dc9357SAndroid Build Coastguard Worker Recs.Clear();
1549*f6dc9357SAndroid Build Coastguard Worker SecurOffsets.Clear();
1550*f6dc9357SAndroid Build Coastguard Worker SecurData.Free();
1551*f6dc9357SAndroid Build Coastguard Worker VirtFolderNames.Clear();
1552*f6dc9357SAndroid Build Coastguard Worker _systemFolderIndex = -1;
1553*f6dc9357SAndroid Build Coastguard Worker _lostFolderIndex_Normal = -1;
1554*f6dc9357SAndroid Build Coastguard Worker _lostFolderIndex_Deleted = -1;
1555*f6dc9357SAndroid Build Coastguard Worker ThereAreAltStreams = false;
1556*f6dc9357SAndroid Build Coastguard Worker // _headerWarning = false;
1557*f6dc9357SAndroid Build Coastguard Worker PhySize = 0;
1558*f6dc9357SAndroid Build Coastguard Worker }
1559*f6dc9357SAndroid Build Coastguard Worker
1560*f6dc9357SAndroid Build Coastguard Worker void CDatabase::ClearAndClose()
1561*f6dc9357SAndroid Build Coastguard Worker {
1562*f6dc9357SAndroid Build Coastguard Worker Clear();
1563*f6dc9357SAndroid Build Coastguard Worker InStream.Release();
1564*f6dc9357SAndroid Build Coastguard Worker }
1565*f6dc9357SAndroid Build Coastguard Worker
1566*f6dc9357SAndroid Build Coastguard Worker
1567*f6dc9357SAndroid Build Coastguard Worker static void CopyName(wchar_t *dest, const wchar_t *src)
1568*f6dc9357SAndroid Build Coastguard Worker {
1569*f6dc9357SAndroid Build Coastguard Worker for (;;)
1570*f6dc9357SAndroid Build Coastguard Worker {
1571*f6dc9357SAndroid Build Coastguard Worker wchar_t c = *src++;
1572*f6dc9357SAndroid Build Coastguard Worker // 18.06
1573*f6dc9357SAndroid Build Coastguard Worker if (c == '\\' || c == '/')
1574*f6dc9357SAndroid Build Coastguard Worker c = '_';
1575*f6dc9357SAndroid Build Coastguard Worker *dest++ = c;
1576*f6dc9357SAndroid Build Coastguard Worker if (c == 0)
1577*f6dc9357SAndroid Build Coastguard Worker return;
1578*f6dc9357SAndroid Build Coastguard Worker }
1579*f6dc9357SAndroid Build Coastguard Worker }
1580*f6dc9357SAndroid Build Coastguard Worker
1581*f6dc9357SAndroid Build Coastguard Worker void CDatabase::GetItemPath(unsigned index, NCOM::CPropVariant &path) const
1582*f6dc9357SAndroid Build Coastguard Worker {
1583*f6dc9357SAndroid Build Coastguard Worker const CItem *item = &Items[index];
1584*f6dc9357SAndroid Build Coastguard Worker unsigned size = 0;
1585*f6dc9357SAndroid Build Coastguard Worker const CMftRec &rec = Recs[item->RecIndex];
1586*f6dc9357SAndroid Build Coastguard Worker size += rec.FileNames[item->NameIndex].Name.Len();
1587*f6dc9357SAndroid Build Coastguard Worker
1588*f6dc9357SAndroid Build Coastguard Worker bool isAltStream = item->IsAltStream();
1589*f6dc9357SAndroid Build Coastguard Worker
1590*f6dc9357SAndroid Build Coastguard Worker if (isAltStream)
1591*f6dc9357SAndroid Build Coastguard Worker {
1592*f6dc9357SAndroid Build Coastguard Worker const CAttr &data = rec.DataAttrs[rec.DataRefs[item->DataIndex].Start];
1593*f6dc9357SAndroid Build Coastguard Worker if (item->RecIndex == kRecIndex_RootDir)
1594*f6dc9357SAndroid Build Coastguard Worker {
1595*f6dc9357SAndroid Build Coastguard Worker wchar_t *s = path.AllocBstr(data.Name.Len() + 1);
1596*f6dc9357SAndroid Build Coastguard Worker s[0] = L':';
1597*f6dc9357SAndroid Build Coastguard Worker if (!data.Name.IsEmpty())
1598*f6dc9357SAndroid Build Coastguard Worker CopyName(s + 1, data.Name.GetRawPtr());
1599*f6dc9357SAndroid Build Coastguard Worker return;
1600*f6dc9357SAndroid Build Coastguard Worker }
1601*f6dc9357SAndroid Build Coastguard Worker
1602*f6dc9357SAndroid Build Coastguard Worker size += data.Name.Len();
1603*f6dc9357SAndroid Build Coastguard Worker size++;
1604*f6dc9357SAndroid Build Coastguard Worker }
1605*f6dc9357SAndroid Build Coastguard Worker
1606*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0;; i++)
1607*f6dc9357SAndroid Build Coastguard Worker {
1608*f6dc9357SAndroid Build Coastguard Worker if (i > 256)
1609*f6dc9357SAndroid Build Coastguard Worker {
1610*f6dc9357SAndroid Build Coastguard Worker path = "[TOO-LONG]";
1611*f6dc9357SAndroid Build Coastguard Worker return;
1612*f6dc9357SAndroid Build Coastguard Worker }
1613*f6dc9357SAndroid Build Coastguard Worker const wchar_t *servName;
1614*f6dc9357SAndroid Build Coastguard Worker if (item->RecIndex < kNumSysRecs
1615*f6dc9357SAndroid Build Coastguard Worker /* && item->RecIndex != kRecIndex_RootDir */)
1616*f6dc9357SAndroid Build Coastguard Worker servName = kVirtualFolder_System;
1617*f6dc9357SAndroid Build Coastguard Worker else
1618*f6dc9357SAndroid Build Coastguard Worker {
1619*f6dc9357SAndroid Build Coastguard Worker int index2 = item->ParentFolder;
1620*f6dc9357SAndroid Build Coastguard Worker if (index2 >= 0)
1621*f6dc9357SAndroid Build Coastguard Worker {
1622*f6dc9357SAndroid Build Coastguard Worker item = &Items[index2];
1623*f6dc9357SAndroid Build Coastguard Worker size += Recs[item->RecIndex].FileNames[item->NameIndex].Name.Len() + 1;
1624*f6dc9357SAndroid Build Coastguard Worker continue;
1625*f6dc9357SAndroid Build Coastguard Worker }
1626*f6dc9357SAndroid Build Coastguard Worker if (index2 == -1)
1627*f6dc9357SAndroid Build Coastguard Worker break;
1628*f6dc9357SAndroid Build Coastguard Worker servName = (index2 == k_ParentFolderIndex_Lost) ?
1629*f6dc9357SAndroid Build Coastguard Worker kVirtualFolder_Lost_Normal :
1630*f6dc9357SAndroid Build Coastguard Worker kVirtualFolder_Lost_Deleted;
1631*f6dc9357SAndroid Build Coastguard Worker }
1632*f6dc9357SAndroid Build Coastguard Worker size += MyStringLen(servName) + 1;
1633*f6dc9357SAndroid Build Coastguard Worker break;
1634*f6dc9357SAndroid Build Coastguard Worker }
1635*f6dc9357SAndroid Build Coastguard Worker
1636*f6dc9357SAndroid Build Coastguard Worker wchar_t *s = path.AllocBstr(size);
1637*f6dc9357SAndroid Build Coastguard Worker
1638*f6dc9357SAndroid Build Coastguard Worker item = &Items[index];
1639*f6dc9357SAndroid Build Coastguard Worker
1640*f6dc9357SAndroid Build Coastguard Worker bool needColon = false;
1641*f6dc9357SAndroid Build Coastguard Worker if (isAltStream)
1642*f6dc9357SAndroid Build Coastguard Worker {
1643*f6dc9357SAndroid Build Coastguard Worker const UString2 &name = rec.DataAttrs[rec.DataRefs[item->DataIndex].Start].Name;
1644*f6dc9357SAndroid Build Coastguard Worker if (!name.IsEmpty())
1645*f6dc9357SAndroid Build Coastguard Worker {
1646*f6dc9357SAndroid Build Coastguard Worker size -= name.Len();
1647*f6dc9357SAndroid Build Coastguard Worker CopyName(s + size, name.GetRawPtr());
1648*f6dc9357SAndroid Build Coastguard Worker }
1649*f6dc9357SAndroid Build Coastguard Worker s[--size] = ':';
1650*f6dc9357SAndroid Build Coastguard Worker needColon = true;
1651*f6dc9357SAndroid Build Coastguard Worker }
1652*f6dc9357SAndroid Build Coastguard Worker
1653*f6dc9357SAndroid Build Coastguard Worker {
1654*f6dc9357SAndroid Build Coastguard Worker const UString2 &name = rec.FileNames[item->NameIndex].Name;
1655*f6dc9357SAndroid Build Coastguard Worker unsigned len = name.Len();
1656*f6dc9357SAndroid Build Coastguard Worker if (len != 0)
1657*f6dc9357SAndroid Build Coastguard Worker CopyName(s + size - len, name.GetRawPtr());
1658*f6dc9357SAndroid Build Coastguard Worker if (needColon)
1659*f6dc9357SAndroid Build Coastguard Worker s[size] = ':';
1660*f6dc9357SAndroid Build Coastguard Worker size -= len;
1661*f6dc9357SAndroid Build Coastguard Worker }
1662*f6dc9357SAndroid Build Coastguard Worker
1663*f6dc9357SAndroid Build Coastguard Worker for (;;)
1664*f6dc9357SAndroid Build Coastguard Worker {
1665*f6dc9357SAndroid Build Coastguard Worker const wchar_t *servName;
1666*f6dc9357SAndroid Build Coastguard Worker if (item->RecIndex < kNumSysRecs
1667*f6dc9357SAndroid Build Coastguard Worker /* && && item->RecIndex != kRecIndex_RootDir */)
1668*f6dc9357SAndroid Build Coastguard Worker servName = kVirtualFolder_System;
1669*f6dc9357SAndroid Build Coastguard Worker else
1670*f6dc9357SAndroid Build Coastguard Worker {
1671*f6dc9357SAndroid Build Coastguard Worker int index2 = item->ParentFolder;
1672*f6dc9357SAndroid Build Coastguard Worker if (index2 >= 0)
1673*f6dc9357SAndroid Build Coastguard Worker {
1674*f6dc9357SAndroid Build Coastguard Worker item = &Items[index2];
1675*f6dc9357SAndroid Build Coastguard Worker const UString2 &name = Recs[item->RecIndex].FileNames[item->NameIndex].Name;
1676*f6dc9357SAndroid Build Coastguard Worker unsigned len = name.Len();
1677*f6dc9357SAndroid Build Coastguard Worker size--;
1678*f6dc9357SAndroid Build Coastguard Worker if (len != 0)
1679*f6dc9357SAndroid Build Coastguard Worker {
1680*f6dc9357SAndroid Build Coastguard Worker size -= len;
1681*f6dc9357SAndroid Build Coastguard Worker CopyName(s + size, name.GetRawPtr());
1682*f6dc9357SAndroid Build Coastguard Worker }
1683*f6dc9357SAndroid Build Coastguard Worker s[size + len] = WCHAR_PATH_SEPARATOR;
1684*f6dc9357SAndroid Build Coastguard Worker continue;
1685*f6dc9357SAndroid Build Coastguard Worker }
1686*f6dc9357SAndroid Build Coastguard Worker if (index2 == -1)
1687*f6dc9357SAndroid Build Coastguard Worker break;
1688*f6dc9357SAndroid Build Coastguard Worker servName = (index2 == k_ParentFolderIndex_Lost) ?
1689*f6dc9357SAndroid Build Coastguard Worker kVirtualFolder_Lost_Normal :
1690*f6dc9357SAndroid Build Coastguard Worker kVirtualFolder_Lost_Deleted;
1691*f6dc9357SAndroid Build Coastguard Worker }
1692*f6dc9357SAndroid Build Coastguard Worker MyStringCopy(s, servName);
1693*f6dc9357SAndroid Build Coastguard Worker s[MyStringLen(servName)] = WCHAR_PATH_SEPARATOR;
1694*f6dc9357SAndroid Build Coastguard Worker break;
1695*f6dc9357SAndroid Build Coastguard Worker }
1696*f6dc9357SAndroid Build Coastguard Worker }
1697*f6dc9357SAndroid Build Coastguard Worker
1698*f6dc9357SAndroid Build Coastguard Worker bool CDatabase::FindSecurityDescritor(UInt32 item, UInt64 &offset, UInt32 &size) const
1699*f6dc9357SAndroid Build Coastguard Worker {
1700*f6dc9357SAndroid Build Coastguard Worker offset = 0;
1701*f6dc9357SAndroid Build Coastguard Worker size = 0;
1702*f6dc9357SAndroid Build Coastguard Worker unsigned left = 0, right = SecurOffsets.Size();
1703*f6dc9357SAndroid Build Coastguard Worker while (left != right)
1704*f6dc9357SAndroid Build Coastguard Worker {
1705*f6dc9357SAndroid Build Coastguard Worker unsigned mid = (left + right) / 2;
1706*f6dc9357SAndroid Build Coastguard Worker size_t offs = SecurOffsets[mid];
1707*f6dc9357SAndroid Build Coastguard Worker UInt32 midValue = Get32(((const Byte *)SecurData) + offs + 4);
1708*f6dc9357SAndroid Build Coastguard Worker if (item == midValue)
1709*f6dc9357SAndroid Build Coastguard Worker {
1710*f6dc9357SAndroid Build Coastguard Worker offset = Get64((const Byte *)SecurData + offs + 8) + 20;
1711*f6dc9357SAndroid Build Coastguard Worker size = Get32((const Byte *)SecurData + offs + 16) - 20;
1712*f6dc9357SAndroid Build Coastguard Worker return true;
1713*f6dc9357SAndroid Build Coastguard Worker }
1714*f6dc9357SAndroid Build Coastguard Worker if (item < midValue)
1715*f6dc9357SAndroid Build Coastguard Worker right = mid;
1716*f6dc9357SAndroid Build Coastguard Worker else
1717*f6dc9357SAndroid Build Coastguard Worker left = mid + 1;
1718*f6dc9357SAndroid Build Coastguard Worker }
1719*f6dc9357SAndroid Build Coastguard Worker return false;
1720*f6dc9357SAndroid Build Coastguard Worker }
1721*f6dc9357SAndroid Build Coastguard Worker
1722*f6dc9357SAndroid Build Coastguard Worker /*
1723*f6dc9357SAndroid Build Coastguard Worker static int CompareIDs(const size_t *p1, const size_t *p2, void *data)
1724*f6dc9357SAndroid Build Coastguard Worker {
1725*f6dc9357SAndroid Build Coastguard Worker UInt32 id1 = Get32(((const Byte *)data) + *p1 + 4);
1726*f6dc9357SAndroid Build Coastguard Worker UInt32 id2 = Get32(((const Byte *)data) + *p2 + 4);
1727*f6dc9357SAndroid Build Coastguard Worker return MyCompare(id1, id2);
1728*f6dc9357SAndroid Build Coastguard Worker }
1729*f6dc9357SAndroid Build Coastguard Worker */
1730*f6dc9357SAndroid Build Coastguard Worker
1731*f6dc9357SAndroid Build Coastguard Worker // security data contains duplication copy after each 256 KB.
1732*f6dc9357SAndroid Build Coastguard Worker static const unsigned kSecureDuplicateStepBits = 18;
1733*f6dc9357SAndroid Build Coastguard Worker
1734*f6dc9357SAndroid Build Coastguard Worker HRESULT CDatabase::ParseSecuritySDS_2()
1735*f6dc9357SAndroid Build Coastguard Worker {
1736*f6dc9357SAndroid Build Coastguard Worker const Byte *p = SecurData;
1737*f6dc9357SAndroid Build Coastguard Worker size_t size = SecurData.Size();
1738*f6dc9357SAndroid Build Coastguard Worker const size_t kDuplicateStep = (size_t)1 << kSecureDuplicateStepBits;
1739*f6dc9357SAndroid Build Coastguard Worker const size_t kDuplicateMask = kDuplicateStep - 1;
1740*f6dc9357SAndroid Build Coastguard Worker size_t lim = MyMin(size, kDuplicateStep);
1741*f6dc9357SAndroid Build Coastguard Worker UInt32 idPrev = 0;
1742*f6dc9357SAndroid Build Coastguard Worker for (size_t pos = 0; pos < size && size - pos >= 20;)
1743*f6dc9357SAndroid Build Coastguard Worker {
1744*f6dc9357SAndroid Build Coastguard Worker UInt32 id = Get32(p + pos + 4);
1745*f6dc9357SAndroid Build Coastguard Worker UInt64 offs = Get64(p + pos + 8);
1746*f6dc9357SAndroid Build Coastguard Worker UInt32 entrySize = Get32(p + pos + 16);
1747*f6dc9357SAndroid Build Coastguard Worker if (offs == pos && entrySize >= 20 && lim - pos >= entrySize)
1748*f6dc9357SAndroid Build Coastguard Worker {
1749*f6dc9357SAndroid Build Coastguard Worker if (id <= idPrev)
1750*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1751*f6dc9357SAndroid Build Coastguard Worker idPrev = id;
1752*f6dc9357SAndroid Build Coastguard Worker SecurOffsets.Add(pos);
1753*f6dc9357SAndroid Build Coastguard Worker pos += entrySize;
1754*f6dc9357SAndroid Build Coastguard Worker pos = (pos + 0xF) & ~(size_t)0xF;
1755*f6dc9357SAndroid Build Coastguard Worker if ((pos & kDuplicateMask) != 0)
1756*f6dc9357SAndroid Build Coastguard Worker continue;
1757*f6dc9357SAndroid Build Coastguard Worker }
1758*f6dc9357SAndroid Build Coastguard Worker else
1759*f6dc9357SAndroid Build Coastguard Worker pos = (pos + kDuplicateStep) & ~kDuplicateMask;
1760*f6dc9357SAndroid Build Coastguard Worker pos += kDuplicateStep;
1761*f6dc9357SAndroid Build Coastguard Worker lim = pos + kDuplicateStep;
1762*f6dc9357SAndroid Build Coastguard Worker if (lim >= size)
1763*f6dc9357SAndroid Build Coastguard Worker lim = size;
1764*f6dc9357SAndroid Build Coastguard Worker }
1765*f6dc9357SAndroid Build Coastguard Worker // we checked that IDs are sorted, so we don't need Sort
1766*f6dc9357SAndroid Build Coastguard Worker // SecurOffsets.Sort(CompareIDs, (void *)p);
1767*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1768*f6dc9357SAndroid Build Coastguard Worker }
1769*f6dc9357SAndroid Build Coastguard Worker
1770*f6dc9357SAndroid Build Coastguard Worker HRESULT CDatabase::Open()
1771*f6dc9357SAndroid Build Coastguard Worker {
1772*f6dc9357SAndroid Build Coastguard Worker Clear();
1773*f6dc9357SAndroid Build Coastguard Worker
1774*f6dc9357SAndroid Build Coastguard Worker /* NTFS layout:
1775*f6dc9357SAndroid Build Coastguard Worker 1) main part (as specified by NumClusters). Only that part is available, if we open "\\.\c:"
1776*f6dc9357SAndroid Build Coastguard Worker 2) additional empty sectors (as specified by NumSectors)
1777*f6dc9357SAndroid Build Coastguard Worker 3) the copy of first sector (boot sector)
1778*f6dc9357SAndroid Build Coastguard Worker
1779*f6dc9357SAndroid Build Coastguard Worker We support both cases:
1780*f6dc9357SAndroid Build Coastguard Worker - the file with only main part
1781*f6dc9357SAndroid Build Coastguard Worker - full file (as raw data on partition), including the copy
1782*f6dc9357SAndroid Build Coastguard Worker of first sector (boot sector) at the end of data
1783*f6dc9357SAndroid Build Coastguard Worker
1784*f6dc9357SAndroid Build Coastguard Worker We don't support the case, when only the copy of boot sector
1785*f6dc9357SAndroid Build Coastguard Worker at the end was detected as NTFS signature.
1786*f6dc9357SAndroid Build Coastguard Worker */
1787*f6dc9357SAndroid Build Coastguard Worker
1788*f6dc9357SAndroid Build Coastguard Worker {
1789*f6dc9357SAndroid Build Coastguard Worker const UInt32 kHeaderSize = 512;
1790*f6dc9357SAndroid Build Coastguard Worker Byte buf[kHeaderSize];
1791*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(InStream, buf, kHeaderSize))
1792*f6dc9357SAndroid Build Coastguard Worker if (!Header.Parse(buf))
1793*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1794*f6dc9357SAndroid Build Coastguard Worker
1795*f6dc9357SAndroid Build Coastguard Worker UInt64 fileSize;
1796*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_GetSize_SeekToEnd(InStream, fileSize))
1797*f6dc9357SAndroid Build Coastguard Worker PhySize = Header.GetPhySize_Clusters();
1798*f6dc9357SAndroid Build Coastguard Worker if (fileSize < PhySize)
1799*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1800*f6dc9357SAndroid Build Coastguard Worker
1801*f6dc9357SAndroid Build Coastguard Worker UInt64 phySizeMax = Header.GetPhySize_Max();
1802*f6dc9357SAndroid Build Coastguard Worker if (fileSize >= phySizeMax)
1803*f6dc9357SAndroid Build Coastguard Worker {
1804*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_SeekSet(InStream, Header.NumSectors << Header.SectorSizeLog))
1805*f6dc9357SAndroid Build Coastguard Worker Byte buf2[kHeaderSize];
1806*f6dc9357SAndroid Build Coastguard Worker if (ReadStream_FALSE(InStream, buf2, kHeaderSize) == S_OK)
1807*f6dc9357SAndroid Build Coastguard Worker {
1808*f6dc9357SAndroid Build Coastguard Worker if (memcmp(buf, buf2, kHeaderSize) == 0)
1809*f6dc9357SAndroid Build Coastguard Worker PhySize = phySizeMax;
1810*f6dc9357SAndroid Build Coastguard Worker // else _headerWarning = true;
1811*f6dc9357SAndroid Build Coastguard Worker }
1812*f6dc9357SAndroid Build Coastguard Worker }
1813*f6dc9357SAndroid Build Coastguard Worker }
1814*f6dc9357SAndroid Build Coastguard Worker
1815*f6dc9357SAndroid Build Coastguard Worker SeekToCluster(Header.MftCluster);
1816*f6dc9357SAndroid Build Coastguard Worker
1817*f6dc9357SAndroid Build Coastguard Worker // we use ByteBuf for records reading.
1818*f6dc9357SAndroid Build Coastguard Worker // so the size of ByteBuf must be >= mftRecordSize
1819*f6dc9357SAndroid Build Coastguard Worker const size_t recSize = (size_t)1 << Header.MftRecordSizeLog;
1820*f6dc9357SAndroid Build Coastguard Worker const size_t kBufSize = MyMax((size_t)(1 << 15), recSize);
1821*f6dc9357SAndroid Build Coastguard Worker ByteBuf.Alloc(kBufSize);
1822*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(InStream, ByteBuf, recSize))
1823*f6dc9357SAndroid Build Coastguard Worker {
1824*f6dc9357SAndroid Build Coastguard Worker const UInt32 allocSize = Get32(ByteBuf + 0x1C);
1825*f6dc9357SAndroid Build Coastguard Worker if (allocSize != recSize)
1826*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1827*f6dc9357SAndroid Build Coastguard Worker }
1828*f6dc9357SAndroid Build Coastguard Worker // MftRecordSizeLog >= SectorSizeLog
1829*f6dc9357SAndroid Build Coastguard Worker const UInt32 numSectorsInRec = 1u << (Header.MftRecordSizeLog - Header.SectorSizeLog);
1830*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<IInStream> mftStream;
1831*f6dc9357SAndroid Build Coastguard Worker CMftRec mftRec;
1832*f6dc9357SAndroid Build Coastguard Worker {
1833*f6dc9357SAndroid Build Coastguard Worker if (!mftRec.Parse(ByteBuf, Header.SectorSizeLog, numSectorsInRec, 0, NULL))
1834*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1835*f6dc9357SAndroid Build Coastguard Worker if (!mftRec.Is_Magic_FILE())
1836*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1837*f6dc9357SAndroid Build Coastguard Worker mftRec.ParseDataNames();
1838*f6dc9357SAndroid Build Coastguard Worker if (mftRec.DataRefs.IsEmpty())
1839*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1840*f6dc9357SAndroid Build Coastguard Worker RINOK(mftRec.GetStream(InStream, 0, Header.ClusterSizeLog, Header.NumClusters, &mftStream))
1841*f6dc9357SAndroid Build Coastguard Worker if (!mftStream)
1842*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1843*f6dc9357SAndroid Build Coastguard Worker }
1844*f6dc9357SAndroid Build Coastguard Worker
1845*f6dc9357SAndroid Build Coastguard Worker // CObjectVector<CAttr> SecurityAttrs;
1846*f6dc9357SAndroid Build Coastguard Worker
1847*f6dc9357SAndroid Build Coastguard Worker const UInt64 mftSize = mftRec.DataAttrs[0].Size;
1848*f6dc9357SAndroid Build Coastguard Worker if ((mftSize >> 4) > Header.GetPhySize_Clusters())
1849*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1850*f6dc9357SAndroid Build Coastguard Worker
1851*f6dc9357SAndroid Build Coastguard Worker {
1852*f6dc9357SAndroid Build Coastguard Worker const UInt64 numFiles = mftSize >> Header.MftRecordSizeLog;
1853*f6dc9357SAndroid Build Coastguard Worker if (numFiles > (1 << 30))
1854*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1855*f6dc9357SAndroid Build Coastguard Worker if (OpenCallback)
1856*f6dc9357SAndroid Build Coastguard Worker {
1857*f6dc9357SAndroid Build Coastguard Worker RINOK(OpenCallback->SetTotal(&numFiles, &mftSize))
1858*f6dc9357SAndroid Build Coastguard Worker }
1859*f6dc9357SAndroid Build Coastguard Worker Recs.ClearAndReserve((unsigned)numFiles);
1860*f6dc9357SAndroid Build Coastguard Worker }
1861*f6dc9357SAndroid Build Coastguard Worker
1862*f6dc9357SAndroid Build Coastguard Worker for (UInt64 pos64 = 0;;)
1863*f6dc9357SAndroid Build Coastguard Worker {
1864*f6dc9357SAndroid Build Coastguard Worker if (OpenCallback)
1865*f6dc9357SAndroid Build Coastguard Worker {
1866*f6dc9357SAndroid Build Coastguard Worker const UInt64 numFiles = Recs.Size();
1867*f6dc9357SAndroid Build Coastguard Worker if ((numFiles & 0x3FFF) == 0)
1868*f6dc9357SAndroid Build Coastguard Worker {
1869*f6dc9357SAndroid Build Coastguard Worker RINOK(OpenCallback->SetCompleted(&numFiles, &pos64))
1870*f6dc9357SAndroid Build Coastguard Worker }
1871*f6dc9357SAndroid Build Coastguard Worker }
1872*f6dc9357SAndroid Build Coastguard Worker size_t readSize = kBufSize;
1873*f6dc9357SAndroid Build Coastguard Worker {
1874*f6dc9357SAndroid Build Coastguard Worker const UInt64 rem = mftSize - pos64;
1875*f6dc9357SAndroid Build Coastguard Worker if (readSize > rem)
1876*f6dc9357SAndroid Build Coastguard Worker readSize = (size_t)rem;
1877*f6dc9357SAndroid Build Coastguard Worker }
1878*f6dc9357SAndroid Build Coastguard Worker if (readSize < recSize)
1879*f6dc9357SAndroid Build Coastguard Worker break;
1880*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(mftStream, ByteBuf, readSize))
1881*f6dc9357SAndroid Build Coastguard Worker pos64 += readSize;
1882*f6dc9357SAndroid Build Coastguard Worker
1883*f6dc9357SAndroid Build Coastguard Worker for (size_t i = 0; readSize >= recSize; i += recSize, readSize -= recSize)
1884*f6dc9357SAndroid Build Coastguard Worker {
1885*f6dc9357SAndroid Build Coastguard Worker PRF(printf("\n---------------------"));
1886*f6dc9357SAndroid Build Coastguard Worker PRF(printf("\n%5d:", Recs.Size()));
1887*f6dc9357SAndroid Build Coastguard Worker
1888*f6dc9357SAndroid Build Coastguard Worker Byte *p = ByteBuf + i;
1889*f6dc9357SAndroid Build Coastguard Worker CMftRec rec;
1890*f6dc9357SAndroid Build Coastguard Worker
1891*f6dc9357SAndroid Build Coastguard Worker CObjectVector<CAttr> *attrs = NULL;
1892*f6dc9357SAndroid Build Coastguard Worker unsigned recIndex = Recs.Size();
1893*f6dc9357SAndroid Build Coastguard Worker switch (recIndex)
1894*f6dc9357SAndroid Build Coastguard Worker {
1895*f6dc9357SAndroid Build Coastguard Worker case kRecIndex_Volume: attrs = &VolAttrs; break;
1896*f6dc9357SAndroid Build Coastguard Worker // case kRecIndex_Security: attrs = &SecurityAttrs; break;
1897*f6dc9357SAndroid Build Coastguard Worker }
1898*f6dc9357SAndroid Build Coastguard Worker
1899*f6dc9357SAndroid Build Coastguard Worker if (!rec.Parse(p, Header.SectorSizeLog, numSectorsInRec, (UInt32)Recs.Size(), attrs))
1900*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1901*f6dc9357SAndroid Build Coastguard Worker Recs.Add(rec);
1902*f6dc9357SAndroid Build Coastguard Worker }
1903*f6dc9357SAndroid Build Coastguard Worker }
1904*f6dc9357SAndroid Build Coastguard Worker
1905*f6dc9357SAndroid Build Coastguard Worker /*
1906*f6dc9357SAndroid Build Coastguard Worker // that code looks too complex. And we can get security info without index parsing
1907*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < SecurityAttrs.Size(); i++)
1908*f6dc9357SAndroid Build Coastguard Worker {
1909*f6dc9357SAndroid Build Coastguard Worker const CAttr &attr = SecurityAttrs[i];
1910*f6dc9357SAndroid Build Coastguard Worker if (attr.Name == L"$SII")
1911*f6dc9357SAndroid Build Coastguard Worker {
1912*f6dc9357SAndroid Build Coastguard Worker if (attr.Type == ATTR_TYPE_INDEX_ROOT)
1913*f6dc9357SAndroid Build Coastguard Worker {
1914*f6dc9357SAndroid Build Coastguard Worker const Byte *data = attr.Data;
1915*f6dc9357SAndroid Build Coastguard Worker size_t size = attr.Data.Size();
1916*f6dc9357SAndroid Build Coastguard Worker
1917*f6dc9357SAndroid Build Coastguard Worker // Index Root
1918*f6dc9357SAndroid Build Coastguard Worker UInt32 attrType = Get32(data);
1919*f6dc9357SAndroid Build Coastguard Worker UInt32 collationRule = Get32(data + 4);
1920*f6dc9357SAndroid Build Coastguard Worker UInt32 indexAllocationEtrySizeSize = Get32(data + 8);
1921*f6dc9357SAndroid Build Coastguard Worker UInt32 clustersPerIndexRecord = Get32(data + 0xC);
1922*f6dc9357SAndroid Build Coastguard Worker data += 0x10;
1923*f6dc9357SAndroid Build Coastguard Worker
1924*f6dc9357SAndroid Build Coastguard Worker // Index Header
1925*f6dc9357SAndroid Build Coastguard Worker UInt32 firstEntryOffset = Get32(data);
1926*f6dc9357SAndroid Build Coastguard Worker UInt32 totalSize = Get32(data + 4);
1927*f6dc9357SAndroid Build Coastguard Worker UInt32 allocSize = Get32(data + 8);
1928*f6dc9357SAndroid Build Coastguard Worker UInt32 flags = Get32(data + 0xC);
1929*f6dc9357SAndroid Build Coastguard Worker
1930*f6dc9357SAndroid Build Coastguard Worker int num = 0;
1931*f6dc9357SAndroid Build Coastguard Worker for (int j = 0 ; j < num; j++)
1932*f6dc9357SAndroid Build Coastguard Worker {
1933*f6dc9357SAndroid Build Coastguard Worker if (Get32(data) != 0x1414 || // offset and size
1934*f6dc9357SAndroid Build Coastguard Worker Get32(data + 4) != 0 ||
1935*f6dc9357SAndroid Build Coastguard Worker Get32(data + 8) != 0x428) // KeySize / EntrySize
1936*f6dc9357SAndroid Build Coastguard Worker break;
1937*f6dc9357SAndroid Build Coastguard Worker UInt32 flags = Get32(data + 12);
1938*f6dc9357SAndroid Build Coastguard Worker UInt32 id = Get32(data + 0x10);
1939*f6dc9357SAndroid Build Coastguard Worker if (id = Get32(data + 0x18))
1940*f6dc9357SAndroid Build Coastguard Worker break;
1941*f6dc9357SAndroid Build Coastguard Worker UInt32 descriptorOffset = Get64(data + 0x1C);
1942*f6dc9357SAndroid Build Coastguard Worker UInt32 descriptorSize = Get64(data + 0x24);
1943*f6dc9357SAndroid Build Coastguard Worker data += 0x28;
1944*f6dc9357SAndroid Build Coastguard Worker }
1945*f6dc9357SAndroid Build Coastguard Worker // break;
1946*f6dc9357SAndroid Build Coastguard Worker }
1947*f6dc9357SAndroid Build Coastguard Worker }
1948*f6dc9357SAndroid Build Coastguard Worker }
1949*f6dc9357SAndroid Build Coastguard Worker */
1950*f6dc9357SAndroid Build Coastguard Worker
1951*f6dc9357SAndroid Build Coastguard Worker unsigned i;
1952*f6dc9357SAndroid Build Coastguard Worker
1953*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < Recs.Size(); i++)
1954*f6dc9357SAndroid Build Coastguard Worker {
1955*f6dc9357SAndroid Build Coastguard Worker CMftRec &rec = Recs[i];
1956*f6dc9357SAndroid Build Coastguard Worker if (!rec.Is_Magic_FILE())
1957*f6dc9357SAndroid Build Coastguard Worker continue;
1958*f6dc9357SAndroid Build Coastguard Worker
1959*f6dc9357SAndroid Build Coastguard Worker if (!rec.BaseMftRef.IsBaseItself())
1960*f6dc9357SAndroid Build Coastguard Worker {
1961*f6dc9357SAndroid Build Coastguard Worker const UInt64 refIndex = rec.BaseMftRef.GetIndex();
1962*f6dc9357SAndroid Build Coastguard Worker if (refIndex >= Recs.Size())
1963*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1964*f6dc9357SAndroid Build Coastguard Worker CMftRec &refRec = Recs[(unsigned)refIndex];
1965*f6dc9357SAndroid Build Coastguard Worker if (!refRec.Is_Magic_FILE())
1966*f6dc9357SAndroid Build Coastguard Worker continue;
1967*f6dc9357SAndroid Build Coastguard Worker
1968*f6dc9357SAndroid Build Coastguard Worker bool moveAttrs = (refRec.SeqNumber == rec.BaseMftRef.GetNumber() && refRec.BaseMftRef.IsBaseItself());
1969*f6dc9357SAndroid Build Coastguard Worker if (rec.InUse() && refRec.InUse())
1970*f6dc9357SAndroid Build Coastguard Worker {
1971*f6dc9357SAndroid Build Coastguard Worker if (!moveAttrs)
1972*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1973*f6dc9357SAndroid Build Coastguard Worker }
1974*f6dc9357SAndroid Build Coastguard Worker else if (rec.InUse() || refRec.InUse())
1975*f6dc9357SAndroid Build Coastguard Worker moveAttrs = false;
1976*f6dc9357SAndroid Build Coastguard Worker if (moveAttrs)
1977*f6dc9357SAndroid Build Coastguard Worker refRec.MoveAttrsFrom(rec);
1978*f6dc9357SAndroid Build Coastguard Worker }
1979*f6dc9357SAndroid Build Coastguard Worker }
1980*f6dc9357SAndroid Build Coastguard Worker
1981*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < Recs.Size(); i++)
1982*f6dc9357SAndroid Build Coastguard Worker {
1983*f6dc9357SAndroid Build Coastguard Worker CMftRec &rec = Recs[i];
1984*f6dc9357SAndroid Build Coastguard Worker if (!rec.Is_Magic_FILE())
1985*f6dc9357SAndroid Build Coastguard Worker continue;
1986*f6dc9357SAndroid Build Coastguard Worker rec.ParseDataNames();
1987*f6dc9357SAndroid Build Coastguard Worker }
1988*f6dc9357SAndroid Build Coastguard Worker
1989*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < Recs.Size(); i++)
1990*f6dc9357SAndroid Build Coastguard Worker {
1991*f6dc9357SAndroid Build Coastguard Worker CMftRec &rec = Recs[i];
1992*f6dc9357SAndroid Build Coastguard Worker if (!rec.Is_Magic_FILE() || !rec.BaseMftRef.IsBaseItself())
1993*f6dc9357SAndroid Build Coastguard Worker continue;
1994*f6dc9357SAndroid Build Coastguard Worker if (i < kNumSysRecs && !_showSystemFiles)
1995*f6dc9357SAndroid Build Coastguard Worker continue;
1996*f6dc9357SAndroid Build Coastguard Worker if (!rec.InUse() && !_showDeletedFiles)
1997*f6dc9357SAndroid Build Coastguard Worker continue;
1998*f6dc9357SAndroid Build Coastguard Worker
1999*f6dc9357SAndroid Build Coastguard Worker rec.MyNumNameLinks = rec.FileNames.Size();
2000*f6dc9357SAndroid Build Coastguard Worker
2001*f6dc9357SAndroid Build Coastguard Worker // printf("\n%4d: ", i);
2002*f6dc9357SAndroid Build Coastguard Worker
2003*f6dc9357SAndroid Build Coastguard Worker /* Actually DataAttrs / DataRefs are sorted by name.
2004*f6dc9357SAndroid Build Coastguard Worker It can not be more than one unnamed stream in DataRefs
2005*f6dc9357SAndroid Build Coastguard Worker And indexOfUnnamedStream <= 0.
2006*f6dc9357SAndroid Build Coastguard Worker */
2007*f6dc9357SAndroid Build Coastguard Worker
2008*f6dc9357SAndroid Build Coastguard Worker int indexOfUnnamedStream = -1;
2009*f6dc9357SAndroid Build Coastguard Worker if (!rec.IsDir())
2010*f6dc9357SAndroid Build Coastguard Worker {
2011*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (di, rec.DataRefs)
2012*f6dc9357SAndroid Build Coastguard Worker if (rec.DataAttrs[rec.DataRefs[di].Start].Name.IsEmpty())
2013*f6dc9357SAndroid Build Coastguard Worker {
2014*f6dc9357SAndroid Build Coastguard Worker indexOfUnnamedStream = (int)di;
2015*f6dc9357SAndroid Build Coastguard Worker break;
2016*f6dc9357SAndroid Build Coastguard Worker }
2017*f6dc9357SAndroid Build Coastguard Worker }
2018*f6dc9357SAndroid Build Coastguard Worker
2019*f6dc9357SAndroid Build Coastguard Worker if (rec.FileNames.IsEmpty())
2020*f6dc9357SAndroid Build Coastguard Worker {
2021*f6dc9357SAndroid Build Coastguard Worker bool needShow = true;
2022*f6dc9357SAndroid Build Coastguard Worker if (i < kNumSysRecs)
2023*f6dc9357SAndroid Build Coastguard Worker {
2024*f6dc9357SAndroid Build Coastguard Worker needShow = false;
2025*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (di, rec.DataRefs)
2026*f6dc9357SAndroid Build Coastguard Worker if (rec.GetSize(di) != 0)
2027*f6dc9357SAndroid Build Coastguard Worker {
2028*f6dc9357SAndroid Build Coastguard Worker needShow = true;
2029*f6dc9357SAndroid Build Coastguard Worker break;
2030*f6dc9357SAndroid Build Coastguard Worker }
2031*f6dc9357SAndroid Build Coastguard Worker }
2032*f6dc9357SAndroid Build Coastguard Worker if (needShow)
2033*f6dc9357SAndroid Build Coastguard Worker {
2034*f6dc9357SAndroid Build Coastguard Worker CFileNameAttr &fna = rec.FileNames.AddNew();
2035*f6dc9357SAndroid Build Coastguard Worker // we set incorrect ParentDirRef, that will place item to [LOST] folder
2036*f6dc9357SAndroid Build Coastguard Worker fna.ParentDirRef.Val = (UInt64)(Int64)-1;
2037*f6dc9357SAndroid Build Coastguard Worker char s[16 + 16];
2038*f6dc9357SAndroid Build Coastguard Worker ConvertUInt32ToString(i, MyStpCpy(s, "[NONAME]-"));
2039*f6dc9357SAndroid Build Coastguard Worker fna.Name.SetFromAscii(s);
2040*f6dc9357SAndroid Build Coastguard Worker fna.NameType = kFileNameType_Win32Dos;
2041*f6dc9357SAndroid Build Coastguard Worker fna.Attrib = 0;
2042*f6dc9357SAndroid Build Coastguard Worker }
2043*f6dc9357SAndroid Build Coastguard Worker }
2044*f6dc9357SAndroid Build Coastguard Worker
2045*f6dc9357SAndroid Build Coastguard Worker // bool isMainName = true;
2046*f6dc9357SAndroid Build Coastguard Worker
2047*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (t, rec.FileNames)
2048*f6dc9357SAndroid Build Coastguard Worker {
2049*f6dc9357SAndroid Build Coastguard Worker #ifdef SHOW_DEBUG_INFO
2050*f6dc9357SAndroid Build Coastguard Worker const CFileNameAttr &fna = rec.FileNames[t];
2051*f6dc9357SAndroid Build Coastguard Worker #endif
2052*f6dc9357SAndroid Build Coastguard Worker PRF(printf("\n %4d ", (int)fna.NameType));
2053*f6dc9357SAndroid Build Coastguard Worker PRF_UTF16(fna.Name);
2054*f6dc9357SAndroid Build Coastguard Worker // PRF(printf(" | "));
2055*f6dc9357SAndroid Build Coastguard Worker
2056*f6dc9357SAndroid Build Coastguard Worker if (rec.FindWin32Name_for_DosName(t) >= 0)
2057*f6dc9357SAndroid Build Coastguard Worker {
2058*f6dc9357SAndroid Build Coastguard Worker rec.MyNumNameLinks--;
2059*f6dc9357SAndroid Build Coastguard Worker continue;
2060*f6dc9357SAndroid Build Coastguard Worker }
2061*f6dc9357SAndroid Build Coastguard Worker
2062*f6dc9357SAndroid Build Coastguard Worker CItem item;
2063*f6dc9357SAndroid Build Coastguard Worker item.NameIndex = t;
2064*f6dc9357SAndroid Build Coastguard Worker item.RecIndex = i;
2065*f6dc9357SAndroid Build Coastguard Worker item.DataIndex = rec.IsDir() ?
2066*f6dc9357SAndroid Build Coastguard Worker k_Item_DataIndex_IsDir :
2067*f6dc9357SAndroid Build Coastguard Worker (indexOfUnnamedStream < 0 ?
2068*f6dc9357SAndroid Build Coastguard Worker k_Item_DataIndex_IsEmptyFile :
2069*f6dc9357SAndroid Build Coastguard Worker indexOfUnnamedStream);
2070*f6dc9357SAndroid Build Coastguard Worker
2071*f6dc9357SAndroid Build Coastguard Worker if (rec.MyItemIndex < 0)
2072*f6dc9357SAndroid Build Coastguard Worker rec.MyItemIndex = (int)Items.Size();
2073*f6dc9357SAndroid Build Coastguard Worker item.ParentHost = (int)Items.Add(item);
2074*f6dc9357SAndroid Build Coastguard Worker
2075*f6dc9357SAndroid Build Coastguard Worker /* we can use that code to reduce the number of alt streams:
2076*f6dc9357SAndroid Build Coastguard Worker it will not show how alt streams for hard links. */
2077*f6dc9357SAndroid Build Coastguard Worker // if (!isMainName) continue; isMainName = false;
2078*f6dc9357SAndroid Build Coastguard Worker
2079*f6dc9357SAndroid Build Coastguard Worker // unsigned numAltStreams = 0;
2080*f6dc9357SAndroid Build Coastguard Worker
2081*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (di, rec.DataRefs)
2082*f6dc9357SAndroid Build Coastguard Worker {
2083*f6dc9357SAndroid Build Coastguard Worker if (!rec.IsDir() && (int)di == indexOfUnnamedStream)
2084*f6dc9357SAndroid Build Coastguard Worker continue;
2085*f6dc9357SAndroid Build Coastguard Worker
2086*f6dc9357SAndroid Build Coastguard Worker const UString2 &subName = rec.DataAttrs[rec.DataRefs[di].Start].Name;
2087*f6dc9357SAndroid Build Coastguard Worker
2088*f6dc9357SAndroid Build Coastguard Worker PRF(printf("\n alt stream: "));
2089*f6dc9357SAndroid Build Coastguard Worker PRF_UTF16(subName);
2090*f6dc9357SAndroid Build Coastguard Worker
2091*f6dc9357SAndroid Build Coastguard Worker {
2092*f6dc9357SAndroid Build Coastguard Worker // $BadClus:$Bad is sparse file for all clusters. So we skip it.
2093*f6dc9357SAndroid Build Coastguard Worker if (i == kRecIndex_BadClus && subName == L"$Bad")
2094*f6dc9357SAndroid Build Coastguard Worker continue;
2095*f6dc9357SAndroid Build Coastguard Worker }
2096*f6dc9357SAndroid Build Coastguard Worker
2097*f6dc9357SAndroid Build Coastguard Worker // numAltStreams++;
2098*f6dc9357SAndroid Build Coastguard Worker ThereAreAltStreams = true;
2099*f6dc9357SAndroid Build Coastguard Worker item.DataIndex = (int)di;
2100*f6dc9357SAndroid Build Coastguard Worker Items.Add(item);
2101*f6dc9357SAndroid Build Coastguard Worker }
2102*f6dc9357SAndroid Build Coastguard Worker }
2103*f6dc9357SAndroid Build Coastguard Worker }
2104*f6dc9357SAndroid Build Coastguard Worker
2105*f6dc9357SAndroid Build Coastguard Worker if (Recs.Size() > kRecIndex_Security)
2106*f6dc9357SAndroid Build Coastguard Worker {
2107*f6dc9357SAndroid Build Coastguard Worker const CMftRec &rec = Recs[kRecIndex_Security];
2108*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (di, rec.DataRefs)
2109*f6dc9357SAndroid Build Coastguard Worker {
2110*f6dc9357SAndroid Build Coastguard Worker const CAttr &attr = rec.DataAttrs[rec.DataRefs[di].Start];
2111*f6dc9357SAndroid Build Coastguard Worker if (attr.Name == L"$SDS")
2112*f6dc9357SAndroid Build Coastguard Worker {
2113*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<IInStream> sdsStream;
2114*f6dc9357SAndroid Build Coastguard Worker RINOK(rec.GetStream(InStream, (int)di, Header.ClusterSizeLog, Header.NumClusters, &sdsStream))
2115*f6dc9357SAndroid Build Coastguard Worker if (sdsStream)
2116*f6dc9357SAndroid Build Coastguard Worker {
2117*f6dc9357SAndroid Build Coastguard Worker const UInt64 size64 = attr.GetSize();
2118*f6dc9357SAndroid Build Coastguard Worker if (size64 < (UInt32)1 << 29)
2119*f6dc9357SAndroid Build Coastguard Worker {
2120*f6dc9357SAndroid Build Coastguard Worker size_t size = (size_t)size64;
2121*f6dc9357SAndroid Build Coastguard Worker if ((((size + 1) >> kSecureDuplicateStepBits) & 1) != 0)
2122*f6dc9357SAndroid Build Coastguard Worker {
2123*f6dc9357SAndroid Build Coastguard Worker size -= (1 << kSecureDuplicateStepBits);
2124*f6dc9357SAndroid Build Coastguard Worker SecurData.Alloc(size);
2125*f6dc9357SAndroid Build Coastguard Worker if (ReadStream_FALSE(sdsStream, SecurData, size) == S_OK)
2126*f6dc9357SAndroid Build Coastguard Worker {
2127*f6dc9357SAndroid Build Coastguard Worker ParseSecuritySDS();
2128*f6dc9357SAndroid Build Coastguard Worker break;
2129*f6dc9357SAndroid Build Coastguard Worker }
2130*f6dc9357SAndroid Build Coastguard Worker }
2131*f6dc9357SAndroid Build Coastguard Worker }
2132*f6dc9357SAndroid Build Coastguard Worker }
2133*f6dc9357SAndroid Build Coastguard Worker break;
2134*f6dc9357SAndroid Build Coastguard Worker }
2135*f6dc9357SAndroid Build Coastguard Worker }
2136*f6dc9357SAndroid Build Coastguard Worker }
2137*f6dc9357SAndroid Build Coastguard Worker
2138*f6dc9357SAndroid Build Coastguard Worker bool thereAreUnknownFolders_Normal = false;
2139*f6dc9357SAndroid Build Coastguard Worker bool thereAreUnknownFolders_Deleted = false;
2140*f6dc9357SAndroid Build Coastguard Worker
2141*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < Items.Size(); i++)
2142*f6dc9357SAndroid Build Coastguard Worker {
2143*f6dc9357SAndroid Build Coastguard Worker CItem &item = Items[i];
2144*f6dc9357SAndroid Build Coastguard Worker const CMftRec &rec = Recs[item.RecIndex];
2145*f6dc9357SAndroid Build Coastguard Worker const CFileNameAttr &fn = rec.FileNames[item.NameIndex];
2146*f6dc9357SAndroid Build Coastguard Worker const CMftRef &parentDirRef = fn.ParentDirRef;
2147*f6dc9357SAndroid Build Coastguard Worker const UInt64 refIndex = parentDirRef.GetIndex();
2148*f6dc9357SAndroid Build Coastguard Worker if (refIndex == kRecIndex_RootDir)
2149*f6dc9357SAndroid Build Coastguard Worker item.ParentFolder = -1;
2150*f6dc9357SAndroid Build Coastguard Worker else
2151*f6dc9357SAndroid Build Coastguard Worker {
2152*f6dc9357SAndroid Build Coastguard Worker int index = Find_DirItem_For_MftRec(refIndex);
2153*f6dc9357SAndroid Build Coastguard Worker if (index < 0 ||
2154*f6dc9357SAndroid Build Coastguard Worker Recs[Items[index].RecIndex].SeqNumber != parentDirRef.GetNumber())
2155*f6dc9357SAndroid Build Coastguard Worker {
2156*f6dc9357SAndroid Build Coastguard Worker if (Recs[item.RecIndex].InUse())
2157*f6dc9357SAndroid Build Coastguard Worker {
2158*f6dc9357SAndroid Build Coastguard Worker thereAreUnknownFolders_Normal = true;
2159*f6dc9357SAndroid Build Coastguard Worker index = k_ParentFolderIndex_Lost;
2160*f6dc9357SAndroid Build Coastguard Worker }
2161*f6dc9357SAndroid Build Coastguard Worker else
2162*f6dc9357SAndroid Build Coastguard Worker {
2163*f6dc9357SAndroid Build Coastguard Worker thereAreUnknownFolders_Deleted = true;
2164*f6dc9357SAndroid Build Coastguard Worker index = k_ParentFolderIndex_Deleted;
2165*f6dc9357SAndroid Build Coastguard Worker }
2166*f6dc9357SAndroid Build Coastguard Worker }
2167*f6dc9357SAndroid Build Coastguard Worker item.ParentFolder = index;
2168*f6dc9357SAndroid Build Coastguard Worker }
2169*f6dc9357SAndroid Build Coastguard Worker }
2170*f6dc9357SAndroid Build Coastguard Worker
2171*f6dc9357SAndroid Build Coastguard Worker unsigned virtIndex = Items.Size();
2172*f6dc9357SAndroid Build Coastguard Worker if (_showSystemFiles)
2173*f6dc9357SAndroid Build Coastguard Worker {
2174*f6dc9357SAndroid Build Coastguard Worker _systemFolderIndex = (int)(virtIndex++);
2175*f6dc9357SAndroid Build Coastguard Worker VirtFolderNames.Add(kVirtualFolder_System);
2176*f6dc9357SAndroid Build Coastguard Worker }
2177*f6dc9357SAndroid Build Coastguard Worker if (thereAreUnknownFolders_Normal)
2178*f6dc9357SAndroid Build Coastguard Worker {
2179*f6dc9357SAndroid Build Coastguard Worker _lostFolderIndex_Normal = (int)(virtIndex++);
2180*f6dc9357SAndroid Build Coastguard Worker VirtFolderNames.Add(kVirtualFolder_Lost_Normal);
2181*f6dc9357SAndroid Build Coastguard Worker }
2182*f6dc9357SAndroid Build Coastguard Worker if (thereAreUnknownFolders_Deleted)
2183*f6dc9357SAndroid Build Coastguard Worker {
2184*f6dc9357SAndroid Build Coastguard Worker _lostFolderIndex_Deleted = (int)(virtIndex++);
2185*f6dc9357SAndroid Build Coastguard Worker VirtFolderNames.Add(kVirtualFolder_Lost_Deleted);
2186*f6dc9357SAndroid Build Coastguard Worker }
2187*f6dc9357SAndroid Build Coastguard Worker
2188*f6dc9357SAndroid Build Coastguard Worker return S_OK;
2189*f6dc9357SAndroid Build Coastguard Worker }
2190*f6dc9357SAndroid Build Coastguard Worker
2191*f6dc9357SAndroid Build Coastguard Worker Z7_class_CHandler_final:
2192*f6dc9357SAndroid Build Coastguard Worker public IInArchive,
2193*f6dc9357SAndroid Build Coastguard Worker public IArchiveGetRawProps,
2194*f6dc9357SAndroid Build Coastguard Worker public IInArchiveGetStream,
2195*f6dc9357SAndroid Build Coastguard Worker public ISetProperties,
2196*f6dc9357SAndroid Build Coastguard Worker public CMyUnknownImp,
2197*f6dc9357SAndroid Build Coastguard Worker public CDatabase
2198*f6dc9357SAndroid Build Coastguard Worker {
2199*f6dc9357SAndroid Build Coastguard Worker Z7_IFACES_IMP_UNK_4(
2200*f6dc9357SAndroid Build Coastguard Worker IInArchive,
2201*f6dc9357SAndroid Build Coastguard Worker IArchiveGetRawProps,
2202*f6dc9357SAndroid Build Coastguard Worker IInArchiveGetStream,
2203*f6dc9357SAndroid Build Coastguard Worker ISetProperties)
2204*f6dc9357SAndroid Build Coastguard Worker };
2205*f6dc9357SAndroid Build Coastguard Worker
2206*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetNumRawProps(UInt32 *numProps))
2207*f6dc9357SAndroid Build Coastguard Worker {
2208*f6dc9357SAndroid Build Coastguard Worker *numProps = 2;
2209*f6dc9357SAndroid Build Coastguard Worker return S_OK;
2210*f6dc9357SAndroid Build Coastguard Worker }
2211*f6dc9357SAndroid Build Coastguard Worker
2212*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetRawPropInfo(UInt32 index, BSTR *name, PROPID *propID))
2213*f6dc9357SAndroid Build Coastguard Worker {
2214*f6dc9357SAndroid Build Coastguard Worker *name = NULL;
2215*f6dc9357SAndroid Build Coastguard Worker *propID = index == 0 ? kpidNtReparse : kpidNtSecure;
2216*f6dc9357SAndroid Build Coastguard Worker return S_OK;
2217*f6dc9357SAndroid Build Coastguard Worker }
2218*f6dc9357SAndroid Build Coastguard Worker
2219*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetParent(UInt32 index, UInt32 *parent, UInt32 *parentType))
2220*f6dc9357SAndroid Build Coastguard Worker {
2221*f6dc9357SAndroid Build Coastguard Worker *parentType = NParentType::kDir;
2222*f6dc9357SAndroid Build Coastguard Worker int par = -1;
2223*f6dc9357SAndroid Build Coastguard Worker
2224*f6dc9357SAndroid Build Coastguard Worker if (index < Items.Size())
2225*f6dc9357SAndroid Build Coastguard Worker {
2226*f6dc9357SAndroid Build Coastguard Worker const CItem &item = Items[index];
2227*f6dc9357SAndroid Build Coastguard Worker
2228*f6dc9357SAndroid Build Coastguard Worker if (item.ParentHost >= 0)
2229*f6dc9357SAndroid Build Coastguard Worker {
2230*f6dc9357SAndroid Build Coastguard Worker *parentType = NParentType::kAltStream;
2231*f6dc9357SAndroid Build Coastguard Worker par = (item.RecIndex == kRecIndex_RootDir ? -1 : item.ParentHost);
2232*f6dc9357SAndroid Build Coastguard Worker }
2233*f6dc9357SAndroid Build Coastguard Worker else if (item.RecIndex < kNumSysRecs)
2234*f6dc9357SAndroid Build Coastguard Worker {
2235*f6dc9357SAndroid Build Coastguard Worker if (_showSystemFiles)
2236*f6dc9357SAndroid Build Coastguard Worker par = _systemFolderIndex;
2237*f6dc9357SAndroid Build Coastguard Worker }
2238*f6dc9357SAndroid Build Coastguard Worker else if (item.ParentFolder >= 0)
2239*f6dc9357SAndroid Build Coastguard Worker par = item.ParentFolder;
2240*f6dc9357SAndroid Build Coastguard Worker else if (item.ParentFolder == k_ParentFolderIndex_Lost)
2241*f6dc9357SAndroid Build Coastguard Worker par = _lostFolderIndex_Normal;
2242*f6dc9357SAndroid Build Coastguard Worker else if (item.ParentFolder == k_ParentFolderIndex_Deleted)
2243*f6dc9357SAndroid Build Coastguard Worker par = _lostFolderIndex_Deleted;
2244*f6dc9357SAndroid Build Coastguard Worker }
2245*f6dc9357SAndroid Build Coastguard Worker *parent = (UInt32)(Int32)par;
2246*f6dc9357SAndroid Build Coastguard Worker return S_OK;
2247*f6dc9357SAndroid Build Coastguard Worker }
2248*f6dc9357SAndroid Build Coastguard Worker
2249*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType))
2250*f6dc9357SAndroid Build Coastguard Worker {
2251*f6dc9357SAndroid Build Coastguard Worker *data = NULL;
2252*f6dc9357SAndroid Build Coastguard Worker *dataSize = 0;
2253*f6dc9357SAndroid Build Coastguard Worker *propType = 0;
2254*f6dc9357SAndroid Build Coastguard Worker
2255*f6dc9357SAndroid Build Coastguard Worker if (propID == kpidName)
2256*f6dc9357SAndroid Build Coastguard Worker {
2257*f6dc9357SAndroid Build Coastguard Worker #ifdef MY_CPU_LE
2258*f6dc9357SAndroid Build Coastguard Worker const UString2 *s;
2259*f6dc9357SAndroid Build Coastguard Worker if (index >= Items.Size())
2260*f6dc9357SAndroid Build Coastguard Worker s = &VirtFolderNames[index - Items.Size()];
2261*f6dc9357SAndroid Build Coastguard Worker else
2262*f6dc9357SAndroid Build Coastguard Worker {
2263*f6dc9357SAndroid Build Coastguard Worker const CItem &item = Items[index];
2264*f6dc9357SAndroid Build Coastguard Worker const CMftRec &rec = Recs[item.RecIndex];
2265*f6dc9357SAndroid Build Coastguard Worker if (item.IsAltStream())
2266*f6dc9357SAndroid Build Coastguard Worker s = &rec.DataAttrs[rec.DataRefs[item.DataIndex].Start].Name;
2267*f6dc9357SAndroid Build Coastguard Worker else
2268*f6dc9357SAndroid Build Coastguard Worker s = &rec.FileNames[item.NameIndex].Name;
2269*f6dc9357SAndroid Build Coastguard Worker }
2270*f6dc9357SAndroid Build Coastguard Worker if (s->IsEmpty())
2271*f6dc9357SAndroid Build Coastguard Worker *data = (const wchar_t *)EmptyString;
2272*f6dc9357SAndroid Build Coastguard Worker else
2273*f6dc9357SAndroid Build Coastguard Worker *data = s->GetRawPtr();
2274*f6dc9357SAndroid Build Coastguard Worker *dataSize = (s->Len() + 1) * (UInt32)sizeof(wchar_t);
2275*f6dc9357SAndroid Build Coastguard Worker *propType = PROP_DATA_TYPE_wchar_t_PTR_Z_LE;
2276*f6dc9357SAndroid Build Coastguard Worker #endif
2277*f6dc9357SAndroid Build Coastguard Worker return S_OK;
2278*f6dc9357SAndroid Build Coastguard Worker }
2279*f6dc9357SAndroid Build Coastguard Worker
2280*f6dc9357SAndroid Build Coastguard Worker if (propID == kpidNtReparse)
2281*f6dc9357SAndroid Build Coastguard Worker {
2282*f6dc9357SAndroid Build Coastguard Worker if (index >= Items.Size())
2283*f6dc9357SAndroid Build Coastguard Worker return S_OK;
2284*f6dc9357SAndroid Build Coastguard Worker const CItem &item = Items[index];
2285*f6dc9357SAndroid Build Coastguard Worker const CMftRec &rec = Recs[item.RecIndex];
2286*f6dc9357SAndroid Build Coastguard Worker const CByteBuffer &reparse = rec.ReparseData;
2287*f6dc9357SAndroid Build Coastguard Worker
2288*f6dc9357SAndroid Build Coastguard Worker if (reparse.Size() != 0)
2289*f6dc9357SAndroid Build Coastguard Worker {
2290*f6dc9357SAndroid Build Coastguard Worker *dataSize = (UInt32)reparse.Size();
2291*f6dc9357SAndroid Build Coastguard Worker *propType = NPropDataType::kRaw;
2292*f6dc9357SAndroid Build Coastguard Worker *data = (const Byte *)reparse;
2293*f6dc9357SAndroid Build Coastguard Worker }
2294*f6dc9357SAndroid Build Coastguard Worker }
2295*f6dc9357SAndroid Build Coastguard Worker
2296*f6dc9357SAndroid Build Coastguard Worker if (propID == kpidNtSecure)
2297*f6dc9357SAndroid Build Coastguard Worker {
2298*f6dc9357SAndroid Build Coastguard Worker if (index >= Items.Size())
2299*f6dc9357SAndroid Build Coastguard Worker return S_OK;
2300*f6dc9357SAndroid Build Coastguard Worker const CItem &item = Items[index];
2301*f6dc9357SAndroid Build Coastguard Worker const CMftRec &rec = Recs[item.RecIndex];
2302*f6dc9357SAndroid Build Coastguard Worker if (rec.SiAttr.SecurityId > 0)
2303*f6dc9357SAndroid Build Coastguard Worker {
2304*f6dc9357SAndroid Build Coastguard Worker UInt64 offset;
2305*f6dc9357SAndroid Build Coastguard Worker UInt32 size;
2306*f6dc9357SAndroid Build Coastguard Worker if (FindSecurityDescritor(rec.SiAttr.SecurityId, offset, size))
2307*f6dc9357SAndroid Build Coastguard Worker {
2308*f6dc9357SAndroid Build Coastguard Worker *dataSize = size;
2309*f6dc9357SAndroid Build Coastguard Worker *propType = NPropDataType::kRaw;
2310*f6dc9357SAndroid Build Coastguard Worker *data = (const Byte *)SecurData + offset;
2311*f6dc9357SAndroid Build Coastguard Worker }
2312*f6dc9357SAndroid Build Coastguard Worker }
2313*f6dc9357SAndroid Build Coastguard Worker }
2314*f6dc9357SAndroid Build Coastguard Worker
2315*f6dc9357SAndroid Build Coastguard Worker return S_OK;
2316*f6dc9357SAndroid Build Coastguard Worker }
2317*f6dc9357SAndroid Build Coastguard Worker
2318*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))
2319*f6dc9357SAndroid Build Coastguard Worker {
2320*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
2321*f6dc9357SAndroid Build Coastguard Worker *stream = NULL;
2322*f6dc9357SAndroid Build Coastguard Worker if (index >= Items.Size())
2323*f6dc9357SAndroid Build Coastguard Worker return S_OK;
2324*f6dc9357SAndroid Build Coastguard Worker IInStream *stream2;
2325*f6dc9357SAndroid Build Coastguard Worker const CItem &item = Items[index];
2326*f6dc9357SAndroid Build Coastguard Worker const CMftRec &rec = Recs[item.RecIndex];
2327*f6dc9357SAndroid Build Coastguard Worker HRESULT res = rec.GetStream(InStream, item.DataIndex, Header.ClusterSizeLog, Header.NumClusters, &stream2);
2328*f6dc9357SAndroid Build Coastguard Worker *stream = (ISequentialInStream *)stream2;
2329*f6dc9357SAndroid Build Coastguard Worker return res;
2330*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
2331*f6dc9357SAndroid Build Coastguard Worker }
2332*f6dc9357SAndroid Build Coastguard Worker
2333*f6dc9357SAndroid Build Coastguard Worker /*
2334*f6dc9357SAndroid Build Coastguard Worker enum
2335*f6dc9357SAndroid Build Coastguard Worker {
2336*f6dc9357SAndroid Build Coastguard Worker kpidLink2 = kpidUserDefined,
2337*f6dc9357SAndroid Build Coastguard Worker kpidLinkType,
2338*f6dc9357SAndroid Build Coastguard Worker kpidRecMTime,
2339*f6dc9357SAndroid Build Coastguard Worker kpidRecMTime2,
2340*f6dc9357SAndroid Build Coastguard Worker kpidMTime2,
2341*f6dc9357SAndroid Build Coastguard Worker kpidCTime2,
2342*f6dc9357SAndroid Build Coastguard Worker kpidATime2
2343*f6dc9357SAndroid Build Coastguard Worker };
2344*f6dc9357SAndroid Build Coastguard Worker
2345*f6dc9357SAndroid Build Coastguard Worker static const CStatProp kProps[] =
2346*f6dc9357SAndroid Build Coastguard Worker {
2347*f6dc9357SAndroid Build Coastguard Worker { NULL, kpidPath, VT_BSTR},
2348*f6dc9357SAndroid Build Coastguard Worker { NULL, kpidSize, VT_UI8},
2349*f6dc9357SAndroid Build Coastguard Worker { NULL, kpidPackSize, VT_UI8},
2350*f6dc9357SAndroid Build Coastguard Worker
2351*f6dc9357SAndroid Build Coastguard Worker // { NULL, kpidLink, VT_BSTR},
2352*f6dc9357SAndroid Build Coastguard Worker
2353*f6dc9357SAndroid Build Coastguard Worker // { "Link 2", kpidLink2, VT_BSTR},
2354*f6dc9357SAndroid Build Coastguard Worker // { "Link Type", kpidLinkType, VT_UI2},
2355*f6dc9357SAndroid Build Coastguard Worker { NULL, kpidINode, VT_UI8},
2356*f6dc9357SAndroid Build Coastguard Worker
2357*f6dc9357SAndroid Build Coastguard Worker { NULL, kpidMTime, VT_FILETIME},
2358*f6dc9357SAndroid Build Coastguard Worker { NULL, kpidCTime, VT_FILETIME},
2359*f6dc9357SAndroid Build Coastguard Worker { NULL, kpidATime, VT_FILETIME},
2360*f6dc9357SAndroid Build Coastguard Worker
2361*f6dc9357SAndroid Build Coastguard Worker // { "Record Modified", kpidRecMTime, VT_FILETIME},
2362*f6dc9357SAndroid Build Coastguard Worker
2363*f6dc9357SAndroid Build Coastguard Worker // { "Modified 2", kpidMTime2, VT_FILETIME},
2364*f6dc9357SAndroid Build Coastguard Worker // { "Created 2", kpidCTime2, VT_FILETIME},
2365*f6dc9357SAndroid Build Coastguard Worker // { "Accessed 2", kpidATime2, VT_FILETIME},
2366*f6dc9357SAndroid Build Coastguard Worker // { "Record Modified 2", kpidRecMTime2, VT_FILETIME},
2367*f6dc9357SAndroid Build Coastguard Worker
2368*f6dc9357SAndroid Build Coastguard Worker { NULL, kpidAttrib, VT_UI4},
2369*f6dc9357SAndroid Build Coastguard Worker { NULL, kpidNumBlocks, VT_UI4},
2370*f6dc9357SAndroid Build Coastguard Worker { NULL, kpidIsDeleted, VT_BOOL},
2371*f6dc9357SAndroid Build Coastguard Worker };
2372*f6dc9357SAndroid Build Coastguard Worker */
2373*f6dc9357SAndroid Build Coastguard Worker
2374*f6dc9357SAndroid Build Coastguard Worker static const Byte kProps[] =
2375*f6dc9357SAndroid Build Coastguard Worker {
2376*f6dc9357SAndroid Build Coastguard Worker kpidPath,
2377*f6dc9357SAndroid Build Coastguard Worker kpidIsDir,
2378*f6dc9357SAndroid Build Coastguard Worker kpidSize,
2379*f6dc9357SAndroid Build Coastguard Worker kpidPackSize,
2380*f6dc9357SAndroid Build Coastguard Worker kpidMTime,
2381*f6dc9357SAndroid Build Coastguard Worker kpidCTime,
2382*f6dc9357SAndroid Build Coastguard Worker kpidATime,
2383*f6dc9357SAndroid Build Coastguard Worker kpidChangeTime,
2384*f6dc9357SAndroid Build Coastguard Worker kpidAttrib,
2385*f6dc9357SAndroid Build Coastguard Worker kpidLinks,
2386*f6dc9357SAndroid Build Coastguard Worker kpidINode,
2387*f6dc9357SAndroid Build Coastguard Worker kpidNumBlocks,
2388*f6dc9357SAndroid Build Coastguard Worker kpidNumAltStreams,
2389*f6dc9357SAndroid Build Coastguard Worker kpidIsAltStream,
2390*f6dc9357SAndroid Build Coastguard Worker kpidShortName,
2391*f6dc9357SAndroid Build Coastguard Worker kpidIsDeleted
2392*f6dc9357SAndroid Build Coastguard Worker };
2393*f6dc9357SAndroid Build Coastguard Worker
2394*f6dc9357SAndroid Build Coastguard Worker enum
2395*f6dc9357SAndroid Build Coastguard Worker {
2396*f6dc9357SAndroid Build Coastguard Worker kpidRecordSize = kpidUserDefined
2397*f6dc9357SAndroid Build Coastguard Worker };
2398*f6dc9357SAndroid Build Coastguard Worker
2399*f6dc9357SAndroid Build Coastguard Worker static const CStatProp kArcProps[] =
2400*f6dc9357SAndroid Build Coastguard Worker {
2401*f6dc9357SAndroid Build Coastguard Worker { NULL, kpidVolumeName, VT_BSTR},
2402*f6dc9357SAndroid Build Coastguard Worker { NULL, kpidFileSystem, VT_BSTR},
2403*f6dc9357SAndroid Build Coastguard Worker { NULL, kpidClusterSize, VT_UI4},
2404*f6dc9357SAndroid Build Coastguard Worker { NULL, kpidSectorSize, VT_UI4},
2405*f6dc9357SAndroid Build Coastguard Worker { "MFT Record Size", kpidRecordSize, VT_UI4},
2406*f6dc9357SAndroid Build Coastguard Worker { NULL, kpidHeadersSize, VT_UI8},
2407*f6dc9357SAndroid Build Coastguard Worker { NULL, kpidCTime, VT_FILETIME},
2408*f6dc9357SAndroid Build Coastguard Worker { NULL, kpidId, VT_UI8},
2409*f6dc9357SAndroid Build Coastguard Worker };
2410*f6dc9357SAndroid Build Coastguard Worker
2411*f6dc9357SAndroid Build Coastguard Worker /*
2412*f6dc9357SAndroid Build Coastguard Worker static const Byte kArcProps[] =
2413*f6dc9357SAndroid Build Coastguard Worker {
2414*f6dc9357SAndroid Build Coastguard Worker kpidVolumeName,
2415*f6dc9357SAndroid Build Coastguard Worker kpidFileSystem,
2416*f6dc9357SAndroid Build Coastguard Worker kpidClusterSize,
2417*f6dc9357SAndroid Build Coastguard Worker kpidHeadersSize,
2418*f6dc9357SAndroid Build Coastguard Worker kpidCTime,
2419*f6dc9357SAndroid Build Coastguard Worker
2420*f6dc9357SAndroid Build Coastguard Worker kpidSectorSize,
2421*f6dc9357SAndroid Build Coastguard Worker kpidId
2422*f6dc9357SAndroid Build Coastguard Worker // kpidSectorsPerTrack,
2423*f6dc9357SAndroid Build Coastguard Worker // kpidNumHeads,
2424*f6dc9357SAndroid Build Coastguard Worker // kpidHiddenSectors
2425*f6dc9357SAndroid Build Coastguard Worker };
2426*f6dc9357SAndroid Build Coastguard Worker */
2427*f6dc9357SAndroid Build Coastguard Worker
2428*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_Props
2429*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_ArcProps_WITH_NAME
2430*f6dc9357SAndroid Build Coastguard Worker
2431*f6dc9357SAndroid Build Coastguard Worker static void NtfsTimeToProp(UInt64 t, NCOM::CPropVariant &prop)
2432*f6dc9357SAndroid Build Coastguard Worker {
2433*f6dc9357SAndroid Build Coastguard Worker FILETIME ft;
2434*f6dc9357SAndroid Build Coastguard Worker ft.dwLowDateTime = (DWORD)t;
2435*f6dc9357SAndroid Build Coastguard Worker ft.dwHighDateTime = (DWORD)(t >> 32);
2436*f6dc9357SAndroid Build Coastguard Worker prop = ft;
2437*f6dc9357SAndroid Build Coastguard Worker }
2438*f6dc9357SAndroid Build Coastguard Worker
2439*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
2440*f6dc9357SAndroid Build Coastguard Worker {
2441*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
2442*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant prop;
2443*f6dc9357SAndroid Build Coastguard Worker
2444*f6dc9357SAndroid Build Coastguard Worker const CMftRec *volRec = (Recs.Size() > kRecIndex_Volume ? &Recs[kRecIndex_Volume] : NULL);
2445*f6dc9357SAndroid Build Coastguard Worker
2446*f6dc9357SAndroid Build Coastguard Worker switch (propID)
2447*f6dc9357SAndroid Build Coastguard Worker {
2448*f6dc9357SAndroid Build Coastguard Worker case kpidClusterSize: prop = Header.ClusterSize(); break;
2449*f6dc9357SAndroid Build Coastguard Worker case kpidPhySize: prop = PhySize; break;
2450*f6dc9357SAndroid Build Coastguard Worker /*
2451*f6dc9357SAndroid Build Coastguard Worker case kpidHeadersSize:
2452*f6dc9357SAndroid Build Coastguard Worker {
2453*f6dc9357SAndroid Build Coastguard Worker UInt64 val = 0;
2454*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < kNumSysRecs; i++)
2455*f6dc9357SAndroid Build Coastguard Worker {
2456*f6dc9357SAndroid Build Coastguard Worker printf("\n%2d: %8I64d ", i, Recs[i].GetPackSize());
2457*f6dc9357SAndroid Build Coastguard Worker if (i == 8)
2458*f6dc9357SAndroid Build Coastguard Worker i = i
2459*f6dc9357SAndroid Build Coastguard Worker val += Recs[i].GetPackSize();
2460*f6dc9357SAndroid Build Coastguard Worker }
2461*f6dc9357SAndroid Build Coastguard Worker prop = val;
2462*f6dc9357SAndroid Build Coastguard Worker break;
2463*f6dc9357SAndroid Build Coastguard Worker }
2464*f6dc9357SAndroid Build Coastguard Worker */
2465*f6dc9357SAndroid Build Coastguard Worker case kpidCTime: if (volRec) NtfsTimeToProp(volRec->SiAttr.CTime, prop); break;
2466*f6dc9357SAndroid Build Coastguard Worker case kpidMTime: if (volRec) NtfsTimeToProp(volRec->SiAttr.MTime, prop); break;
2467*f6dc9357SAndroid Build Coastguard Worker case kpidShortComment:
2468*f6dc9357SAndroid Build Coastguard Worker case kpidVolumeName:
2469*f6dc9357SAndroid Build Coastguard Worker {
2470*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (i, VolAttrs)
2471*f6dc9357SAndroid Build Coastguard Worker {
2472*f6dc9357SAndroid Build Coastguard Worker const CAttr &attr = VolAttrs[i];
2473*f6dc9357SAndroid Build Coastguard Worker if (attr.Type == ATTR_TYPE_VOLUME_NAME)
2474*f6dc9357SAndroid Build Coastguard Worker {
2475*f6dc9357SAndroid Build Coastguard Worker UString2 name;
2476*f6dc9357SAndroid Build Coastguard Worker GetString(attr.Data, (unsigned)attr.Data.Size() / 2, name);
2477*f6dc9357SAndroid Build Coastguard Worker if (!name.IsEmpty())
2478*f6dc9357SAndroid Build Coastguard Worker prop = name.GetRawPtr();
2479*f6dc9357SAndroid Build Coastguard Worker break;
2480*f6dc9357SAndroid Build Coastguard Worker }
2481*f6dc9357SAndroid Build Coastguard Worker }
2482*f6dc9357SAndroid Build Coastguard Worker break;
2483*f6dc9357SAndroid Build Coastguard Worker }
2484*f6dc9357SAndroid Build Coastguard Worker case kpidFileSystem:
2485*f6dc9357SAndroid Build Coastguard Worker {
2486*f6dc9357SAndroid Build Coastguard Worker AString s ("NTFS");
2487*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (i, VolAttrs)
2488*f6dc9357SAndroid Build Coastguard Worker {
2489*f6dc9357SAndroid Build Coastguard Worker const CAttr &attr = VolAttrs[i];
2490*f6dc9357SAndroid Build Coastguard Worker if (attr.Type == ATTR_TYPE_VOLUME_INFO)
2491*f6dc9357SAndroid Build Coastguard Worker {
2492*f6dc9357SAndroid Build Coastguard Worker CVolInfo vi;
2493*f6dc9357SAndroid Build Coastguard Worker if (attr.ParseVolInfo(vi))
2494*f6dc9357SAndroid Build Coastguard Worker {
2495*f6dc9357SAndroid Build Coastguard Worker s.Add_Space();
2496*f6dc9357SAndroid Build Coastguard Worker s.Add_UInt32(vi.MajorVer);
2497*f6dc9357SAndroid Build Coastguard Worker s.Add_Dot();
2498*f6dc9357SAndroid Build Coastguard Worker s.Add_UInt32(vi.MinorVer);
2499*f6dc9357SAndroid Build Coastguard Worker }
2500*f6dc9357SAndroid Build Coastguard Worker break;
2501*f6dc9357SAndroid Build Coastguard Worker }
2502*f6dc9357SAndroid Build Coastguard Worker }
2503*f6dc9357SAndroid Build Coastguard Worker prop = s;
2504*f6dc9357SAndroid Build Coastguard Worker break;
2505*f6dc9357SAndroid Build Coastguard Worker }
2506*f6dc9357SAndroid Build Coastguard Worker case kpidSectorSize: prop = (UInt32)1 << Header.SectorSizeLog; break;
2507*f6dc9357SAndroid Build Coastguard Worker case kpidRecordSize: prop = (UInt32)1 << Header.MftRecordSizeLog; break;
2508*f6dc9357SAndroid Build Coastguard Worker case kpidId: prop = Header.SerialNumber; break;
2509*f6dc9357SAndroid Build Coastguard Worker
2510*f6dc9357SAndroid Build Coastguard Worker case kpidIsTree: prop = true; break;
2511*f6dc9357SAndroid Build Coastguard Worker case kpidIsDeleted: prop = _showDeletedFiles; break;
2512*f6dc9357SAndroid Build Coastguard Worker case kpidIsAltStream: prop = ThereAreAltStreams; break;
2513*f6dc9357SAndroid Build Coastguard Worker case kpidIsAux: prop = true; break;
2514*f6dc9357SAndroid Build Coastguard Worker case kpidINode: prop = true; break;
2515*f6dc9357SAndroid Build Coastguard Worker
2516*f6dc9357SAndroid Build Coastguard Worker case kpidWarning:
2517*f6dc9357SAndroid Build Coastguard Worker if (_lostFolderIndex_Normal >= 0)
2518*f6dc9357SAndroid Build Coastguard Worker prop = "There are lost files";
2519*f6dc9357SAndroid Build Coastguard Worker break;
2520*f6dc9357SAndroid Build Coastguard Worker
2521*f6dc9357SAndroid Build Coastguard Worker /*
2522*f6dc9357SAndroid Build Coastguard Worker case kpidWarningFlags:
2523*f6dc9357SAndroid Build Coastguard Worker {
2524*f6dc9357SAndroid Build Coastguard Worker UInt32 flags = 0;
2525*f6dc9357SAndroid Build Coastguard Worker if (_headerWarning)
2526*f6dc9357SAndroid Build Coastguard Worker flags |= k_ErrorFlags_HeadersError;
2527*f6dc9357SAndroid Build Coastguard Worker if (flags != 0)
2528*f6dc9357SAndroid Build Coastguard Worker prop = flags;
2529*f6dc9357SAndroid Build Coastguard Worker break;
2530*f6dc9357SAndroid Build Coastguard Worker }
2531*f6dc9357SAndroid Build Coastguard Worker */
2532*f6dc9357SAndroid Build Coastguard Worker
2533*f6dc9357SAndroid Build Coastguard Worker // case kpidMediaType: prop = Header.MediaType; break;
2534*f6dc9357SAndroid Build Coastguard Worker // case kpidSectorsPerTrack: prop = Header.SectorsPerTrack; break;
2535*f6dc9357SAndroid Build Coastguard Worker // case kpidNumHeads: prop = Header.NumHeads; break;
2536*f6dc9357SAndroid Build Coastguard Worker // case kpidHiddenSectors: prop = Header.NumHiddenSectors; break;
2537*f6dc9357SAndroid Build Coastguard Worker }
2538*f6dc9357SAndroid Build Coastguard Worker prop.Detach(value);
2539*f6dc9357SAndroid Build Coastguard Worker return S_OK;
2540*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
2541*f6dc9357SAndroid Build Coastguard Worker }
2542*f6dc9357SAndroid Build Coastguard Worker
2543*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))
2544*f6dc9357SAndroid Build Coastguard Worker {
2545*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
2546*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant prop;
2547*f6dc9357SAndroid Build Coastguard Worker if (index >= Items.Size())
2548*f6dc9357SAndroid Build Coastguard Worker {
2549*f6dc9357SAndroid Build Coastguard Worker switch (propID)
2550*f6dc9357SAndroid Build Coastguard Worker {
2551*f6dc9357SAndroid Build Coastguard Worker case kpidName:
2552*f6dc9357SAndroid Build Coastguard Worker case kpidPath:
2553*f6dc9357SAndroid Build Coastguard Worker prop = VirtFolderNames[index - Items.Size()].GetRawPtr();
2554*f6dc9357SAndroid Build Coastguard Worker break;
2555*f6dc9357SAndroid Build Coastguard Worker case kpidIsDir: prop = true; break;
2556*f6dc9357SAndroid Build Coastguard Worker case kpidIsAux: prop = true; break;
2557*f6dc9357SAndroid Build Coastguard Worker case kpidIsDeleted:
2558*f6dc9357SAndroid Build Coastguard Worker if ((int)index == _lostFolderIndex_Deleted)
2559*f6dc9357SAndroid Build Coastguard Worker prop = true;
2560*f6dc9357SAndroid Build Coastguard Worker break;
2561*f6dc9357SAndroid Build Coastguard Worker }
2562*f6dc9357SAndroid Build Coastguard Worker prop.Detach(value);
2563*f6dc9357SAndroid Build Coastguard Worker return S_OK;
2564*f6dc9357SAndroid Build Coastguard Worker }
2565*f6dc9357SAndroid Build Coastguard Worker
2566*f6dc9357SAndroid Build Coastguard Worker const CItem &item = Items[index];
2567*f6dc9357SAndroid Build Coastguard Worker const CMftRec &rec = Recs[item.RecIndex];
2568*f6dc9357SAndroid Build Coastguard Worker
2569*f6dc9357SAndroid Build Coastguard Worker const CAttr *data= NULL;
2570*f6dc9357SAndroid Build Coastguard Worker if (item.DataIndex >= 0)
2571*f6dc9357SAndroid Build Coastguard Worker data = &rec.DataAttrs[rec.DataRefs[item.DataIndex].Start];
2572*f6dc9357SAndroid Build Coastguard Worker
2573*f6dc9357SAndroid Build Coastguard Worker // const CFileNameAttr *fn = &rec.FileNames[item.NameIndex];
2574*f6dc9357SAndroid Build Coastguard Worker /*
2575*f6dc9357SAndroid Build Coastguard Worker if (rec.FileNames.Size() > 0)
2576*f6dc9357SAndroid Build Coastguard Worker fn = &rec.FileNames[0];
2577*f6dc9357SAndroid Build Coastguard Worker */
2578*f6dc9357SAndroid Build Coastguard Worker
2579*f6dc9357SAndroid Build Coastguard Worker switch (propID)
2580*f6dc9357SAndroid Build Coastguard Worker {
2581*f6dc9357SAndroid Build Coastguard Worker case kpidPath:
2582*f6dc9357SAndroid Build Coastguard Worker GetItemPath(index, prop);
2583*f6dc9357SAndroid Build Coastguard Worker break;
2584*f6dc9357SAndroid Build Coastguard Worker
2585*f6dc9357SAndroid Build Coastguard Worker /*
2586*f6dc9357SAndroid Build Coastguard Worker case kpidLink:
2587*f6dc9357SAndroid Build Coastguard Worker if (!rec.ReparseAttr.SubsName.IsEmpty())
2588*f6dc9357SAndroid Build Coastguard Worker {
2589*f6dc9357SAndroid Build Coastguard Worker prop = rec.ReparseAttr.SubsName;
2590*f6dc9357SAndroid Build Coastguard Worker }
2591*f6dc9357SAndroid Build Coastguard Worker break;
2592*f6dc9357SAndroid Build Coastguard Worker case kpidLink2:
2593*f6dc9357SAndroid Build Coastguard Worker if (!rec.ReparseAttr.PrintName.IsEmpty())
2594*f6dc9357SAndroid Build Coastguard Worker {
2595*f6dc9357SAndroid Build Coastguard Worker prop = rec.ReparseAttr.PrintName;
2596*f6dc9357SAndroid Build Coastguard Worker }
2597*f6dc9357SAndroid Build Coastguard Worker break;
2598*f6dc9357SAndroid Build Coastguard Worker
2599*f6dc9357SAndroid Build Coastguard Worker case kpidLinkType:
2600*f6dc9357SAndroid Build Coastguard Worker if (rec.ReparseAttr.Tag != 0)
2601*f6dc9357SAndroid Build Coastguard Worker {
2602*f6dc9357SAndroid Build Coastguard Worker prop = (rec.ReparseAttr.Tag & 0xFFFF);
2603*f6dc9357SAndroid Build Coastguard Worker }
2604*f6dc9357SAndroid Build Coastguard Worker break;
2605*f6dc9357SAndroid Build Coastguard Worker */
2606*f6dc9357SAndroid Build Coastguard Worker
2607*f6dc9357SAndroid Build Coastguard Worker case kpidINode:
2608*f6dc9357SAndroid Build Coastguard Worker {
2609*f6dc9357SAndroid Build Coastguard Worker // const CMftRec &rec = Recs[item.RecIndex];
2610*f6dc9357SAndroid Build Coastguard Worker // prop = ((UInt64)rec.SeqNumber << 48) | item.RecIndex;
2611*f6dc9357SAndroid Build Coastguard Worker prop = (UInt32)item.RecIndex;
2612*f6dc9357SAndroid Build Coastguard Worker break;
2613*f6dc9357SAndroid Build Coastguard Worker }
2614*f6dc9357SAndroid Build Coastguard Worker case kpidStreamId:
2615*f6dc9357SAndroid Build Coastguard Worker {
2616*f6dc9357SAndroid Build Coastguard Worker if (item.DataIndex >= 0)
2617*f6dc9357SAndroid Build Coastguard Worker prop = ((UInt64)item.RecIndex << 32) | (unsigned)item.DataIndex;
2618*f6dc9357SAndroid Build Coastguard Worker break;
2619*f6dc9357SAndroid Build Coastguard Worker }
2620*f6dc9357SAndroid Build Coastguard Worker
2621*f6dc9357SAndroid Build Coastguard Worker case kpidName:
2622*f6dc9357SAndroid Build Coastguard Worker {
2623*f6dc9357SAndroid Build Coastguard Worker const UString2 *s;
2624*f6dc9357SAndroid Build Coastguard Worker if (item.IsAltStream())
2625*f6dc9357SAndroid Build Coastguard Worker s = &rec.DataAttrs[rec.DataRefs[item.DataIndex].Start].Name;
2626*f6dc9357SAndroid Build Coastguard Worker else
2627*f6dc9357SAndroid Build Coastguard Worker s = &rec.FileNames[item.NameIndex].Name;
2628*f6dc9357SAndroid Build Coastguard Worker if (s->IsEmpty())
2629*f6dc9357SAndroid Build Coastguard Worker prop = (const wchar_t *)EmptyString;
2630*f6dc9357SAndroid Build Coastguard Worker else
2631*f6dc9357SAndroid Build Coastguard Worker prop = s->GetRawPtr();
2632*f6dc9357SAndroid Build Coastguard Worker break;
2633*f6dc9357SAndroid Build Coastguard Worker }
2634*f6dc9357SAndroid Build Coastguard Worker
2635*f6dc9357SAndroid Build Coastguard Worker case kpidShortName:
2636*f6dc9357SAndroid Build Coastguard Worker {
2637*f6dc9357SAndroid Build Coastguard Worker if (!item.IsAltStream())
2638*f6dc9357SAndroid Build Coastguard Worker {
2639*f6dc9357SAndroid Build Coastguard Worker int dosNameIndex = rec.FindDosName(item.NameIndex);
2640*f6dc9357SAndroid Build Coastguard Worker if (dosNameIndex >= 0)
2641*f6dc9357SAndroid Build Coastguard Worker {
2642*f6dc9357SAndroid Build Coastguard Worker const UString2 &s = rec.FileNames[dosNameIndex].Name;
2643*f6dc9357SAndroid Build Coastguard Worker if (s.IsEmpty())
2644*f6dc9357SAndroid Build Coastguard Worker prop = (const wchar_t *)EmptyString;
2645*f6dc9357SAndroid Build Coastguard Worker else
2646*f6dc9357SAndroid Build Coastguard Worker prop = s.GetRawPtr();
2647*f6dc9357SAndroid Build Coastguard Worker }
2648*f6dc9357SAndroid Build Coastguard Worker }
2649*f6dc9357SAndroid Build Coastguard Worker break;
2650*f6dc9357SAndroid Build Coastguard Worker }
2651*f6dc9357SAndroid Build Coastguard Worker
2652*f6dc9357SAndroid Build Coastguard Worker case kpidIsDir: prop = item.IsDir(); break;
2653*f6dc9357SAndroid Build Coastguard Worker case kpidIsAltStream: prop = item.IsAltStream(); break;
2654*f6dc9357SAndroid Build Coastguard Worker case kpidIsDeleted: prop = !rec.InUse(); break;
2655*f6dc9357SAndroid Build Coastguard Worker case kpidIsAux: prop = false; break;
2656*f6dc9357SAndroid Build Coastguard Worker
2657*f6dc9357SAndroid Build Coastguard Worker case kpidMTime: NtfsTimeToProp(rec.SiAttr.MTime, prop); break;
2658*f6dc9357SAndroid Build Coastguard Worker case kpidCTime: NtfsTimeToProp(rec.SiAttr.CTime, prop); break;
2659*f6dc9357SAndroid Build Coastguard Worker case kpidATime: NtfsTimeToProp(rec.SiAttr.ATime, prop); break;
2660*f6dc9357SAndroid Build Coastguard Worker case kpidChangeTime: NtfsTimeToProp(rec.SiAttr.ThisRecMTime, prop); break;
2661*f6dc9357SAndroid Build Coastguard Worker
2662*f6dc9357SAndroid Build Coastguard Worker /*
2663*f6dc9357SAndroid Build Coastguard Worker case kpidMTime2: if (fn) NtfsTimeToProp(fn->MTime, prop); break;
2664*f6dc9357SAndroid Build Coastguard Worker case kpidCTime2: if (fn) NtfsTimeToProp(fn->CTime, prop); break;
2665*f6dc9357SAndroid Build Coastguard Worker case kpidATime2: if (fn) NtfsTimeToProp(fn->ATime, prop); break;
2666*f6dc9357SAndroid Build Coastguard Worker case kpidRecMTime2: if (fn) NtfsTimeToProp(fn->ThisRecMTime, prop); break;
2667*f6dc9357SAndroid Build Coastguard Worker */
2668*f6dc9357SAndroid Build Coastguard Worker
2669*f6dc9357SAndroid Build Coastguard Worker case kpidAttrib:
2670*f6dc9357SAndroid Build Coastguard Worker {
2671*f6dc9357SAndroid Build Coastguard Worker UInt32 attrib;
2672*f6dc9357SAndroid Build Coastguard Worker /* WinXP-64: The CFileNameAttr::Attrib is not updated after some changes. Why?
2673*f6dc9357SAndroid Build Coastguard Worker CSiAttr:attrib is updated better. So we use CSiAttr:Sttrib */
2674*f6dc9357SAndroid Build Coastguard Worker /*
2675*f6dc9357SAndroid Build Coastguard Worker if (fn)
2676*f6dc9357SAndroid Build Coastguard Worker attrib = fn->Attrib;
2677*f6dc9357SAndroid Build Coastguard Worker else
2678*f6dc9357SAndroid Build Coastguard Worker */
2679*f6dc9357SAndroid Build Coastguard Worker attrib = rec.SiAttr.Attrib;
2680*f6dc9357SAndroid Build Coastguard Worker if (item.IsDir())
2681*f6dc9357SAndroid Build Coastguard Worker attrib |= FILE_ATTRIBUTE_DIRECTORY;
2682*f6dc9357SAndroid Build Coastguard Worker
2683*f6dc9357SAndroid Build Coastguard Worker /* some system entries can contain extra flags (Index View).
2684*f6dc9357SAndroid Build Coastguard Worker // 0x10000000 (Directory)
2685*f6dc9357SAndroid Build Coastguard Worker // 0x20000000 FILE_ATTR_VIEW_INDEX_PRESENT MFT_RECORD_IS_VIEW_INDEX (Index View)
2686*f6dc9357SAndroid Build Coastguard Worker But we don't need them */
2687*f6dc9357SAndroid Build Coastguard Worker attrib &= 0xFFFF;
2688*f6dc9357SAndroid Build Coastguard Worker
2689*f6dc9357SAndroid Build Coastguard Worker prop = attrib;
2690*f6dc9357SAndroid Build Coastguard Worker break;
2691*f6dc9357SAndroid Build Coastguard Worker }
2692*f6dc9357SAndroid Build Coastguard Worker case kpidLinks: if (rec.MyNumNameLinks != 1) prop = rec.MyNumNameLinks; break;
2693*f6dc9357SAndroid Build Coastguard Worker
2694*f6dc9357SAndroid Build Coastguard Worker case kpidNumAltStreams:
2695*f6dc9357SAndroid Build Coastguard Worker {
2696*f6dc9357SAndroid Build Coastguard Worker if (!item.IsAltStream())
2697*f6dc9357SAndroid Build Coastguard Worker {
2698*f6dc9357SAndroid Build Coastguard Worker unsigned num = rec.DataRefs.Size();
2699*f6dc9357SAndroid Build Coastguard Worker if (num > 0)
2700*f6dc9357SAndroid Build Coastguard Worker {
2701*f6dc9357SAndroid Build Coastguard Worker if (!rec.IsDir() && rec.DataAttrs[rec.DataRefs[0].Start].Name.IsEmpty())
2702*f6dc9357SAndroid Build Coastguard Worker num--;
2703*f6dc9357SAndroid Build Coastguard Worker if (num > 0)
2704*f6dc9357SAndroid Build Coastguard Worker prop = (UInt32)num;
2705*f6dc9357SAndroid Build Coastguard Worker }
2706*f6dc9357SAndroid Build Coastguard Worker }
2707*f6dc9357SAndroid Build Coastguard Worker break;
2708*f6dc9357SAndroid Build Coastguard Worker }
2709*f6dc9357SAndroid Build Coastguard Worker
2710*f6dc9357SAndroid Build Coastguard Worker case kpidSize: if (data) prop = data->GetSize(); else if (!item.IsDir()) prop = (UInt64)0; break;
2711*f6dc9357SAndroid Build Coastguard Worker case kpidPackSize: if (data) prop = data->GetPackSize(); else if (!item.IsDir()) prop = (UInt64)0; break;
2712*f6dc9357SAndroid Build Coastguard Worker case kpidNumBlocks: if (data) prop = (UInt32)rec.GetNumExtents(item.DataIndex, Header.ClusterSizeLog, Header.NumClusters); break;
2713*f6dc9357SAndroid Build Coastguard Worker }
2714*f6dc9357SAndroid Build Coastguard Worker prop.Detach(value);
2715*f6dc9357SAndroid Build Coastguard Worker return S_OK;
2716*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
2717*f6dc9357SAndroid Build Coastguard Worker }
2718*f6dc9357SAndroid Build Coastguard Worker
2719*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *callback))
2720*f6dc9357SAndroid Build Coastguard Worker {
2721*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
2722*f6dc9357SAndroid Build Coastguard Worker {
2723*f6dc9357SAndroid Build Coastguard Worker OpenCallback = callback;
2724*f6dc9357SAndroid Build Coastguard Worker InStream = stream;
2725*f6dc9357SAndroid Build Coastguard Worker HRESULT res;
2726*f6dc9357SAndroid Build Coastguard Worker try
2727*f6dc9357SAndroid Build Coastguard Worker {
2728*f6dc9357SAndroid Build Coastguard Worker res = CDatabase::Open();
2729*f6dc9357SAndroid Build Coastguard Worker if (res == S_OK)
2730*f6dc9357SAndroid Build Coastguard Worker return S_OK;
2731*f6dc9357SAndroid Build Coastguard Worker }
2732*f6dc9357SAndroid Build Coastguard Worker catch(...)
2733*f6dc9357SAndroid Build Coastguard Worker {
2734*f6dc9357SAndroid Build Coastguard Worker Close();
2735*f6dc9357SAndroid Build Coastguard Worker throw;
2736*f6dc9357SAndroid Build Coastguard Worker }
2737*f6dc9357SAndroid Build Coastguard Worker Close();
2738*f6dc9357SAndroid Build Coastguard Worker return res;
2739*f6dc9357SAndroid Build Coastguard Worker }
2740*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
2741*f6dc9357SAndroid Build Coastguard Worker }
2742*f6dc9357SAndroid Build Coastguard Worker
2743*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Close())
2744*f6dc9357SAndroid Build Coastguard Worker {
2745*f6dc9357SAndroid Build Coastguard Worker ClearAndClose();
2746*f6dc9357SAndroid Build Coastguard Worker return S_OK;
2747*f6dc9357SAndroid Build Coastguard Worker }
2748*f6dc9357SAndroid Build Coastguard Worker
2749*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
2750*f6dc9357SAndroid Build Coastguard Worker Int32 testMode, IArchiveExtractCallback *extractCallback))
2751*f6dc9357SAndroid Build Coastguard Worker {
2752*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
2753*f6dc9357SAndroid Build Coastguard Worker const bool allFilesMode = (numItems == (UInt32)(Int32)-1);
2754*f6dc9357SAndroid Build Coastguard Worker if (allFilesMode)
2755*f6dc9357SAndroid Build Coastguard Worker numItems = Items.Size();
2756*f6dc9357SAndroid Build Coastguard Worker if (numItems == 0)
2757*f6dc9357SAndroid Build Coastguard Worker return S_OK;
2758*f6dc9357SAndroid Build Coastguard Worker UInt32 i;
2759*f6dc9357SAndroid Build Coastguard Worker UInt64 totalSize = 0;
2760*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < numItems; i++)
2761*f6dc9357SAndroid Build Coastguard Worker {
2762*f6dc9357SAndroid Build Coastguard Worker const UInt32 index = allFilesMode ? i : indices[i];
2763*f6dc9357SAndroid Build Coastguard Worker if (index >= (UInt32)Items.Size())
2764*f6dc9357SAndroid Build Coastguard Worker continue;
2765*f6dc9357SAndroid Build Coastguard Worker const CItem &item = Items[allFilesMode ? i : indices[i]];
2766*f6dc9357SAndroid Build Coastguard Worker const CMftRec &rec = Recs[item.RecIndex];
2767*f6dc9357SAndroid Build Coastguard Worker if (item.DataIndex >= 0)
2768*f6dc9357SAndroid Build Coastguard Worker totalSize += rec.GetSize((unsigned)item.DataIndex);
2769*f6dc9357SAndroid Build Coastguard Worker }
2770*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetTotal(totalSize))
2771*f6dc9357SAndroid Build Coastguard Worker
2772*f6dc9357SAndroid Build Coastguard Worker UInt64 totalPackSize;
2773*f6dc9357SAndroid Build Coastguard Worker totalSize = totalPackSize = 0;
2774*f6dc9357SAndroid Build Coastguard Worker
2775*f6dc9357SAndroid Build Coastguard Worker UInt32 clusterSize = Header.ClusterSize();
2776*f6dc9357SAndroid Build Coastguard Worker CByteBuffer buf(clusterSize);
2777*f6dc9357SAndroid Build Coastguard Worker
2778*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
2779*f6dc9357SAndroid Build Coastguard Worker lps->Init(extractCallback, false);
2780*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;
2781*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ISequentialOutStream, CDummyOutStream> outStream;
2782*f6dc9357SAndroid Build Coastguard Worker
2783*f6dc9357SAndroid Build Coastguard Worker for (i = 0;; i++)
2784*f6dc9357SAndroid Build Coastguard Worker {
2785*f6dc9357SAndroid Build Coastguard Worker lps->InSize = totalPackSize;
2786*f6dc9357SAndroid Build Coastguard Worker lps->OutSize = totalSize;
2787*f6dc9357SAndroid Build Coastguard Worker RINOK(lps->SetCur())
2788*f6dc9357SAndroid Build Coastguard Worker if (i >= numItems)
2789*f6dc9357SAndroid Build Coastguard Worker break;
2790*f6dc9357SAndroid Build Coastguard Worker
2791*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ISequentialOutStream> realOutStream;
2792*f6dc9357SAndroid Build Coastguard Worker const Int32 askMode = testMode ?
2793*f6dc9357SAndroid Build Coastguard Worker NExtract::NAskMode::kTest :
2794*f6dc9357SAndroid Build Coastguard Worker NExtract::NAskMode::kExtract;
2795*f6dc9357SAndroid Build Coastguard Worker const UInt32 index = allFilesMode ? i : indices[i];
2796*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->GetStream(index, &realOutStream, askMode))
2797*f6dc9357SAndroid Build Coastguard Worker
2798*f6dc9357SAndroid Build Coastguard Worker if (index >= (UInt32)Items.Size() || Items[index].IsDir())
2799*f6dc9357SAndroid Build Coastguard Worker {
2800*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->PrepareOperation(askMode))
2801*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))
2802*f6dc9357SAndroid Build Coastguard Worker continue;
2803*f6dc9357SAndroid Build Coastguard Worker }
2804*f6dc9357SAndroid Build Coastguard Worker
2805*f6dc9357SAndroid Build Coastguard Worker const CItem &item = Items[index];
2806*f6dc9357SAndroid Build Coastguard Worker
2807*f6dc9357SAndroid Build Coastguard Worker if (!testMode && !realOutStream)
2808*f6dc9357SAndroid Build Coastguard Worker continue;
2809*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->PrepareOperation(askMode))
2810*f6dc9357SAndroid Build Coastguard Worker
2811*f6dc9357SAndroid Build Coastguard Worker outStream->SetStream(realOutStream);
2812*f6dc9357SAndroid Build Coastguard Worker realOutStream.Release();
2813*f6dc9357SAndroid Build Coastguard Worker outStream->Init();
2814*f6dc9357SAndroid Build Coastguard Worker
2815*f6dc9357SAndroid Build Coastguard Worker const CMftRec &rec = Recs[item.RecIndex];
2816*f6dc9357SAndroid Build Coastguard Worker
2817*f6dc9357SAndroid Build Coastguard Worker int res = NExtract::NOperationResult::kDataError;
2818*f6dc9357SAndroid Build Coastguard Worker {
2819*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<IInStream> inStream;
2820*f6dc9357SAndroid Build Coastguard Worker HRESULT hres = rec.GetStream(InStream, item.DataIndex, Header.ClusterSizeLog, Header.NumClusters, &inStream);
2821*f6dc9357SAndroid Build Coastguard Worker if (hres == S_FALSE)
2822*f6dc9357SAndroid Build Coastguard Worker res = NExtract::NOperationResult::kUnsupportedMethod;
2823*f6dc9357SAndroid Build Coastguard Worker else
2824*f6dc9357SAndroid Build Coastguard Worker {
2825*f6dc9357SAndroid Build Coastguard Worker RINOK(hres)
2826*f6dc9357SAndroid Build Coastguard Worker if (inStream)
2827*f6dc9357SAndroid Build Coastguard Worker {
2828*f6dc9357SAndroid Build Coastguard Worker hres = copyCoder.Interface()->Code(inStream, outStream, NULL, NULL, lps);
2829*f6dc9357SAndroid Build Coastguard Worker if (hres != S_OK && hres != S_FALSE)
2830*f6dc9357SAndroid Build Coastguard Worker {
2831*f6dc9357SAndroid Build Coastguard Worker RINOK(hres)
2832*f6dc9357SAndroid Build Coastguard Worker }
2833*f6dc9357SAndroid Build Coastguard Worker if (/* copyCoderSpec->TotalSize == item.GetSize() && */ hres == S_OK)
2834*f6dc9357SAndroid Build Coastguard Worker res = NExtract::NOperationResult::kOK;
2835*f6dc9357SAndroid Build Coastguard Worker }
2836*f6dc9357SAndroid Build Coastguard Worker }
2837*f6dc9357SAndroid Build Coastguard Worker }
2838*f6dc9357SAndroid Build Coastguard Worker if (item.DataIndex >= 0)
2839*f6dc9357SAndroid Build Coastguard Worker {
2840*f6dc9357SAndroid Build Coastguard Worker const CAttr &data = rec.DataAttrs[rec.DataRefs[item.DataIndex].Start];
2841*f6dc9357SAndroid Build Coastguard Worker totalPackSize += data.GetPackSize();
2842*f6dc9357SAndroid Build Coastguard Worker totalSize += data.GetSize();
2843*f6dc9357SAndroid Build Coastguard Worker }
2844*f6dc9357SAndroid Build Coastguard Worker outStream->ReleaseStream();
2845*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetOperationResult(res))
2846*f6dc9357SAndroid Build Coastguard Worker }
2847*f6dc9357SAndroid Build Coastguard Worker return S_OK;
2848*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
2849*f6dc9357SAndroid Build Coastguard Worker }
2850*f6dc9357SAndroid Build Coastguard Worker
2851*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))
2852*f6dc9357SAndroid Build Coastguard Worker {
2853*f6dc9357SAndroid Build Coastguard Worker *numItems = Items.Size() + VirtFolderNames.Size();
2854*f6dc9357SAndroid Build Coastguard Worker return S_OK;
2855*f6dc9357SAndroid Build Coastguard Worker }
2856*f6dc9357SAndroid Build Coastguard Worker
2857*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps))
2858*f6dc9357SAndroid Build Coastguard Worker {
2859*f6dc9357SAndroid Build Coastguard Worker InitProps();
2860*f6dc9357SAndroid Build Coastguard Worker
2861*f6dc9357SAndroid Build Coastguard Worker for (UInt32 i = 0; i < numProps; i++)
2862*f6dc9357SAndroid Build Coastguard Worker {
2863*f6dc9357SAndroid Build Coastguard Worker const wchar_t *name = names[i];
2864*f6dc9357SAndroid Build Coastguard Worker const PROPVARIANT &prop = values[i];
2865*f6dc9357SAndroid Build Coastguard Worker
2866*f6dc9357SAndroid Build Coastguard Worker if (StringsAreEqualNoCase_Ascii(name, "ld"))
2867*f6dc9357SAndroid Build Coastguard Worker {
2868*f6dc9357SAndroid Build Coastguard Worker RINOK(PROPVARIANT_to_bool(prop, _showDeletedFiles))
2869*f6dc9357SAndroid Build Coastguard Worker }
2870*f6dc9357SAndroid Build Coastguard Worker else if (StringsAreEqualNoCase_Ascii(name, "ls"))
2871*f6dc9357SAndroid Build Coastguard Worker {
2872*f6dc9357SAndroid Build Coastguard Worker RINOK(PROPVARIANT_to_bool(prop, _showSystemFiles))
2873*f6dc9357SAndroid Build Coastguard Worker }
2874*f6dc9357SAndroid Build Coastguard Worker else if (IsString1PrefixedByString2_NoCase_Ascii(name, "mt"))
2875*f6dc9357SAndroid Build Coastguard Worker {
2876*f6dc9357SAndroid Build Coastguard Worker }
2877*f6dc9357SAndroid Build Coastguard Worker else if (IsString1PrefixedByString2_NoCase_Ascii(name, "memuse"))
2878*f6dc9357SAndroid Build Coastguard Worker {
2879*f6dc9357SAndroid Build Coastguard Worker }
2880*f6dc9357SAndroid Build Coastguard Worker else
2881*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
2882*f6dc9357SAndroid Build Coastguard Worker }
2883*f6dc9357SAndroid Build Coastguard Worker return S_OK;
2884*f6dc9357SAndroid Build Coastguard Worker }
2885*f6dc9357SAndroid Build Coastguard Worker
2886*f6dc9357SAndroid Build Coastguard Worker static const Byte k_Signature[] = { 'N', 'T', 'F', 'S', ' ', ' ', ' ', ' ', 0 };
2887*f6dc9357SAndroid Build Coastguard Worker
2888*f6dc9357SAndroid Build Coastguard Worker REGISTER_ARC_I(
2889*f6dc9357SAndroid Build Coastguard Worker "NTFS", "ntfs img", NULL, 0xD9,
2890*f6dc9357SAndroid Build Coastguard Worker k_Signature,
2891*f6dc9357SAndroid Build Coastguard Worker 3,
2892*f6dc9357SAndroid Build Coastguard Worker 0,
2893*f6dc9357SAndroid Build Coastguard Worker NULL)
2894*f6dc9357SAndroid Build Coastguard Worker
2895*f6dc9357SAndroid Build Coastguard Worker }}
2896