CommonPal.h 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Copyright (c) ChakraCore Project Contributors. All rights reserved.
  4. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  5. //-------------------------------------------------------------------------------------------------------
  6. #pragma once
  7. #define __MAKE_WARNING__(X) "This compiler does not support '" ## X ## "'"
  8. // Define _ALWAYSINLINE for template that want to always inline, but doesn't allow inline linkage in clang
  9. #if defined(__GNUC__) || defined(__clang__)
  10. #if __has_attribute(always_inline)
  11. #define _ALWAYSINLINE __attribute__((always_inline))
  12. #define __forceinline inline _ALWAYSINLINE
  13. #else // No always_inline support
  14. #pragma message __MAKE_WARNING__("always_inline")
  15. #define _ALWAYSINLINE inline
  16. #define __forceinline _ALWAYSINLINE
  17. #endif
  18. #if __has_attribute(noinline)
  19. #ifdef CLANG_HAS_DISABLE_TAIL_CALLS
  20. #define _NOINLINE __attribute__((noinline, disable_tail_calls))
  21. #else
  22. #define _NOINLINE __attribute__((noinline))
  23. #endif
  24. #else // No noinline support
  25. #pragma message __MAKE_WARNING__("noinline")
  26. #define _NOINLINE
  27. #endif
  28. #else // Windows
  29. #define _ALWAYSINLINE __forceinline
  30. #define _NOINLINE __declspec(noinline)
  31. #endif
  32. // Only VC compiler support overflow guard
  33. #if defined(__GNUC__) || defined(__clang__)
  34. #define DECLSPEC_GUARD_OVERFLOW
  35. #else // Windows
  36. #define DECLSPEC_GUARD_OVERFLOW __declspec(guard(overflow))
  37. #endif
  38. #ifndef THREAD_LOCAL
  39. #ifndef __APPLE__
  40. #if defined(_MSC_VER) && _MSC_VER <= 1800 // VS2013?
  41. #define THREAD_LOCAL __declspec(thread)
  42. #else // VS2015+, linux Clang etc.
  43. #define THREAD_LOCAL thread_local
  44. #endif // VS2013?
  45. #else // __APPLE__
  46. #ifndef __IOS__
  47. #define THREAD_LOCAL _Thread_local
  48. #else
  49. #define THREAD_LOCAL
  50. #endif
  51. #endif // __APPLE__
  52. #endif // THREAD_LOCAL
  53. // VS2015 RTM has bugs with constexpr, so require min of VS2015 Update 3 (known good version)
  54. #if !defined(_MSC_VER) || _MSC_FULL_VER >= 190024210
  55. #define HAS_CONSTEXPR 1
  56. #endif
  57. #ifdef HAS_CONSTEXPR
  58. #define OPT_CONSTEXPR constexpr
  59. #else
  60. #define OPT_CONSTEXPR
  61. #endif
  62. #ifdef __clang__
  63. #define CLANG_WNO_BEGIN_(x) \
  64. _Pragma("clang diagnostic push")\
  65. _Pragma(#x)
  66. #define CLANG_WNO_BEGIN(x) CLANG_WNO_BEGIN_(clang diagnostic ignored x)
  67. #define CLANG_WNO_END
  68. _Pragma("clang diagnostic pop")
  69. #else
  70. #define CLANG_WNO_BEGIN(x)
  71. #define CLANG_WNO_END
  72. #endif
  73. #ifndef __has_builtin
  74. #define __has_builtin(x) 0
  75. #endif
  76. #ifdef _WIN32
  77. #pragma warning(push)
  78. #pragma warning(disable: 4995) /* 'function': name was marked as #pragma deprecated */
  79. // === Windows Header Files ===
  80. #define WIN32_LEAN_AND_MEAN 1
  81. #define INC_OLE2 /* for windows.h */
  82. #define CONST_VTABLE /* for objbase.h */
  83. #include <windows.h>
  84. /* Don't want GetObject and GetClassName to be defined to GetObjectW and GetClassNameW */
  85. #undef GetObject
  86. #undef GetClassName
  87. #undef Yield /* winbase.h defines this but we want to use it for Js::OpCode::Yield; it is Win16 legacy, no harm undef'ing it */
  88. #pragma warning(pop)
  89. // xplat-todo: get a better name for this macro
  90. #define _u(s) L##s
  91. #define INIT_PRIORITY(x)
  92. #define get_cpuid __cpuid
  93. #else // !_WIN32
  94. #define USING_PAL_STDLIB 1
  95. #define STRSAFE_INLINE 1
  96. #ifdef PAL_STDCPP_COMPAT
  97. #include <wchar.h>
  98. #include <math.h>
  99. #include <time.h>
  100. #if defined(_AMD64_) || defined(__i686__)
  101. #include <smmintrin.h>
  102. #include <xmmintrin.h>
  103. #endif // defined(_AMD64_) || defined(__i686__)
  104. #endif
  105. #include "inc/pal.h"
  106. #include "inc/rt/palrt.h"
  107. #include "inc/rt/no_sal2.h"
  108. #include "inc/rt/oaidl.h"
  109. #define _u(s) u##s
  110. typedef GUID UUID;
  111. #define INIT_PRIORITY(x) __attribute__((init_priority(x)))
  112. #ifdef PAL_STDCPP_COMPAT
  113. #define FILE PAL_FILE
  114. #endif
  115. #if defined(_AMD64_) || defined(__i686__)
  116. // xplat-todo: verify below is correct
  117. #include <cpuid.h>
  118. inline int get_cpuid(int cpuInfo[4], int function_id)
  119. {
  120. return __get_cpuid(
  121. static_cast<unsigned int>(function_id),
  122. reinterpret_cast<unsigned int*>(&cpuInfo[0]),
  123. reinterpret_cast<unsigned int*>(&cpuInfo[1]),
  124. reinterpret_cast<unsigned int*>(&cpuInfo[2]),
  125. reinterpret_cast<unsigned int*>(&cpuInfo[3]));
  126. }
  127. #elif defined(_ARM_)
  128. inline int get_cpuid(int cpuInfo[4], int function_id)
  129. {
  130. int empty[4] = {0};
  131. memcpy(cpuInfo, empty, sizeof(int) * 4);
  132. // xplat-todo: implement me!!
  133. }
  134. #endif
  135. inline void DebugBreak()
  136. {
  137. __builtin_trap();
  138. }
  139. #define EXIT_FAILURE 1
  140. #define _BitScanForward BitScanForward
  141. #define _BitScanForward64 BitScanForward64
  142. #define _BitScanReverse BitScanReverse
  143. #define _BitScanReverse64 BitScanReverse64
  144. #define _bittest BitTest
  145. #define _bittestandset BitTestAndSet
  146. #define _interlockedbittestandset InterlockedBitTestAndSet
  147. #define DbgRaiseAssertionFailure() __builtin_trap()
  148. // These are not available in pal
  149. #define fwprintf_s fwprintf
  150. // PAL LoadLibraryExW not supported
  151. #define LOAD_LIBRARY_SEARCH_SYSTEM32 0
  152. // winnt.h
  153. #define FAST_FAIL_INVALID_ARG 5
  154. // winerror.h
  155. #define FACILITY_JSCRIPT 2306
  156. #define JSCRIPT_E_CANTEXECUTE _HRESULT_TYPEDEF_(0x89020001L)
  157. #define DISP_E_UNKNOWNINTERFACE _HRESULT_TYPEDEF_(0x80020001L)
  158. #define DISP_E_MEMBERNOTFOUND _HRESULT_TYPEDEF_(0x80020003L)
  159. #define DISP_E_UNKNOWNNAME _HRESULT_TYPEDEF_(0x80020006L)
  160. #define DISP_E_NONAMEDARGS _HRESULT_TYPEDEF_(0x80020007L)
  161. #define DISP_E_EXCEPTION _HRESULT_TYPEDEF_(0x80020009L)
  162. #define DISP_E_BADINDEX _HRESULT_TYPEDEF_(0x8002000BL)
  163. #define DISP_E_UNKNOWNLCID _HRESULT_TYPEDEF_(0x8002000CL)
  164. #define DISP_E_ARRAYISLOCKED _HRESULT_TYPEDEF_(0x8002000DL)
  165. #define DISP_E_BADPARAMCOUNT _HRESULT_TYPEDEF_(0x8002000EL)
  166. #define DISP_E_PARAMNOTOPTIONAL _HRESULT_TYPEDEF_(0x8002000FL)
  167. #define DISP_E_NOTACOLLECTION _HRESULT_TYPEDEF_(0x80020011L)
  168. #define TYPE_E_DLLFUNCTIONNOTFOUND _HRESULT_TYPEDEF_(0x8002802FL)
  169. #define TYPE_E_TYPEMISMATCH _HRESULT_TYPEDEF_(0x80028CA0L)
  170. #define TYPE_E_OUTOFBOUNDS _HRESULT_TYPEDEF_(0x80028CA1L)
  171. #define TYPE_E_IOERROR _HRESULT_TYPEDEF_(0x80028CA2L)
  172. #define TYPE_E_CANTCREATETMPFILE _HRESULT_TYPEDEF_(0x80028CA3L)
  173. #define TYPE_E_CANTLOADLIBRARY _HRESULT_TYPEDEF_(0x80029C4AL)
  174. #define STG_E_TOOMANYOPENFILES _HRESULT_TYPEDEF_(0x80030004L)
  175. #define STG_E_ACCESSDENIED _HRESULT_TYPEDEF_(0x80030005L)
  176. #define STG_E_INSUFFICIENTMEMORY _HRESULT_TYPEDEF_(0x80030008L)
  177. #define STG_E_NOMOREFILES _HRESULT_TYPEDEF_(0x80030012L)
  178. #define STG_E_DISKISWRITEPROTECTED _HRESULT_TYPEDEF_(0x80030013L)
  179. #define STG_E_READFAULT _HRESULT_TYPEDEF_(0x8003001EL)
  180. #define STG_E_SHAREVIOLATION _HRESULT_TYPEDEF_(0x80030020L)
  181. #define STG_E_LOCKVIOLATION _HRESULT_TYPEDEF_(0x80030021L)
  182. #define STG_E_MEDIUMFULL _HRESULT_TYPEDEF_(0x80030070L)
  183. #define STG_E_INVALIDNAME _HRESULT_TYPEDEF_(0x800300FCL)
  184. #define STG_E_INUSE _HRESULT_TYPEDEF_(0x80030100L)
  185. #define STG_E_NOTCURRENT _HRESULT_TYPEDEF_(0x80030101L)
  186. #define STG_E_CANTSAVE _HRESULT_TYPEDEF_(0x80030103L)
  187. #define REGDB_E_CLASSNOTREG _HRESULT_TYPEDEF_(0x80040154L)
  188. #define MK_E_UNAVAILABLE _HRESULT_TYPEDEF_(0x800401E3L)
  189. #define MK_E_INVALIDEXTENSION _HRESULT_TYPEDEF_(0x800401E6L)
  190. #define MK_E_CANTOPENFILE _HRESULT_TYPEDEF_(0x800401EAL)
  191. #define CO_E_APPNOTFOUND _HRESULT_TYPEDEF_(0x800401F5L)
  192. #define CO_E_APPDIDNTREG _HRESULT_TYPEDEF_(0x800401FEL)
  193. #define GetScode(hr) ((SCODE) (hr))
  194. // activscp.h
  195. #define SCRIPT_E_RECORDED _HRESULT_TYPEDEF_(0x86664004L)
  196. #define GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS (0x00000004)
  197. typedef
  198. enum tagBREAKPOINT_STATE
  199. {
  200. BREAKPOINT_DELETED = 0,
  201. BREAKPOINT_DISABLED = 1,
  202. BREAKPOINT_ENABLED = 2
  203. } BREAKPOINT_STATE;
  204. typedef
  205. enum tagBREAKRESUME_ACTION
  206. {
  207. BREAKRESUMEACTION_ABORT = 0,
  208. BREAKRESUMEACTION_CONTINUE = ( BREAKRESUMEACTION_ABORT + 1 ) ,
  209. BREAKRESUMEACTION_STEP_INTO = ( BREAKRESUMEACTION_CONTINUE + 1 ) ,
  210. BREAKRESUMEACTION_STEP_OVER = ( BREAKRESUMEACTION_STEP_INTO + 1 ) ,
  211. BREAKRESUMEACTION_STEP_OUT = ( BREAKRESUMEACTION_STEP_OVER + 1 ) ,
  212. BREAKRESUMEACTION_IGNORE = ( BREAKRESUMEACTION_STEP_OUT + 1 ) ,
  213. BREAKRESUMEACTION_STEP_DOCUMENT = ( BREAKRESUMEACTION_IGNORE + 1 )
  214. } BREAKRESUMEACTION;
  215. enum tagDBGPROP_ATTRIB_FLAGS
  216. {
  217. DBGPROP_ATTRIB_NO_ATTRIB= 0,
  218. DBGPROP_ATTRIB_VALUE_IS_INVALID= 0x8,
  219. DBGPROP_ATTRIB_VALUE_IS_EXPANDABLE= 0x10,
  220. DBGPROP_ATTRIB_VALUE_IS_FAKE= 0x20,
  221. DBGPROP_ATTRIB_VALUE_IS_METHOD= 0x100,
  222. DBGPROP_ATTRIB_VALUE_IS_EVENT= 0x200,
  223. DBGPROP_ATTRIB_VALUE_IS_RAW_STRING= 0x400,
  224. DBGPROP_ATTRIB_VALUE_READONLY= 0x800,
  225. DBGPROP_ATTRIB_ACCESS_PUBLIC= 0x1000,
  226. DBGPROP_ATTRIB_ACCESS_PRIVATE= 0x2000,
  227. DBGPROP_ATTRIB_ACCESS_PROTECTED= 0x4000,
  228. DBGPROP_ATTRIB_ACCESS_FINAL= 0x8000,
  229. DBGPROP_ATTRIB_STORAGE_GLOBAL= 0x10000,
  230. DBGPROP_ATTRIB_STORAGE_STATIC= 0x20000,
  231. DBGPROP_ATTRIB_STORAGE_FIELD= 0x40000,
  232. DBGPROP_ATTRIB_STORAGE_VIRTUAL= 0x80000,
  233. DBGPROP_ATTRIB_TYPE_IS_CONSTANT= 0x100000,
  234. DBGPROP_ATTRIB_TYPE_IS_SYNCHRONIZED= 0x200000,
  235. DBGPROP_ATTRIB_TYPE_IS_VOLATILE= 0x400000,
  236. DBGPROP_ATTRIB_HAS_EXTENDED_ATTRIBS= 0x800000,
  237. DBGPROP_ATTRIB_FRAME_INTRYBLOCK= 0x1000000,
  238. DBGPROP_ATTRIB_FRAME_INCATCHBLOCK= 0x2000000,
  239. DBGPROP_ATTRIB_FRAME_INFINALLYBLOCK= 0x4000000,
  240. DBGPROP_ATTRIB_VALUE_IS_RETURN_VALUE= 0x8000000
  241. };
  242. typedef DWORD DBGPROP_ATTRIB_FLAGS;
  243. enum tagDBGPROP_INFO_FLAgS
  244. {
  245. DBGPROP_INFO_NAME= 0x1,
  246. DBGPROP_INFO_TYPE= 0x2,
  247. DBGPROP_INFO_VALUE= 0x4,
  248. DBGPROP_INFO_FULLNAME= 0x20,
  249. DBGPROP_INFO_ATTRIBUTES= 0x8,
  250. DBGPROP_INFO_DEBUGPROP= 0x10,
  251. DBGPROP_INFO_BEAUTIFY= 0x2000000,
  252. DBGPROP_INFO_CALLTOSTRING= 0x4000000,
  253. DBGPROP_INFO_AUTOEXPAND= 0x800000
  254. };
  255. typedef DWORD DBGPROP_INFO_FLAGS;
  256. #define DBGPROP_INFO_STANDARD ((((DBGPROP_INFO_NAME | DBGPROP_INFO_TYPE) | DBGPROP_INFO_VALUE) | DBGPROP_INFO_ATTRIBUTES))
  257. #define DBGPROP_INFO_ALL ((((((DBGPROP_INFO_NAME | DBGPROP_INFO_TYPE ) | DBGPROP_INFO_VALUE) | DBGPROP_INFO_FULLNAME) | DBGPROP_INFO_ATTRIBUTES) | DBGPROP_INFO_DEBUGPROP))
  258. // _countof
  259. #if defined _M_X64 || defined _M_ARM || defined _M_ARM64
  260. #define _UNALIGNED __unaligned
  261. #else
  262. #define _UNALIGNED
  263. #endif
  264. #ifdef __cplusplus
  265. extern "C++"
  266. {
  267. template <typename _CountofType, size_t _SizeOfArray>
  268. char(*__countof_helper(_UNALIGNED _CountofType(&_Array)[_SizeOfArray]))[_SizeOfArray];
  269. #define __crt_countof(_Array) (sizeof(*__countof_helper(_Array)) + 0)
  270. }
  271. #else
  272. #define __crt_countof(_Array) (sizeof(_Array) / sizeof(_Array[0]))
  273. #endif
  274. #ifndef _countof
  275. #define _countof __crt_countof
  276. #endif
  277. // _countof
  278. #define ARRAYSIZE(A) _countof(A)
  279. //
  280. // Singly linked list structure. Can be used as either a list head, or
  281. // as link words.
  282. //
  283. typedef struct _SINGLE_LIST_ENTRY {
  284. struct _SINGLE_LIST_ENTRY *Next;
  285. } SINGLE_LIST_ENTRY, *PSINGLE_LIST_ENTRY;
  286. #if defined(TARGET_64)
  287. //
  288. // The type SINGLE_LIST_ENTRY is not suitable for use with SLISTs. For
  289. // TARGET_64, an entry on an SLIST is required to be 16-byte aligned, while a
  290. // SINGLE_LIST_ENTRY structure has only 8 byte alignment.
  291. //
  292. // Therefore, all SLIST code should use the SLIST_ENTRY type instead of the
  293. // SINGLE_LIST_ENTRY type.
  294. //
  295. #pragma warning(push)
  296. #pragma warning(disable:4324) // structure padded due to align()
  297. typedef struct DECLSPEC_ALIGN(16) _SLIST_ENTRY {
  298. struct _SLIST_ENTRY *Next;
  299. } SLIST_ENTRY, *PSLIST_ENTRY;
  300. #pragma warning(pop)
  301. #else // defined(TARGET_64)
  302. typedef struct _SINGLE_LIST_ENTRY SLIST_ENTRY, *PSLIST_ENTRY;
  303. #endif // defined(TARGET_64)
  304. #if defined(_AMD64_)
  305. typedef union DECLSPEC_ALIGN(16) _SLIST_HEADER {
  306. struct { // original struct
  307. ULONGLONG Alignment;
  308. ULONGLONG Region;
  309. } DUMMYSTRUCTNAME;
  310. struct { // x64 16-byte header
  311. ULONGLONG Depth : 16;
  312. ULONGLONG Sequence : 48;
  313. ULONGLONG Reserved : 4;
  314. ULONGLONG NextEntry : 60; // last 4 bits are always 0's
  315. } HeaderX64;
  316. } SLIST_HEADER, *PSLIST_HEADER;
  317. #elif defined(_X86_)
  318. typedef union _SLIST_HEADER {
  319. ULONGLONG Alignment;
  320. struct {
  321. SLIST_ENTRY Next;
  322. WORD Depth;
  323. WORD CpuId;
  324. } DUMMYSTRUCTNAME;
  325. } SLIST_HEADER, *PSLIST_HEADER;
  326. #elif defined(_ARM_)
  327. typedef union _SLIST_HEADER {
  328. ULONGLONG Alignment;
  329. struct {
  330. SLIST_ENTRY Next;
  331. WORD Depth;
  332. WORD Reserved;
  333. } DUMMYSTRUCTNAME;
  334. } SLIST_HEADER, *PSLIST_HEADER;
  335. #elif defined(_ARM64_)
  336. typedef union _SLIST_HEADER {
  337. ULONGLONG Alignment;
  338. struct {
  339. SLIST_ENTRY Next;
  340. WORD Depth;
  341. WORD Reserved;
  342. } DUMMYSTRUCTNAME;
  343. } SLIST_HEADER, *PSLIST_HEADER;
  344. #endif
  345. PALIMPORT VOID PALAPI InitializeSListHead(IN OUT PSLIST_HEADER ListHead);
  346. PALIMPORT PSLIST_ENTRY PALAPI InterlockedPushEntrySList(IN OUT PSLIST_HEADER ListHead, IN OUT PSLIST_ENTRY ListEntry);
  347. PALIMPORT PSLIST_ENTRY PALAPI InterlockedPopEntrySList(IN OUT PSLIST_HEADER ListHead);
  348. template <class T>
  349. inline T InterlockedExchangeAdd(
  350. IN OUT T volatile *Addend,
  351. IN T Value)
  352. {
  353. return __sync_fetch_and_add(Addend, Value);
  354. }
  355. template <class T>
  356. inline T InterlockedExchangeSubtract(
  357. IN OUT T volatile *Addend,
  358. IN T Value)
  359. {
  360. return __sync_fetch_and_sub(Addend, Value);
  361. }
  362. template <class T>
  363. inline T InterlockedIncrement(
  364. IN OUT T volatile *Addend)
  365. {
  366. return __sync_add_and_fetch(Addend, T(1));
  367. }
  368. template <class T>
  369. inline T InterlockedDecrement(
  370. IN OUT T volatile *Addend)
  371. {
  372. return __sync_sub_and_fetch(Addend, T(1));
  373. }
  374. inline __int64 _abs64(__int64 n)
  375. {
  376. return n < 0 ? -n : n;
  377. }
  378. int GetCurrentThreadStackLimits(ULONG_PTR* lowLimit, ULONG_PTR* highLimit);
  379. bool IsAddressOnStack(ULONG_PTR address);
  380. errno_t rand_s(unsigned int* randomValue);
  381. inline char16* wmemset(char16* wcs, char16 wc, size_t n)
  382. {
  383. while (n)
  384. {
  385. wcs[--n] = wc;
  386. }
  387. return wcs;
  388. }
  389. inline errno_t wmemcpy_s(char16* dest, size_t destSize, const char16* src, size_t count)
  390. {
  391. return memcpy_s(dest, sizeof(char16) * destSize, src, sizeof(char16) * count);
  392. }
  393. inline int _wunlink(const char16* filename)
  394. {
  395. // WARN: does not set errno when fail
  396. return DeleteFile(filename) ? 0 : -1;
  397. }
  398. template <size_t size>
  399. inline errno_t _wcserror_s(char16 (&buffer)[size], int errnum)
  400. {
  401. const char* str = strerror(errnum);
  402. // WARN: does not return detail errno when fail
  403. return MultiByteToWideChar(CP_ACP, 0, str, -1, buffer, size) ? 0 : -1;
  404. }
  405. #define midl_user_allocate(size) \
  406. HeapAlloc(GetProcessHeap(), 0, (size))
  407. #define midl_user_free(ptr) \
  408. if (ptr != NULL) { HeapFree(GetProcessHeap(), NULL, ptr); }
  409. DWORD __cdecl CharLowerBuffW(const char16* lpsz, DWORD cchLength);
  410. DWORD __cdecl CharUpperBuffW(const char16* lpsz, DWORD cchLength);
  411. #define MAXUINT32 ((uint32_t)~((uint32_t)0))
  412. #define MAXINT32 ((int32_t)(MAXUINT32 >> 1))
  413. #define BYTE_MAX 0xff
  414. #define USHORT_MAX 0xffff
  415. #ifdef UNICODE
  416. #define StringCchPrintf StringCchPrintfW
  417. #endif
  418. #endif // _WIN32
  419. // Use intsafe.h for internal builds (currently missing some files with stdint.h)
  420. #if defined(_WIN32) && defined(NTBUILD)
  421. #define ENABLE_INTSAFE_SIGNED_FUNCTIONS 1
  422. #include <intsafe.h>
  423. #else
  424. #include <stdint.h>
  425. #endif
  426. // `typename QualifiedName` declarations outside of template code not supported before MSVC 2015 update 1
  427. #if defined(_MSC_VER) && _MSC_VER < 1910 && !defined(__clang__)
  428. #define _TYPENAME
  429. #else
  430. #define _TYPENAME typename
  431. #endif
  432. #if (defined(_MSC_VER) && _MSC_VER < 1900) || defined(NTBUILD)
  433. // "noexcept" not supported before VS 2015
  434. #define _NOEXCEPT_ throw()
  435. #else
  436. #define _NOEXCEPT_ noexcept
  437. #endif
  438. #ifdef _MSC_VER
  439. extern "C" PVOID _ReturnAddress(VOID);
  440. #pragma intrinsic(_ReturnAddress)
  441. extern "C" void * _AddressOfReturnAddress(void);
  442. #elif defined(__GNUC__) || defined(__clang__)
  443. #define _ReturnAddress() __builtin_return_address(0)
  444. #if !__has_builtin(_AddressOfReturnAddress)
  445. __forceinline void * _AddressOfReturnAddress()
  446. {
  447. return (void*)((char*) __builtin_frame_address(0) + sizeof(void*));
  448. }
  449. #else
  450. extern "C" void * _AddressOfReturnAddress(void);
  451. #endif
  452. #else
  453. #error _AddressOfReturnAddress and _ReturnAddress not defined for this platform
  454. #endif
  455. // Define strsafe related types and defines for non-VC++ compilers
  456. #ifndef _MSC_VER
  457. // xplat-todo: figure out why strsafe.h includes stdio etc
  458. // which prevents me from directly including PAL's strsafe.h
  459. #ifdef __cplusplus
  460. #define _STRSAFE_EXTERN_C extern "C"
  461. #else
  462. #define _STRSAFE_EXTERN_C extern
  463. #endif
  464. // If you do not want to use these functions inline (and instead want to link w/ strsafe.lib), then
  465. // #define STRSAFE_LIB before including this header file.
  466. #if defined(STRSAFE_LIB)
  467. #define STRSAFEAPI _STRSAFE_EXTERN_C HRESULT __stdcall
  468. #pragma comment(lib, "strsafe.lib")
  469. #elif defined(STRSAFE_LIB_IMPL)
  470. #define STRSAFEAPI _STRSAFE_EXTERN_C HRESULT __stdcall
  471. #else
  472. #define STRSAFEAPI inline HRESULT __stdcall
  473. #define STRSAFE_INLINE
  474. #endif
  475. STRSAFEAPI StringCchPrintfW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszFormat, ...);
  476. STRSAFEAPI StringVPrintfWorkerW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszFormat, va_list argList);
  477. #define STRSAFE_MAX_CCH 2147483647 // max # of characters we support (same as INT_MAX)
  478. // STRSAFE error return codes
  479. //
  480. #define STRSAFE_E_INSUFFICIENT_BUFFER ((HRESULT)0x8007007AL) // 0x7A = 122L = ERROR_INSUFFICIENT_BUFFER
  481. #define STRSAFE_E_INVALID_PARAMETER ((HRESULT)0x80070057L) // 0x57 = 87L = ERROR_INVALID_PARAMETER
  482. #define STRSAFE_E_END_OF_FILE ((HRESULT)0x80070026L) // 0x26 = 38L = ERROR_HANDLE_EOF
  483. #endif
  484. // Provide the definitions for non-windows platforms
  485. #ifndef _MSC_VER
  486. STRSAFEAPI StringVPrintfWorkerW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszFormat, va_list argList)
  487. {
  488. HRESULT hr = S_OK;
  489. if (cchDest == 0)
  490. {
  491. // can not null terminate a zero-byte dest buffer
  492. hr = STRSAFE_E_INVALID_PARAMETER;
  493. }
  494. else
  495. {
  496. int iRet;
  497. size_t cchMax;
  498. // leave the last space for the null terminator
  499. cchMax = cchDest - 1;
  500. iRet = _vsnwprintf(pszDest, cchMax, pszFormat, argList);
  501. // ASSERT((iRet < 0) || (((size_t)iRet) <= cchMax));
  502. if ((iRet < 0) || (((size_t)iRet) > cchMax))
  503. {
  504. // need to null terminate the string
  505. pszDest += cchMax;
  506. *pszDest = _u('\0');
  507. // we have truncated pszDest
  508. hr = STRSAFE_E_INSUFFICIENT_BUFFER;
  509. }
  510. else if (((size_t)iRet) == cchMax)
  511. {
  512. // need to null terminate the string
  513. pszDest += cchMax;
  514. *pszDest = _u('\0');
  515. }
  516. }
  517. return hr;
  518. }
  519. STRSAFEAPI StringCchPrintfW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszFormat, ...)
  520. {
  521. HRESULT hr;
  522. if (cchDest > STRSAFE_MAX_CCH)
  523. {
  524. hr = STRSAFE_E_INVALID_PARAMETER;
  525. }
  526. else
  527. {
  528. va_list argList;
  529. va_start(argList, pszFormat);
  530. hr = StringVPrintfWorkerW(pszDest, cchDest, pszFormat, argList);
  531. va_end(argList);
  532. }
  533. return hr;
  534. }
  535. #endif
  536. #ifndef _WIN32
  537. __inline
  538. HRESULT ULongMult(ULONG ulMultiplicand, ULONG ulMultiplier, ULONG* pulResult);
  539. #endif
  540. /* **** WARNING : finallyFunc is not allowed to raise exception *****
  541. * **** DO NOT ADD stack probe or memory allocations within the finallyFunc ****
  542. */
  543. template <class TryFunc, class FinallyFunc>
  544. void TryFinally(const TryFunc& tryFunc, const FinallyFunc& finallyFunc)
  545. {
  546. class FinallyObject
  547. {
  548. public:
  549. FinallyObject(const FinallyFunc& finallyFunc) : finallyFunc(finallyFunc), abnormalTermination(true) {}
  550. ~FinallyObject() { finallyFunc(abnormalTermination); }
  551. void SetHasNoAbnormalTermination() { abnormalTermination = false; }
  552. private:
  553. const FinallyFunc& finallyFunc;
  554. bool abnormalTermination;
  555. } finallyObject(finallyFunc);
  556. tryFunc();
  557. finallyObject.SetHasNoAbnormalTermination();
  558. }
  559. #ifdef DISABLE_SEH
  560. #define __TRY_FINALLY_BEGIN TryFinally([&]()
  561. #define __FINALLY , [&](bool /* hasException */)
  562. #define __TRY_FINALLY_END );
  563. #else
  564. #define __TRY_FINALLY_BEGIN __try
  565. #define __FINALLY __finally
  566. #define __TRY_FINALLY_END
  567. #endif
  568. namespace PlatformAgnostic
  569. {
  570. __forceinline unsigned char _BitTestAndSet(LONG *_BitBase, int _BitPos)
  571. {
  572. #if defined(__clang__) && !defined(_ARM_) && !defined(_ARM64_)
  573. // Clang doesn't expand _bittestandset intrinic to bts, and it's implemention also doesn't work for _BitPos >= 32
  574. unsigned char retval = 0;
  575. asm(
  576. "bts %[_BitPos], %[_BitBase]\n\t"
  577. "setc %b[retval]\n\t"
  578. : [_BitBase] "+m" (*_BitBase), [retval] "+rm" (retval)
  579. : [_BitPos] "ri" (_BitPos)
  580. : "cc" // clobber condition code
  581. );
  582. return retval;
  583. #else
  584. return _bittestandset(_BitBase, _BitPos);
  585. #endif
  586. }
  587. __forceinline unsigned char _BitTest(LONG *_BitBase, int _BitPos)
  588. {
  589. #if defined(__clang__) && !defined(_ARM_) && !defined(_ARM64_)
  590. // Clang doesn't expand _bittest intrinic to bt, and it's implemention also doesn't work for _BitPos >= 32
  591. unsigned char retval;
  592. asm(
  593. "bt %[_BitPos], %[_BitBase]\n\t"
  594. "setc %b[retval]\n\t"
  595. : [retval] "+rm" (retval)
  596. : [_BitPos] "ri" (_BitPos), [_BitBase] "m" (*_BitBase)
  597. : "cc" // clobber condition code
  598. );
  599. return retval;
  600. #else
  601. return _bittest(_BitBase, _BitPos);
  602. #endif
  603. }
  604. __forceinline unsigned char _InterlockedBitTestAndSet(volatile LONG *_BitBase, int _BitPos)
  605. {
  606. #if defined(__clang__) && !defined(_ARM_) && !defined(_ARM64_)
  607. // Clang doesn't expand _interlockedbittestandset intrinic to lock bts, and it's implemention also doesn't work for _BitPos >= 32
  608. unsigned char retval;
  609. asm(
  610. "lock bts %[_BitPos], %[_BitBase]\n\t"
  611. "setc %b[retval]\n\t"
  612. : [_BitBase] "+m" (*_BitBase), [retval] "+rm" (retval)
  613. : [_BitPos] "ri" (_BitPos)
  614. : "cc" // clobber condition code
  615. );
  616. return retval;
  617. #else
  618. return _interlockedbittestandset(_BitBase, _BitPos);
  619. #endif
  620. }
  621. __forceinline unsigned char _InterlockedBitTestAndReset(volatile LONG *_BitBase, int _BitPos)
  622. {
  623. #if defined(__clang__) && !defined(_ARM_) && !defined(_ARM64_)
  624. // Clang doesn't expand _interlockedbittestandset intrinic to lock btr, and it's implemention also doesn't work for _BitPos >= 32
  625. unsigned char retval;
  626. asm(
  627. "lock btr %[_BitPos], %[_BitBase]\n\t"
  628. "setc %b[retval]\n\t"
  629. : [_BitBase] "+m" (*_BitBase), [retval] "+rm" (retval)
  630. : [_BitPos] "ri" (_BitPos)
  631. : "cc" // clobber condition code
  632. );
  633. return retval;
  634. #elif !defined(__ANDROID__)
  635. return _interlockedbittestandreset(_BitBase, (long)_BitPos);
  636. #else
  637. // xplat-todo: Implement _interlockedbittestandreset for Android
  638. abort();
  639. #endif
  640. }
  641. };
  642. #include "PlatformAgnostic/DateTime.h"
  643. #include "PlatformAgnostic/Numbers.h"
  644. #include "PlatformAgnostic/Arrays.h"
  645. #include "PlatformAgnostic/SystemInfo.h"
  646. #include "PlatformAgnostic/Thread.h"
  647. #include "PlatformAgnostic/AssemblyCommon.h"
  648. #include "PlatformAgnostic/Debugger.h"