1// PropVariantConv.cpp
2
3#include "StdAfx.h"
4
5#include "../Common/IntToString.h"
6
7#include "Defs.h"
8#include "PropVariantConv.h"
9
10#define UINT_TO_STR_2(c, val) { s[0] = (c); s[1] = (char)('0' + (val) / 10); s[2] = (char)('0' + (val) % 10); s += 3; }
11
12bool ConvertUtcFileTimeToString2(const FILETIME &utc, unsigned ns100, char *s, int level) throw()
13{
14  *s = 0;
15  FILETIME ft;
16  if (!FileTimeToLocalFileTime(&utc, &ft))
17    return false;
18
19  SYSTEMTIME st;
20  if (!BOOLToBool(FileTimeToSystemTime(&ft, &st)))
21  {
22    // win10 : that function doesn't work, if bit 63 of 64-bit FILETIME is set.
23    return false;
24  }
25
26  {
27    unsigned val = st.wYear;
28    if (val >= 10000)
29    {
30      *s++ = (char)('0' + val / 10000);
31      val %= 10000;
32    }
33    s[3] = (char)('0' + val % 10); val /= 10;
34    s[2] = (char)('0' + val % 10); val /= 10;
35    s[1] = (char)('0' + val % 10);
36    s[0] = (char)('0' + val / 10);
37    s += 4;
38  }
39  UINT_TO_STR_2('-', st.wMonth)
40  UINT_TO_STR_2('-', st.wDay)
41
42  if (level > kTimestampPrintLevel_DAY)
43  {
44    UINT_TO_STR_2(' ', st.wHour)
45    UINT_TO_STR_2(':', st.wMinute)
46
47    if (level >= kTimestampPrintLevel_SEC)
48    {
49      UINT_TO_STR_2(':', st.wSecond)
50
51      if (level > kTimestampPrintLevel_SEC)
52      {
53        *s++ = '.';
54        /*
55        {
56          unsigned val = st.wMilliseconds;
57          s[2] = (char)('0' + val % 10); val /= 10;
58          s[1] = (char)('0' + val % 10);
59          s[0] = (char)('0' + val / 10);
60          s += 3;
61        }
62        *s++ = ' ';
63        */
64
65        {
66          unsigned numDigits = 7;
67          UInt32 val = (UInt32)((((UInt64)ft.dwHighDateTime << 32) + ft.dwLowDateTime) % 10000000);
68          for (unsigned i = numDigits; i != 0;)
69          {
70            i--;
71            s[i] = (char)('0' + val % 10); val /= 10;
72          }
73          if (numDigits > (unsigned)level)
74            numDigits = (unsigned)level;
75          s += numDigits;
76        }
77        if (level >= kTimestampPrintLevel_NTFS + 1)
78        {
79          *s++ = (char)('0' + (ns100 / 10));
80          if (level >= kTimestampPrintLevel_NTFS + 2)
81            *s++ = (char)('0' + (ns100 % 10));
82        }
83      }
84    }
85  }
86
87  *s = 0;
88  return true;
89}
90
91
92bool ConvertUtcFileTimeToString(const FILETIME &utc, char *s, int level) throw()
93{
94  return ConvertUtcFileTimeToString2(utc, 0, s, level);
95}
96
97bool ConvertUtcFileTimeToString2(const FILETIME &ft, unsigned ns100, wchar_t *dest, int level) throw()
98{
99  char s[32];
100  bool res = ConvertUtcFileTimeToString2(ft, ns100, s, level);
101  for (unsigned i = 0;; i++)
102  {
103    Byte c = (Byte)s[i];
104    dest[i] = c;
105    if (c == 0)
106      break;
107  }
108  return res;
109}
110
111bool ConvertUtcFileTimeToString(const FILETIME &ft, wchar_t *dest, int level) throw()
112{
113  char s[32];
114  bool res = ConvertUtcFileTimeToString(ft, s, level);
115  for (unsigned i = 0;; i++)
116  {
117    Byte c = (Byte)s[i];
118    dest[i] = c;
119    if (c == 0)
120      break;
121  }
122  return res;
123}
124
125
126void ConvertPropVariantToShortString(const PROPVARIANT &prop, char *dest) throw()
127{
128  *dest = 0;
129  switch (prop.vt)
130  {
131    case VT_EMPTY: return;
132    case VT_BSTR: dest[0] = '?'; dest[1] = 0; return;
133    case VT_UI1: ConvertUInt32ToString(prop.bVal, dest); return;
134    case VT_UI2: ConvertUInt32ToString(prop.uiVal, dest); return;
135    case VT_UI4: ConvertUInt32ToString(prop.ulVal, dest); return;
136    case VT_UI8: ConvertUInt64ToString(prop.uhVal.QuadPart, dest); return;
137    case VT_FILETIME:
138    {
139      // const unsigned prec = prop.wReserved1;
140      int level = 0;
141      /*
142      if (prec == 0)
143        level = 7;
144      else if (prec > 16 && prec <= 16 + 9)
145        level = prec - 16;
146      */
147      ConvertUtcFileTimeToString(prop.filetime, dest, level);
148      return;
149    }
150    // case VT_I1: return ConvertInt64ToString(prop.cVal, dest); return;
151    case VT_I2: ConvertInt64ToString(prop.iVal, dest); return;
152    case VT_I4: ConvertInt64ToString(prop.lVal, dest); return;
153    case VT_I8: ConvertInt64ToString(prop.hVal.QuadPart, dest); return;
154    case VT_BOOL: dest[0] = VARIANT_BOOLToBool(prop.boolVal) ? '+' : '-'; dest[1] = 0; return;
155    default: dest[0] = '?'; dest[1] = ':'; ConvertUInt64ToString(prop.vt, dest + 2);
156  }
157}
158
159void ConvertPropVariantToShortString(const PROPVARIANT &prop, wchar_t *dest) throw()
160{
161  *dest = 0;
162  switch (prop.vt)
163  {
164    case VT_EMPTY: return;
165    case VT_BSTR: dest[0] = '?'; dest[1] = 0; return;
166    case VT_UI1: ConvertUInt32ToString(prop.bVal, dest); return;
167    case VT_UI2: ConvertUInt32ToString(prop.uiVal, dest); return;
168    case VT_UI4: ConvertUInt32ToString(prop.ulVal, dest); return;
169    case VT_UI8: ConvertUInt64ToString(prop.uhVal.QuadPart, dest); return;
170    case VT_FILETIME:
171    {
172      // const unsigned prec = prop.wReserved1;
173      int level = 0;
174      /*
175      if (prec == 0)
176        level = 7;
177      else if (prec > 16 && prec <= 16 + 9)
178        level = prec - 16;
179      */
180      ConvertUtcFileTimeToString(prop.filetime, dest, level);
181      return;
182    }
183    // case VT_I1: return ConvertInt64ToString(prop.cVal, dest); return;
184    case VT_I2: ConvertInt64ToString(prop.iVal, dest); return;
185    case VT_I4: ConvertInt64ToString(prop.lVal, dest); return;
186    case VT_I8: ConvertInt64ToString(prop.hVal.QuadPart, dest); return;
187    case VT_BOOL: dest[0] = VARIANT_BOOLToBool(prop.boolVal) ? (wchar_t)'+' : (wchar_t)'-'; dest[1] = 0; return;
188    default: dest[0] = '?'; dest[1] = ':'; ConvertUInt32ToString(prop.vt, dest + 2);
189  }
190}
191