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 15static inline void *AllocateForBSTR(size_t cb) { return ::malloc(cb); } 16static 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 33typedef 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 40BSTR 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 61BSTR 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 78BSTR 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 88void SysFreeString(BSTR bstr) 89{ 90 if (bstr) 91 FreeForBSTR((CBstrSizeType *)bstr - 1); 92} 93 94UINT SysStringByteLen(BSTR bstr) 95{ 96 if (!bstr) 97 return 0; 98 return *((CBstrSizeType *)bstr - 1); 99} 100 101UINT SysStringLen(BSTR bstr) 102{ 103 if (!bstr) 104 return 0; 105 return *((CBstrSizeType *)bstr - 1) / (UINT)sizeof(OLECHAR); 106} 107 108 109HRESULT 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 117HRESULT 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 135LONG 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 144DWORD GetLastError() 145{ 146 return (DWORD)errno; 147} 148 149void SetLastError(DWORD dw) 150{ 151 errno = (int)dw; 152} 153 154 155static 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 180BOOL 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 188BOOL 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/* 197VOID 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 210DWORD 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 229BOOL 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