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 0;
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