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
12 static const unsigned k_TimeStringBufferSize = 64;
13
14 bool g_Timestamp_Show_UTC;
15 #if 0
16 bool g_Timestamp_Show_DisableZ;
17 bool g_Timestamp_Show_TDelimeter;
18 bool g_Timestamp_Show_ZoneOffset;
19 #endif
20
21 Z7_NO_INLINE
ConvertUtcFileTimeToString2(const FILETIME & utc,unsigned ns100,char * s,int level,unsigned flags)22 bool ConvertUtcFileTimeToString2(const FILETIME &utc, unsigned ns100, char *s, int level, unsigned flags) throw()
23 {
24 *s = 0;
25 FILETIME ft;
26
27 #if 0
28 Int64 bias64 = 0;
29 #endif
30
31 const bool show_utc =
32 (flags & kTimestampPrintFlags_Force_UTC) ? true :
33 (flags & kTimestampPrintFlags_Force_LOCAL) ? false :
34 g_Timestamp_Show_UTC;
35
36 if (show_utc)
37 ft = utc;
38 else
39 {
40 if (!FileTimeToLocalFileTime(&utc, &ft))
41 return false;
42 #if 0
43 if (g_Timestamp_Show_ZoneOffset)
44 {
45 const UInt64 utc64 = (((UInt64)utc.dwHighDateTime) << 32) + utc.dwLowDateTime;
46 const UInt64 loc64 = (((UInt64) ft.dwHighDateTime) << 32) + ft.dwLowDateTime;
47 bias64 = (Int64)utc64 - (Int64)loc64;
48 }
49 #endif
50 }
51
52 SYSTEMTIME st;
53 if (!BOOLToBool(FileTimeToSystemTime(&ft, &st)))
54 {
55 // win10 : that function doesn't work, if bit 63 of 64-bit FILETIME is set.
56 return false;
57 }
58
59 {
60 unsigned val = st.wYear;
61 if (val >= 10000)
62 {
63 *s++ = (char)('0' + val / 10000);
64 val %= 10000;
65 }
66 s[3] = (char)('0' + val % 10); val /= 10;
67 s[2] = (char)('0' + val % 10); val /= 10;
68 s[1] = (char)('0' + val % 10);
69 s[0] = (char)('0' + val / 10);
70 s += 4;
71 }
72 UINT_TO_STR_2('-', st.wMonth)
73 UINT_TO_STR_2('-', st.wDay)
74
75 if (level > kTimestampPrintLevel_DAY)
76 {
77 const char setChar =
78 #if 0
79 g_Timestamp_Show_TDelimeter ? 'T' : // ISO 8601
80 #endif
81 ' ';
82 UINT_TO_STR_2(setChar, st.wHour)
83 UINT_TO_STR_2(':', st.wMinute)
84
85 if (level >= kTimestampPrintLevel_SEC)
86 {
87 UINT_TO_STR_2(':', st.wSecond)
88
89 if (level > kTimestampPrintLevel_SEC)
90 {
91 *s++ = '.';
92 /*
93 {
94 unsigned val = st.wMilliseconds;
95 s[2] = (char)('0' + val % 10); val /= 10;
96 s[1] = (char)('0' + val % 10);
97 s[0] = (char)('0' + val / 10);
98 s += 3;
99 }
100 *s++ = ' ';
101 */
102
103 {
104 unsigned numDigits = 7;
105 UInt32 val = (UInt32)((((UInt64)ft.dwHighDateTime << 32) + ft.dwLowDateTime) % 10000000);
106 for (unsigned i = numDigits; i != 0;)
107 {
108 i--;
109 s[i] = (char)('0' + val % 10); val /= 10;
110 }
111 if (numDigits > (unsigned)level)
112 numDigits = (unsigned)level;
113 s += numDigits;
114 }
115 if (level >= kTimestampPrintLevel_NTFS + 1)
116 {
117 *s++ = (char)('0' + (ns100 / 10));
118 if (level >= kTimestampPrintLevel_NTFS + 2)
119 *s++ = (char)('0' + (ns100 % 10));
120 }
121 }
122 }
123 }
124
125 if (show_utc)
126 {
127 if ((flags & kTimestampPrintFlags_DisableZ) == 0
128 #if 0
129 && !g_Timestamp_Show_DisableZ
130 #endif
131 )
132 *s++ = 'Z';
133 }
134 #if 0
135 else if (g_Timestamp_Show_ZoneOffset)
136 {
137 #if 1
138 {
139 char c;
140 if (bias64 < 0)
141 {
142 bias64 = -bias64;
143 c = '+';
144 }
145 else
146 c = '-';
147 UInt32 bias = (UInt32)((UInt64)bias64 / (10000000 * 60));
148 #else
149 TIME_ZONE_INFORMATION zi;
150 const DWORD dw = GetTimeZoneInformation(&zi);
151 if (dw <= TIME_ZONE_ID_DAYLIGHT) // == 2
152 {
153 // UTC = LOCAL + Bias
154 Int32 bias = zi.Bias;
155 char c;
156 if (bias < 0)
157 {
158 bias = -bias;
159 c = '+';
160 }
161 else
162 c = '-';
163 #endif
164 const UInt32 hours = (UInt32)bias / 60;
165 const UInt32 mins = (UInt32)bias % 60;
166 UINT_TO_STR_2(c, hours)
167 UINT_TO_STR_2(':', mins)
168 }
169 }
170 #endif
171 *s = 0;
172 return true;
173 }
174
175
176 bool ConvertUtcFileTimeToString(const FILETIME &utc, char *s, int level) throw()
177 {
178 return ConvertUtcFileTimeToString2(utc, 0, s, level);
179 }
180
181 bool ConvertUtcFileTimeToString2(const FILETIME &ft, unsigned ns100, wchar_t *dest, int level) throw()
182 {
183 char s[k_TimeStringBufferSize];
184 const bool res = ConvertUtcFileTimeToString2(ft, ns100, s, level);
185 for (unsigned i = 0;; i++)
186 {
187 const Byte c = (Byte)s[i];
188 dest[i] = c;
189 if (c == 0)
190 break;
191 }
192 return res;
193 }
194
195 bool ConvertUtcFileTimeToString(const FILETIME &ft, wchar_t *dest, int level) throw()
196 {
197 char s[k_TimeStringBufferSize];
198 const bool res = ConvertUtcFileTimeToString(ft, s, level);
199 for (unsigned i = 0;; i++)
200 {
201 const Byte c = (Byte)s[i];
202 dest[i] = c;
203 if (c == 0)
204 break;
205 }
206 return res;
207 }
208
209
210 void ConvertPropVariantToShortString(const PROPVARIANT &prop, char *dest) throw()
211 {
212 *dest = 0;
213 switch (prop.vt)
214 {
215 case VT_EMPTY: return;
216 case VT_BSTR: dest[0] = '?'; dest[1] = 0; return;
217 case VT_UI1: ConvertUInt32ToString(prop.bVal, dest); return;
218 case VT_UI2: ConvertUInt32ToString(prop.uiVal, dest); return;
219 case VT_UI4: ConvertUInt32ToString(prop.ulVal, dest); return;
220 case VT_UI8: ConvertUInt64ToString(prop.uhVal.QuadPart, dest); return;
221 case VT_FILETIME:
222 {
223 // const unsigned prec = prop.wReserved1;
224 int level = 0;
225 /*
226 if (prec == 0)
227 level = 7;
228 else if (prec > 16 && prec <= 16 + 9)
229 level = prec - 16;
230 */
231 ConvertUtcFileTimeToString(prop.filetime, dest, level);
232 return;
233 }
234 // case VT_I1: return ConvertInt64ToString(prop.cVal, dest); return;
235 case VT_I2: ConvertInt64ToString(prop.iVal, dest); return;
236 case VT_I4: ConvertInt64ToString(prop.lVal, dest); return;
237 case VT_I8: ConvertInt64ToString(prop.hVal.QuadPart, dest); return;
238 case VT_BOOL: dest[0] = VARIANT_BOOLToBool(prop.boolVal) ? '+' : '-'; dest[1] = 0; return;
239 default: dest[0] = '?'; dest[1] = ':'; ConvertUInt64ToString(prop.vt, dest + 2);
240 }
241 }
242
243 void ConvertPropVariantToShortString(const PROPVARIANT &prop, wchar_t *dest) throw()
244 {
245 *dest = 0;
246 switch (prop.vt)
247 {
248 case VT_EMPTY: return;
249 case VT_BSTR: dest[0] = '?'; dest[1] = 0; return;
250 case VT_UI1: ConvertUInt32ToString(prop.bVal, dest); return;
251 case VT_UI2: ConvertUInt32ToString(prop.uiVal, dest); return;
252 case VT_UI4: ConvertUInt32ToString(prop.ulVal, dest); return;
253 case VT_UI8: ConvertUInt64ToString(prop.uhVal.QuadPart, dest); return;
254 case VT_FILETIME:
255 {
256 // const unsigned prec = prop.wReserved1;
257 int level = 0;
258 /*
259 if (prec == 0)
260 level = 7;
261 else if (prec > 16 && prec <= 16 + 9)
262 level = prec - 16;
263 */
264 ConvertUtcFileTimeToString(prop.filetime, dest, level);
265 return;
266 }
267 // case VT_I1: return ConvertInt64ToString(prop.cVal, dest); return;
268 case VT_I2: ConvertInt64ToString(prop.iVal, dest); return;
269 case VT_I4: ConvertInt64ToString(prop.lVal, dest); return;
270 case VT_I8: ConvertInt64ToString(prop.hVal.QuadPart, dest); return;
271 case VT_BOOL: dest[0] = VARIANT_BOOLToBool(prop.boolVal) ? (wchar_t)'+' : (wchar_t)'-'; dest[1] = 0; return;
272 default: dest[0] = '?'; dest[1] = ':'; ConvertUInt32ToString(prop.vt, dest + 2);
273 }
274 }
275