SysDepWin.cpp
上传用户:woshihumen
上传日期:2013-07-18
资源大小:484k
文件大小:49k
源码类别:

Email服务器

开发平台:

Visual C++

  1. /*
  2.  *  XMail by Davide Libenzi ( Intranet and Internet mail server )
  3.  *  Copyright (C) 1999,..,2004  Davide Libenzi
  4.  *
  5.  *  This program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2 of the License, or
  8.  *  (at your option) any later version.
  9.  *
  10.  *  This program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  *  GNU General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with this program; if not, write to the Free Software
  17.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18.  *
  19.  *  Davide Libenzi <davidel@xmailserver.org>
  20.  *
  21.  */
  22. #include "SysInclude.h"
  23. #include "SysDep.h"
  24. #include "AppDefines.h"
  25. #define MAX_TLS_KEYS                    64
  26. #define UNUSED_TLS_KEY_PROC             ((void (*)(void *)) -1)
  27. #define SOCK_VERSION_REQUESTED          MAKEWORD(2, 0)
  28. #define SHUTDOWN_RECV_TIMEOUT           2
  29. ///////////////////////////////////////////////////////////////////////////////
  30. //  Under certain circumstances ( M$ Proxy installed ?! ) a waiting operation
  31. //  may be unlocked even if the IO terminal is not ready to perform following
  32. //  IO request ( an error code WSAEWOULDBLOCK is returned ). The only solution
  33. //  I see is to sleep a bit to prevent processor time wasting :(
  34. ///////////////////////////////////////////////////////////////////////////////
  35. #define BLOCKED_SNDRCV_MSSLEEP          200
  36. #define HANDLE_SOCKS_SUCKS()            do { Sleep(BLOCKED_SNDRCV_MSSLEEP); } while (0)
  37. #define SAIN_Addr(s)                    (s).sin_addr.S_un.S_addr
  38. #define MIN_TCP_SEND_SIZE               (1024 * 8)
  39. #define MAX_TCP_SEND_SIZE               (1024 * 128)
  40. #define K_IO_TIME_RATIO                 8
  41. #define MAX_STACK_SHIFT                 2048
  42. #define STACK_ALIGN_BYTES               sizeof(int)
  43. struct TlsKeyEntry {
  44. void (*pFreeProc) (void *);
  45. };
  46. struct TlsKeyData {
  47. void *pData;
  48. };
  49. struct FileFindData {
  50. char szFindPath[SYS_MAX_PATH];
  51. HANDLE hFind;
  52. WIN32_FIND_DATA WFD;
  53. };
  54. struct ThreadRunner {
  55. unsigned int (*pThreadProc) (void *);
  56. void *pThreadData;
  57. };
  58. static void SysInitTlsKeyEntries(void);
  59. static void SysInitTlsKeys(void);
  60. static void SysCleanupTlsKeys(void);
  61. static char const *SysGetLastError(void);
  62. static int SysSetServerName(void);
  63. static int SysBlockSocket(SYS_SOCKET SockFD, int OnOff);
  64. static int SysSetSocketsOptions(SYS_SOCKET SockFD);
  65. static int SysRecvLL(SYS_SOCKET SockFD, char *pszBuffer, int iBufferSize);
  66. static int SysSendLL(SYS_SOCKET SockFD, char const *pszBuffer, int iBufferSize);
  67. static unsigned int SysThreadRunner(void *pRunData);
  68. static int SysThreadSetup(void);
  69. static int SysThreadCleanup(void);
  70. static BOOL WINAPI SysBreakHandlerRoutine(DWORD dwCtrlType);
  71. static void SysTimetToFileTime(time_t tTime, LPFILETIME pFT);
  72. static time_t SysFileTimeToTimet(LPFILETIME pFT);
  73. static unsigned int SysStkCall(unsigned int (*pProc) (void *), void *pData);
  74. static char szServerName[SYS_MAX_PATH];
  75. static CRITICAL_SECTION csTLS;
  76. static bool bSetupEntries = true;
  77. static TlsKeyEntry TlsKeyEntries[MAX_TLS_KEYS];
  78. static __declspec(thread)
  79. TlsKeyData TlsKeys[MAX_TLS_KEYS];
  80. static time_t tSysStart;
  81. static SYS_INT64 PCFreq;
  82. static SYS_INT64 PCSysStart;
  83. static unsigned int uSRandBase;
  84. static int iSndBufSize = -1, iRcvBufSize = -1;
  85. static CRITICAL_SECTION csLog;
  86. static void (*SysBreakHandler) (void) = NULL;
  87. static HANDLE hShutdownEvent = NULL;
  88. static void SysInitTlsKeyEntries(void)
  89. {
  90. if (bSetupEntries) {
  91. for (int ii = 0; ii < MAX_TLS_KEYS; ii++)
  92. TlsKeyEntries[ii].pFreeProc = UNUSED_TLS_KEY_PROC;
  93. bSetupEntries = false;
  94. }
  95. }
  96. static void SysInitTlsKeys(void)
  97. {
  98. for (int ii = 0; ii < MAX_TLS_KEYS; ii++)
  99. TlsKeys[ii].pData = NULL;
  100. }
  101. static void SysCleanupTlsKeys(void)
  102. {
  103. EnterCriticalSection(&csTLS);
  104. for (int ii = 0; ii < MAX_TLS_KEYS; ii++) {
  105. if ((TlsKeyEntries[ii].pFreeProc != UNUSED_TLS_KEY_PROC) &&
  106.     (TlsKeyEntries[ii].pFreeProc != NULL))
  107. TlsKeyEntries[ii].pFreeProc(TlsKeys[ii].pData);
  108. TlsKeys[ii].pData = NULL;
  109. }
  110. LeaveCriticalSection(&csTLS);
  111. }
  112. static char const *SysGetLastError(void)
  113. {
  114. char *pszMessage = NULL;
  115. DWORD dwError = GetLastError();
  116. DWORD dwRet =
  117.     FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
  118.   FORMAT_MESSAGE_ARGUMENT_ARRAY,
  119.   NULL,
  120.   dwError,
  121.   LANG_NEUTRAL,
  122.   (LPTSTR) & pszMessage,
  123.   0,
  124.   NULL);
  125. static char szMessage[1024] = "";
  126. if (dwRet == 0)
  127. SysSNPrintf(szMessage, sizeof(szMessage) - 1, "(0x%lX) Unknown error",
  128.     (unsigned long) dwError);
  129. else
  130. SysSNPrintf(szMessage, sizeof(szMessage) - 1, "(0x%lX) %s",
  131.     (unsigned long) dwError, pszMessage);
  132. if (pszMessage != NULL)
  133. LocalFree((HLOCAL) pszMessage);
  134. return (szMessage);
  135. }
  136. static int SysSetServerName(void)
  137. {
  138. int iSize;
  139. char *pszSlash;
  140. char *pszDot;
  141. char szPath[SYS_MAX_PATH] = APP_NAME_STR;
  142. GetModuleFileName(NULL, szPath, CountOf(szPath));
  143. if ((pszSlash = strrchr(szPath, '\')) == NULL)
  144. pszSlash = szPath;
  145. else
  146. pszSlash++;
  147. if ((pszDot = strchr(pszSlash, '.')) == NULL)
  148. pszDot = pszSlash + strlen(pszSlash);
  149. iSize = Min(sizeof(szServerName) - 1, (int) (pszDot - pszSlash));
  150. Cpy2Sz(szServerName, pszSlash, iSize);
  151. return (0);
  152. }
  153. int SysInitLibrary(void)
  154. {
  155. ///////////////////////////////////////////////////////////////////////////////
  156. //  Setup timers
  157. ///////////////////////////////////////////////////////////////////////////////
  158. LARGE_INTEGER PerfCntFreq;
  159. LARGE_INTEGER PerfCntCurr;
  160. QueryPerformanceFrequency(&PerfCntFreq);
  161. QueryPerformanceCounter(&PerfCntCurr);
  162. PCFreq = *(SYS_INT64 *) & PerfCntFreq;
  163. PCFreq /= 1000;
  164. PCSysStart = *(SYS_INT64 *) & PerfCntCurr;
  165. _tzset();
  166. time(&tSysStart);
  167. uSRandBase = (unsigned int) tSysStart;
  168. ///////////////////////////////////////////////////////////////////////////////
  169. //  Set the server name
  170. ///////////////////////////////////////////////////////////////////////////////
  171. SysSetServerName();
  172. ///////////////////////////////////////////////////////////////////////////////
  173. //  Setup sockets
  174. ///////////////////////////////////////////////////////////////////////////////
  175. WSADATA WSD;
  176. ZeroData(WSD);
  177. if (WSAStartup(SOCK_VERSION_REQUESTED, &WSD)) {
  178. ErrSetErrorCode(ERR_NETWORK);
  179. return (ERR_NETWORK);
  180. }
  181. InitializeCriticalSection(&csTLS);
  182. SysInitTlsKeyEntries();
  183. InitializeCriticalSection(&csLog);
  184. if ((hShutdownEvent = CreateEvent(NULL, TRUE, FALSE, NULL)) == NULL) {
  185. DeleteCriticalSection(&csLog);
  186. DeleteCriticalSection(&csTLS);
  187. ErrSetErrorCode(ERR_CREATEEVENT);
  188. return (ERR_CREATEEVENT);
  189. }
  190. if (SysThreadSetup() < 0) {
  191. ErrorPush();
  192. CloseHandle(hShutdownEvent);
  193. DeleteCriticalSection(&csLog);
  194. DeleteCriticalSection(&csTLS);
  195. return (ErrorPop());
  196. }
  197. return (0);
  198. }
  199. void SysCleanupLibrary(void)
  200. {
  201. SysThreadCleanup();
  202. DeleteCriticalSection(&csLog);
  203. DeleteCriticalSection(&csTLS);
  204. CloseHandle(hShutdownEvent);
  205. WSACleanup();
  206. }
  207. int SysShutdownLibrary(int iMode)
  208. {
  209. SetEvent(hShutdownEvent);
  210. return (0);
  211. }
  212. int SysSetupSocketBuffers(int *piSndBufSize, int *piRcvBufSize)
  213. {
  214. if (piSndBufSize != NULL)
  215. iSndBufSize = *piSndBufSize;
  216. if (piRcvBufSize != NULL)
  217. iRcvBufSize = *piRcvBufSize;
  218. return (0);
  219. }
  220. SYS_SOCKET SysCreateSocket(int iAddressFamily, int iType, int iProtocol)
  221. {
  222. SOCKET SockFD = WSASocket(iAddressFamily, iType, iProtocol, NULL, 0,
  223.   WSA_FLAG_OVERLAPPED);
  224. if (SockFD == INVALID_SOCKET) {
  225. ErrSetErrorCode(ERR_SOCKET_CREATE);
  226. return (SYS_INVALID_SOCKET);
  227. }
  228. if (SysSetSocketsOptions((SYS_SOCKET) SockFD) < 0) {
  229. SysCloseSocket((SYS_SOCKET) SockFD);
  230. return (SYS_INVALID_SOCKET);
  231. }
  232. return ((SYS_SOCKET) SockFD);
  233. }
  234. static int SysBlockSocket(SYS_SOCKET SockFD, int OnOff)
  235. {
  236. u_long IoctlLong = (OnOff) ? 0 : 1;
  237. if (ioctlsocket(SockFD, FIONBIO, &IoctlLong) == SOCKET_ERROR) {
  238. ErrSetErrorCode(ERR_NETWORK);
  239. return (ERR_NETWORK);
  240. }
  241. return (0);
  242. }
  243. static int SysSetSocketsOptions(SYS_SOCKET SockFD)
  244. {
  245. ///////////////////////////////////////////////////////////////////////////////
  246. //  Set socket buffer sizes
  247. ///////////////////////////////////////////////////////////////////////////////
  248. if (iSndBufSize > 0) {
  249. int iSize = iSndBufSize;
  250. setsockopt((int) SockFD, SOL_SOCKET, SO_SNDBUF, (const char *) &iSize,
  251.    sizeof(iSize));
  252. }
  253. if (iRcvBufSize > 0) {
  254. int iSize = iRcvBufSize;
  255. setsockopt((int) SockFD, SOL_SOCKET, SO_RCVBUF, (const char *) &iSize,
  256.    sizeof(iSize));
  257. }
  258. int iActivate = 1;
  259. if (setsockopt(SockFD, SOL_SOCKET, SO_REUSEADDR, (const char *) &iActivate,
  260.        sizeof(iActivate)) != 0) {
  261. ErrSetErrorCode(ERR_SETSOCKOPT);
  262. return (ERR_SETSOCKOPT);
  263. }
  264. ///////////////////////////////////////////////////////////////////////////////
  265. //  Disable linger
  266. ///////////////////////////////////////////////////////////////////////////////
  267. struct linger Ling;
  268. ZeroData(Ling);
  269. Ling.l_onoff = 0;
  270. Ling.l_linger = 0;
  271. setsockopt(SockFD, SOL_SOCKET, SO_LINGER, (const char *) &Ling, sizeof(Ling));
  272. ///////////////////////////////////////////////////////////////////////////////
  273. //  Set KEEPALIVE if supported
  274. ///////////////////////////////////////////////////////////////////////////////
  275. setsockopt(SockFD, SOL_SOCKET, SO_KEEPALIVE, (const char *) &iActivate,
  276.    sizeof(iActivate));
  277. return (0);
  278. }
  279. void SysCloseSocket(SYS_SOCKET SockFD)
  280. {
  281. closesocket(SockFD);
  282. }
  283. int SysBindSocket(SYS_SOCKET SockFD, const struct sockaddr *SockName, int iNameLen)
  284. {
  285. if (bind(SockFD, SockName, iNameLen) == SOCKET_ERROR) {
  286. ErrSetErrorCode(ERR_SOCKET_BIND);
  287. return (ERR_SOCKET_BIND);
  288. }
  289. return (0);
  290. }
  291. void SysListenSocket(SYS_SOCKET SockFD, int iConnections)
  292. {
  293. listen(SockFD, iConnections);
  294. }
  295. static int SysRecvLL(SYS_SOCKET SockFD, char *pszBuffer, int iBufferSize)
  296. {
  297. DWORD dwRtxBytes = 0;
  298. DWORD dwRtxFlags = 0;
  299. WSABUF WSABuff;
  300. ZeroData(WSABuff);
  301. WSABuff.len = iBufferSize;
  302. WSABuff.buf = pszBuffer;
  303. return ((WSARecv(SockFD, &WSABuff, 1, &dwRtxBytes, &dwRtxFlags,
  304.  NULL, NULL) == 0) ? (int) dwRtxBytes : -WSAGetLastError());
  305. }
  306. static int SysSendLL(SYS_SOCKET SockFD, char const *pszBuffer, int iBufferSize)
  307. {
  308. DWORD dwRtxBytes = 0;
  309. WSABUF WSABuff;
  310. ZeroData(WSABuff);
  311. WSABuff.len = iBufferSize;
  312. WSABuff.buf = (char *) pszBuffer;
  313. return ((WSASend(SockFD, &WSABuff, 1, &dwRtxBytes, 0,
  314.  NULL, NULL) == 0) ? (int) dwRtxBytes : -WSAGetLastError());
  315. }
  316. int SysRecvData(SYS_SOCKET SockFD, char *pszBuffer, int iBufferSize, int iTimeout)
  317. {
  318. HANDLE hReadEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  319. if (hReadEvent == NULL) {
  320. ErrSetErrorCode(ERR_CREATEEVENT);
  321. return (ERR_CREATEEVENT);
  322. }
  323. int iRecvBytes = 0;
  324. HANDLE hWaitEvents[2] = { hReadEvent, hShutdownEvent };
  325. for (;;) {
  326. WSAEventSelect(SockFD, (WSAEVENT) hReadEvent, FD_READ | FD_CLOSE);
  327. DWORD dwWaitResult = WSAWaitForMultipleEvents(2, hWaitEvents, FALSE,
  328.       (DWORD) (iTimeout * 1000), TRUE);
  329. WSAEventSelect(SockFD, (WSAEVENT) hReadEvent, 0);
  330. if (dwWaitResult == (WSA_WAIT_EVENT_0 + 1)) {
  331. CloseHandle(hReadEvent);
  332. ErrSetErrorCode(ERR_SERVER_SHUTDOWN);
  333. return (ERR_SERVER_SHUTDOWN);
  334. } else if (dwWaitResult != WSA_WAIT_EVENT_0) {
  335. CloseHandle(hReadEvent);
  336. ErrSetErrorCode(ERR_TIMEOUT);
  337. return (ERR_TIMEOUT);
  338. }
  339. if ((iRecvBytes = SysRecvLL(SockFD, pszBuffer, iBufferSize)) >= 0)
  340. break;
  341. int iErrorCode = -iRecvBytes;
  342. if (iErrorCode != WSAEWOULDBLOCK) {
  343. CloseHandle(hReadEvent);
  344. ErrSetErrorCode(ERR_NETWORK);
  345. return (ERR_NETWORK);
  346. }
  347. ///////////////////////////////////////////////////////////////////////////////
  348. //  You should never get here if Win32 API worked fine
  349. ///////////////////////////////////////////////////////////////////////////////
  350. HANDLE_SOCKS_SUCKS();
  351. }
  352. CloseHandle(hReadEvent);
  353. return (iRecvBytes);
  354. }
  355. int SysRecv(SYS_SOCKET SockFD, char *pszBuffer, int iBufferSize, int iTimeout)
  356. {
  357. int iRtxBytes = 0;
  358. while (iRtxBytes < iBufferSize) {
  359. int iRtxCurrent = SysRecvData(SockFD, pszBuffer + iRtxBytes,
  360.       iBufferSize - iRtxBytes, iTimeout);
  361. if (iRtxCurrent <= 0)
  362. return (iRtxBytes);
  363. iRtxBytes += iRtxCurrent;
  364. }
  365. return (iRtxBytes);
  366. }
  367. int SysRecvDataFrom(SYS_SOCKET SockFD, struct sockaddr *pFrom, int iFromlen,
  368.     char *pszBuffer, int iBufferSize, int iTimeout)
  369. {
  370. HANDLE hReadEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  371. if (hReadEvent == NULL) {
  372. ErrSetErrorCode(ERR_CREATEEVENT);
  373. return (ERR_CREATEEVENT);
  374. }
  375. DWORD dwRtxBytes = 0;
  376. WSABUF WSABuff;
  377. HANDLE hWaitEvents[2] = { hReadEvent, hShutdownEvent };
  378. ZeroData(WSABuff);
  379. WSABuff.len = iBufferSize;
  380. WSABuff.buf = pszBuffer;
  381. for (;;) {
  382. WSAEventSelect(SockFD, (WSAEVENT) hReadEvent, FD_READ | FD_CLOSE);
  383. DWORD dwWaitResult = WSAWaitForMultipleEvents(2, hWaitEvents, FALSE,
  384.       (DWORD) (iTimeout * 1000), TRUE);
  385. WSAEventSelect(SockFD, (WSAEVENT) hReadEvent, 0);
  386. if (dwWaitResult == (WSA_WAIT_EVENT_0 + 1)) {
  387. CloseHandle(hReadEvent);
  388. ErrSetErrorCode(ERR_SERVER_SHUTDOWN);
  389. return (ERR_SERVER_SHUTDOWN);
  390. } else if (dwWaitResult != WSA_WAIT_EVENT_0) {
  391. CloseHandle(hReadEvent);
  392. ErrSetErrorCode(ERR_TIMEOUT);
  393. return (ERR_TIMEOUT);
  394. }
  395. INT FromLen = (INT) iFromlen;
  396. DWORD dwRtxFlags = 0;
  397. if (WSARecvFrom(SockFD, &WSABuff, 1, &dwRtxBytes, &dwRtxFlags,
  398. pFrom, &FromLen, NULL, NULL) == 0)
  399. break;
  400. if (WSAGetLastError() != WSAEWOULDBLOCK) {
  401. CloseHandle(hReadEvent);
  402. ErrSetErrorCode(ERR_NETWORK);
  403. return (ERR_NETWORK);
  404. }
  405. ///////////////////////////////////////////////////////////////////////////////
  406. //  You should never get here if Win32 API worked fine
  407. ///////////////////////////////////////////////////////////////////////////////
  408. HANDLE_SOCKS_SUCKS();
  409. }
  410. CloseHandle(hReadEvent);
  411. return ((int) dwRtxBytes);
  412. }
  413. int SysSendData(SYS_SOCKET SockFD, char const *pszBuffer, int iBufferSize, int iTimeout)
  414. {
  415. HANDLE hWriteEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  416. if (hWriteEvent == NULL) {
  417. ErrSetErrorCode(ERR_CREATEEVENT);
  418. return (ERR_CREATEEVENT);
  419. }
  420. int iSendBytes = 0;
  421. HANDLE hWaitEvents[2] = { hWriteEvent, hShutdownEvent };
  422. for (;;) {
  423. WSAEventSelect(SockFD, (WSAEVENT) hWriteEvent, FD_WRITE | FD_CLOSE);
  424. DWORD dwWaitResult = WSAWaitForMultipleEvents(2, hWaitEvents, FALSE,
  425.       (DWORD) (iTimeout * 1000), TRUE);
  426. WSAEventSelect(SockFD, (WSAEVENT) hWriteEvent, 0);
  427. if (dwWaitResult == (WSA_WAIT_EVENT_0 + 1)) {
  428. CloseHandle(hWriteEvent);
  429. ErrSetErrorCode(ERR_SERVER_SHUTDOWN);
  430. return (ERR_SERVER_SHUTDOWN);
  431. } else if (dwWaitResult != WSA_WAIT_EVENT_0) {
  432. CloseHandle(hWriteEvent);
  433. ErrSetErrorCode(ERR_TIMEOUT);
  434. return (ERR_TIMEOUT);
  435. }
  436. if ((iSendBytes = SysSendLL(SockFD, pszBuffer, iBufferSize)) >= 0)
  437. break;
  438. int iErrorCode = -iSendBytes;
  439. if (iErrorCode != WSAEWOULDBLOCK) {
  440. CloseHandle(hWriteEvent);
  441. ErrSetErrorCode(ERR_NETWORK);
  442. return (ERR_NETWORK);
  443. }
  444. ///////////////////////////////////////////////////////////////////////////////
  445. //  You should never get here if Win32 API worked fine
  446. ///////////////////////////////////////////////////////////////////////////////
  447. HANDLE_SOCKS_SUCKS();
  448. }
  449. CloseHandle(hWriteEvent);
  450. return (iSendBytes);
  451. }
  452. int SysSend(SYS_SOCKET SockFD, char const *pszBuffer, int iBufferSize, int iTimeout)
  453. {
  454. int iRtxBytes = 0;
  455. while (iRtxBytes < iBufferSize) {
  456. int iRtxCurrent = SysSendData(SockFD, pszBuffer + iRtxBytes,
  457.       iBufferSize - iRtxBytes, iTimeout);
  458. if (iRtxCurrent <= 0)
  459. return (iRtxBytes);
  460. iRtxBytes += iRtxCurrent;
  461. }
  462. return (iRtxBytes);
  463. }
  464. int SysSendDataTo(SYS_SOCKET SockFD, const struct sockaddr *pTo,
  465.   int iToLen, char const *pszBuffer, int iBufferSize, int iTimeout)
  466. {
  467. HANDLE hWriteEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  468. if (hWriteEvent == NULL) {
  469. ErrSetErrorCode(ERR_CREATEEVENT);
  470. return (ERR_CREATEEVENT);
  471. }
  472. DWORD dwRtxBytes = 0;
  473. WSABUF WSABuff;
  474. HANDLE hWaitEvents[2] = { hWriteEvent, hShutdownEvent };
  475. ZeroData(WSABuff);
  476. WSABuff.len = iBufferSize;
  477. WSABuff.buf = (char *) pszBuffer;
  478. for (;;) {
  479. WSAEventSelect(SockFD, (WSAEVENT) hWriteEvent, FD_WRITE | FD_CLOSE);
  480. DWORD dwWaitResult = WSAWaitForMultipleEvents(2, hWaitEvents, FALSE,
  481.       (DWORD) (iTimeout * 1000), TRUE);
  482. WSAEventSelect(SockFD, (WSAEVENT) hWriteEvent, 0);
  483. if (dwWaitResult == (WSA_WAIT_EVENT_0 + 1)) {
  484. CloseHandle(hWriteEvent);
  485. ErrSetErrorCode(ERR_SERVER_SHUTDOWN);
  486. return (ERR_SERVER_SHUTDOWN);
  487. } else if (dwWaitResult != WSA_WAIT_EVENT_0) {
  488. CloseHandle(hWriteEvent);
  489. ErrSetErrorCode(ERR_TIMEOUT);
  490. return (ERR_TIMEOUT);
  491. }
  492. DWORD dwRtxFlags = 0;
  493. if (WSASendTo(SockFD, &WSABuff, 1, &dwRtxBytes, dwRtxFlags,
  494.       pTo, iToLen, NULL, NULL) == 0)
  495. break;
  496. if (WSAGetLastError() != WSAEWOULDBLOCK) {
  497. CloseHandle(hWriteEvent);
  498. ErrSetErrorCode(ERR_NETWORK);
  499. return (ERR_NETWORK);
  500. }
  501. ///////////////////////////////////////////////////////////////////////////////
  502. //  You should never get here if Win32 API worked fine
  503. ///////////////////////////////////////////////////////////////////////////////
  504. HANDLE_SOCKS_SUCKS();
  505. }
  506. CloseHandle(hWriteEvent);
  507. return ((int) dwRtxBytes);
  508. }
  509. int SysConnect(SYS_SOCKET SockFD, const SYS_INET_ADDR * pSockName, int iNameLen, int iTimeout)
  510. {
  511. HANDLE hConnectEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  512. if (hConnectEvent == NULL) {
  513. ErrSetErrorCode(ERR_CREATEEVENT);
  514. return (ERR_CREATEEVENT);
  515. }
  516. WSAEventSelect(SockFD, (WSAEVENT) hConnectEvent, FD_CONNECT);
  517. int iConnectResult = WSAConnect(SockFD, (const struct sockaddr *) &pSockName->Addr,
  518. iNameLen, NULL, NULL, NULL, NULL);
  519. int iConnectError = WSAGetLastError();
  520. if ((iConnectResult != 0) && (iConnectError == WSAEWOULDBLOCK)) {
  521. HANDLE hWaitEvents[2] = { hConnectEvent, hShutdownEvent };
  522. DWORD dwWaitResult = WSAWaitForMultipleEvents(2, hWaitEvents, FALSE,
  523.       (DWORD) (iTimeout * 1000), TRUE);
  524. if (dwWaitResult == WSA_WAIT_EVENT_0) {
  525. WSANETWORKEVENTS NetEvents;
  526. if ((WSAEnumNetworkEvents(SockFD, hConnectEvent, &NetEvents) != 0) ||
  527.     (NetEvents.iErrorCode[FD_CONNECT_BIT] != 0)) {
  528. ErrSetErrorCode(ERR_CONNECT);
  529. iConnectResult = ERR_CONNECT;
  530. } else
  531. iConnectResult = 0;
  532. } else if (dwWaitResult == (WSA_WAIT_EVENT_0 + 1)) {
  533. ErrSetErrorCode(ERR_SERVER_SHUTDOWN);
  534. iConnectResult = ERR_SERVER_SHUTDOWN;
  535. } else {
  536. ErrSetErrorCode(ERR_TIMEOUT);
  537. iConnectResult = ERR_TIMEOUT;
  538. }
  539. }
  540. WSAEventSelect(SockFD, (WSAEVENT) hConnectEvent, 0);
  541. CloseHandle(hConnectEvent);
  542. return (iConnectResult);
  543. }
  544. SYS_SOCKET SysAccept(SYS_SOCKET SockFD, SYS_INET_ADDR * pSockName, int *iNameLen, int iTimeout)
  545. {
  546. HANDLE hAcceptEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  547. if (hAcceptEvent == NULL) {
  548. ErrSetErrorCode(ERR_CREATEEVENT);
  549. return (SYS_INVALID_SOCKET);
  550. }
  551. WSAEventSelect(SockFD, (WSAEVENT) hAcceptEvent, FD_ACCEPT);
  552. SOCKET SockFDAccept =
  553.     WSAAccept(SockFD, (struct sockaddr *) &pSockName->Addr, iNameLen, NULL, 0);
  554. int iConnectError = WSAGetLastError();
  555. if ((SockFDAccept == INVALID_SOCKET) && (iConnectError == WSAEWOULDBLOCK)) {
  556. HANDLE hWaitEvents[2] = { hAcceptEvent, hShutdownEvent };
  557. DWORD dwWaitResult = WSAWaitForMultipleEvents(2, hWaitEvents, FALSE,
  558.       (DWORD) (iTimeout * 1000), TRUE);
  559. if (dwWaitResult == WSA_WAIT_EVENT_0)
  560. SockFDAccept =
  561.     WSAAccept(SockFD, (struct sockaddr *) &pSockName->Addr, iNameLen,
  562.       NULL, 0);
  563. else if (dwWaitResult == (WSA_WAIT_EVENT_0 + 1))
  564. ErrSetErrorCode(ERR_SERVER_SHUTDOWN);
  565. else
  566. ErrSetErrorCode(ERR_TIMEOUT);
  567. }
  568. WSAEventSelect(SockFD, (WSAEVENT) hAcceptEvent, 0);
  569. CloseHandle(hAcceptEvent);
  570. if (SockFDAccept != INVALID_SOCKET) {
  571. if ((SysBlockSocket(SockFDAccept, 0) < 0) ||
  572.     (SysSetSocketsOptions(SockFDAccept) < 0)) {
  573. SysCloseSocket(SockFDAccept);
  574. return (SYS_INVALID_SOCKET);
  575. }
  576. }
  577. return (SockFDAccept);
  578. }
  579. int SysSelect(int iMaxFD, SYS_fd_set * pReadFDs, SYS_fd_set * pWriteFDs, SYS_fd_set * pExcptFDs,
  580.       int iTimeout)
  581. {
  582. struct timeval TV;
  583. ZeroData(TV);
  584. TV.tv_sec = iTimeout;
  585. TV.tv_usec = 0;
  586. int iSelectResult = select(iMaxFD + 1, pReadFDs, pWriteFDs, pExcptFDs, &TV);
  587. if (iSelectResult < 0) {
  588. ErrSetErrorCode(ERR_SELECT);
  589. return (ERR_SELECT);
  590. }
  591. if (iSelectResult == 0) {
  592. ErrSetErrorCode(ERR_TIMEOUT);
  593. return (ERR_TIMEOUT);
  594. }
  595. return (iSelectResult);
  596. }
  597. int SysSendFile(SYS_SOCKET SockFD, char const *pszFileName, unsigned long ulBaseOffset,
  598. unsigned long ulEndOffset, int iTimeout)
  599. {
  600. ///////////////////////////////////////////////////////////////////////////////
  601. //  Open the source file
  602. ///////////////////////////////////////////////////////////////////////////////
  603. HANDLE hFile = CreateFile(pszFileName, GENERIC_READ, FILE_SHARE_READ,
  604.   NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  605. if (hFile == INVALID_HANDLE_VALUE) {
  606. ErrSetErrorCode(ERR_FILE_OPEN);
  607. return (ERR_FILE_OPEN);
  608. }
  609. ///////////////////////////////////////////////////////////////////////////////
  610. //  Create file mapping and the file
  611. ///////////////////////////////////////////////////////////////////////////////
  612. DWORD dwFileSizeHi = 0;
  613. DWORD dwFileSizeLo = GetFileSize(hFile, &dwFileSizeHi);
  614. HANDLE hFileMap = CreateFileMapping(hFile, NULL, PAGE_READONLY,
  615.     dwFileSizeHi, dwFileSizeLo, NULL);
  616. if (hFileMap == NULL) {
  617. CloseHandle(hFile);
  618. ErrSetErrorCode(ERR_CREATEFILEMAPPING);
  619. return (ERR_CREATEFILEMAPPING);
  620. }
  621. void *pAddress = MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 0);
  622. if (pAddress == NULL) {
  623. CloseHandle(hFileMap);
  624. CloseHandle(hFile);
  625. ErrSetErrorCode(ERR_MAPVIEWOFFILE);
  626. return (ERR_MAPVIEWOFFILE);
  627. }
  628. ///////////////////////////////////////////////////////////////////////////////
  629. //  Send the file
  630. ///////////////////////////////////////////////////////////////////////////////
  631. int iSndBuffSize = MIN_TCP_SEND_SIZE;
  632. SYS_UINT64 ullFileSize = (((SYS_UINT64) dwFileSizeHi) << 32) | (SYS_UINT64) dwFileSizeLo;
  633. SYS_UINT64 ullEndOffset = (ulEndOffset != (unsigned long) -1) ?
  634.     ((SYS_UINT64) ulEndOffset) : ullFileSize;
  635. SYS_UINT64 ullCurrOffset = (SYS_UINT64) ulBaseOffset;
  636. char *pszBuffer = (char *) pAddress + ulBaseOffset;
  637. time_t tStart;
  638. while (ullCurrOffset < ullEndOffset) {
  639. int iCurrSend = (int) Min(iSndBuffSize, ullEndOffset - ullCurrOffset);
  640. tStart = time(NULL);
  641. if ((iCurrSend = SysSendData(SockFD, pszBuffer, iCurrSend, iTimeout)) < 0) {
  642. ErrorPush();
  643. UnmapViewOfFile(pAddress);
  644. CloseHandle(hFileMap);
  645. CloseHandle(hFile);
  646. return (ErrorPop());
  647. }
  648. if ((((time(NULL) - tStart) * K_IO_TIME_RATIO) < iTimeout) &&
  649.     (iSndBuffSize < MAX_TCP_SEND_SIZE))
  650. iSndBuffSize = Min(iSndBuffSize * 2, MAX_TCP_SEND_SIZE);
  651. pszBuffer += iCurrSend;
  652. ullCurrOffset += (SYS_UINT64) iCurrSend;
  653. }
  654. UnmapViewOfFile(pAddress);
  655. CloseHandle(hFileMap);
  656. CloseHandle(hFile);
  657. return (0);
  658. }
  659. int SysSetupAddress(SYS_INET_ADDR & AddrInfo, int iFamily,
  660.     NET_ADDRESS const &NetAddr, int iPortNo)
  661. {
  662. ZeroData(AddrInfo);
  663. AddrInfo.Addr.sin_family = iFamily;
  664. SAIN_Addr(AddrInfo.Addr) = NetAddr;
  665. AddrInfo.Addr.sin_port = htons((short) iPortNo);
  666. return (0);
  667. }
  668. int SysGetAddrAddress(SYS_INET_ADDR const &AddrInfo, NET_ADDRESS & NetAddr)
  669. {
  670. NetAddr = SAIN_Addr(AddrInfo.Addr);
  671. return (0);
  672. }
  673. int SysGetAddrPort(SYS_INET_ADDR const &AddrInfo)
  674. {
  675. return (ntohs(AddrInfo.Addr.sin_port));
  676. }
  677. int SysSetAddrAddress(SYS_INET_ADDR & AddrInfo, NET_ADDRESS const &NetAddr)
  678. {
  679. SAIN_Addr(AddrInfo.Addr) = NetAddr;
  680. return (0);
  681. }
  682. int SysSetAddrPort(SYS_INET_ADDR & AddrInfo, int iPortNo)
  683. {
  684. AddrInfo.Addr.sin_port = htons((short) iPortNo);
  685. return (0);
  686. }
  687. int SysGetHostByName(char const *pszName, NET_ADDRESS & NetAddr)
  688. {
  689. struct hostent *pHostEnt = gethostbyname(pszName);
  690. if ((pHostEnt == NULL) || (pHostEnt->h_addr_list[0] == NULL)) {
  691. ErrSetErrorCode(ERR_BAD_SERVER_ADDR, pszName);
  692. return (ERR_BAD_SERVER_ADDR);
  693. }
  694. memcpy(&NetAddr, pHostEnt->h_addr_list[0], sizeof(NetAddr));
  695. return (0);
  696. }
  697. int SysGetHostByAddr(SYS_INET_ADDR const &AddrInfo, char *pszFQDN)
  698. {
  699. struct hostent *pHostEnt = gethostbyaddr((const char *) &SAIN_Addr(AddrInfo.Addr),
  700.  sizeof(SAIN_Addr(AddrInfo.Addr)), AF_INET);
  701. if (pHostEnt == NULL) {
  702. char szIP[128] = "???.???.???.???";
  703. ErrSetErrorCode(ERR_GET_SOCK_HOST, SysInetNToA(AddrInfo, szIP));
  704. return (ERR_GET_SOCK_HOST);
  705. }
  706. strcpy(pszFQDN, pHostEnt->h_name);
  707. return (0);
  708. }
  709. int SysGetPeerInfo(SYS_SOCKET SockFD, SYS_INET_ADDR & AddrInfo)
  710. {
  711. ZeroData(AddrInfo);
  712. socklen_t InfoSize = sizeof(AddrInfo.Addr);
  713. if (getpeername(SockFD, (struct sockaddr *) &AddrInfo.Addr, &InfoSize) == -1) {
  714. ErrSetErrorCode(ERR_GET_PEER_INFO);
  715. return (ERR_GET_PEER_INFO);
  716. }
  717. return (0);
  718. }
  719. int SysGetSockInfo(SYS_SOCKET SockFD, SYS_INET_ADDR & AddrInfo)
  720. {
  721. ZeroData(AddrInfo);
  722. socklen_t InfoSize = sizeof(AddrInfo.Addr);
  723. if (getsockname(SockFD, (struct sockaddr *) &AddrInfo.Addr, &InfoSize) == -1) {
  724. ErrSetErrorCode(ERR_GET_SOCK_INFO);
  725. return (ERR_GET_SOCK_INFO);
  726. }
  727. return (0);
  728. }
  729. char *SysInetNToA(SYS_INET_ADDR const &AddrInfo, char *pszIP)
  730. {
  731. union {
  732. unsigned int a;
  733. unsigned char b[4];
  734. } UAddr;
  735. memcpy(&UAddr, &AddrInfo.Addr.sin_addr, sizeof(UAddr));
  736. sprintf(pszIP, "%u.%u.%u.%u",
  737. (unsigned int) UAddr.b[0],
  738. (unsigned int) UAddr.b[1], (unsigned int) UAddr.b[2], (unsigned int) UAddr.b[3]);
  739. return (pszIP);
  740. }
  741. int SysInetAddr(char const *pszDotName, NET_ADDRESS & NetAddr)
  742. {
  743. if ((NetAddr = (NET_ADDRESS) inet_addr(pszDotName)) == SYS_INVALID_NET_ADDRESS) {
  744. ErrSetErrorCode(ERR_BAD_SERVER_ADDR, pszDotName);
  745. return (ERR_BAD_SERVER_ADDR);
  746. }
  747. return (0);
  748. }
  749. int SysSameAddress(NET_ADDRESS const &NetAddr1, NET_ADDRESS const &NetAddr2)
  750. {
  751. return (memcmp(&NetAddr1, &NetAddr2, sizeof(NET_ADDRESS)) == 0);
  752. }
  753. SYS_SEMAPHORE SysCreateSemaphore(int iInitCount, int iMaxCount)
  754. {
  755. HANDLE hSemaphore = CreateSemaphore(NULL, iInitCount, iMaxCount, NULL);
  756. if (hSemaphore == NULL) {
  757. ErrSetErrorCode(ERR_CREATESEMAPHORE);
  758. return (SYS_INVALID_SEMAPHORE);
  759. }
  760. return ((SYS_SEMAPHORE) hSemaphore);
  761. }
  762. int SysCloseSemaphore(SYS_SEMAPHORE hSemaphore)
  763. {
  764. if (!CloseHandle((HANDLE) hSemaphore)) {
  765. ErrSetErrorCode(ERR_CLOSEHANDLE);
  766. return (ERR_CLOSEHANDLE);
  767. }
  768. return (0);
  769. }
  770. int SysWaitSemaphore(SYS_SEMAPHORE hSemaphore, int iTimeout)
  771. {
  772. if (WaitForSingleObject((HANDLE) hSemaphore, (DWORD) (iTimeout * 1000)) != WAIT_OBJECT_0) {
  773. ErrSetErrorCode(ERR_TIMEOUT);
  774. return (ERR_TIMEOUT);
  775. }
  776. return (0);
  777. }
  778. int SysReleaseSemaphore(SYS_SEMAPHORE hSemaphore, int iCount)
  779. {
  780. if (!ReleaseSemaphore((HANDLE) hSemaphore, (LONG) iCount, NULL)) {
  781. ErrSetErrorCode(ERR_RELEASESEMAPHORE);
  782. return (ERR_RELEASESEMAPHORE);
  783. }
  784. return (0);
  785. }
  786. int SysTryWaitSemaphore(SYS_SEMAPHORE hSemaphore)
  787. {
  788. if (WaitForSingleObject((HANDLE) hSemaphore, 0) != WAIT_OBJECT_0) {
  789. ErrSetErrorCode(ERR_TIMEOUT);
  790. return (ERR_TIMEOUT);
  791. }
  792. return (0);
  793. }
  794. SYS_MUTEX SysCreateMutex(void)
  795. {
  796. HANDLE hMutex = CreateMutex(NULL, FALSE, NULL);
  797. if (hMutex == NULL) {
  798. ErrSetErrorCode(ERR_CREATEMUTEX);
  799. return (SYS_INVALID_MUTEX);
  800. }
  801. return ((SYS_MUTEX) hMutex);
  802. }
  803. int SysCloseMutex(SYS_MUTEX hMutex)
  804. {
  805. if (!CloseHandle((HANDLE) hMutex)) {
  806. ErrSetErrorCode(ERR_CLOSEHANDLE);
  807. return (ERR_CLOSEHANDLE);
  808. }
  809. return (0);
  810. }
  811. int SysLockMutex(SYS_MUTEX hMutex, int iTimeout)
  812. {
  813. if (WaitForSingleObject((HANDLE) hMutex, (DWORD) (iTimeout * 1000)) != WAIT_OBJECT_0) {
  814. ErrSetErrorCode(ERR_TIMEOUT);
  815. return (ERR_TIMEOUT);
  816. }
  817. return (0);
  818. }
  819. int SysUnlockMutex(SYS_MUTEX hMutex)
  820. {
  821. ReleaseMutex((HANDLE) hMutex);
  822. return (0);
  823. }
  824. int SysTryLockMutex(SYS_MUTEX hMutex)
  825. {
  826. if (WaitForSingleObject((HANDLE) hMutex, 0) != WAIT_OBJECT_0) {
  827. ErrSetErrorCode(ERR_TIMEOUT);
  828. return (ERR_TIMEOUT);
  829. }
  830. return (0);
  831. }
  832. SYS_EVENT SysCreateEvent(int iManualReset)
  833. {
  834. HANDLE hEvent = CreateEvent(NULL, iManualReset, FALSE, NULL);
  835. if (hEvent == NULL) {
  836. ErrSetErrorCode(ERR_CREATEEVENT);
  837. return (SYS_INVALID_EVENT);
  838. }
  839. return ((SYS_EVENT) hEvent);
  840. }
  841. int SysCloseEvent(SYS_EVENT hEvent)
  842. {
  843. if (!CloseHandle((HANDLE) hEvent)) {
  844. ErrSetErrorCode(ERR_CLOSEHANDLE);
  845. return (ERR_CLOSEHANDLE);
  846. }
  847. return (0);
  848. }
  849. int SysWaitEvent(SYS_EVENT hEvent, int iTimeout)
  850. {
  851. if (WaitForSingleObject((HANDLE) hEvent, (DWORD) (iTimeout * 1000)) != WAIT_OBJECT_0) {
  852. ErrSetErrorCode(ERR_TIMEOUT);
  853. return (ERR_TIMEOUT);
  854. }
  855. return (0);
  856. }
  857. int SysSetEvent(SYS_EVENT hEvent)
  858. {
  859. SetEvent((HANDLE) hEvent);
  860. return (0);
  861. }
  862. int SysResetEvent(SYS_EVENT hEvent)
  863. {
  864. ResetEvent((HANDLE) hEvent);
  865. return (0);
  866. }
  867. int SysTryWaitEvent(SYS_EVENT hEvent)
  868. {
  869. if (WaitForSingleObject((HANDLE) hEvent, 0) != WAIT_OBJECT_0) {
  870. ErrSetErrorCode(ERR_TIMEOUT);
  871. return (ERR_TIMEOUT);
  872. }
  873. return (0);
  874. }
  875. static unsigned int SysThreadRunner(void *pRunData)
  876. {
  877. ThreadRunner *pTR = (ThreadRunner *) pRunData;
  878. if (SysThreadSetup() < 0) {
  879. SysFree(pTR);
  880. return (ErrGetErrorCode());
  881. }
  882. unsigned int uResultCode = SysStkCall(pTR->pThreadProc, pTR->pThreadData);
  883. SysThreadCleanup();
  884. SysFree(pTR);
  885. return (uResultCode);
  886. }
  887. SYS_THREAD SysCreateThread(unsigned int (*pThreadProc) (void *), void *pThreadData)
  888. {
  889. ///////////////////////////////////////////////////////////////////////////////
  890. //  Alloc thread runner data
  891. ///////////////////////////////////////////////////////////////////////////////
  892. ThreadRunner *pTR = (ThreadRunner *) SysAlloc(sizeof(ThreadRunner));
  893. if (pTR == NULL)
  894. return (SYS_INVALID_THREAD);
  895. pTR->pThreadProc = pThreadProc;
  896. pTR->pThreadData = pThreadData;
  897. ///////////////////////////////////////////////////////////////////////////////
  898. //  Create the thread
  899. ///////////////////////////////////////////////////////////////////////////////
  900. unsigned int uThreadId = 0;
  901. unsigned long ulThread = _beginthreadex(NULL, 0,
  902. (unsigned (__stdcall *) (void *)) SysThreadRunner,
  903. pTR, 0, &uThreadId);
  904. if (ulThread == 0) {
  905. SysFree(pTR);
  906. ErrSetErrorCode(ERR_BEGINTHREADEX);
  907. return (SYS_INVALID_THREAD);
  908. }
  909. return ((SYS_THREAD) ulThread);
  910. }
  911. SYS_THREAD SysCreateServiceThread(unsigned int (*pThreadProc) (void *), SYS_SOCKET SockFD)
  912. {
  913. SYS_THREAD ThreadID = SysCreateThread(pThreadProc, (void *) (unsigned int) SockFD);
  914. return (ThreadID);
  915. }
  916. static int SysThreadSetup(void)
  917. {
  918. SysInitTlsKeys();
  919. return (0);
  920. }
  921. static int SysThreadCleanup(void)
  922. {
  923. SysCleanupTlsKeys();
  924. return (0);
  925. }
  926. void SysCloseThread(SYS_THREAD ThreadID, int iForce)
  927. {
  928. if (iForce)
  929. TerminateThread((HANDLE) ThreadID, (DWORD) - 1);
  930. CloseHandle((HANDLE) ThreadID);
  931. }
  932. int SysSetThreadPriority(SYS_THREAD ThreadID, int iPriority)
  933. {
  934. BOOL bSetResult = FALSE;
  935. switch (iPriority) {
  936. case (SYS_PRIORITY_NORMAL):
  937. bSetResult = SetThreadPriority((HANDLE) ThreadID, THREAD_PRIORITY_NORMAL);
  938. break;
  939. case (SYS_PRIORITY_LOWER):
  940. bSetResult = SetThreadPriority((HANDLE) ThreadID, THREAD_PRIORITY_BELOW_NORMAL);
  941. break;
  942. case (SYS_PRIORITY_HIGHER):
  943. bSetResult = SetThreadPriority((HANDLE) ThreadID, THREAD_PRIORITY_ABOVE_NORMAL);
  944. break;
  945. }
  946. if (!bSetResult) {
  947. ErrSetErrorCode(ERR_SET_THREAD_PRIORITY);
  948. return (ERR_SET_THREAD_PRIORITY);
  949. }
  950. return (0);
  951. }
  952. int SysWaitThread(SYS_THREAD ThreadID, int iTimeout)
  953. {
  954. if (WaitForSingleObject((HANDLE) ThreadID, (DWORD) (iTimeout * 1000)) != WAIT_OBJECT_0) {
  955. ErrSetErrorCode(ERR_TIMEOUT);
  956. return (ERR_TIMEOUT);
  957. }
  958. return (0);
  959. }
  960. unsigned long SysGetCurrentThreadId(void)
  961. {
  962. return ((unsigned long) GetCurrentThreadId());
  963. }
  964. int SysExec(char const *pszCommand, char const *const *pszArgs, int iWaitTimeout,
  965.     int iPriority, int *piExitStatus)
  966. {
  967. int ii;
  968. int iCommandLength = strlen(pszCommand) + 4;
  969. for (ii = 1; pszArgs[ii] != NULL; ii++)
  970. iCommandLength += strlen(pszArgs[ii]) + 4;
  971. char *pszCmdLine = (char *) SysAlloc(iCommandLength + 1);
  972. if (pszCmdLine == NULL)
  973. return (ErrGetErrorCode());
  974. strcpy(pszCmdLine, pszCommand);
  975. for (ii = 1; pszArgs[ii] != NULL; ii++)
  976. sprintf(StrAppend(pszCmdLine), " "%s"", pszArgs[ii]);
  977. PROCESS_INFORMATION PI;
  978. STARTUPINFO SI;
  979. ZeroData(PI);
  980. ZeroData(SI);
  981. SI.cb = sizeof(STARTUPINFO);
  982. BOOL bProcessCreated = CreateProcess(NULL, pszCmdLine, NULL, NULL, FALSE,
  983.      CREATE_NO_WINDOW | NORMAL_PRIORITY_CLASS, NULL, NULL,
  984.      &SI, &PI);
  985. SysFree(pszCmdLine);
  986. if (!bProcessCreated) {
  987. ErrSetErrorCode(ERR_PROCESS_EXECUTE);
  988. return (ERR_PROCESS_EXECUTE);
  989. }
  990. SysSetThreadPriority((SYS_THREAD) PI.hThread, iPriority);
  991. if (iWaitTimeout > 0) {
  992. if (WaitForSingleObject(PI.hProcess, iWaitTimeout * 1000) != WAIT_OBJECT_0) {
  993. CloseHandle(PI.hThread);
  994. CloseHandle(PI.hProcess);
  995. ErrSetErrorCode(ERR_TIMEOUT);
  996. return (ERR_TIMEOUT);
  997. }
  998. if (piExitStatus != NULL) {
  999. DWORD dwExitCode = 0;
  1000. if (!GetExitCodeProcess(PI.hProcess, &dwExitCode))
  1001. *piExitStatus = -1;
  1002. else
  1003. *piExitStatus = (int) dwExitCode;
  1004. }
  1005. } else if (piExitStatus != NULL)
  1006. *piExitStatus = -1;
  1007. CloseHandle(PI.hThread);
  1008. CloseHandle(PI.hProcess);
  1009. return (0);
  1010. }
  1011. static BOOL WINAPI SysBreakHandlerRoutine(DWORD dwCtrlType)
  1012. {
  1013. BOOL bReturnValue = FALSE;
  1014. switch (dwCtrlType) {
  1015. case (CTRL_C_EVENT):
  1016. case (CTRL_CLOSE_EVENT):
  1017. case (CTRL_SHUTDOWN_EVENT):
  1018. if (SysBreakHandler != NULL)
  1019. SysBreakHandler(), bReturnValue = TRUE;
  1020. break;
  1021. }
  1022. return (bReturnValue);
  1023. }
  1024. void SysSetBreakHandler(void (*BreakHandler) (void))
  1025. {
  1026. if (SysBreakHandler == NULL)
  1027. SetConsoleCtrlHandler(SysBreakHandlerRoutine,
  1028.       (BreakHandler != NULL) ? TRUE : FALSE);
  1029. SysBreakHandler = BreakHandler;
  1030. }
  1031. int SysCreateTlsKey(SYS_TLSKEY & TlsKey, void (*pFreeProc) (void *))
  1032. {
  1033. EnterCriticalSection(&csTLS);
  1034. for (int ii = 0; ii < MAX_TLS_KEYS; ii++) {
  1035. if (TlsKeyEntries[ii].pFreeProc == UNUSED_TLS_KEY_PROC) {
  1036. TlsKeyEntries[ii].pFreeProc = pFreeProc;
  1037. LeaveCriticalSection(&csTLS);
  1038. TlsKey = (SYS_TLSKEY) ii;
  1039. return (0);
  1040. }
  1041. }
  1042. LeaveCriticalSection(&csTLS);
  1043. ErrSetErrorCode(ERR_NOMORE_TLSKEYS);
  1044. return (ERR_NOMORE_TLSKEYS);
  1045. }
  1046. int SysDeleteTlsKey(SYS_TLSKEY & TlsKey)
  1047. {
  1048. int iKey = (int) TlsKey;
  1049. EnterCriticalSection(&csTLS);
  1050. if ((iKey < 0) || (iKey >= MAX_TLS_KEYS) ||
  1051.     (TlsKeyEntries[iKey].pFreeProc == UNUSED_TLS_KEY_PROC)) {
  1052. LeaveCriticalSection(&csTLS);
  1053. ErrSetErrorCode(ERR_INVALID_TLSKEY);
  1054. return (ERR_INVALID_TLSKEY);
  1055. }
  1056. TlsKeyEntries[iKey].pFreeProc = UNUSED_TLS_KEY_PROC;
  1057. LeaveCriticalSection(&csTLS);
  1058. TlsKey = (SYS_TLSKEY) - 1;
  1059. return (0);
  1060. }
  1061. int SysSetTlsKeyData(SYS_TLSKEY & TlsKey, void *pData)
  1062. {
  1063. int iKey = (int) TlsKey;
  1064. if ((iKey < 0) || (iKey >= MAX_TLS_KEYS) ||
  1065.     (TlsKeyEntries[iKey].pFreeProc == UNUSED_TLS_KEY_PROC)) {
  1066. ErrSetErrorCode(ERR_INVALID_TLSKEY);
  1067. return (ERR_INVALID_TLSKEY);
  1068. }
  1069. TlsKeys[iKey].pData = pData;
  1070. return (0);
  1071. }
  1072. void *SysGetTlsKeyData(SYS_TLSKEY & TlsKey)
  1073. {
  1074. int iKey = (int) TlsKey;
  1075. if ((iKey < 0) || (iKey >= MAX_TLS_KEYS) ||
  1076.     (TlsKeyEntries[iKey].pFreeProc == UNUSED_TLS_KEY_PROC)) {
  1077. ErrSetErrorCode(ERR_INVALID_TLSKEY);
  1078. return (NULL);
  1079. }
  1080. return (TlsKeys[iKey].pData);
  1081. }
  1082. void SysThreadOnce(SYS_THREAD_ONCE * pThrOnce, void (*pOnceProc) (void))
  1083. {
  1084. if (InterlockedExchange(&pThrOnce->lOnce, 1) == 0) {
  1085. pOnceProc();
  1086. pThrOnce->lDone++;
  1087. }
  1088. while (!pThrOnce->lDone)
  1089. Sleep(0);
  1090. }
  1091. void *SysAlloc(unsigned int uSize)
  1092. {
  1093. void *pData = malloc(uSize);
  1094. if (pData != NULL)
  1095. memset(pData, 0, uSize);
  1096. else
  1097. ErrSetErrorCode(ERR_MEMORY);
  1098. return (pData);
  1099. }
  1100. void SysFree(void *pData)
  1101. {
  1102. free(pData);
  1103. }
  1104. void *SysRealloc(void *pData, unsigned int uSize)
  1105. {
  1106. void *pNewData = realloc(pData, uSize);
  1107. if (pNewData == NULL)
  1108. ErrSetErrorCode(ERR_MEMORY);
  1109. return (pNewData);
  1110. }
  1111. int SysLockFile(const char *pszFileName, char const *pszLockExt)
  1112. {
  1113. char szLockFile[SYS_MAX_PATH] = "";
  1114. SysSNPrintf(szLockFile, sizeof(szLockFile) - 1, "%s%s", pszFileName, pszLockExt);
  1115. ///////////////////////////////////////////////////////////////////////////////
  1116. //  Try to create lock file
  1117. ///////////////////////////////////////////////////////////////////////////////
  1118. HANDLE hFile = CreateFile(szLockFile, GENERIC_READ | GENERIC_WRITE,
  1119.   0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
  1120. if (hFile == INVALID_HANDLE_VALUE) {
  1121. if (GetLastError() == ERROR_ALREADY_EXISTS) {
  1122. ErrSetErrorCode(ERR_LOCKED);
  1123. return (ERR_LOCKED);
  1124. }
  1125. ErrSetErrorCode(ERR_FILE_CREATE);
  1126. return (ERR_FILE_CREATE);
  1127. }
  1128. DWORD dwWritten = 0;
  1129. char szLock[128] = "";
  1130. sprintf(szLock, "%lu", (unsigned long) GetCurrentThreadId());
  1131. if (!WriteFile(hFile, szLock, strlen(szLock) + 1, &dwWritten, NULL)) {
  1132. CloseHandle(hFile);
  1133. ErrSetErrorCode(ERR_FILE_WRITE);
  1134. return (ERR_FILE_WRITE);
  1135. }
  1136. CloseHandle(hFile);
  1137. return (0);
  1138. }
  1139. int SysUnlockFile(const char *pszFileName, char const *pszLockExt)
  1140. {
  1141. char szLockFile[SYS_MAX_PATH] = "";
  1142. SysSNPrintf(szLockFile, sizeof(szLockFile) - 1, "%s%s", pszFileName, pszLockExt);
  1143. if (_unlink(szLockFile) != 0) {
  1144. ErrSetErrorCode(ERR_NOT_LOCKED);
  1145. return (ERR_NOT_LOCKED);
  1146. }
  1147. return (0);
  1148. }
  1149. SYS_HANDLE SysOpenModule(char const *pszFilePath)
  1150. {
  1151. HMODULE hModule = LoadLibrary(pszFilePath);
  1152. if (hModule == NULL) {
  1153. ErrSetErrorCode(ERR_LOADMODULE, pszFilePath);
  1154. return (SYS_INVALID_HANDLE);
  1155. }
  1156. return ((SYS_HANDLE) hModule);
  1157. }
  1158. int SysCloseModule(SYS_HANDLE hModule)
  1159. {
  1160. FreeLibrary((HMODULE) hModule);
  1161. return (0);
  1162. }
  1163. void *SysGetSymbol(SYS_HANDLE hModule, char const *pszSymbol)
  1164. {
  1165. void *pSymbol = (void *) GetProcAddress((HMODULE) hModule, pszSymbol);
  1166. if (pSymbol == NULL) {
  1167. ErrSetErrorCode(ERR_LOADMODULESYMBOL, pszSymbol);
  1168. return (NULL);
  1169. }
  1170. return (pSymbol);
  1171. }
  1172. int SysEventLogV(int iLogLevel, char const *pszFormat, va_list Args)
  1173. {
  1174. HANDLE hEventSource = RegisterEventSource(NULL, szServerName);
  1175. if (hEventSource == NULL) {
  1176. ErrSetErrorCode(ERR_REGISTER_EVENT_SOURCE);
  1177. return (ERR_REGISTER_EVENT_SOURCE);
  1178. }
  1179. char *pszStrings[2];
  1180. char szBuffer[2048] = "";
  1181. _vsnprintf(szBuffer, sizeof(szBuffer) - 1, pszFormat, Args);
  1182. pszStrings[0] = szBuffer;
  1183. ReportEvent(hEventSource,
  1184.     iLogLevel == LOG_LEV_ERROR ? EVENTLOG_ERROR_TYPE:
  1185.     iLogLevel == LOG_LEV_WARNING ? EVENTLOG_WARNING_TYPE:
  1186.     EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, (const char **) pszStrings, NULL);
  1187. DeregisterEventSource(hEventSource);
  1188. return (0);
  1189. }
  1190. int SysEventLog(int iLogLevel, char const *pszFormat, ...)
  1191. {
  1192. va_list Args;
  1193. va_start(Args, pszFormat);
  1194. int iLogResult = SysEventLogV(iLogLevel, pszFormat, Args);
  1195. va_end(Args);
  1196. return (0);
  1197. }
  1198. int SysLogMessage(int iLogLevel, char const *pszFormat, ...)
  1199. {
  1200. extern bool bServerDebug;
  1201. EnterCriticalSection(&csLog);
  1202. va_list Args;
  1203. va_start(Args, pszFormat);
  1204. if (bServerDebug) {
  1205. ///////////////////////////////////////////////////////////////////////////////
  1206. //  Debug implementation
  1207. ///////////////////////////////////////////////////////////////////////////////
  1208. vprintf(pszFormat, Args);
  1209. } else {
  1210. switch (iLogLevel) {
  1211. case (LOG_LEV_WARNING):
  1212. case (LOG_LEV_ERROR):
  1213. SysEventLogV(iLogLevel, pszFormat, Args);
  1214. break;
  1215. }
  1216. }
  1217. va_end(Args);
  1218. LeaveCriticalSection(&csLog);
  1219. return (0);
  1220. }
  1221. void SysSleep(int iTimeout)
  1222. {
  1223. SysMsSleep(iTimeout * 1000);
  1224. }
  1225. void SysMsSleep(int iMsTimeout)
  1226. {
  1227. Sleep(iMsTimeout);
  1228. }
  1229. static void SysTimetToFileTime(time_t tTime, LPFILETIME pFT)
  1230. {
  1231. LONGLONG llTime = Int32x32To64(tTime, 10000000) + 116444736000000000;
  1232. pFT->dwLowDateTime = (DWORD) llTime;
  1233. pFT->dwHighDateTime = (DWORD) (llTime >> 32);
  1234. }
  1235. static time_t SysFileTimeToTimet(LPFILETIME pFT)
  1236. {
  1237. LONGLONG llTime = ((LONGLONG) pFT->dwLowDateTime) |
  1238.     (((LONGLONG) pFT->dwHighDateTime) << 32);
  1239. return ((time_t) ((llTime - 116444736000000000) / 10000000));
  1240. }
  1241. SYS_INT64 SysMsTime(void)
  1242. {
  1243. LARGE_INTEGER PerfCntCurr;
  1244. QueryPerformanceCounter(&PerfCntCurr);
  1245. SYS_INT64 MsTicks = *(SYS_INT64 *) & PerfCntCurr;
  1246. MsTicks -= PCSysStart;
  1247. MsTicks /= PCFreq;
  1248. MsTicks += (SYS_INT64) tSysStart *1000;
  1249. return (MsTicks);
  1250. }
  1251. int SysExistFile(const char *pszFilePath)
  1252. {
  1253. DWORD dwAttr = GetFileAttributes(pszFilePath);
  1254. if (dwAttr == (DWORD) - 1)
  1255. return (0);
  1256. return ((dwAttr & FILE_ATTRIBUTE_DIRECTORY) ? 0 : 1);
  1257. }
  1258. int SysExistDir(const char *pszDirPath)
  1259. {
  1260. DWORD dwAttr = GetFileAttributes(pszDirPath);
  1261. if (dwAttr == (DWORD) - 1)
  1262. return (0);
  1263. return ((dwAttr & FILE_ATTRIBUTE_DIRECTORY) ? 1 : 0);
  1264. }
  1265. SYS_HANDLE SysFirstFile(const char *pszPath, char *pszFileName)
  1266. {
  1267. char szMatch[SYS_MAX_PATH] = "";
  1268. strcpy(szMatch, pszPath);
  1269. AppendSlash(szMatch);
  1270. strcat(szMatch, "*");
  1271. WIN32_FIND_DATA WFD;
  1272. HANDLE hFind = FindFirstFile(szMatch, &WFD);
  1273. if (hFind == INVALID_HANDLE_VALUE)
  1274. return (SYS_INVALID_HANDLE);
  1275. FileFindData *pFFD = (FileFindData *) SysAlloc(sizeof(FileFindData));
  1276. if (pFFD == NULL) {
  1277. FindClose(hFind);
  1278. return (SYS_INVALID_HANDLE);
  1279. }
  1280. strcpy(pFFD->szFindPath, pszPath);
  1281. AppendSlash(pFFD->szFindPath);
  1282. pFFD->hFind = hFind;
  1283. pFFD->WFD = WFD;
  1284. strcpy(pszFileName, pFFD->WFD.cFileName);
  1285. return ((SYS_HANDLE) pFFD);
  1286. }
  1287. int SysIsDirectory(SYS_HANDLE hFind)
  1288. {
  1289. FileFindData *pFFD = (FileFindData *) hFind;
  1290. return ((pFFD->WFD.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? 1 : 0);
  1291. }
  1292. unsigned long SysGetSize(SYS_HANDLE hFind)
  1293. {
  1294. FileFindData *pFFD = (FileFindData *) hFind;
  1295. return ((unsigned long) pFFD->WFD.nFileSizeLow);
  1296. }
  1297. int SysNextFile(SYS_HANDLE hFind, char *pszFileName)
  1298. {
  1299. FileFindData *pFFD = (FileFindData *) hFind;
  1300. if (!FindNextFile(pFFD->hFind, &pFFD->WFD))
  1301. return (0);
  1302. strcpy(pszFileName, pFFD->WFD.cFileName);
  1303. return (1);
  1304. }
  1305. void SysFindClose(SYS_HANDLE hFind)
  1306. {
  1307. FileFindData *pFFD = (FileFindData *) hFind;
  1308. FindClose(pFFD->hFind);
  1309. SysFree(pFFD);
  1310. }
  1311. int SysGetFileInfo(char const *pszFileName, SYS_FILE_INFO & FI)
  1312. {
  1313. WIN32_FIND_DATA WFD;
  1314. HANDLE hFind = FindFirstFile(pszFileName, &WFD);
  1315. if (hFind == INVALID_HANDLE_VALUE) {
  1316. ErrSetErrorCode(ERR_STAT);
  1317. return (ERR_STAT);
  1318. }
  1319. ZeroData(FI);
  1320. FI.iFileType = (WFD.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? ftDirectory : ftNormal;
  1321. FI.ulSize = (unsigned long) WFD.nFileSizeLow;
  1322. FI.tMod = SysFileTimeToTimet(&WFD.ftLastWriteTime);
  1323. FindClose(hFind);
  1324. return (0);
  1325. }
  1326. int SysSetFileModTime(char const *pszFileName, time_t tMod)
  1327. {
  1328. HANDLE hFile = CreateFile(pszFileName, GENERIC_WRITE,
  1329.   FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  1330.   NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  1331. if (hFile == INVALID_HANDLE_VALUE) {
  1332. ErrSetErrorCode(ERR_SET_FILE_TIME);
  1333. return (ERR_SET_FILE_TIME);
  1334. }
  1335. FILETIME MFT;
  1336. SysTimetToFileTime(tMod, &MFT);
  1337. if (!SetFileTime(hFile, NULL, &MFT, &MFT)) {
  1338. CloseHandle(hFile);
  1339. ErrSetErrorCode(ERR_SET_FILE_TIME);
  1340. return (ERR_SET_FILE_TIME);
  1341. }
  1342. CloseHandle(hFile);
  1343. return (0);
  1344. }
  1345. char *SysStrDup(const char *pszString)
  1346. {
  1347. int iStrLength = strlen(pszString);
  1348. char *pszBuffer = (char *) SysAlloc(iStrLength + 1);
  1349. if (pszBuffer != NULL)
  1350. strcpy(pszBuffer, pszString);
  1351. return (pszBuffer);
  1352. }
  1353. char *SysGetEnv(const char *pszVarName)
  1354. {
  1355. char szRKeyPath[256] = "";
  1356. SysSNPrintf(szRKeyPath, sizeof(szRKeyPath) - 1, "SOFTWARE\%s\%s",
  1357.     APP_PRODUCER, szServerName);
  1358. HKEY hKey;
  1359. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szRKeyPath, 0, KEY_QUERY_VALUE,
  1360.  &hKey) == ERROR_SUCCESS) {
  1361. char szKeyValue[2048] = "";
  1362. DWORD dwSize = sizeof(szKeyValue);
  1363. DWORD dwKeyType;
  1364. if (RegQueryValueEx(hKey, pszVarName, NULL, &dwKeyType, (u_char *) szKeyValue,
  1365.     &dwSize) == ERROR_SUCCESS) {
  1366. RegCloseKey(hKey);
  1367. return (SysStrDup(szKeyValue));
  1368. }
  1369. RegCloseKey(hKey);
  1370. }
  1371. const char *pszValue = getenv(pszVarName);
  1372. return ((pszValue != NULL) ? SysStrDup(pszValue) : NULL);
  1373. }
  1374. char *SysGetTmpFile(char *pszFileName)
  1375. {
  1376. char szTmpPath[SYS_MAX_PATH] = "";
  1377. GetTempPath(sizeof(szTmpPath) - 1, szTmpPath);
  1378. static unsigned int uFileSeqNr = 0;
  1379. SYS_LONGLONG llFileID =
  1380.     (((SYS_LONGLONG) GetCurrentThreadId()) << 32) | (SYS_LONGLONG)++ uFileSeqNr;
  1381. SysSNPrintf(pszFileName, SYS_MAX_PATH - 1, "%smsrv%I64x.tmp", szTmpPath, llFileID);
  1382. return (pszFileName);
  1383. }
  1384. int SysRemove(const char *pszFileName)
  1385. {
  1386. if (!DeleteFile(pszFileName)) {
  1387. ErrSetErrorCode(ERR_FILE_DELETE);
  1388. return (ERR_FILE_DELETE);
  1389. }
  1390. return (0);
  1391. }
  1392. int SysMakeDir(const char *pszPath)
  1393. {
  1394. if (!CreateDirectory(pszPath, NULL)) {
  1395. ErrSetErrorCode(ERR_DIR_CREATE);
  1396. return (ERR_DIR_CREATE);
  1397. }
  1398. return (0);
  1399. }
  1400. int SysRemoveDir(const char *pszPath)
  1401. {
  1402. if (!RemoveDirectory(pszPath)) {
  1403. ErrSetErrorCode(ERR_DIR_DELETE);
  1404. return (ERR_DIR_DELETE);
  1405. }
  1406. return (0);
  1407. }
  1408. int SysMoveFile(char const *pszOldName, char const *pszNewName)
  1409. {
  1410. if (!MoveFileEx(pszOldName, pszNewName,
  1411. MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED)) {
  1412. ErrSetErrorCode(ERR_FILE_MOVE);
  1413. return (ERR_FILE_MOVE);
  1414. }
  1415. return (0);
  1416. }
  1417. int SysVSNPrintf(char *pszBuffer, int iSize, char const *pszFormat, va_list Args)
  1418. {
  1419. return (_vsnprintf(pszBuffer, iSize, pszFormat, Args));
  1420. }
  1421. int SysFileSync(FILE * pFile)
  1422. {
  1423. if (fflush(pFile) || _commit(_fileno(pFile))) {
  1424. ErrSetErrorCode(ERR_FILE_WRITE);
  1425. return (ERR_FILE_WRITE);
  1426. }
  1427. return (0);
  1428. }
  1429. char *SysStrTok(char *pszData, char const *pszDelim, char **ppszSavePtr)
  1430. {
  1431. return (*ppszSavePtr = strtok(pszData, pszDelim));
  1432. }
  1433. char *SysCTime(time_t * pTimer, char *pszBuffer)
  1434. {
  1435. return (strcpy(pszBuffer, ctime(pTimer)));
  1436. }
  1437. struct tm *SysLocalTime(time_t * pTimer, struct tm *pTStruct)
  1438. {
  1439. *pTStruct = *localtime(pTimer);
  1440. return (pTStruct);
  1441. }
  1442. struct tm *SysGMTime(time_t * pTimer, struct tm *pTStruct)
  1443. {
  1444. *pTStruct = *gmtime(pTimer);
  1445. return (pTStruct);
  1446. }
  1447. char *SysAscTime(struct tm *pTStruct, char *pszBuffer, int iBufferSize)
  1448. {
  1449. strncpy(pszBuffer, asctime(pTStruct), iBufferSize);
  1450. pszBuffer[iBufferSize - 1] = '';
  1451. return (pszBuffer);
  1452. }
  1453. long SysGetTimeZone(void)
  1454. {
  1455. return ((long) _timezone);
  1456. }
  1457. long SysGetDayLight(void)
  1458. {
  1459. time_t tCurr = time(NULL);
  1460. struct tm tmCurr = *localtime(&tCurr);
  1461. return ((long) ((tmCurr.tm_isdst <= 0) ? 0 : 3600));
  1462. }
  1463. int SysGetDiskSpace(char const *pszPath, SYS_INT64 * pTotal, SYS_INT64 * pFree)
  1464. {
  1465. ULARGE_INTEGER BytesAvail;
  1466. ULARGE_INTEGER BytesOnDisk;
  1467. ULARGE_INTEGER BytesFree;
  1468. char szXPath[SYS_MAX_PATH] = "";
  1469. StrSNCpy(szXPath, pszPath);
  1470. AppendSlash(szXPath);
  1471. if (!GetDiskFreeSpaceEx(szXPath, &BytesAvail, &BytesOnDisk, &BytesFree)) {
  1472. ErrSetErrorCode(ERR_GET_DISK_SPACE_INFO);
  1473. return (ERR_GET_DISK_SPACE_INFO);
  1474. }
  1475. *pTotal = *(SYS_INT64 *) & BytesOnDisk;
  1476. *pFree = *(SYS_INT64 *) & BytesAvail;
  1477. return (0);
  1478. }
  1479. int SysMemoryInfo(SYS_INT64 * pRamTotal, SYS_INT64 * pRamFree,
  1480.   SYS_INT64 * pVirtTotal, SYS_INT64 * pVirtFree)
  1481. {
  1482. #if _WIN32_WINNT >= 0x0500
  1483. MEMORYSTATUSEX MSEX;
  1484. ZeroData(MSEX);
  1485. if (!GlobalMemoryStatusEx(&MSEX)) {
  1486. ErrSetErrorCode(ERR_GET_MEMORY_INFO);
  1487. return (ERR_GET_MEMORY_INFO);
  1488. }
  1489. *pRamTotal = (SYS_INT64) MSEX.ullTotalPhys;
  1490. *pRamFree = (SYS_INT64) MSEX.ullAvailPhys;
  1491. *pVirtTotal = (SYS_INT64) MSEX.ullTotalVirtual;
  1492. *pVirtFree = (SYS_INT64) MSEX.ullAvailVirtual;
  1493. #else // #if defined(_WIN32_WINNT 0x0500)
  1494. MEMORYSTATUS MS;
  1495. ZeroData(MS);
  1496. GlobalMemoryStatus(&MS);
  1497. *pRamTotal = (SYS_INT64) MS.dwTotalPhys;
  1498. *pRamFree = (SYS_INT64) MS.dwAvailPhys;
  1499. *pVirtTotal = (SYS_INT64) MS.dwTotalVirtual;
  1500. *pVirtFree = (SYS_INT64) MS.dwAvailVirtual;
  1501. #endif // #if defined(_WIN32_WINNT 0x0500)
  1502. return (0);
  1503. }
  1504. static unsigned int SysStkCall(unsigned int (*pProc) (void *), void *pData)
  1505. {
  1506. srand(GetCurrentThreadId() * (unsigned int) time(NULL) * uSRandBase);
  1507. unsigned int uResult;
  1508. unsigned int uStkDisp =
  1509.     (unsigned int) (rand() % MAX_STACK_SHIFT) & ~(STACK_ALIGN_BYTES - 1);
  1510. #if !defined(USE_ASM_STK_DISP)
  1511. void *pStkSpace = _alloca(uStkDisp);
  1512. uResult = pProc(pData);
  1513. #else
  1514. __asm {
  1515. sub esp, uStkDisp;
  1516. }
  1517. uResult = pProc(pData);
  1518. __asm {
  1519. add esp, uStkDisp;
  1520. }
  1521. #endif
  1522. return (uResult);
  1523. }