1 | // Licensed to the .NET Foundation under one or more agreements. |
2 | // The .NET Foundation licenses this file to you under the MIT license. |
3 | // See the LICENSE file in the project root for more information. |
4 | // =========================================================================== |
5 | // File: palclr.h |
6 | // |
7 | // Various macros and constants that are necessary to make the CLR portable. |
8 | // |
9 | |
10 | // =========================================================================== |
11 | |
12 | |
13 | #if !defined(FEATURE_PAL) |
14 | |
15 | #ifndef __PALCLR_H__ |
16 | #define __PALCLR_H__ |
17 | |
18 | // This macro is used to standardize the wide character string literals between UNIX and Windows. |
19 | // Unix L"" is UTF32, and on windows it's UTF16. Because of built-in assumptions on the size |
20 | // of string literals, it's important to match behaviour between Unix and Windows. Unix will be defined |
21 | // as u"" (char16_t) |
22 | #ifdef PLATFORM_UNIX |
23 | #define W(str) u##str |
24 | #else // PLATFORM_UNIX |
25 | #define W(str) L##str |
26 | #endif // PLATFORM_UNIX |
27 | |
28 | #include <windef.h> |
29 | |
30 | #if !defined(_DEBUG_IMPL) && defined(_DEBUG) && !defined(DACCESS_COMPILE) |
31 | #define _DEBUG_IMPL 1 |
32 | #endif |
33 | |
34 | // |
35 | // CPP_ASSERT() can be used within a class definition, to perform a |
36 | // compile-time assertion involving private names within the class. |
37 | // |
38 | // MS compiler doesn't allow redefinition of the typedef within a template. |
39 | // gcc doesn't allow redefinition of the typedef within a class, though |
40 | // it does at file scope. |
41 | #define CPP_ASSERT(n, e) typedef char __C_ASSERT__##n[(e) ? 1 : -1]; |
42 | |
43 | |
44 | // PORTABILITY_ASSERT and PORTABILITY_WARNING macros are meant to be used to |
45 | // mark places in the code that needs attention for portability. The usual |
46 | // usage pattern is: |
47 | // |
48 | // int get_scratch_register() { |
49 | // #if defined(_TARGET_X86_) |
50 | // return eax; |
51 | // #elif defined(_TARGET_AMD64_) |
52 | // return rax; |
53 | // #elif defined(_TARGET_ARM_) |
54 | // return r0; |
55 | // #else |
56 | // PORTABILITY_ASSERT("scratch register"); |
57 | // return 0; |
58 | // #endif |
59 | // } |
60 | // |
61 | // PORTABILITY_ASSERT is meant to be used inside functions/methods. It can |
62 | // introduce compile-time and/or run-time errors. |
63 | // PORTABILITY_WARNING is meant to be used outside functions/methods. It can |
64 | // introduce compile-time errors or warnings only. |
65 | // |
66 | // People starting new ports will first define these to just cause run-time |
67 | // errors. Once they fix all the places that need attention for portability, |
68 | // they can define PORTABILITY_ASSERT and PORTABILITY_WARNING to cause |
69 | // compile-time errors to make sure that they haven't missed anything. |
70 | // |
71 | // If it is reasonably possible all codepaths containing PORTABILITY_ASSERT |
72 | // should be compilable (e.g. functions should return NULL or something if |
73 | // they are expected to return a value). |
74 | // |
75 | // The message in these two macros should not contain any keywords like TODO |
76 | // or NYI. It should be just the brief description of the problem. |
77 | |
78 | #if defined(_TARGET_X86_) |
79 | // Finished ports - compile-time errors |
80 | #define PORTABILITY_WARNING(message) NEED_TO_PORT_THIS_ONE(NEED_TO_PORT_THIS_ONE) |
81 | #define PORTABILITY_ASSERT(message) NEED_TO_PORT_THIS_ONE(NEED_TO_PORT_THIS_ONE) |
82 | #else |
83 | // Ports in progress - run-time asserts only |
84 | #define PORTABILITY_WARNING(message) |
85 | #define PORTABILITY_ASSERT(message) _ASSERTE(false && message) |
86 | #endif |
87 | |
88 | #define DIRECTORY_SEPARATOR_CHAR_A '\\' |
89 | #define DIRECTORY_SEPARATOR_STR_A "\\" |
90 | #define DIRECTORY_SEPARATOR_CHAR_W W('\\') |
91 | #define DIRECTORY_SEPARATOR_STR_W W("\\") |
92 | |
93 | #define PATH_SEPARATOR_CHAR_W W(';') |
94 | #define PATH_SEPARATOR_STR_W W(";") |
95 | |
96 | #define VOLUME_SEPARATOR_CHAR_W W(':') |
97 | |
98 | // PAL Macros |
99 | // Not all compilers support fully anonymous aggregate types, so the |
100 | // PAL provides names for those types. To allow existing definitions of |
101 | // those types to continue to work, we provide macros that should be |
102 | // used to reference fields within those types. |
103 | |
104 | #ifndef DECIMAL_SCALE |
105 | #define DECIMAL_SCALE(dec) ((dec).scale) |
106 | #endif |
107 | |
108 | #ifndef DECIMAL_SIGN |
109 | #define DECIMAL_SIGN(dec) ((dec).sign) |
110 | #endif |
111 | |
112 | #ifndef DECIMAL_SIGNSCALE |
113 | #define DECIMAL_SIGNSCALE(dec) ((dec).signscale) |
114 | #endif |
115 | |
116 | #ifndef DECIMAL_LO32 |
117 | #define DECIMAL_LO32(dec) ((dec).Lo32) |
118 | #endif |
119 | |
120 | #ifndef DECIMAL_MID32 |
121 | #define DECIMAL_MID32(dec) ((dec).Mid32) |
122 | #endif |
123 | |
124 | #ifndef DECIMAL_HI32 |
125 | #define DECIMAL_HI32(dec) ((dec).Hi32) |
126 | #endif |
127 | |
128 | #ifndef DECIMAL_LO64_GET |
129 | #define DECIMAL_LO64_GET(dec) ((dec).Lo64) |
130 | #endif |
131 | |
132 | #ifndef DECIMAL_LO64_SET |
133 | #define DECIMAL_LO64_SET(dec,value) {(dec).Lo64 = value; } |
134 | #endif |
135 | |
136 | #ifndef IMAGE_RELOC_FIELD |
137 | #define IMAGE_RELOC_FIELD(img, f) ((img).f) |
138 | #endif |
139 | |
140 | #ifndef IMAGE_IMPORT_DESC_FIELD |
141 | #define IMAGE_IMPORT_DESC_FIELD(img, f) ((img).f) |
142 | #endif |
143 | |
144 | #define IMAGE_RDE_ID(img) ((img)->Id) |
145 | |
146 | #define IMAGE_RDE_NAME(img) ((img)->Name) |
147 | |
148 | #define IMAGE_RDE_OFFSET(img) ((img)->OffsetToData) |
149 | |
150 | #ifndef IMAGE_RDE_NAME_FIELD |
151 | #define IMAGE_RDE_NAME_FIELD(img, f) ((img)->f) |
152 | #endif |
153 | |
154 | #define IMAGE_RDE_OFFSET_FIELD(img, f) ((img)->f) |
155 | |
156 | #ifndef IMAGE_FE64_FIELD |
157 | #define IMAGE_FE64_FIELD(img, f) ((img).f) |
158 | #endif |
159 | |
160 | #ifndef IMPORT_OBJ_HEADER_FIELD |
161 | #define IMPORT_OBJ_HEADER_FIELD(obj, f) ((obj).f) |
162 | #endif |
163 | |
164 | #ifndef IMAGE_COR20_HEADER_FIELD |
165 | #define IMAGE_COR20_HEADER_FIELD(obj, f) ((obj).f) |
166 | #endif |
167 | |
168 | |
169 | // PAL Numbers |
170 | // Used to ensure cross-compiler compatibility when declaring large |
171 | // integer constants. 64-bit integer constants should be wrapped in the |
172 | // declarations listed here. |
173 | // |
174 | // Each of the #defines here is wrapped to avoid conflicts with pal.h. |
175 | |
176 | #if defined(_MSC_VER) |
177 | |
178 | // MSVC's way of declaring large integer constants |
179 | // If you define these in one step, without the _HELPER macros, you |
180 | // get extra whitespace when composing these with other concatenating macros. |
181 | #ifndef I64 |
182 | #define I64_HELPER(x) x ## i64 |
183 | #define I64(x) I64_HELPER(x) |
184 | #endif |
185 | |
186 | #ifndef UI64 |
187 | #define UI64_HELPER(x) x ## ui64 |
188 | #define UI64(x) UI64_HELPER(x) |
189 | #endif |
190 | |
191 | #else |
192 | |
193 | // GCC's way of declaring large integer constants |
194 | // If you define these in one step, without the _HELPER macros, you |
195 | // get extra whitespace when composing these with other concatenating macros. |
196 | #ifndef I64 |
197 | #define I64_HELPER(x) x ## LL |
198 | #define I64(x) I64_HELPER(x) |
199 | #endif |
200 | |
201 | #ifndef UI64 |
202 | #define UI64_HELPER(x) x ## ULL |
203 | #define UI64(x) UI64_HELPER(x) |
204 | #endif |
205 | |
206 | #endif |
207 | |
208 | |
209 | // PAL SEH |
210 | // Macros for portable exception handling. The Win32 SEH is emulated using |
211 | // these macros and setjmp/longjmp on Unix |
212 | // |
213 | // Usage notes: |
214 | // |
215 | // - The filter has to be a function taking two parameters: |
216 | // LONG MyFilter(PEXCEPTION_POINTERS *pExceptionInfo, PVOID pv) |
217 | // |
218 | // - It is not possible to directly use the local variables in the filter. |
219 | // All the local information that the filter has to need to know about should |
220 | // be passed through pv parameter |
221 | // |
222 | // - Do not use goto to jump out of the PAL_TRY block |
223 | // (jumping out of the try block is not a good idea even on Win32, because of |
224 | // it causes stack unwind) |
225 | // |
226 | // - It is not possible to directly use the local variables in the try block. |
227 | // All the local information that the filter has to need to know about should |
228 | // be passed through pv parameter |
229 | // |
230 | // |
231 | // Simple examples: |
232 | // |
233 | // struct Param { ... local variables used in try block and filter ... } param; |
234 | // PAL_TRY(Param *, pParam, ¶m) { // read as: Param *pParam = ¶m; |
235 | // .... |
236 | // } PAL_FINALLY { |
237 | // .... |
238 | // } |
239 | // PAL_ENDTRY |
240 | // |
241 | // |
242 | // struct Param { ... local variables used in try block and filter ... } param; |
243 | // PAL_TRY(Param *, pParam, ¶m) { |
244 | // .... |
245 | // } PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { |
246 | // .... |
247 | // } |
248 | // PAL_ENDTRY |
249 | // |
250 | // |
251 | // LONG MyFilter(PEXCEPTION_POINTERS *pExceptionInfo, PVOID pv) |
252 | // { |
253 | // ... |
254 | // } |
255 | // PAL_TRY(void *, unused, NULL) { |
256 | // .... |
257 | // } PAL_EXCEPT_FILTER(MyFilter) { |
258 | // .... |
259 | // } |
260 | // PAL_ENDTRY |
261 | // |
262 | // |
263 | // Complex example: |
264 | // |
265 | // struct MyParams |
266 | // { |
267 | // ... |
268 | // } params; |
269 | // |
270 | // PAL_TRY(MyParams *, pMyParamsOuter, ¶ms) { |
271 | // PAL_TRY(MyParams *, pMyParamsInnter, pMyParamsOuter) { |
272 | // ... |
273 | // if (error) goto Done; |
274 | // ... |
275 | // Done: ; |
276 | // } PAL_EXCEPT_FILTER(OtherFilter) { |
277 | // ... |
278 | // } |
279 | // PAL_ENDTRY |
280 | // } |
281 | // PAL_FINALLY { |
282 | // } |
283 | // PAL_ENDTRY |
284 | // |
285 | |
286 | #include "staticcontract.h" |
287 | |
288 | #define HardwareExceptionHolder |
289 | |
290 | // Note: PAL_SEH_RESTORE_GUARD_PAGE is only ever defined in clrex.h, so we only restore guard pages automatically |
291 | // when these macros are used from within the VM. |
292 | #define PAL_SEH_RESTORE_GUARD_PAGE |
293 | |
294 | #define PAL_TRY_NAKED \ |
295 | { \ |
296 | bool __exHandled; __exHandled = false; \ |
297 | DWORD __exCode; __exCode = 0; \ |
298 | SCAN_EHMARKER(); \ |
299 | __try \ |
300 | { \ |
301 | SCAN_EHMARKER_TRY(); |
302 | |
303 | #define PAL_EXCEPT_NAKED(Disposition) \ |
304 | } \ |
305 | __except(__exCode = GetExceptionCode(), Disposition) \ |
306 | { \ |
307 | __exHandled = true; \ |
308 | SCAN_EHMARKER_CATCH(); \ |
309 | PAL_SEH_RESTORE_GUARD_PAGE |
310 | |
311 | #define PAL_EXCEPT_FILTER_NAKED(pfnFilter, param) \ |
312 | } \ |
313 | __except(__exCode = GetExceptionCode(), \ |
314 | pfnFilter(GetExceptionInformation(), param)) \ |
315 | { \ |
316 | __exHandled = true; \ |
317 | SCAN_EHMARKER_CATCH(); \ |
318 | PAL_SEH_RESTORE_GUARD_PAGE |
319 | |
320 | #define PAL_FINALLY_NAKED \ |
321 | } \ |
322 | __finally \ |
323 | { \ |
324 | |
325 | #define PAL_ENDTRY_NAKED \ |
326 | } \ |
327 | PAL_ENDTRY_NAKED_DBG \ |
328 | } \ |
329 | |
330 | |
331 | #if defined(_DEBUG) && !defined(DACCESS_COMPILE) |
332 | // |
333 | // In debug mode, compile the try body as a method of a local class. |
334 | // This way, the compiler will check that the body is not directly |
335 | // accessing any local variables and arguments. |
336 | // |
337 | #define PAL_TRY(__ParamType, __paramDef, __paramRef) \ |
338 | { \ |
339 | __ParamType __param = __paramRef; \ |
340 | __ParamType __paramToPassToFilter = __paramRef; \ |
341 | class __Body \ |
342 | { \ |
343 | public: \ |
344 | static void Run(__ParamType __paramDef) \ |
345 | { \ |
346 | PAL_TRY_HANDLER_DBG_BEGIN |
347 | |
348 | // PAL_TRY implementation that abstracts usage of COMPILER_INSTANCE*, which is used by |
349 | // JIT64. On Windows, we dont need to do anything special as we dont have nested classes/methods |
350 | // as on PAL. |
351 | #define PAL_TRY_CI(__ParamType, __paramDef, __paramRef) \ |
352 | { \ |
353 | struct __HandlerData { \ |
354 | __ParamType __param; \ |
355 | COMPILER_INSTANCE *__ciPtr; \ |
356 | }; \ |
357 | __HandlerData handlerData; \ |
358 | handlerData.__param = __paramRef; \ |
359 | handlerData.__ciPtr = ciPtr; \ |
360 | __HandlerData* __param = &handlerData; \ |
361 | __ParamType __paramToPassToFilter = __paramRef; \ |
362 | class __Body \ |
363 | { \ |
364 | public: \ |
365 | static void Run(__HandlerData* __pHandlerData) \ |
366 | { \ |
367 | PAL_TRY_HANDLER_DBG_BEGIN \ |
368 | COMPILER_INSTANCE *ciPtr = __pHandlerData->__ciPtr; \ |
369 | __ParamType __paramDef = __pHandlerData->__param; |
370 | |
371 | |
372 | #define PAL_TRY_FOR_DLLMAIN(__ParamType, __paramDef, __paramRef, __reason) \ |
373 | { \ |
374 | __ParamType __param = __paramRef; \ |
375 | __ParamType __paramToPassToFilter = __paramRef; \ |
376 | class __Body \ |
377 | { \ |
378 | public: \ |
379 | static void Run(__ParamType __paramDef) \ |
380 | { \ |
381 | PAL_TRY_HANDLER_DBG_BEGIN_DLLMAIN(__reason) |
382 | |
383 | #define PAL_EXCEPT(Disposition) \ |
384 | PAL_TRY_HANDLER_DBG_END \ |
385 | } \ |
386 | }; \ |
387 | PAL_TRY_NAKED \ |
388 | __Body::Run(__param); \ |
389 | PAL_EXCEPT_NAKED(Disposition) |
390 | |
391 | #define PAL_EXCEPT_FILTER(pfnFilter) \ |
392 | PAL_TRY_HANDLER_DBG_END \ |
393 | } \ |
394 | }; \ |
395 | PAL_TRY_NAKED \ |
396 | __Body::Run(__param); \ |
397 | PAL_EXCEPT_FILTER_NAKED(pfnFilter, __paramToPassToFilter) |
398 | |
399 | #define PAL_FINALLY \ |
400 | PAL_TRY_HANDLER_DBG_END \ |
401 | } \ |
402 | }; \ |
403 | PAL_TRY_NAKED \ |
404 | __Body::Run(__param); \ |
405 | PAL_FINALLY_NAKED |
406 | |
407 | #define PAL_ENDTRY \ |
408 | PAL_ENDTRY_NAKED \ |
409 | } |
410 | |
411 | #else // _DEBUG |
412 | |
413 | #define PAL_TRY(__ParamType, __paramDef, __paramRef) \ |
414 | { \ |
415 | __ParamType __param = __paramRef; \ |
416 | __ParamType __paramDef = __param; \ |
417 | PAL_TRY_NAKED \ |
418 | PAL_TRY_HANDLER_DBG_BEGIN |
419 | |
420 | // PAL_TRY implementation that abstracts usage of COMPILER_INSTANCE*, which is used by |
421 | // JIT64. On Windows, we dont need to do anything special as we dont have nested classes/methods |
422 | // as on PAL. |
423 | #define PAL_TRY_CI(__ParamType, __paramDef, __paramRef) PAL_TRY(__ParamType, __paramDef, __paramRef) |
424 | |
425 | #define PAL_TRY_FOR_DLLMAIN(__ParamType, __paramDef, __paramRef, __reason) \ |
426 | { \ |
427 | __ParamType __param = __paramRef; \ |
428 | __ParamType __paramDef; __paramDef = __param; \ |
429 | PAL_TRY_NAKED \ |
430 | PAL_TRY_HANDLER_DBG_BEGIN_DLLMAIN(__reason) |
431 | |
432 | #define PAL_EXCEPT(Disposition) \ |
433 | PAL_TRY_HANDLER_DBG_END \ |
434 | PAL_EXCEPT_NAKED(Disposition) |
435 | |
436 | #define PAL_EXCEPT_FILTER(pfnFilter) \ |
437 | PAL_TRY_HANDLER_DBG_END \ |
438 | PAL_EXCEPT_FILTER_NAKED(pfnFilter, __param) |
439 | |
440 | #define PAL_FINALLY \ |
441 | PAL_TRY_HANDLER_DBG_END \ |
442 | PAL_FINALLY_NAKED |
443 | |
444 | #define PAL_ENDTRY \ |
445 | PAL_ENDTRY_NAKED \ |
446 | } |
447 | |
448 | #endif // _DEBUG |
449 | |
450 | // Executes the handler if the specified exception code matches |
451 | // the one in the exception. Otherwise, returns EXCEPTION_CONTINUE_SEARCH. |
452 | #define PAL_EXCEPT_IF_EXCEPTION_CODE(dwExceptionCode) PAL_EXCEPT((GetExceptionCode() == dwExceptionCode)?EXCEPTION_EXECUTE_HANDLER:EXCEPTION_CONTINUE_SEARCH) |
453 | |
454 | #define PAL_CPP_TRY try |
455 | #define PAL_CPP_ENDTRY |
456 | #define PAL_CPP_THROW(type, obj) do { SCAN_THROW_MARKER; throw obj; } while (false) |
457 | #define PAL_CPP_RETHROW do { SCAN_THROW_MARKER; throw; } while (false) |
458 | #define PAL_CPP_CATCH_DERIVED(type, obj) catch (type * obj) |
459 | #define PAL_CPP_CATCH_ALL catch (...) |
460 | #define PAL_CPP_CATCH_EXCEPTION_NOARG catch (Exception *) |
461 | |
462 | |
463 | // SELECTANY macro is intended to prevent duplication of static const |
464 | // arrays declared in .h files in binary modules. |
465 | // The problem is that const variables have static internal linkage |
466 | // in C++. That means that if a const variable is declared in a .h file |
467 | // the compiler will emit it into every translation unit that uses that .h file. |
468 | // That will cause duplication of the data when those translation units |
469 | // are linked into a binary module. |
470 | // SELECTANY declares a variable as extern to give it external linkage |
471 | // and it provides __declspec(selectany) to instruct the linker to merge |
472 | // duplicate external const static data copies into one. |
473 | // |
474 | #if defined(SOURCE_FORMATTING) |
475 | #define SELECTANY extern |
476 | #else |
477 | #define SELECTANY extern __declspec(selectany) |
478 | #endif |
479 | #if defined(SOURCE_FORMATTING) |
480 | #define __annotation(x) |
481 | #endif |
482 | |
483 | |
484 | #if defined(_DEBUG_IMPL) && !defined(JIT_BUILD) && !defined(JIT64_BUILD) && !defined(CROSS_COMPILE) && !defined(_TARGET_ARM_) // @ARMTODO: no contracts for speed |
485 | #define PAL_TRY_HANDLER_DBG_BEGIN \ |
486 | BOOL ___oldOkayToThrowValue = FALSE; \ |
487 | SO_INFRASTRUCTURE_CODE(BOOL ___oldSOTolerantState = FALSE;) \ |
488 | ClrDebugState *___pState = ::GetClrDebugState(); \ |
489 | __try \ |
490 | { \ |
491 | ___oldOkayToThrowValue = ___pState->IsOkToThrow(); \ |
492 | SO_INFRASTRUCTURE_CODE(___oldSOTolerantState = ___pState->IsSOTolerant();) \ |
493 | ___pState->SetOkToThrow(); \ |
494 | PAL_ENTER_THROWS_REGION; |
495 | |
496 | // Special version that avoids touching the debug state after doing work in a DllMain for process or thread detach. |
497 | #define PAL_TRY_HANDLER_DBG_BEGIN_DLLMAIN(_reason) \ |
498 | BOOL ___oldOkayToThrowValue = FALSE; \ |
499 | SO_INFRASTRUCTURE_CODE(BOOL ___oldSOTolerantState = FALSE;) \ |
500 | ClrDebugState *___pState = NULL; \ |
501 | if (_reason != DLL_PROCESS_ATTACH) \ |
502 | ___pState = CheckClrDebugState(); \ |
503 | __try \ |
504 | { \ |
505 | if (___pState) \ |
506 | { \ |
507 | ___oldOkayToThrowValue = ___pState->IsOkToThrow(); \ |
508 | SO_INFRASTRUCTURE_CODE(___oldSOTolerantState = ___pState->IsSOTolerant();) \ |
509 | ___pState->SetOkToThrow(); \ |
510 | } \ |
511 | if ((_reason == DLL_PROCESS_DETACH) || (_reason == DLL_THREAD_DETACH)) \ |
512 | { \ |
513 | ___pState = NULL; \ |
514 | } \ |
515 | PAL_ENTER_THROWS_REGION; |
516 | |
517 | #define PAL_TRY_HANDLER_DBG_END \ |
518 | PAL_LEAVE_THROWS_REGION \ |
519 | } \ |
520 | __finally \ |
521 | { \ |
522 | if (___pState != NULL) \ |
523 | { \ |
524 | _ASSERTE(___pState == CheckClrDebugState()); \ |
525 | ___pState->SetOkToThrow( ___oldOkayToThrowValue ); \ |
526 | SO_INFRASTRUCTURE_CODE(___pState->SetSOTolerance( ___oldSOTolerantState );) \ |
527 | } \ |
528 | } |
529 | |
530 | #define PAL_ENDTRY_NAKED_DBG \ |
531 | if (__exHandled) \ |
532 | { \ |
533 | RESTORE_SO_TOLERANCE_STATE; \ |
534 | } \ |
535 | |
536 | #else |
537 | #define PAL_TRY_HANDLER_DBG_BEGIN ANNOTATION_TRY_BEGIN; |
538 | #define PAL_TRY_HANDLER_DBG_BEGIN_DLLMAIN(_reason) ANNOTATION_TRY_BEGIN; |
539 | #define PAL_TRY_HANDLER_DBG_END ANNOTATION_TRY_END; |
540 | #define PAL_ENDTRY_NAKED_DBG |
541 | #endif // defined(ENABLE_CONTRACTS_IMPL) && !defined(JIT64_BUILD) |
542 | |
543 | |
544 | #if !BIGENDIAN |
545 | // For little-endian machines, do nothing |
546 | #define VAL16(x) x |
547 | #define VAL32(x) x |
548 | #define VAL64(x) x |
549 | #define SwapString(x) |
550 | #define SwapStringLength(x, y) |
551 | #define SwapGuid(x) |
552 | #endif // !BIGENDIAN |
553 | |
554 | #ifdef _MSC_VER |
555 | // Get Unaligned values from a potentially unaligned object |
556 | #define GET_UNALIGNED_16(_pObject) (*(UINT16 UNALIGNED *)(_pObject)) |
557 | #define GET_UNALIGNED_32(_pObject) (*(UINT32 UNALIGNED *)(_pObject)) |
558 | #define GET_UNALIGNED_64(_pObject) (*(UINT64 UNALIGNED *)(_pObject)) |
559 | |
560 | // Set Value on an potentially unaligned object |
561 | #define SET_UNALIGNED_16(_pObject, _Value) (*(UNALIGNED UINT16 *)(_pObject)) = (UINT16)(_Value) |
562 | #define SET_UNALIGNED_32(_pObject, _Value) (*(UNALIGNED UINT32 *)(_pObject)) = (UINT32)(_Value) |
563 | #define SET_UNALIGNED_64(_pObject, _Value) (*(UNALIGNED UINT64 *)(_pObject)) = (UINT64)(_Value) |
564 | |
565 | // Get Unaligned values from a potentially unaligned object and swap the value |
566 | #define GET_UNALIGNED_VAL16(_pObject) VAL16(GET_UNALIGNED_16(_pObject)) |
567 | #define GET_UNALIGNED_VAL32(_pObject) VAL32(GET_UNALIGNED_32(_pObject)) |
568 | #define GET_UNALIGNED_VAL64(_pObject) VAL64(GET_UNALIGNED_64(_pObject)) |
569 | |
570 | // Set a swap Value on an potentially unaligned object |
571 | #define SET_UNALIGNED_VAL16(_pObject, _Value) SET_UNALIGNED_16(_pObject, VAL16((UINT16)_Value)) |
572 | #define SET_UNALIGNED_VAL32(_pObject, _Value) SET_UNALIGNED_32(_pObject, VAL32((UINT32)_Value)) |
573 | #define SET_UNALIGNED_VAL64(_pObject, _Value) SET_UNALIGNED_64(_pObject, VAL64((UINT64)_Value)) |
574 | #endif |
575 | |
576 | #ifdef _WIN64 |
577 | #define VALPTR(x) VAL64(x) |
578 | #define GET_UNALIGNED_PTR(x) GET_UNALIGNED_64(x) |
579 | #define GET_UNALIGNED_VALPTR(x) GET_UNALIGNED_VAL64(x) |
580 | #define SET_UNALIGNED_PTR(p,x) SET_UNALIGNED_64(p,x) |
581 | #define SET_UNALIGNED_VALPTR(p,x) SET_UNALIGNED_VAL64(p,x) |
582 | #else |
583 | #define VALPTR(x) VAL32(x) |
584 | #define GET_UNALIGNED_PTR(x) GET_UNALIGNED_32(x) |
585 | #define GET_UNALIGNED_VALPTR(x) GET_UNALIGNED_VAL32(x) |
586 | #define SET_UNALIGNED_PTR(p,x) SET_UNALIGNED_32(p,x) |
587 | #define SET_UNALIGNED_VALPTR(p,x) SET_UNALIGNED_VAL32(p,x) |
588 | #endif |
589 | |
590 | #define MAKEDLLNAME_W(name) name W(".dll") |
591 | #define MAKEDLLNAME_A(name) name ".dll" |
592 | |
593 | #ifdef UNICODE |
594 | #define MAKEDLLNAME(x) MAKEDLLNAME_W(x) |
595 | #else |
596 | #define MAKEDLLNAME(x) MAKEDLLNAME_A(x) |
597 | #endif |
598 | |
599 | #if !defined(MAX_LONGPATH) |
600 | #define MAX_LONGPATH 260 /* max. length of full pathname */ |
601 | #endif |
602 | #if !defined(MAX_PATH_FNAME) |
603 | #define MAX_PATH_FNAME MAX_PATH /* max. length of full pathname */ |
604 | #endif |
605 | |
606 | #define __clr_reserved __reserved |
607 | |
608 | #endif // __PALCLR_H__ |
609 | |
610 | #include "palclr_win.h" |
611 | |
612 | #endif // !defined(FEATURE_PAL) |
613 | |