1 // MyWindows.cpp
2
3 #include "StdAfx.h"
4
5 #ifndef _WIN32
6
7 #include <stdlib.h>
8 #include <time.h>
9 #ifdef __GNUC__
10 #include <sys/time.h>
11 #endif
12
13 #include "MyWindows.h"
14
AllocateForBSTR(size_t cb)15 static inline void *AllocateForBSTR(size_t cb) { return ::malloc(cb); }
FreeForBSTR(void * pv)16 static inline void FreeForBSTR(void *pv) { ::free(pv);}
17
18 /* Win32 uses DWORD (32-bit) type to store size of string before (OLECHAR *) string.
19 We must select CBstrSizeType for another systems (not Win32):
20
21 if (CBstrSizeType is UINT32),
22 then we support only strings smaller than 4 GB.
23 Win32 version always has that limitation.
24
25 if (CBstrSizeType is UINT),
26 (UINT can be 16/32/64-bit)
27 We can support strings larger than 4 GB (if UINT is 64-bit),
28 but sizeof(UINT) can be different in parts compiled by
29 different compilers/settings,
30 and we can't send such BSTR strings between such parts.
31 */
32
33 typedef UINT32 CBstrSizeType;
34 // typedef UINT CBstrSizeType;
35
36 #define k_BstrSize_Max 0xFFFFFFFF
37 // #define k_BstrSize_Max UINT_MAX
38 // #define k_BstrSize_Max ((UINT)(INT)-1)
39
SysAllocStringByteLen(LPCSTR s,UINT len)40 BSTR SysAllocStringByteLen(LPCSTR s, UINT len)
41 {
42 /* Original SysAllocStringByteLen in Win32 maybe fills only unaligned null OLECHAR at the end.
43 We provide also aligned null OLECHAR at the end. */
44
45 if (len >= (k_BstrSize_Max - (UINT)sizeof(OLECHAR) - (UINT)sizeof(OLECHAR) - (UINT)sizeof(CBstrSizeType)))
46 return NULL;
47
48 UINT size = (len + (UINT)sizeof(OLECHAR) + (UINT)sizeof(OLECHAR) - 1) & ~((UINT)sizeof(OLECHAR) - 1);
49 void *p = AllocateForBSTR(size + (UINT)sizeof(CBstrSizeType));
50 if (!p)
51 return NULL;
52 *(CBstrSizeType *)p = (CBstrSizeType)len;
53 BSTR bstr = (BSTR)((CBstrSizeType *)p + 1);
54 if (s)
55 memcpy(bstr, s, len);
56 for (; len < size; len++)
57 ((Byte *)bstr)[len] = 0;
58 return bstr;
59 }
60
SysAllocStringLen(const OLECHAR * s,UINT len)61 BSTR SysAllocStringLen(const OLECHAR *s, UINT len)
62 {
63 if (len >= (k_BstrSize_Max - (UINT)sizeof(OLECHAR) - (UINT)sizeof(CBstrSizeType)) / (UINT)sizeof(OLECHAR))
64 return NULL;
65
66 UINT size = len * (UINT)sizeof(OLECHAR);
67 void *p = AllocateForBSTR(size + (UINT)sizeof(CBstrSizeType) + (UINT)sizeof(OLECHAR));
68 if (!p)
69 return NULL;
70 *(CBstrSizeType *)p = (CBstrSizeType)size;
71 BSTR bstr = (BSTR)((CBstrSizeType *)p + 1);
72 if (s)
73 memcpy(bstr, s, size);
74 bstr[len] = 0;
75 return bstr;
76 }
77
SysAllocString(const OLECHAR * s)78 BSTR SysAllocString(const OLECHAR *s)
79 {
80 if (!s)
81 return NULL;
82 const OLECHAR *s2 = s;
83 while (*s2 != 0)
84 s2++;
85 return SysAllocStringLen(s, (UINT)(s2 - s));
86 }
87
SysFreeString(BSTR bstr)88 void SysFreeString(BSTR bstr)
89 {
90 if (bstr)
91 FreeForBSTR((CBstrSizeType *)bstr - 1);
92 }
93
SysStringByteLen(BSTR bstr)94 UINT SysStringByteLen(BSTR bstr)
95 {
96 if (!bstr)
97 return 0;
98 return *((CBstrSizeType *)bstr - 1);
99 }
100
SysStringLen(BSTR bstr)101 UINT SysStringLen(BSTR bstr)
102 {
103 if (!bstr)
104 return 0;
105 return *((CBstrSizeType *)bstr - 1) / (UINT)sizeof(OLECHAR);
106 }
107
108
VariantClear(VARIANTARG * prop)109 HRESULT VariantClear(VARIANTARG *prop)
110 {
111 if (prop->vt == VT_BSTR)
112 SysFreeString(prop->bstrVal);
113 prop->vt = VT_EMPTY;
114 return S_OK;
115 }
116
VariantCopy(VARIANTARG * dest,const VARIANTARG * src)117 HRESULT VariantCopy(VARIANTARG *dest, const VARIANTARG *src)
118 {
119 HRESULT res = ::VariantClear(dest);
120 if (res != S_OK)
121 return res;
122 if (src->vt == VT_BSTR)
123 {
124 dest->bstrVal = SysAllocStringByteLen((LPCSTR)src->bstrVal,
125 SysStringByteLen(src->bstrVal));
126 if (!dest->bstrVal)
127 return E_OUTOFMEMORY;
128 dest->vt = VT_BSTR;
129 }
130 else
131 *dest = *src;
132 return S_OK;
133 }
134
CompareFileTime(const FILETIME * ft1,const FILETIME * ft2)135 LONG CompareFileTime(const FILETIME* ft1, const FILETIME* ft2)
136 {
137 if (ft1->dwHighDateTime < ft2->dwHighDateTime) return -1;
138 if (ft1->dwHighDateTime > ft2->dwHighDateTime) return 1;
139 if (ft1->dwLowDateTime < ft2->dwLowDateTime) return -1;
140 if (ft1->dwLowDateTime > ft2->dwLowDateTime) return 1;
141 return 0;
142 }
143
GetLastError()144 DWORD GetLastError()
145 {
146 return (DWORD)errno;
147 }
148
SetLastError(DWORD dw)149 void SetLastError(DWORD dw)
150 {
151 errno = (int)dw;
152 }
153
154
TIME_GetBias()155 static LONG TIME_GetBias()
156 {
157 time_t utc = time(NULL);
158 struct tm *ptm = localtime(&utc);
159 int localdaylight = ptm->tm_isdst; /* daylight for local timezone */
160 ptm = gmtime(&utc);
161 ptm->tm_isdst = localdaylight; /* use local daylight, not that of Greenwich */
162 LONG bias = (int)(mktime(ptm)-utc);
163 return bias;
164 }
165
166 #define TICKS_PER_SEC 10000000
167 /*
168 #define SECS_PER_DAY (24 * 60 * 60)
169 #define SECS_1601_TO_1970 ((369 * 365 + 89) * (UInt64)SECS_PER_DAY)
170 #define TICKS_1601_TO_1970 (SECS_1601_TO_1970 * TICKS_PER_SEC)
171 */
172
173 #define GET_TIME_64(pft) ((pft)->dwLowDateTime | ((UInt64)(pft)->dwHighDateTime << 32))
174
175 #define SET_FILETIME(ft, v64) \
176 (ft)->dwLowDateTime = (DWORD)v64; \
177 (ft)->dwHighDateTime = (DWORD)(v64 >> 32);
178
179
FileTimeToLocalFileTime(const FILETIME * fileTime,FILETIME * localFileTime)180 BOOL WINAPI FileTimeToLocalFileTime(const FILETIME *fileTime, FILETIME *localFileTime)
181 {
182 UInt64 v = GET_TIME_64(fileTime);
183 v = (UInt64)((Int64)v - (Int64)TIME_GetBias() * TICKS_PER_SEC);
184 SET_FILETIME(localFileTime, v)
185 return TRUE;
186 }
187
LocalFileTimeToFileTime(const FILETIME * localFileTime,FILETIME * fileTime)188 BOOL WINAPI LocalFileTimeToFileTime(const FILETIME *localFileTime, FILETIME *fileTime)
189 {
190 UInt64 v = GET_TIME_64(localFileTime);
191 v = (UInt64)((Int64)v + (Int64)TIME_GetBias() * TICKS_PER_SEC);
192 SET_FILETIME(fileTime, v)
193 return TRUE;
194 }
195
196 /*
197 VOID WINAPI GetSystemTimeAsFileTime(FILETIME *ft)
198 {
199 UInt64 t = 0;
200 timeval tv;
201 if (gettimeofday(&tv, NULL) == 0)
202 {
203 t = tv.tv_sec * (UInt64)TICKS_PER_SEC + TICKS_1601_TO_1970;
204 t += tv.tv_usec * 10;
205 }
206 SET_FILETIME(ft, t)
207 }
208 */
209
GetTickCount(VOID)210 DWORD WINAPI GetTickCount(VOID)
211 {
212 #ifndef _WIN32
213 // gettimeofday() doesn't work in some MINGWs by unknown reason
214 timeval tv;
215 if (gettimeofday(&tv, NULL) == 0)
216 {
217 // tv_sec and tv_usec are (long)
218 return (DWORD)((UInt64)(Int64)tv.tv_sec * (UInt64)1000 + (UInt64)(Int64)tv.tv_usec / 1000);
219 }
220 #endif
221 return (DWORD)time(NULL) * 1000;
222 }
223
224
225 #define PERIOD_4 (4 * 365 + 1)
226 #define PERIOD_100 (PERIOD_4 * 25 - 1)
227 #define PERIOD_400 (PERIOD_100 * 4 + 1)
228
FileTimeToSystemTime(const FILETIME * ft,SYSTEMTIME * st)229 BOOL WINAPI FileTimeToSystemTime(const FILETIME *ft, SYSTEMTIME *st)
230 {
231 UInt32 v;
232 UInt64 v64 = GET_TIME_64(ft);
233 v64 /= 10000;
234 st->wMilliseconds = (WORD)(v64 % 1000); v64 /= 1000;
235 st->wSecond = (WORD)(v64 % 60); v64 /= 60;
236 st->wMinute = (WORD)(v64 % 60); v64 /= 60;
237 v = (UInt32)v64;
238 st->wHour = (WORD)(v % 24); v /= 24;
239
240 // 1601-01-01 was Monday
241 st->wDayOfWeek = (WORD)((v + 1) % 7);
242
243 UInt32 leaps, year, day, mon;
244 leaps = (3 * ((4 * v + (365 - 31 - 28) * 4 + 3) / PERIOD_400) + 3) / 4;
245 v += 28188 + leaps;
246 // leaps - the number of exceptions from PERIOD_4 rules starting from 1600-03-01
247 // (1959 / 64) - converts day from 03-01 to month
248 year = (20 * v - 2442) / (5 * PERIOD_4);
249 day = v - (year * PERIOD_4) / 4;
250 mon = (64 * day) / 1959;
251 st->wDay = (WORD)(day - (1959 * mon) / 64);
252 mon -= 1;
253 year += 1524;
254 if (mon > 12)
255 {
256 mon -= 12;
257 year++;
258 }
259 st->wMonth = (WORD)mon;
260 st->wYear = (WORD)year;
261
262 /*
263 unsigned year, mon;
264 unsigned char ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
265 unsigned t;
266
267 year = (WORD)(1601 + v / PERIOD_400 * 400);
268 v %= PERIOD_400;
269
270 t = v / PERIOD_100; if (t == 4) t = 3; year += t * 100; v -= t * PERIOD_100;
271 t = v / PERIOD_4; if (t == 25) t = 24; year += t * 4; v -= t * PERIOD_4;
272 t = v / 365; if (t == 4) t = 3; year += t; v -= t * 365;
273
274 st->wYear = (WORD)year;
275
276 if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))
277 ms[1] = 29;
278 for (mon = 0;; mon++)
279 {
280 unsigned d = ms[mon];
281 if (v < d)
282 break;
283 v -= d;
284 }
285 st->wDay = (WORD)(v + 1);
286 st->wMonth = (WORD)(mon + 1);
287 */
288
289 return TRUE;
290 }
291
292 #endif
293