1370b324cSopenharmony_ci// PropIDUtils.cpp
2370b324cSopenharmony_ci
3370b324cSopenharmony_ci#include "StdAfx.h"
4370b324cSopenharmony_ci
5370b324cSopenharmony_ci#include "../../../../C/CpuArch.h"
6370b324cSopenharmony_ci
7370b324cSopenharmony_ci#include "../../../Common/IntToString.h"
8370b324cSopenharmony_ci#include "../../../Common/StringConvert.h"
9370b324cSopenharmony_ci
10370b324cSopenharmony_ci#include "../../../Windows/FileIO.h"
11370b324cSopenharmony_ci#include "../../../Windows/PropVariantConv.h"
12370b324cSopenharmony_ci
13370b324cSopenharmony_ci#include "../../PropID.h"
14370b324cSopenharmony_ci
15370b324cSopenharmony_ci#include "PropIDUtils.h"
16370b324cSopenharmony_ci
17370b324cSopenharmony_ci#ifndef Z7_SFX
18370b324cSopenharmony_ci#define Get16(x) GetUi16(x)
19370b324cSopenharmony_ci#define Get32(x) GetUi32(x)
20370b324cSopenharmony_ci#endif
21370b324cSopenharmony_ci
22370b324cSopenharmony_ciusing namespace NWindows;
23370b324cSopenharmony_ci
24370b324cSopenharmony_cistatic const unsigned kNumWinAtrribFlags = 21;
25370b324cSopenharmony_cistatic const char g_WinAttribChars[kNumWinAtrribFlags + 1] = "RHS8DAdNTsLCOIEV.X.PU";
26370b324cSopenharmony_ci
27370b324cSopenharmony_ci/*
28370b324cSopenharmony_ciFILE_ATTRIBUTE_
29370b324cSopenharmony_ci
30370b324cSopenharmony_ci0 READONLY
31370b324cSopenharmony_ci1 HIDDEN
32370b324cSopenharmony_ci2 SYSTEM
33370b324cSopenharmony_ci3 (Volume label - obsolete)
34370b324cSopenharmony_ci4 DIRECTORY
35370b324cSopenharmony_ci5 ARCHIVE
36370b324cSopenharmony_ci6 DEVICE
37370b324cSopenharmony_ci7 NORMAL
38370b324cSopenharmony_ci8 TEMPORARY
39370b324cSopenharmony_ci9 SPARSE_FILE
40370b324cSopenharmony_ci10 REPARSE_POINT
41370b324cSopenharmony_ci11 COMPRESSED
42370b324cSopenharmony_ci12 OFFLINE
43370b324cSopenharmony_ci13 NOT_CONTENT_INDEXED (I - Win10 attrib/Explorer)
44370b324cSopenharmony_ci14 ENCRYPTED
45370b324cSopenharmony_ci15 INTEGRITY_STREAM (V - ReFS Win8/Win2012)
46370b324cSopenharmony_ci16 VIRTUAL (reserved)
47370b324cSopenharmony_ci17 NO_SCRUB_DATA (X - ReFS Win8/Win2012 attrib)
48370b324cSopenharmony_ci18 RECALL_ON_OPEN or EA
49370b324cSopenharmony_ci19 PINNED
50370b324cSopenharmony_ci20 UNPINNED
51370b324cSopenharmony_ci21 STRICTLY_SEQUENTIAL
52370b324cSopenharmony_ci22 RECALL_ON_DATA_ACCESS
53370b324cSopenharmony_ci*/
54370b324cSopenharmony_ci
55370b324cSopenharmony_ci
56370b324cSopenharmony_cistatic const char kPosixTypes[16] = { '0', 'p', 'c', '3', 'd', '5', 'b', '7', '-', '9', 'l', 'B', 's', 'D', 'E', 'F' };
57370b324cSopenharmony_ci#define MY_ATTR_CHAR(a, n, c) (((a) & (1 << (n))) ? c : '-')
58370b324cSopenharmony_ci
59370b324cSopenharmony_cistatic void ConvertPosixAttribToString(char *s, UInt32 a) throw()
60370b324cSopenharmony_ci{
61370b324cSopenharmony_ci  s[0] = kPosixTypes[(a >> 12) & 0xF];
62370b324cSopenharmony_ci  for (int i = 6; i >= 0; i -= 3)
63370b324cSopenharmony_ci  {
64370b324cSopenharmony_ci    s[7 - i] = MY_ATTR_CHAR(a, i + 2, 'r');
65370b324cSopenharmony_ci    s[8 - i] = MY_ATTR_CHAR(a, i + 1, 'w');
66370b324cSopenharmony_ci    s[9 - i] = MY_ATTR_CHAR(a, i + 0, 'x');
67370b324cSopenharmony_ci  }
68370b324cSopenharmony_ci  if ((a & 0x800) != 0) s[3] = ((a & (1 << 6)) ? 's' : 'S'); // S_ISUID
69370b324cSopenharmony_ci  if ((a & 0x400) != 0) s[6] = ((a & (1 << 3)) ? 's' : 'S'); // S_ISGID
70370b324cSopenharmony_ci  if ((a & 0x200) != 0) s[9] = ((a & (1 << 0)) ? 't' : 'T'); // S_ISVTX
71370b324cSopenharmony_ci  s[10] = 0;
72370b324cSopenharmony_ci
73370b324cSopenharmony_ci  a &= ~(UInt32)0xFFFF;
74370b324cSopenharmony_ci  if (a != 0)
75370b324cSopenharmony_ci  {
76370b324cSopenharmony_ci    s[10] = ' ';
77370b324cSopenharmony_ci    ConvertUInt32ToHex8Digits(a, s + 11);
78370b324cSopenharmony_ci  }
79370b324cSopenharmony_ci}
80370b324cSopenharmony_ci
81370b324cSopenharmony_ci
82370b324cSopenharmony_civoid ConvertWinAttribToString(char *s, UInt32 wa) throw()
83370b324cSopenharmony_ci{
84370b324cSopenharmony_ci  /*
85370b324cSopenharmony_ci  some programs store posix attributes in high 16 bits.
86370b324cSopenharmony_ci  p7zip - stores additional 0x8000 flag marker.
87370b324cSopenharmony_ci  macos - stores additional 0x4000 flag marker.
88370b324cSopenharmony_ci  info-zip - no additional marker.
89370b324cSopenharmony_ci  */
90370b324cSopenharmony_ci
91370b324cSopenharmony_ci  const bool isPosix = ((wa & 0xF0000000) != 0);
92370b324cSopenharmony_ci
93370b324cSopenharmony_ci  UInt32 posix = 0;
94370b324cSopenharmony_ci  if (isPosix)
95370b324cSopenharmony_ci  {
96370b324cSopenharmony_ci    posix = wa >> 16;
97370b324cSopenharmony_ci    wa &= (UInt32)0x3FFF;
98370b324cSopenharmony_ci  }
99370b324cSopenharmony_ci
100370b324cSopenharmony_ci  for (unsigned i = 0; i < kNumWinAtrribFlags; i++)
101370b324cSopenharmony_ci  {
102370b324cSopenharmony_ci    UInt32 flag = (1 << i);
103370b324cSopenharmony_ci    if ((wa & flag) != 0)
104370b324cSopenharmony_ci    {
105370b324cSopenharmony_ci      char c = g_WinAttribChars[i];
106370b324cSopenharmony_ci      if (c != '.')
107370b324cSopenharmony_ci      {
108370b324cSopenharmony_ci        wa &= ~flag;
109370b324cSopenharmony_ci        // if (i != 7) // we can disable N (NORMAL) printing
110370b324cSopenharmony_ci        *s++ = c;
111370b324cSopenharmony_ci      }
112370b324cSopenharmony_ci    }
113370b324cSopenharmony_ci  }
114370b324cSopenharmony_ci
115370b324cSopenharmony_ci  if (wa != 0)
116370b324cSopenharmony_ci  {
117370b324cSopenharmony_ci    *s++ = ' ';
118370b324cSopenharmony_ci    ConvertUInt32ToHex8Digits(wa, s);
119370b324cSopenharmony_ci    s += strlen(s);
120370b324cSopenharmony_ci  }
121370b324cSopenharmony_ci
122370b324cSopenharmony_ci  *s = 0;
123370b324cSopenharmony_ci
124370b324cSopenharmony_ci  if (isPosix)
125370b324cSopenharmony_ci  {
126370b324cSopenharmony_ci    *s++ = ' ';
127370b324cSopenharmony_ci    ConvertPosixAttribToString(s, posix);
128370b324cSopenharmony_ci  }
129370b324cSopenharmony_ci}
130370b324cSopenharmony_ci
131370b324cSopenharmony_ci
132370b324cSopenharmony_civoid ConvertPropertyToShortString2(char *dest, const PROPVARIANT &prop, PROPID propID, int level) throw()
133370b324cSopenharmony_ci{
134370b324cSopenharmony_ci  *dest = 0;
135370b324cSopenharmony_ci
136370b324cSopenharmony_ci  if (prop.vt == VT_FILETIME)
137370b324cSopenharmony_ci  {
138370b324cSopenharmony_ci    const FILETIME &ft = prop.filetime;
139370b324cSopenharmony_ci    unsigned ns100 = 0;
140370b324cSopenharmony_ci    int numDigits = kTimestampPrintLevel_NTFS;
141370b324cSopenharmony_ci    const unsigned prec = prop.wReserved1;
142370b324cSopenharmony_ci    const unsigned ns100_Temp = prop.wReserved2;
143370b324cSopenharmony_ci    if (prec != 0
144370b324cSopenharmony_ci        && prec <= k_PropVar_TimePrec_1ns
145370b324cSopenharmony_ci        && ns100_Temp < 100
146370b324cSopenharmony_ci        && prop.wReserved3 == 0)
147370b324cSopenharmony_ci    {
148370b324cSopenharmony_ci      ns100 = ns100_Temp;
149370b324cSopenharmony_ci      if (prec == k_PropVar_TimePrec_Unix ||
150370b324cSopenharmony_ci          prec == k_PropVar_TimePrec_DOS)
151370b324cSopenharmony_ci        numDigits = 0;
152370b324cSopenharmony_ci      else if (prec == k_PropVar_TimePrec_HighPrec)
153370b324cSopenharmony_ci        numDigits = 9;
154370b324cSopenharmony_ci      else
155370b324cSopenharmony_ci      {
156370b324cSopenharmony_ci        numDigits = (int)prec - (int)k_PropVar_TimePrec_Base;
157370b324cSopenharmony_ci        if (
158370b324cSopenharmony_ci            // numDigits < kTimestampPrintLevel_DAY // for debuf
159370b324cSopenharmony_ci            numDigits < kTimestampPrintLevel_SEC
160370b324cSopenharmony_ci            )
161370b324cSopenharmony_ci
162370b324cSopenharmony_ci          numDigits = kTimestampPrintLevel_NTFS;
163370b324cSopenharmony_ci      }
164370b324cSopenharmony_ci    }
165370b324cSopenharmony_ci    if (ft.dwHighDateTime == 0 && ft.dwLowDateTime == 0 && ns100 == 0)
166370b324cSopenharmony_ci      return;
167370b324cSopenharmony_ci    if (level > numDigits)
168370b324cSopenharmony_ci      level = numDigits;
169370b324cSopenharmony_ci    ConvertUtcFileTimeToString2(ft, ns100, dest, level);
170370b324cSopenharmony_ci    return;
171370b324cSopenharmony_ci  }
172370b324cSopenharmony_ci
173370b324cSopenharmony_ci  switch (propID)
174370b324cSopenharmony_ci  {
175370b324cSopenharmony_ci    case kpidCRC:
176370b324cSopenharmony_ci    {
177370b324cSopenharmony_ci      if (prop.vt != VT_UI4)
178370b324cSopenharmony_ci        break;
179370b324cSopenharmony_ci      ConvertUInt32ToHex8Digits(prop.ulVal, dest);
180370b324cSopenharmony_ci      return;
181370b324cSopenharmony_ci    }
182370b324cSopenharmony_ci    case kpidAttrib:
183370b324cSopenharmony_ci    {
184370b324cSopenharmony_ci      if (prop.vt != VT_UI4)
185370b324cSopenharmony_ci        break;
186370b324cSopenharmony_ci      const UInt32 a = prop.ulVal;
187370b324cSopenharmony_ci
188370b324cSopenharmony_ci      /*
189370b324cSopenharmony_ci      if ((a & 0x8000) && (a & 0x7FFF) == 0)
190370b324cSopenharmony_ci        ConvertPosixAttribToString(dest, a >> 16);
191370b324cSopenharmony_ci      else
192370b324cSopenharmony_ci      */
193370b324cSopenharmony_ci      ConvertWinAttribToString(dest, a);
194370b324cSopenharmony_ci      return;
195370b324cSopenharmony_ci    }
196370b324cSopenharmony_ci    case kpidPosixAttrib:
197370b324cSopenharmony_ci    {
198370b324cSopenharmony_ci      if (prop.vt != VT_UI4)
199370b324cSopenharmony_ci        break;
200370b324cSopenharmony_ci      ConvertPosixAttribToString(dest, prop.ulVal);
201370b324cSopenharmony_ci      return;
202370b324cSopenharmony_ci    }
203370b324cSopenharmony_ci    case kpidINode:
204370b324cSopenharmony_ci    {
205370b324cSopenharmony_ci      if (prop.vt != VT_UI8)
206370b324cSopenharmony_ci        break;
207370b324cSopenharmony_ci      ConvertUInt32ToString((UInt32)(prop.uhVal.QuadPart >> 48), dest);
208370b324cSopenharmony_ci      dest += strlen(dest);
209370b324cSopenharmony_ci      *dest++ = '-';
210370b324cSopenharmony_ci      const UInt64 low = prop.uhVal.QuadPart & (((UInt64)1 << 48) - 1);
211370b324cSopenharmony_ci      ConvertUInt64ToString(low, dest);
212370b324cSopenharmony_ci      return;
213370b324cSopenharmony_ci    }
214370b324cSopenharmony_ci    case kpidVa:
215370b324cSopenharmony_ci    {
216370b324cSopenharmony_ci      UInt64 v = 0;
217370b324cSopenharmony_ci      if (prop.vt == VT_UI4)
218370b324cSopenharmony_ci        v = prop.ulVal;
219370b324cSopenharmony_ci      else if (prop.vt == VT_UI8)
220370b324cSopenharmony_ci        v = (UInt64)prop.uhVal.QuadPart;
221370b324cSopenharmony_ci      else
222370b324cSopenharmony_ci        break;
223370b324cSopenharmony_ci      dest[0] = '0';
224370b324cSopenharmony_ci      dest[1] = 'x';
225370b324cSopenharmony_ci      ConvertUInt64ToHex(v, dest + 2);
226370b324cSopenharmony_ci      return;
227370b324cSopenharmony_ci    }
228370b324cSopenharmony_ci
229370b324cSopenharmony_ci    /*
230370b324cSopenharmony_ci    case kpidDevice:
231370b324cSopenharmony_ci    {
232370b324cSopenharmony_ci      UInt64 v = 0;
233370b324cSopenharmony_ci      if (prop.vt == VT_UI4)
234370b324cSopenharmony_ci        v = prop.ulVal;
235370b324cSopenharmony_ci      else if (prop.vt == VT_UI8)
236370b324cSopenharmony_ci        v = (UInt64)prop.uhVal.QuadPart;
237370b324cSopenharmony_ci      else
238370b324cSopenharmony_ci        break;
239370b324cSopenharmony_ci      ConvertUInt32ToString(MY_dev_major(v), dest);
240370b324cSopenharmony_ci      dest += strlen(dest);
241370b324cSopenharmony_ci      *dest++ = ',';
242370b324cSopenharmony_ci      ConvertUInt32ToString(MY_dev_minor(v), dest);
243370b324cSopenharmony_ci      return;
244370b324cSopenharmony_ci    }
245370b324cSopenharmony_ci    */
246370b324cSopenharmony_ci  }
247370b324cSopenharmony_ci
248370b324cSopenharmony_ci  ConvertPropVariantToShortString(prop, dest);
249370b324cSopenharmony_ci}
250370b324cSopenharmony_ci
251370b324cSopenharmony_civoid ConvertPropertyToString2(UString &dest, const PROPVARIANT &prop, PROPID propID, int level)
252370b324cSopenharmony_ci{
253370b324cSopenharmony_ci  if (prop.vt == VT_BSTR)
254370b324cSopenharmony_ci  {
255370b324cSopenharmony_ci    dest.SetFromBstr(prop.bstrVal);
256370b324cSopenharmony_ci    return;
257370b324cSopenharmony_ci  }
258370b324cSopenharmony_ci  char temp[64];
259370b324cSopenharmony_ci  ConvertPropertyToShortString2(temp, prop, propID, level);
260370b324cSopenharmony_ci  dest = temp;
261370b324cSopenharmony_ci}
262370b324cSopenharmony_ci
263370b324cSopenharmony_ci#ifndef Z7_SFX
264370b324cSopenharmony_ci
265370b324cSopenharmony_cistatic inline unsigned GetHex(unsigned v)
266370b324cSopenharmony_ci{
267370b324cSopenharmony_ci  return (v < 10) ? ('0' + v) : ('A' + (v - 10));
268370b324cSopenharmony_ci}
269370b324cSopenharmony_ci
270370b324cSopenharmony_cistatic inline void AddHexToString(AString &res, unsigned v)
271370b324cSopenharmony_ci{
272370b324cSopenharmony_ci  res += (char)GetHex(v >> 4);
273370b324cSopenharmony_ci  res += (char)GetHex(v & 0xF);
274370b324cSopenharmony_ci}
275370b324cSopenharmony_ci
276370b324cSopenharmony_ci/*
277370b324cSopenharmony_cistatic AString Data_To_Hex(const Byte *data, size_t size)
278370b324cSopenharmony_ci{
279370b324cSopenharmony_ci  AString s;
280370b324cSopenharmony_ci  for (size_t i = 0; i < size; i++)
281370b324cSopenharmony_ci    AddHexToString(s, data[i]);
282370b324cSopenharmony_ci  return s;
283370b324cSopenharmony_ci}
284370b324cSopenharmony_ci*/
285370b324cSopenharmony_ci
286370b324cSopenharmony_cistatic const char * const sidNames[] =
287370b324cSopenharmony_ci{
288370b324cSopenharmony_ci    "0"
289370b324cSopenharmony_ci  , "Dialup"
290370b324cSopenharmony_ci  , "Network"
291370b324cSopenharmony_ci  , "Batch"
292370b324cSopenharmony_ci  , "Interactive"
293370b324cSopenharmony_ci  , "Logon"  // S-1-5-5-X-Y
294370b324cSopenharmony_ci  , "Service"
295370b324cSopenharmony_ci  , "Anonymous"
296370b324cSopenharmony_ci  , "Proxy"
297370b324cSopenharmony_ci  , "EnterpriseDC"
298370b324cSopenharmony_ci  , "Self"
299370b324cSopenharmony_ci  , "AuthenticatedUsers"
300370b324cSopenharmony_ci  , "RestrictedCode"
301370b324cSopenharmony_ci  , "TerminalServer"
302370b324cSopenharmony_ci  , "RemoteInteractiveLogon"
303370b324cSopenharmony_ci  , "ThisOrganization"
304370b324cSopenharmony_ci  , "16"
305370b324cSopenharmony_ci  , "IUserIIS"
306370b324cSopenharmony_ci  , "LocalSystem"
307370b324cSopenharmony_ci  , "LocalService"
308370b324cSopenharmony_ci  , "NetworkService"
309370b324cSopenharmony_ci  , "Domains"
310370b324cSopenharmony_ci};
311370b324cSopenharmony_ci
312370b324cSopenharmony_cistruct CSecID2Name
313370b324cSopenharmony_ci{
314370b324cSopenharmony_ci  UInt32 n;
315370b324cSopenharmony_ci  const char *sz;
316370b324cSopenharmony_ci};
317370b324cSopenharmony_ci
318370b324cSopenharmony_cistatic int FindPairIndex(const CSecID2Name * pairs, unsigned num, UInt32 id)
319370b324cSopenharmony_ci{
320370b324cSopenharmony_ci  for (unsigned i = 0; i < num; i++)
321370b324cSopenharmony_ci    if (pairs[i].n == id)
322370b324cSopenharmony_ci      return (int)i;
323370b324cSopenharmony_ci  return -1;
324370b324cSopenharmony_ci}
325370b324cSopenharmony_ci
326370b324cSopenharmony_cistatic const CSecID2Name sid_32_Names[] =
327370b324cSopenharmony_ci{
328370b324cSopenharmony_ci  { 544, "Administrators" },
329370b324cSopenharmony_ci  { 545, "Users" },
330370b324cSopenharmony_ci  { 546, "Guests" },
331370b324cSopenharmony_ci  { 547, "PowerUsers" },
332370b324cSopenharmony_ci  { 548, "AccountOperators" },
333370b324cSopenharmony_ci  { 549, "ServerOperators" },
334370b324cSopenharmony_ci  { 550, "PrintOperators" },
335370b324cSopenharmony_ci  { 551, "BackupOperators" },
336370b324cSopenharmony_ci  { 552, "Replicators" },
337370b324cSopenharmony_ci  { 553, "Backup Operators" },
338370b324cSopenharmony_ci  { 554, "PreWindows2000CompatibleAccess" },
339370b324cSopenharmony_ci  { 555, "RemoteDesktopUsers" },
340370b324cSopenharmony_ci  { 556, "NetworkConfigurationOperators" },
341370b324cSopenharmony_ci  { 557, "IncomingForestTrustBuilders" },
342370b324cSopenharmony_ci  { 558, "PerformanceMonitorUsers" },
343370b324cSopenharmony_ci  { 559, "PerformanceLogUsers" },
344370b324cSopenharmony_ci  { 560, "WindowsAuthorizationAccessGroup" },
345370b324cSopenharmony_ci  { 561, "TerminalServerLicenseServers" },
346370b324cSopenharmony_ci  { 562, "DistributedCOMUsers" },
347370b324cSopenharmony_ci  { 569, "CryptographicOperators" },
348370b324cSopenharmony_ci  { 573, "EventLogReaders" },
349370b324cSopenharmony_ci  { 574, "CertificateServiceDCOMAccess" }
350370b324cSopenharmony_ci};
351370b324cSopenharmony_ci
352370b324cSopenharmony_cistatic const CSecID2Name sid_21_Names[] =
353370b324cSopenharmony_ci{
354370b324cSopenharmony_ci  { 500, "Administrator" },
355370b324cSopenharmony_ci  { 501, "Guest" },
356370b324cSopenharmony_ci  { 502, "KRBTGT" },
357370b324cSopenharmony_ci  { 512, "DomainAdmins" },
358370b324cSopenharmony_ci  { 513, "DomainUsers" },
359370b324cSopenharmony_ci  { 515, "DomainComputers" },
360370b324cSopenharmony_ci  { 516, "DomainControllers" },
361370b324cSopenharmony_ci  { 517, "CertPublishers" },
362370b324cSopenharmony_ci  { 518, "SchemaAdmins" },
363370b324cSopenharmony_ci  { 519, "EnterpriseAdmins" },
364370b324cSopenharmony_ci  { 520, "GroupPolicyCreatorOwners" },
365370b324cSopenharmony_ci  { 553, "RASandIASServers" },
366370b324cSopenharmony_ci  { 553, "RASandIASServers" },
367370b324cSopenharmony_ci  { 571, "AllowedRODCPasswordReplicationGroup" },
368370b324cSopenharmony_ci  { 572, "DeniedRODCPasswordReplicationGroup" }
369370b324cSopenharmony_ci};
370370b324cSopenharmony_ci
371370b324cSopenharmony_cistruct CServicesToName
372370b324cSopenharmony_ci{
373370b324cSopenharmony_ci  UInt32 n[5];
374370b324cSopenharmony_ci  const char *sz;
375370b324cSopenharmony_ci};
376370b324cSopenharmony_ci
377370b324cSopenharmony_cistatic const CServicesToName services_to_name[] =
378370b324cSopenharmony_ci{
379370b324cSopenharmony_ci  { { 0x38FB89B5, 0xCBC28419, 0x6D236C5C, 0x6E770057, 0x876402C0 } , "TrustedInstaller" }
380370b324cSopenharmony_ci};
381370b324cSopenharmony_ci
382370b324cSopenharmony_cistatic void ParseSid(AString &s, const Byte *p, UInt32 lim, UInt32 &sidSize)
383370b324cSopenharmony_ci{
384370b324cSopenharmony_ci  sidSize = 0;
385370b324cSopenharmony_ci  if (lim < 8)
386370b324cSopenharmony_ci  {
387370b324cSopenharmony_ci    s += "ERROR";
388370b324cSopenharmony_ci    return;
389370b324cSopenharmony_ci  }
390370b324cSopenharmony_ci  const UInt32 rev = p[0];
391370b324cSopenharmony_ci  if (rev != 1)
392370b324cSopenharmony_ci  {
393370b324cSopenharmony_ci    s += "UNSUPPORTED";
394370b324cSopenharmony_ci    return;
395370b324cSopenharmony_ci  }
396370b324cSopenharmony_ci  const UInt32 num = p[1];
397370b324cSopenharmony_ci  if (8 + num * 4 > lim)
398370b324cSopenharmony_ci  {
399370b324cSopenharmony_ci    s += "ERROR";
400370b324cSopenharmony_ci    return;
401370b324cSopenharmony_ci  }
402370b324cSopenharmony_ci  sidSize = 8 + num * 4;
403370b324cSopenharmony_ci  const UInt32 authority = GetBe32(p + 4);
404370b324cSopenharmony_ci
405370b324cSopenharmony_ci  if (p[2] == 0 && p[3] == 0 && authority == 5 && num >= 1)
406370b324cSopenharmony_ci  {
407370b324cSopenharmony_ci    const UInt32 v0 = Get32(p + 8);
408370b324cSopenharmony_ci    if (v0 < Z7_ARRAY_SIZE(sidNames))
409370b324cSopenharmony_ci    {
410370b324cSopenharmony_ci      s += sidNames[v0];
411370b324cSopenharmony_ci      return;
412370b324cSopenharmony_ci    }
413370b324cSopenharmony_ci    if (v0 == 32 && num == 2)
414370b324cSopenharmony_ci    {
415370b324cSopenharmony_ci      const UInt32 v1 = Get32(p + 12);
416370b324cSopenharmony_ci      const int index = FindPairIndex(sid_32_Names, Z7_ARRAY_SIZE(sid_32_Names), v1);
417370b324cSopenharmony_ci      if (index >= 0)
418370b324cSopenharmony_ci      {
419370b324cSopenharmony_ci        s += sid_32_Names[(unsigned)index].sz;
420370b324cSopenharmony_ci        return;
421370b324cSopenharmony_ci      }
422370b324cSopenharmony_ci    }
423370b324cSopenharmony_ci    if (v0 == 21 && num == 5)
424370b324cSopenharmony_ci    {
425370b324cSopenharmony_ci      UInt32 v4 = Get32(p + 8 + 4 * 4);
426370b324cSopenharmony_ci      const int index = FindPairIndex(sid_21_Names, Z7_ARRAY_SIZE(sid_21_Names), v4);
427370b324cSopenharmony_ci      if (index >= 0)
428370b324cSopenharmony_ci      {
429370b324cSopenharmony_ci        s += sid_21_Names[(unsigned)index].sz;
430370b324cSopenharmony_ci        return;
431370b324cSopenharmony_ci      }
432370b324cSopenharmony_ci    }
433370b324cSopenharmony_ci    if (v0 == 80 && num == 6)
434370b324cSopenharmony_ci    {
435370b324cSopenharmony_ci      for (unsigned i = 0; i < Z7_ARRAY_SIZE(services_to_name); i++)
436370b324cSopenharmony_ci      {
437370b324cSopenharmony_ci        const CServicesToName &sn = services_to_name[i];
438370b324cSopenharmony_ci        int j;
439370b324cSopenharmony_ci        for (j = 0; j < 5 && sn.n[j] == Get32(p + 8 + 4 + j * 4); j++);
440370b324cSopenharmony_ci        if (j == 5)
441370b324cSopenharmony_ci        {
442370b324cSopenharmony_ci          s += sn.sz;
443370b324cSopenharmony_ci          return;
444370b324cSopenharmony_ci        }
445370b324cSopenharmony_ci      }
446370b324cSopenharmony_ci    }
447370b324cSopenharmony_ci  }
448370b324cSopenharmony_ci
449370b324cSopenharmony_ci  s += "S-1-";
450370b324cSopenharmony_ci  if (p[2] == 0 && p[3] == 0)
451370b324cSopenharmony_ci    s.Add_UInt32(authority);
452370b324cSopenharmony_ci  else
453370b324cSopenharmony_ci  {
454370b324cSopenharmony_ci    s += "0x";
455370b324cSopenharmony_ci    for (int i = 2; i < 8; i++)
456370b324cSopenharmony_ci      AddHexToString(s, p[i]);
457370b324cSopenharmony_ci  }
458370b324cSopenharmony_ci  for (UInt32 i = 0; i < num; i++)
459370b324cSopenharmony_ci  {
460370b324cSopenharmony_ci    s.Add_Minus();
461370b324cSopenharmony_ci    s.Add_UInt32(Get32(p + 8 + i * 4));
462370b324cSopenharmony_ci  }
463370b324cSopenharmony_ci}
464370b324cSopenharmony_ci
465370b324cSopenharmony_cistatic void ParseOwner(AString &s, const Byte *p, UInt32 size, UInt32 pos)
466370b324cSopenharmony_ci{
467370b324cSopenharmony_ci  if (pos > size)
468370b324cSopenharmony_ci  {
469370b324cSopenharmony_ci    s += "ERROR";
470370b324cSopenharmony_ci    return;
471370b324cSopenharmony_ci  }
472370b324cSopenharmony_ci  UInt32 sidSize = 0;
473370b324cSopenharmony_ci  ParseSid(s, p + pos, size - pos, sidSize);
474370b324cSopenharmony_ci}
475370b324cSopenharmony_ci
476370b324cSopenharmony_cistatic void ParseAcl(AString &s, const Byte *p, UInt32 size, const char *strName, UInt32 flags, UInt32 offset)
477370b324cSopenharmony_ci{
478370b324cSopenharmony_ci  const UInt32 control = Get16(p + 2);
479370b324cSopenharmony_ci  if ((flags & control) == 0)
480370b324cSopenharmony_ci    return;
481370b324cSopenharmony_ci  const UInt32 pos = Get32(p + offset);
482370b324cSopenharmony_ci  s.Add_Space();
483370b324cSopenharmony_ci  s += strName;
484370b324cSopenharmony_ci  if (pos >= size)
485370b324cSopenharmony_ci    return;
486370b324cSopenharmony_ci  p += pos;
487370b324cSopenharmony_ci  size -= pos;
488370b324cSopenharmony_ci  if (size < 8)
489370b324cSopenharmony_ci    return;
490370b324cSopenharmony_ci  if (Get16(p) != 2) // revision
491370b324cSopenharmony_ci    return;
492370b324cSopenharmony_ci  const UInt32 num = Get32(p + 4);
493370b324cSopenharmony_ci  s.Add_UInt32(num);
494370b324cSopenharmony_ci
495370b324cSopenharmony_ci  /*
496370b324cSopenharmony_ci  UInt32 aclSize = Get16(p + 2);
497370b324cSopenharmony_ci  if (num >= (1 << 16))
498370b324cSopenharmony_ci    return;
499370b324cSopenharmony_ci  if (aclSize > size)
500370b324cSopenharmony_ci    return;
501370b324cSopenharmony_ci  size = aclSize;
502370b324cSopenharmony_ci  size -= 8;
503370b324cSopenharmony_ci  p += 8;
504370b324cSopenharmony_ci  for (UInt32 i = 0 ; i < num; i++)
505370b324cSopenharmony_ci  {
506370b324cSopenharmony_ci    if (size <= 8)
507370b324cSopenharmony_ci      return;
508370b324cSopenharmony_ci    // Byte type = p[0];
509370b324cSopenharmony_ci    // Byte flags = p[1];
510370b324cSopenharmony_ci    // UInt32 aceSize = Get16(p + 2);
511370b324cSopenharmony_ci    // UInt32 mask = Get32(p + 4);
512370b324cSopenharmony_ci    p += 8;
513370b324cSopenharmony_ci    size -= 8;
514370b324cSopenharmony_ci
515370b324cSopenharmony_ci    UInt32 sidSize = 0;
516370b324cSopenharmony_ci    s.Add_Space();
517370b324cSopenharmony_ci    ParseSid(s, p, size, sidSize);
518370b324cSopenharmony_ci    if (sidSize == 0)
519370b324cSopenharmony_ci      return;
520370b324cSopenharmony_ci    p += sidSize;
521370b324cSopenharmony_ci    size -= sidSize;
522370b324cSopenharmony_ci  }
523370b324cSopenharmony_ci
524370b324cSopenharmony_ci  // the tail can contain zeros. So (size != 0) is not ERROR
525370b324cSopenharmony_ci  // if (size != 0) s += " ERROR";
526370b324cSopenharmony_ci  */
527370b324cSopenharmony_ci}
528370b324cSopenharmony_ci
529370b324cSopenharmony_ci/*
530370b324cSopenharmony_ci#define MY_SE_OWNER_DEFAULTED       (0x0001)
531370b324cSopenharmony_ci#define MY_SE_GROUP_DEFAULTED       (0x0002)
532370b324cSopenharmony_ci*/
533370b324cSopenharmony_ci#define MY_SE_DACL_PRESENT          (0x0004)
534370b324cSopenharmony_ci/*
535370b324cSopenharmony_ci#define MY_SE_DACL_DEFAULTED        (0x0008)
536370b324cSopenharmony_ci*/
537370b324cSopenharmony_ci#define MY_SE_SACL_PRESENT          (0x0010)
538370b324cSopenharmony_ci/*
539370b324cSopenharmony_ci#define MY_SE_SACL_DEFAULTED        (0x0020)
540370b324cSopenharmony_ci#define MY_SE_DACL_AUTO_INHERIT_REQ (0x0100)
541370b324cSopenharmony_ci#define MY_SE_SACL_AUTO_INHERIT_REQ (0x0200)
542370b324cSopenharmony_ci#define MY_SE_DACL_AUTO_INHERITED   (0x0400)
543370b324cSopenharmony_ci#define MY_SE_SACL_AUTO_INHERITED   (0x0800)
544370b324cSopenharmony_ci#define MY_SE_DACL_PROTECTED        (0x1000)
545370b324cSopenharmony_ci#define MY_SE_SACL_PROTECTED        (0x2000)
546370b324cSopenharmony_ci#define MY_SE_RM_CONTROL_VALID      (0x4000)
547370b324cSopenharmony_ci#define MY_SE_SELF_RELATIVE         (0x8000)
548370b324cSopenharmony_ci*/
549370b324cSopenharmony_ci
550370b324cSopenharmony_civoid ConvertNtSecureToString(const Byte *data, UInt32 size, AString &s)
551370b324cSopenharmony_ci{
552370b324cSopenharmony_ci  s.Empty();
553370b324cSopenharmony_ci  if (size < 20 || size > (1 << 18))
554370b324cSopenharmony_ci  {
555370b324cSopenharmony_ci    s += "ERROR";
556370b324cSopenharmony_ci    return;
557370b324cSopenharmony_ci  }
558370b324cSopenharmony_ci  if (Get16(data) != 1) // revision
559370b324cSopenharmony_ci  {
560370b324cSopenharmony_ci    s += "UNSUPPORTED";
561370b324cSopenharmony_ci    return;
562370b324cSopenharmony_ci  }
563370b324cSopenharmony_ci  ParseOwner(s, data, size, Get32(data + 4));
564370b324cSopenharmony_ci  s.Add_Space();
565370b324cSopenharmony_ci  ParseOwner(s, data, size, Get32(data + 8));
566370b324cSopenharmony_ci  ParseAcl(s, data, size, "s:", MY_SE_SACL_PRESENT, 12);
567370b324cSopenharmony_ci  ParseAcl(s, data, size, "d:", MY_SE_DACL_PRESENT, 16);
568370b324cSopenharmony_ci  s.Add_Space();
569370b324cSopenharmony_ci  s.Add_UInt32(size);
570370b324cSopenharmony_ci  // s += '\n';
571370b324cSopenharmony_ci  // s += Data_To_Hex(data, size);
572370b324cSopenharmony_ci}
573370b324cSopenharmony_ci
574370b324cSopenharmony_ci#ifdef _WIN32
575370b324cSopenharmony_ci
576370b324cSopenharmony_cistatic bool CheckSid(const Byte *data, UInt32 size, UInt32 pos) throw()
577370b324cSopenharmony_ci{
578370b324cSopenharmony_ci  if (pos >= size)
579370b324cSopenharmony_ci    return false;
580370b324cSopenharmony_ci  size -= pos;
581370b324cSopenharmony_ci  if (size < 8)
582370b324cSopenharmony_ci    return false;
583370b324cSopenharmony_ci  const UInt32 rev = data[pos];
584370b324cSopenharmony_ci  if (rev != 1)
585370b324cSopenharmony_ci    return false;
586370b324cSopenharmony_ci  const UInt32 num = data[pos + 1];
587370b324cSopenharmony_ci  return (8 + num * 4 <= size);
588370b324cSopenharmony_ci}
589370b324cSopenharmony_ci
590370b324cSopenharmony_cistatic bool CheckAcl(const Byte *p, UInt32 size, UInt32 flags, UInt32 offset) throw()
591370b324cSopenharmony_ci{
592370b324cSopenharmony_ci  const UInt32 control = Get16(p + 2);
593370b324cSopenharmony_ci  if ((flags & control) == 0)
594370b324cSopenharmony_ci    return true;
595370b324cSopenharmony_ci  const UInt32 pos = Get32(p + offset);
596370b324cSopenharmony_ci  if (pos >= size)
597370b324cSopenharmony_ci    return false;
598370b324cSopenharmony_ci  p += pos;
599370b324cSopenharmony_ci  size -= pos;
600370b324cSopenharmony_ci  if (size < 8)
601370b324cSopenharmony_ci    return false;
602370b324cSopenharmony_ci  const UInt32 aclSize = Get16(p + 2);
603370b324cSopenharmony_ci  return (aclSize <= size);
604370b324cSopenharmony_ci}
605370b324cSopenharmony_ci
606370b324cSopenharmony_cibool CheckNtSecure(const Byte *data, UInt32 size) throw()
607370b324cSopenharmony_ci{
608370b324cSopenharmony_ci  if (size < 20)
609370b324cSopenharmony_ci    return false;
610370b324cSopenharmony_ci  if (Get16(data) != 1) // revision
611370b324cSopenharmony_ci    return true; // windows function can handle such error, so we allow it
612370b324cSopenharmony_ci  if (size > (1 << 18))
613370b324cSopenharmony_ci    return false;
614370b324cSopenharmony_ci  if (!CheckSid(data, size, Get32(data + 4))) return false;
615370b324cSopenharmony_ci  if (!CheckSid(data, size, Get32(data + 8))) return false;
616370b324cSopenharmony_ci  if (!CheckAcl(data, size, MY_SE_SACL_PRESENT, 12)) return false;
617370b324cSopenharmony_ci  if (!CheckAcl(data, size, MY_SE_DACL_PRESENT, 16)) return false;
618370b324cSopenharmony_ci  return true;
619370b324cSopenharmony_ci}
620370b324cSopenharmony_ci
621370b324cSopenharmony_ci#endif
622370b324cSopenharmony_ci
623370b324cSopenharmony_ci
624370b324cSopenharmony_ci
625370b324cSopenharmony_ci// IO_REPARSE_TAG_*
626370b324cSopenharmony_ci
627370b324cSopenharmony_cistatic const CSecID2Name k_ReparseTags[] =
628370b324cSopenharmony_ci{
629370b324cSopenharmony_ci  { 0xA0000003, "MOUNT_POINT" },
630370b324cSopenharmony_ci  { 0xC0000004, "HSM" },
631370b324cSopenharmony_ci  { 0x80000005, "DRIVE_EXTENDER" },
632370b324cSopenharmony_ci  { 0x80000006, "HSM2" },
633370b324cSopenharmony_ci  { 0x80000007, "SIS" },
634370b324cSopenharmony_ci  { 0x80000008, "WIM" },
635370b324cSopenharmony_ci  { 0x80000009, "CSV" },
636370b324cSopenharmony_ci  { 0x8000000A, "DFS" },
637370b324cSopenharmony_ci  { 0x8000000B, "FILTER_MANAGER" },
638370b324cSopenharmony_ci  { 0xA000000C, "SYMLINK" },
639370b324cSopenharmony_ci  { 0xA0000010, "IIS_CACHE" },
640370b324cSopenharmony_ci  { 0x80000012, "DFSR" },
641370b324cSopenharmony_ci  { 0x80000013, "DEDUP" },
642370b324cSopenharmony_ci  { 0xC0000014, "APPXSTRM" },
643370b324cSopenharmony_ci  { 0x80000014, "NFS" },
644370b324cSopenharmony_ci  { 0x80000015, "FILE_PLACEHOLDER" },
645370b324cSopenharmony_ci  { 0x80000016, "DFM" },
646370b324cSopenharmony_ci  { 0x80000017, "WOF" },
647370b324cSopenharmony_ci  { 0x80000018, "WCI" },
648370b324cSopenharmony_ci  { 0x8000001B, "APPEXECLINK" },
649370b324cSopenharmony_ci  { 0xA000001D, "LX_SYMLINK" },
650370b324cSopenharmony_ci  { 0x80000023, "AF_UNIX" },
651370b324cSopenharmony_ci  { 0x80000024, "LX_FIFO" },
652370b324cSopenharmony_ci  { 0x80000025, "LX_CHR" },
653370b324cSopenharmony_ci  { 0x80000026, "LX_BLK" }
654370b324cSopenharmony_ci};
655370b324cSopenharmony_ci
656370b324cSopenharmony_cibool ConvertNtReparseToString(const Byte *data, UInt32 size, UString &s)
657370b324cSopenharmony_ci{
658370b324cSopenharmony_ci  s.Empty();
659370b324cSopenharmony_ci  NFile::CReparseAttr attr;
660370b324cSopenharmony_ci
661370b324cSopenharmony_ci  if (attr.Parse(data, size))
662370b324cSopenharmony_ci  {
663370b324cSopenharmony_ci    if (attr.IsSymLink_WSL())
664370b324cSopenharmony_ci    {
665370b324cSopenharmony_ci      s += "WSL: ";
666370b324cSopenharmony_ci      s += attr.GetPath();
667370b324cSopenharmony_ci    }
668370b324cSopenharmony_ci    else
669370b324cSopenharmony_ci    {
670370b324cSopenharmony_ci      if (!attr.IsSymLink_Win())
671370b324cSopenharmony_ci        s += "Junction: ";
672370b324cSopenharmony_ci      s += attr.GetPath();
673370b324cSopenharmony_ci      if (s.IsEmpty())
674370b324cSopenharmony_ci        s += "Link: ";
675370b324cSopenharmony_ci      if (!attr.IsOkNamePair())
676370b324cSopenharmony_ci      {
677370b324cSopenharmony_ci        s += " : ";
678370b324cSopenharmony_ci        s += attr.PrintName;
679370b324cSopenharmony_ci      }
680370b324cSopenharmony_ci    }
681370b324cSopenharmony_ci    if (attr.MinorError)
682370b324cSopenharmony_ci      s += " : MINOR_ERROR";
683370b324cSopenharmony_ci    return true;
684370b324cSopenharmony_ci    // s += " "; // for debug
685370b324cSopenharmony_ci  }
686370b324cSopenharmony_ci
687370b324cSopenharmony_ci  if (size < 8)
688370b324cSopenharmony_ci    return false;
689370b324cSopenharmony_ci  const UInt32 tag = Get32(data);
690370b324cSopenharmony_ci  const UInt32 len = Get16(data + 4);
691370b324cSopenharmony_ci  if (len + 8 > size)
692370b324cSopenharmony_ci    return false;
693370b324cSopenharmony_ci  if (Get16(data + 6) != 0) // padding
694370b324cSopenharmony_ci    return false;
695370b324cSopenharmony_ci
696370b324cSopenharmony_ci  /*
697370b324cSopenharmony_ci  #define my_IO_REPARSE_TAG_DEDUP        (0x80000013L)
698370b324cSopenharmony_ci  if (tag == my_IO_REPARSE_TAG_DEDUP)
699370b324cSopenharmony_ci  {
700370b324cSopenharmony_ci  }
701370b324cSopenharmony_ci  */
702370b324cSopenharmony_ci
703370b324cSopenharmony_ci  {
704370b324cSopenharmony_ci    const int index = FindPairIndex(k_ReparseTags, Z7_ARRAY_SIZE(k_ReparseTags), tag);
705370b324cSopenharmony_ci    if (index >= 0)
706370b324cSopenharmony_ci      s += k_ReparseTags[(unsigned)index].sz;
707370b324cSopenharmony_ci    else
708370b324cSopenharmony_ci    {
709370b324cSopenharmony_ci      s += "REPARSE:";
710370b324cSopenharmony_ci      char hex[16];
711370b324cSopenharmony_ci      ConvertUInt32ToHex8Digits(tag, hex);
712370b324cSopenharmony_ci      s += hex;
713370b324cSopenharmony_ci    }
714370b324cSopenharmony_ci  }
715370b324cSopenharmony_ci
716370b324cSopenharmony_ci  s += ":";
717370b324cSopenharmony_ci  s.Add_UInt32(len);
718370b324cSopenharmony_ci
719370b324cSopenharmony_ci  if (len != 0)
720370b324cSopenharmony_ci  {
721370b324cSopenharmony_ci    s.Add_Space();
722370b324cSopenharmony_ci
723370b324cSopenharmony_ci    data += 8;
724370b324cSopenharmony_ci
725370b324cSopenharmony_ci    for (UInt32 i = 0; i < len; i++)
726370b324cSopenharmony_ci    {
727370b324cSopenharmony_ci      if (i >= 16)
728370b324cSopenharmony_ci      {
729370b324cSopenharmony_ci        s += "...";
730370b324cSopenharmony_ci        break;
731370b324cSopenharmony_ci      }
732370b324cSopenharmony_ci      const unsigned b = data[i];
733370b324cSopenharmony_ci      s += (char)GetHex((b >> 4) & 0xF);
734370b324cSopenharmony_ci      s += (char)GetHex(b & 0xF);
735370b324cSopenharmony_ci    }
736370b324cSopenharmony_ci  }
737370b324cSopenharmony_ci
738370b324cSopenharmony_ci  return true;
739370b324cSopenharmony_ci}
740370b324cSopenharmony_ci
741370b324cSopenharmony_ci#endif
742