WinFunctions.cpp 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. //===-- WinFunctions.cpp - Windows Functions for other platforms --*- C++ -*-===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // This file defines Windows-specific functions used in the codebase for
  11. // non-Windows platforms.
  12. //
  13. //===----------------------------------------------------------------------===//
  14. #ifndef _WIN32
  15. #include <fcntl.h>
  16. #include <map>
  17. #include <string.h>
  18. #include <sys/stat.h>
  19. #include <unistd.h>
  20. #include "dxc/Support/WinFunctions.h"
  21. HRESULT StringCchCopyEx(LPSTR pszDest, size_t cchDest, LPCSTR pszSrc,
  22. LPSTR *ppszDestEnd, size_t *pcchRemaining, DWORD dwFlags) {
  23. assert(dwFlags == 0 && "dwFlag values not supported in StringCchCopyEx");
  24. char *zPtr = 0;
  25. zPtr = stpncpy(pszDest, pszSrc, cchDest);
  26. if (ppszDestEnd)
  27. *ppszDestEnd = zPtr;
  28. if (pcchRemaining)
  29. *pcchRemaining = cchDest - (zPtr - pszDest);
  30. return S_OK;
  31. }
  32. HRESULT StringCchPrintfA(char *dst, size_t dstSize, const char *format, ...) {
  33. va_list args;
  34. va_start(args, format);
  35. va_list argscopy;
  36. va_copy(argscopy, args);
  37. // C++11 snprintf can return the size of the resulting string if it was to be
  38. // constructed.
  39. size_t size = vsnprintf(nullptr, 0, format, argscopy) + 1; // Extra space for '\0'
  40. if (size > dstSize) {
  41. *dst = '\0';
  42. } else {
  43. vsnprintf(dst, size, format, args);
  44. }
  45. va_end(argscopy);
  46. va_end(args);
  47. return S_OK;
  48. }
  49. HRESULT UIntAdd(UINT uAugend, UINT uAddend, UINT *puResult) {
  50. HRESULT hr;
  51. if ((uAugend + uAddend) >= uAugend) {
  52. *puResult = (uAugend + uAddend);
  53. hr = S_OK;
  54. } else {
  55. *puResult = 0xffffffff;
  56. hr = ERROR_ARITHMETIC_OVERFLOW;
  57. }
  58. return hr;
  59. }
  60. HRESULT IntToUInt(int in, UINT *out) {
  61. HRESULT hr;
  62. if (in >= 0) {
  63. *out = (UINT)in;
  64. hr = S_OK;
  65. } else {
  66. *out = 0xffffffff;
  67. hr = ERROR_ARITHMETIC_OVERFLOW;
  68. }
  69. return hr;
  70. }
  71. HRESULT SizeTToInt(size_t in, int *out) {
  72. HRESULT hr;
  73. if(in <= INT_MAX) {
  74. *out = (int)in;
  75. hr = S_OK;
  76. }
  77. else {
  78. *out = 0xffffffff;
  79. hr = ERROR_ARITHMETIC_OVERFLOW;
  80. }
  81. return hr;
  82. }
  83. HRESULT UInt32Mult(UINT a, UINT b, UINT *out) {
  84. uint64_t result = (uint64_t)a * (uint64_t)b;
  85. if (result > uint64_t(UINT_MAX))
  86. return ERROR_ARITHMETIC_OVERFLOW;
  87. *out = (uint32_t)result;
  88. return S_OK;
  89. }
  90. int strnicmp(const char *str1, const char *str2, size_t count) {
  91. size_t i = 0;
  92. for (; i < count && str1[i] && str2[i]; ++i) {
  93. int d = std::tolower(str1[i]) - std::tolower(str2[i]);
  94. if (d != 0)
  95. return d;
  96. }
  97. if (i == count) {
  98. // All 'count' characters matched.
  99. return 0;
  100. }
  101. // str1 or str2 reached NULL before 'count' characters were compared.
  102. return str1[i] - str2[i];
  103. }
  104. int _stricmp(const char *str1, const char *str2) {
  105. size_t i = 0;
  106. for (; str1[i] && str2[i]; ++i) {
  107. int d = std::tolower(str1[i]) - std::tolower(str2[i]);
  108. if (d != 0)
  109. return d;
  110. }
  111. return str1[i] - str2[i];
  112. }
  113. int _wcsicmp(const wchar_t *str1, const wchar_t *str2) {
  114. size_t i = 0;
  115. for (; str1[i] && str2[i]; ++i) {
  116. int d = std::towlower(str1[i]) - std::towlower(str2[i]);
  117. if (d != 0)
  118. return d;
  119. }
  120. return str1[i] - str2[i];
  121. }
  122. int _wcsnicmp(const wchar_t *str1, const wchar_t *str2, size_t n) {
  123. size_t i = 0;
  124. for (; i < n && str1[i] && str2[i]; ++i) {
  125. int d = std::towlower(str1[i]) - std::towlower(str2[i]);
  126. if (d != 0)
  127. return d;
  128. }
  129. if (i >= n) return 0;
  130. return str1[i] - str2[i];
  131. }
  132. unsigned char _BitScanForward(unsigned long * Index, unsigned long Mask) {
  133. unsigned long l;
  134. if (!Mask) return 0;
  135. for (l=0; !(Mask&1); l++) Mask >>= 1;
  136. *Index = l;
  137. return 1;
  138. }
  139. HRESULT CoGetMalloc(DWORD dwMemContext, IMalloc **ppMalloc) {
  140. *ppMalloc = new IMalloc;
  141. (*ppMalloc)->AddRef();
  142. return S_OK;
  143. }
  144. HANDLE CreateFile2(_In_ LPCWSTR lpFileName, _In_ DWORD dwDesiredAccess,
  145. _In_ DWORD dwShareMode, _In_ DWORD dwCreationDisposition,
  146. _In_opt_ void *pCreateExParams) {
  147. return CreateFileW(lpFileName, dwDesiredAccess, dwShareMode, pCreateExParams,
  148. dwCreationDisposition, FILE_ATTRIBUTE_NORMAL, nullptr);
  149. }
  150. HANDLE CreateFileW(_In_ LPCWSTR lpFileName, _In_ DWORD dwDesiredAccess,
  151. _In_ DWORD dwShareMode, _In_opt_ void *lpSecurityAttributes,
  152. _In_ DWORD dwCreationDisposition,
  153. _In_ DWORD dwFlagsAndAttributes,
  154. _In_opt_ HANDLE hTemplateFile) {
  155. CW2A pUtf8FileName(lpFileName);
  156. size_t fd = -1;
  157. int flags = 0;
  158. if (dwDesiredAccess & GENERIC_WRITE)
  159. if (dwDesiredAccess & GENERIC_READ)
  160. flags |= O_RDWR;
  161. else
  162. flags |= O_WRONLY;
  163. else // dwDesiredAccess may be 0, but open() demands something here. This is mostly harmless
  164. flags |= O_RDONLY;
  165. if (dwCreationDisposition == CREATE_ALWAYS)
  166. flags |= (O_CREAT | O_TRUNC);
  167. if (dwCreationDisposition == OPEN_ALWAYS)
  168. flags |= O_CREAT;
  169. else if (dwCreationDisposition == CREATE_NEW)
  170. flags |= (O_CREAT | O_EXCL);
  171. else if (dwCreationDisposition == TRUNCATE_EXISTING)
  172. flags |= O_TRUNC;
  173. // OPEN_EXISTING represents default open() behavior
  174. // Catch Implementation limitations.
  175. assert(!lpSecurityAttributes && "security attributes not supported in CreateFileW yet");
  176. assert(!hTemplateFile && "template file not supported in CreateFileW yet");
  177. assert(dwFlagsAndAttributes == FILE_ATTRIBUTE_NORMAL &&
  178. "Attributes other than NORMAL not supported in CreateFileW yet");
  179. while ((int)(fd = open(pUtf8FileName, flags, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0) {
  180. if (errno != EINTR)
  181. return INVALID_HANDLE_VALUE;
  182. }
  183. return (HANDLE)fd;
  184. }
  185. BOOL GetFileSizeEx(_In_ HANDLE hFile, _Out_ PLARGE_INTEGER lpFileSize) {
  186. int fd = (size_t)hFile;
  187. struct stat fdstat;
  188. int rv = fstat(fd, &fdstat);
  189. if (!rv) {
  190. lpFileSize->QuadPart = (LONGLONG)fdstat.st_size;
  191. return true;
  192. }
  193. return false;
  194. }
  195. BOOL ReadFile(_In_ HANDLE hFile, _Out_ LPVOID lpBuffer,
  196. _In_ DWORD nNumberOfBytesToRead,
  197. _Out_opt_ LPDWORD lpNumberOfBytesRead,
  198. _Inout_opt_ void *lpOverlapped) {
  199. size_t fd = (size_t)hFile;
  200. ssize_t rv = -1;
  201. // Implementation limitation
  202. assert(!lpOverlapped && "Overlapping not supported in ReadFile yet.");
  203. rv = read(fd, lpBuffer, nNumberOfBytesToRead);
  204. if (rv < 0)
  205. return false;
  206. *lpNumberOfBytesRead = rv;
  207. return true;
  208. }
  209. BOOL WriteFile(_In_ HANDLE hFile, _In_ LPCVOID lpBuffer,
  210. _In_ DWORD nNumberOfBytesToWrite,
  211. _Out_opt_ LPDWORD lpNumberOfBytesWritten,
  212. _Inout_opt_ void *lpOverlapped) {
  213. size_t fd = (size_t)hFile;
  214. ssize_t rv = -1;
  215. // Implementation limitation
  216. assert(!lpOverlapped && "Overlapping not supported in WriteFile yet.");
  217. rv = write(fd, lpBuffer, nNumberOfBytesToWrite);
  218. if (rv < 0)
  219. return false;
  220. *lpNumberOfBytesWritten = rv;
  221. return true;
  222. }
  223. BOOL CloseHandle(_In_ HANDLE hObject) {
  224. int fd = (size_t)hObject;
  225. return !close(fd);
  226. }
  227. // Half-hearted implementation of a heap structure
  228. // Enables size queries, maximum allocation limit, and collective free at heap destruction
  229. // Does not perform any preallocation or allocation organization.
  230. // Does not respect any flags except for HEAP_ZERO_MEMORY
  231. struct SimpleAllocation {
  232. LPVOID ptr;
  233. SIZE_T size;
  234. };
  235. struct SimpleHeap {
  236. std::map<LPCVOID, SimpleAllocation> allocs;
  237. SIZE_T maxSize, curSize;
  238. };
  239. HANDLE HeapCreate(DWORD flOptions, SIZE_T dwInitialSize , SIZE_T dwMaximumSize) {
  240. SimpleHeap *simpHeap = new SimpleHeap;
  241. simpHeap->maxSize = dwMaximumSize;
  242. simpHeap->curSize = 0;
  243. return (HANDLE)simpHeap;
  244. }
  245. BOOL HeapDestroy(HANDLE hHeap) {
  246. SimpleHeap *simpHeap = (SimpleHeap*)hHeap;
  247. for (auto it = simpHeap->allocs.begin(), e = simpHeap->allocs.end(); it != e; it++)
  248. free(it->second.ptr);
  249. delete simpHeap;
  250. return true;
  251. }
  252. LPVOID HeapAlloc(HANDLE hHeap, DWORD dwFlags, SIZE_T dwBytes) {
  253. LPVOID ptr = nullptr;
  254. SimpleHeap *simpHeap = (SimpleHeap*)hHeap;
  255. if (simpHeap->maxSize && simpHeap->curSize + dwBytes > simpHeap->maxSize)
  256. return nullptr;
  257. if (dwFlags == HEAP_ZERO_MEMORY)
  258. ptr = calloc(1, dwBytes);
  259. else
  260. ptr = malloc(dwBytes);
  261. simpHeap->allocs[ptr] = {ptr, dwBytes};
  262. simpHeap->curSize += dwBytes;
  263. return ptr;
  264. }
  265. LPVOID HeapReAlloc(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem, SIZE_T dwBytes) {
  266. LPVOID ptr = nullptr;
  267. SimpleHeap *simpHeap = (SimpleHeap*)hHeap;
  268. SIZE_T oSize = simpHeap->allocs[lpMem].size;
  269. if (simpHeap->maxSize && simpHeap->curSize - oSize + dwBytes > simpHeap->maxSize)
  270. return nullptr;
  271. ptr = realloc(lpMem, dwBytes);
  272. if (dwFlags == HEAP_ZERO_MEMORY && oSize < dwBytes)
  273. memset((char*)ptr + oSize, 0, dwBytes - oSize);
  274. simpHeap->allocs.erase(lpMem);
  275. simpHeap->curSize -= oSize;
  276. simpHeap->allocs[ptr] = {ptr, dwBytes};
  277. simpHeap->curSize += dwBytes;
  278. return ptr;
  279. }
  280. BOOL HeapFree(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem) {
  281. SimpleHeap *simpHeap = (SimpleHeap*)hHeap;
  282. SIZE_T oSize = simpHeap->allocs[lpMem].size;
  283. free(lpMem);
  284. simpHeap->allocs.erase(lpMem);
  285. simpHeap->curSize -= oSize;
  286. return true;
  287. }
  288. SIZE_T HeapSize(HANDLE hHeap, DWORD dwFlags, LPCVOID lpMem) {
  289. SimpleHeap *simpHeap = (SimpleHeap*)hHeap;
  290. return simpHeap->allocs[lpMem].size;
  291. }
  292. static SimpleHeap g_processHeap;
  293. HANDLE GetProcessHeap() {
  294. return (HANDLE)&g_processHeap;
  295. }
  296. #endif // _WIN32