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.
5 /******************************************************************
7 * intsafe.h -- This module defines helper functions to prevent *
8 * integer overflow issues. *
11 ******************************************************************/
12 #ifndef _INTSAFE_H_INCLUDED_
13 #define _INTSAFE_H_INCLUDED_
19 #include <specstrings.h> // for IN, etc.
26 #define UnsignedMultiply128 _umul128
29 IN ULONG64 Multiplier,
30 IN ULONG64 Multiplicand,
31 OUT ULONG64 *HighProduct
34 #pragma intrinsic(_umul128)
44 typedef unsigned __int64 size_t;
45 typedef unsigned __int64 UINT_PTR;
46 typedef unsigned __int64 ULONG_PTR;
47 typedef unsigned __int64 DWORD_PTR;
48 typedef unsigned __int64 SIZE_T;
50 typedef __w64 unsigned int size_t;
51 typedef __w64 unsigned int UINT_PTR;
52 typedef __w64 unsigned long ULONG_PTR;
53 typedef __w64 unsigned long DWORD_PTR;
54 typedef __w64 unsigned long SIZE_T;
59 typedef unsigned char UCHAR;
60 typedef unsigned short USHORT;
61 typedef unsigned short WORD;
62 typedef unsigned int UINT;
63 typedef unsigned long ULONG;
64 typedef unsigned long DWORD;
65 typedef unsigned __int64 ULONGLONG;
71 #define SUCCEEDED(hr) (((HRESULT)(hr)) >= 0)
75 #define FAILED(hr) (((HRESULT)(hr)) < 0)
78 #define S_OK ((HRESULT)0x00000000L)
80 #endif // !FEATURE_PAL
82 #define INTSAFE_E_ARITHMETIC_OVERFLOW ((HRESULT)0x80070216L) // 0x216 = 534 = ERROR_ARITHMETIC_OVERFLOW
85 #define LOWORD(l) ((WORD)(((DWORD_PTR)(l)) & 0xffff))
89 #define HIWORD(l) ((WORD)(((DWORD_PTR)(l)) >> 16))
92 #define HIDWORD(_qw) ((ULONG)((_qw) >> 32))
93 #define LODWORD(_qw) ((ULONG)(_qw))
95 #if defined(MIDL_PASS) || defined(RC_INVOKED) || defined(_M_CEE_PURE) \
96 || defined(_68K_) || defined(_MPPC_) || defined(_PPC_) \
97 || defined(_M_IA64) || defined(_M_AMD64) || defined(__ARM_ARCH)
100 #define UInt32x32To64(a, b) ((unsigned __int64)((ULONG)(a)) * (unsigned __int64)((ULONG)(b)))
103 #elif defined(_M_IX86)
105 #ifndef UInt32x32To64
106 #define UInt32x32To64(a, b) (unsigned __int64)((unsigned __int64)(ULONG)(a) * (ULONG)(b))
111 #error Must define a target architecture.
115 #define INT_MAX 2147483647
116 #define LONG_MAX 2147483647L
117 #define USHRT_MAX 0xffff
118 #define UINT_MAX 0xffffffff
119 #define ULONG_MAX 0xffffffffUL
120 #define DWORD_MAX 0xffffffffUL
123 // It is common for -1 to be used as an error value for various types
125 #define USHORT_ERROR (0xffff)
126 #define INT_ERROR (-1)
127 #define LONG_ERROR (-1L)
128 #define UINT_ERROR (0xffffffff)
129 #define ULONG_ERROR (0xffffffffUL)
131 #define ULONGLONG_ERROR (0xffffffffffffffffui64)
132 #define HIDWORD_MASK (0xffffffff00000000ui64)
134 #define ULONGLONG_ERROR (0xffffffffffffffffULL)
135 #define HIDWORD_MASK (0xffffffff00000000ULL)
138 #define SIZET_ERROR ULONGLONG_ERROR
140 #define SIZET_ERROR ULONG_ERROR
144 // We make some assumptions about the sizes of various types. Let's be
145 // explicit about those assumptions and check them.
147 C_ASSERT(sizeof(unsigned short) == 2);
148 C_ASSERT(sizeof(unsigned int) == 4);
149 C_ASSERT(sizeof(ULONG) == 4);
152 // INT -> signed char conversion
158 OUT signed char* pch)
160 HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
163 if ((iOperand >= -128) && (iOperand <= 127))
165 *pch = (signed char)iOperand;
173 // INT -> UCHAR conversion
181 HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
184 if ((iOperand >= 0) && (iOperand <= 255))
186 *pch = (UCHAR)iOperand;
194 // LONG -> UCHAR conversion
202 HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
205 if ((lOperand >= 0) && (lOperand <= 255))
207 *pch = (UCHAR)lOperand;
215 // __inline is not sufficient. __forceinline is necessary.
216 // If the function is not inlined and you link .objs compiled with different compiler switches,
217 // you get one or the other function arbitrarily chosen.
219 // INT -> CHAR conversion
227 #ifdef _CHAR_UNSIGNED
228 return IntToUChar(iOperand, (UCHAR*)pch);
230 return IntToSignedChar(iOperand, (signed char*)pch);
235 // INT -> USHORT conversion
241 OUT USHORT* pusResult)
243 HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
244 *pusResult = USHORT_ERROR;
246 if ((iOperand >= 0) && (iOperand <= USHRT_MAX))
248 *pusResult = (USHORT)iOperand;
256 // INT -> UINT conversion
264 HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
265 *puResult = UINT_ERROR;
269 *puResult = (UINT)iOperand;
277 // INT -> ULONG conversion
283 OUT ULONG* pulResult)
285 HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
286 *pulResult = ULONG_ERROR;
290 *pulResult = (ULONG)iOperand;
298 // INT -> ULONGLONG conversion
304 OUT ULONGLONG* pullResult)
306 HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
307 *pullResult = ULONG_ERROR;
311 *pullResult = (ULONGLONG)iOperand;
319 // UINT -> signed char conversion
325 OUT signed char* pch)
327 HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
332 *pch = (signed char)uOperand;
340 // UINT -> UCHAR conversion
348 HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
353 *pch = (UCHAR)uOperand;
361 // UINT -> BYTE conversion
363 #define UIntToByte UIntToUChar
366 // __inline is not sufficient. __forceinline is necessary.
367 // If the function is not inlined and you link .objs compiled with different compiler switches,
368 // you get one or the other function arbitrarily chosen.
370 // UINT -> CHAR conversion
378 #ifdef _CHAR_UNSIGNED
379 return UIntToUChar(uOperand, (UCHAR*)pch);
381 return UIntToSignedChar(uOperand, (signed char*)pch);
382 #endif // _CHAR_UNSIGNED
386 // UINT -> INT conversion
394 HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
395 *piResult = INT_ERROR;
397 if (uOperand <= INT_MAX)
399 *piResult = (INT)uOperand;
407 // UINT -> LONG conversion
415 if (Operand <= LONG_MAX)
417 *Result = (LONG)Operand;
422 *Result = LONG_ERROR;
423 return INTSAFE_E_ARITHMETIC_OVERFLOW;
428 // UINT -> ULONG conversion
434 OUT ULONG* pulResult)
436 *pulResult = (ULONG)uOperand;
442 // ULONG -> UCHAR conversion
448 OUT signed char* pch)
450 HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
453 if (ulOperand <= 127)
455 *pch = (signed char)ulOperand;
463 // ULONG -> UCHAR conversion
469 OUT unsigned char* pch)
471 HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
474 if (ulOperand <= 255)
476 *pch = (unsigned char)ulOperand;
484 // __inline is not sufficient. __forceinline is necessary.
485 // If the function is not inlined and you link .objs compiled with different compiler switches,
486 // you get one or the other function arbitrarily chosen.
488 // ULONG -> CHAR conversion
496 #ifdef _CHAR_UNSIGNED
497 return ULongToUChar(ulOperand, (unsigned char*)pch);
499 return ULongToSignedChar(ulOperand, (signed char*)pch);
500 #endif // _CHAR_UNSIGNED
504 // ULONG -> USHORT conversion
510 OUT USHORT* pusResult)
512 HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
513 *pusResult = USHORT_ERROR;
515 if (ulOperand <= USHRT_MAX)
517 *pusResult = (USHORT)ulOperand;
525 // ULONG -> INT conversion
533 if (ulOperand <= INT_MAX)
535 *piResult = (INT)ulOperand;
540 *piResult = INT_ERROR;
541 return INTSAFE_E_ARITHMETIC_OVERFLOW;
546 // ULONG -> UINT conversion
554 *puResult = (UINT)ulOperand;
560 // ULONG -> LONG conversion
568 if (Operand <= LONG_MAX)
570 *Result = (LONG)Operand;
575 *Result = LONG_ERROR;
576 return INTSAFE_E_ARITHMETIC_OVERFLOW;
581 // ULONGLONG -> INT conversion
586 IN ULONGLONG ullOperand,
589 if (ullOperand <= INT_MAX)
591 *piResult = (INT)ullOperand;
596 *piResult = INT_ERROR;
597 return INTSAFE_E_ARITHMETIC_OVERFLOW;
602 // ULONGLONG -> LONG conversion
607 IN ULONGLONG Operand,
610 if (Operand <= LONG_MAX)
612 *Result = (LONG)Operand;
617 *Result = LONG_ERROR;
618 return INTSAFE_E_ARITHMETIC_OVERFLOW;
623 // UINT -> USHORT conversion
629 OUT USHORT* pusResult)
631 HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
632 *pusResult = USHORT_ERROR;
634 if (uOperand <= USHRT_MAX)
636 *pusResult = (USHORT)uOperand;
644 // ULONGLONG -> USHORT conversion
649 IN ULONGLONG ullOperand,
650 OUT USHORT* pusResult)
652 HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
653 USHORT usResult = USHORT_ERROR;
655 if (ullOperand <= USHRT_MAX)
657 usResult = (USHORT)ullOperand;
660 *pusResult = usResult;
666 // ULONGLONG -> ULONG conversion
671 IN ULONGLONG ullOperand,
672 OUT ULONG* pulResult)
674 HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
675 *pulResult = ULONG_ERROR;
677 if (ullOperand <= ULONG_MAX)
679 *pulResult = (ULONG)ullOperand;
687 // UINT_PTR -> ULONG conversion
688 // ULONG_PTR -> ULONG conversion
692 #define UIntPtrToULong ULongLongToULong
693 #define ULongPtrToULong ULongLongToULong
703 *pResult = (ULONG)Operand;
710 IN ULONG_PTR Operand,
713 *pResult = (ULONG)Operand;
720 // ULONGLONG -> UINT conversion
725 IN ULONGLONG ullOperand,
728 HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
729 *puResult = UINT_ERROR;
731 if (ullOperand <= UINT_MAX)
733 *puResult = (UINT)ullOperand;
741 // UINT_PTR -> UINT conversion
742 // ULONG_PTR -> UINT conversion
746 #define UIntPtrToUInt ULongLongToUInt
747 #define ULongPtrToUInt ULongLongToUInt
757 *pResult = (UINT)Operand;
764 IN ULONG_PTR Operand,
767 *pResult = (UINT)Operand;
774 // * -> BYTE conversion (BYTE is always unsigned char)
776 #define IntToByte IntToUChar
777 #define UIntToByte UIntToUChar
778 #define LongToByte LongToUChar
779 #define ULongToByte ULongToUChar
782 // * -> WORD conversion (WORD is always unsigned short)
784 #define IntToWord IntToUShort
785 #define LongToWord LongToUShort
786 #define LongLongToWord LongLongToUShort
787 #define UIntToWord UIntToUShort
788 #define ULongToWord ULongToUShort
789 #define ULongLongToWord ULongLongToUShort
790 #define UIntPtrToWord UIntPtrToUShort
791 #define ULongPtrToWord ULongPtrToUShort
792 #define SizeTToWord SizeTToUShort
793 #define SIZETToWord SIZETToUShort
796 // WORD -> * conversion (WORD is always unsigned short)
798 #define WordToUChar UShortToUChar
799 #define WordToByte UShortToByte
800 #define WordToChar UShortToChar
801 #define WordToSignedChar UShortToSignedChar
802 #define WordToInt UShortToInt
803 #define WordToLong UShortToLong
804 #define WordToLongLong UShortToLongLong
805 #define WordToIntPtr UShortToIntPtr
806 #define WordToLongPtr UShortToLongPtr
809 // * -> DWORD conversion (DWORD is always ULONG)
811 #define CharToDWord CharToULong
812 #define SignedCharToDWord SignedCharToULong
813 #define ShortToDWord ShortToULong
814 #define IntToDWord IntToULong
815 #define LongToDWord LongToULong
816 #define LongLongToDWord LongLongToULong
817 #define UIntToDWord UIntToULong
818 #define ULongLongToDWord ULongLongToULong
819 #define IntPtrToDWord IntPtrToULong
820 #define LongPtrToDWord LongPtrToULong
821 #define UIntPtrToDWord UIntPtrToULong
822 #define ULongPtrToDWord ULongPtrToULong
823 #define SizeTToDWord SizeTToULong
824 #define SIZETToDWord SIZETToULong
827 // DWORD -> * conversion (DWORD is always ULONG)
829 #define DWordToChar ULongToChar
830 #define DWordToUChar ULongToUChar
831 #define DWordToByte ULongToByte
832 #define DWordToSignedChar ULongToSignedChar
833 #define DWordToUShort ULongToUShort
834 #define DWordToUInt ULongToUInt
835 #define DWordToInt ULongToInt
836 #define DWordToLong ULongToLong
837 #define DWordToLongLong ULongToLongLong
838 #define DWordToIntPtr ULongToIntPtr
839 #define DWordToLongPtr ULongToLongPtr
843 // * -> UINT_PTR conversion (UINT_PTR is UINT on Win32, ULONGLONG on Win64)
846 #define CharToUIntPtr CharToULongLong
847 #define SignedCharToUIntPtr SignedCharToULongLong
848 #define ShortToUIntPtr ShortToULongLong
849 #define IntToUIntPtr IntToULongLong
850 #define LongToUIntPtr LongToULongLong
851 #define LongLongToUIntPtr LongLongToULongLong
852 #define IntPtrToUIntPtr IntPtrToULongLong
853 #define LongPtrToUIntPtr LongPtrToULongLong
855 #define CharToUIntPtr CharToUInt
856 #define SignedCharToUIntPtr SignedCharToUInt
857 #define ShortToUIntPtr ShortToUInt
863 OUT UINT_PTR* puResult)
865 return IntToUInt(iOperand, (UINT*)puResult);
868 #define LongToUIntPtr LongToUInt
869 #define LongLongToUIntPtr LongLongToUInt
871 #define IntPtrToUIntPtr IntPtrToUInt
872 #define LongPtrToUIntPtr LongPtrToUInt
878 IN ULONGLONG ullOperand,
879 OUT UINT_PTR* puResult)
882 *puResult = ullOperand;
885 return ULongLongToUInt(ullOperand, (UINT*)puResult);
891 // UINT_PTR -> * conversion (UINT_PTR is UINT on Win32, ULONGLONG on Win64)
894 #define UIntPtrToUShort ULongLongToUShort
895 #define UIntPtrToInt ULongLongToInt
896 #define UIntPtrToLong ULongLongToLong
897 #define UIntPtrToLongLong ULongLongToLongLong
898 #define UIntPtrToIntPtr ULongLongToIntPtr
899 #define UIntPtrToLongPtr ULongLongToLongPtr
905 IN UINT_PTR uOperand,
906 OUT USHORT* pusResult)
908 return UIntToUShort((UINT)uOperand, pusResult);
914 IN UINT_PTR uOperand,
917 return UIntToInt((UINT)uOperand, piResult);
926 return UIntToLong((UINT)Operand, Result);
929 #define UIntPtrToLongLong UIntToLongLong
930 #define UIntPtrToIntPtr UIntToIntPtr
931 #define UIntPtrToLongPtr UIntToLongPtr
936 // * -> ULONG_PTR conversion (ULONG_PTR is ULONG on Win32, ULONGLONG on Win64)
939 #define CharToULongPtr CharToULongLong
940 #define SignedCharToULongPtr SignedCharToULongLong
941 #define ShortToULongPtr ShortToULongLong
942 #define IntToULongPtr IntToULongLong
943 #define LongToULongPtr LongToULongLong
944 #define LongLongToULongPtr LongLongToULongLong
945 #define IntPtrToULongPtr IntPtrToULongLong
946 #define LongPtrToULongPtr LongPtrToULongLong
948 #define CharToULongPtr CharToULong
949 #define SignedCharToULongPtr SignedCharToULong
950 #define ShortToULongPtr ShortToULong
956 OUT ULONG_PTR* pulResult)
958 return IntToULong(iOperand, (ULONG*)pulResult);
961 #define LongToULongPtr LongToULong
962 #define LongLongToULongPtr LongLongToULong
964 #define IntPtrToULongPtr IntPtrToULong
965 #define LongPtrToULongPtr LongPtrToULong
971 IN ULONGLONG ullOperand,
972 OUT ULONG_PTR* pulResult)
975 *pulResult = ullOperand;
978 return ULongLongToULong(ullOperand, (ULONG*)pulResult);
984 // ULONG_PTR -> * conversion (ULONG_PTR is ULONG on Win32, ULONGLONG on Win64)
987 #define ULongPtrToUShort ULongLongToUShort
988 #define ULongPtrToInt ULongLongToInt
989 #define ULongPtrToLong ULongLongToLong
990 #define ULongPtrToLongLong ULongLongToLongLong
991 #define ULongPtrToIntPtr ULongLongToIntPtr
992 #define ULongPtrToLongPtr ULongLongToLongPtr
998 IN ULONG_PTR ulOperand,
999 OUT USHORT* pusResult)
1001 return ULongToUShort((ULONG)ulOperand, pusResult);
1007 IN ULONG_PTR ulOperand,
1010 return ULongToInt((ULONG)ulOperand, piResult);
1016 IN ULONG_PTR Operand,
1019 return ULongToLong((ULONG)Operand, Result);
1022 #define ULongPtrToLongLong ULongToLongLong
1023 #define ULongPtrToIntPtr ULongToIntPtr
1024 #define ULongPtrToLongPtr ULongToLongPtr
1028 // * -> size_t conversion (size_t is always UINT_PTR)
1030 #define CharToSizeT CharToUIntPtr
1031 #define SignedCharToSizeT SignedCharToUIntPtr
1032 #define ShortToSizeT ShortToUIntPtr
1033 #define IntToSizeT IntToUIntPtr
1034 #define LongToSizeT LongToUIntPtr
1035 #define LongLongToSizeT LongLongToUIntPtr
1036 #define ULongLongToSizeT ULongLongToUIntPtr
1037 #define IntPtrToSizeT IntPtrToUIntPtr
1038 #define LongPtrToSizeT LongPtrToUIntPtr
1041 // size_t -> * conversion (size_t is always UINT_PTR)
1043 #define SizeTToUShort UIntPtrToUShort
1044 #define SizeTToUInt UIntPtrToUInt
1045 #define SizeTToULong UIntPtrToULong
1046 #define SizeTToInt UIntPtrToInt
1047 #define SizeTToLong UIntPtrToLong
1048 #define SizeTToLongLong UIntPtrToLongLong
1049 #define SizeTToIntPtr UIntPtrToIntPtr
1050 #define SizeTToLongPtr UIntPtrToLongPtr
1053 // * -> SIZE_T conversion (SIZE_T is always ULONG_PTR)
1055 #define CharToSIZET CharToULongPtr
1056 #define SignedCharToSIZET SignedCharToULongPtr
1057 #define ShortToSIZET ShortToULongPtr
1058 #define IntToSIZET IntToULongPtr
1059 #define LongToSIZET LongToULongPtr
1060 #define LongLongToSIZET LongLongToULongPtr
1061 #define IntPtrToSIZET IntPtrToULongPtr
1062 #define LongPtrToSIZET LongPtrToULongPtr
1063 #define ULongLongToSIZET ULongLongToULongPtr
1066 // SIZE_T -> * conversion (SIZE_T is always ULONG_PTR)
1068 #define SIZETToUShort ULongPtrToUShort
1069 #define SIZETToUInt ULongPtrToUInt
1070 #define SIZETToULong ULongPtrToULong
1071 #define SIZETToUIntPtr ULongPtrToUIntPtr
1072 #define SIZETToULongPtr ULongPtrToULongPtr
1073 #define SIZETToInt ULongPtrToInt
1074 #define SIZETToLong ULongPtrToLong
1075 #define SIZETToLongLong ULongPtrToLongLong
1076 #define SIZETToIntPtr ULongPtrToIntPtr
1077 #define SIZETToLongPtr ULongPtrToLongPtr
1080 // * -> DWORD_PTR conversion (DWORD_PTR is always ULONG_PTR)
1082 #define CharToDWordPtr CharToULongPtr
1083 #define SignedCharToDWordPtr SignedCharToULongPtr
1084 #define ShortToDWordPtr ShortToULongPtr
1085 #define IntToDWordPtr IntToULongPtr
1086 #define LongToDWordPtr LongToULongPtr
1087 #define LongLongToDWordPtr LongLongToULongPtr
1088 #define ULongLongToDWordPtr ULongLongToULongPtr
1089 #define IntPtrToDWordPtr IntPtrToULongPtr
1090 #define LongPtrToDWordPtr LongPtrToULongPtr
1093 // DWORD_PTR -> * conversion (DWORD_PTR is always ULONG_PTR)
1095 #define DWordPtrToUShort ULongPtrToUShort
1096 #define DWordPtrToUInt ULongPtrToUInt
1097 #define DWordPtrToULong ULongPtrToULong
1098 #define DWordPtrToDWord ULongPtrToDWord
1099 #define DWordPtrToInt ULongPtrToInt
1100 #define DWordPtrToLong ULongPtrToLong
1101 #define DWordPtrToLongLong ULongPtrToLongLong
1102 #define DWordPtrToIntPtr ULongPtrToIntPtr
1103 #define DWordPtrToLongPtr ULongPtrToLongPtr
1113 OUT USHORT* pusResult)
1115 HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
1116 *pusResult = USHORT_ERROR;
1118 if (((USHORT)(usAugend + usAddend)) >= usAugend)
1120 *pusResult = (usAugend + usAddend);
1130 #define WordAdd UShortAdd
1142 HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
1143 *puResult = UINT_ERROR;
1145 if ((uAugend + uAddend) >= uAugend)
1147 *puResult = (uAugend + uAddend);
1155 // UINT_PTR addition
1157 #define UIntPtrAdd SizeTAdd
1167 OUT ULONG* pulResult)
1169 HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
1170 *pulResult = ULONG_ERROR;
1172 if ((ulAugend + ulAddend) >= ulAugend)
1174 *pulResult = (ulAugend + ulAddend);
1182 // ULONG_PTR addition
1185 #define ULongPtrAdd ULongLongAdd
1190 IN ULONG_PTR ulAugend,
1191 IN ULONG_PTR ulAddend,
1192 OUT ULONG_PTR* pulResult)
1194 return ULongAdd((ULONG)ulAugend, (ULONG)ulAddend, (ULONG*)pulResult);
1201 #define DWordAdd ULongAdd
1204 // DWORD_PTR addition
1206 #define DWordPtrAdd ULongPtrAdd
1216 OUT size_t* pResult)
1218 HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
1219 *pResult = SIZET_ERROR;
1221 if ((Augend + Addend) >= Augend)
1223 *pResult = (Augend + Addend);
1233 #define SIZETAdd ULongPtrAdd
1236 // ULONGLONG addition
1241 IN ULONGLONG ullAugend,
1242 IN ULONGLONG ullAddend,
1243 OUT ULONGLONG* pullResult)
1245 HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
1246 *pullResult = ULONGLONG_ERROR;
1248 if ((ullAugend + ullAddend) >= ullAugend)
1250 *pullResult = (ullAugend + ullAddend);
1258 // USHORT subtraction
1263 IN USHORT usMinuend,
1264 IN USHORT usSubtrahend,
1265 OUT USHORT* pusResult)
1267 HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
1268 *pusResult = USHORT_ERROR;
1270 if (usMinuend >= usSubtrahend)
1272 *pusResult = (usMinuend - usSubtrahend);
1282 #define WordSub UShortSub
1292 IN UINT uSubtrahend,
1295 HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
1296 *puResult = UINT_ERROR;
1298 if (uMinuend >= uSubtrahend)
1300 *puResult = (uMinuend - uSubtrahend);
1308 // UINT_PTR subtraction
1310 #define UIntPtrSub SizeTSub
1313 // ULONG subtraction
1319 IN ULONG ulSubtrahend,
1320 OUT ULONG* pulResult)
1322 HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
1323 *pulResult = ULONG_ERROR;
1325 if (ulMinuend >= ulSubtrahend)
1327 *pulResult = (ulMinuend - ulSubtrahend);
1335 // ULONG_PTR subtraction
1338 #define ULongPtrSub ULongLongSub
1343 IN ULONG_PTR ulMinuend,
1344 IN ULONG_PTR ulSubtrahend,
1345 OUT ULONG_PTR* pulResult)
1347 return ULongSub((ULONG)ulMinuend, (ULONG)ulSubtrahend, (ULONG*)pulResult);
1353 // DWORD subtraction
1355 #define DWordSub ULongSub
1358 // DWORD_PTR subtraction
1360 #define DWordPtrSub ULongPtrSub
1363 // size_t subtraction
1369 IN size_t Subtrahend,
1370 OUT size_t* pResult)
1372 HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
1373 *pResult = SIZET_ERROR;
1375 if (Minuend >= Subtrahend)
1377 *pResult = (Minuend - Subtrahend);
1385 // SIZE_T subtraction
1387 #define SIZETSub ULongPtrSub
1390 // ULONGLONG subtraction
1395 IN ULONGLONG ullMinuend,
1396 IN ULONGLONG ullSubtrahend,
1397 OUT ULONGLONG* pullResult)
1399 HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
1400 *pullResult = ULONGLONG_ERROR;
1402 if (ullMinuend >= ullSubtrahend)
1404 *pullResult = (ullMinuend - ullSubtrahend);
1412 // USHORT multiplication
1417 IN USHORT usMultiplicand,
1418 IN USHORT usMultiplier,
1419 OUT USHORT* pusResult)
1421 ULONG ulResult = ((ULONG)usMultiplicand) * (ULONG)usMultiplier;
1423 return ULongToUShort(ulResult, pusResult);
1427 // WORD multiplication
1429 #define WordMult UShortMult
1432 // UINT multiplication
1437 IN UINT uMultiplicand,
1438 IN UINT uMultiplier,
1441 ULONGLONG ull64Result = UInt32x32To64(uMultiplicand, uMultiplier);
1443 return ULongLongToUInt(ull64Result, puResult);
1447 // UINT_PTR multiplication
1450 #define UIntPtrMult ULongLongMult
1455 IN UINT_PTR ulMultiplicand,
1456 IN UINT_PTR ulMultiplier,
1457 OUT UINT_PTR* pulResult)
1459 return UIntMult((UINT)ulMultiplicand, (UINT)ulMultiplier, (UINT*)pulResult);
1464 // ULONG multiplication
1469 IN ULONG ulMultiplicand,
1470 IN ULONG ulMultiplier,
1471 OUT ULONG* pulResult)
1473 ULONGLONG ull64Result = UInt32x32To64(ulMultiplicand, ulMultiplier);
1475 return ULongLongToULong(ull64Result, pulResult);
1479 // ULONG_PTR multiplication
1482 #define ULongPtrMult ULongLongMult
1487 IN ULONG_PTR ulMultiplicand,
1488 IN ULONG_PTR ulMultiplier,
1489 OUT ULONG_PTR* pulResult)
1491 return ULongMult((ULONG)ulMultiplicand, (ULONG)ulMultiplier, (ULONG*)pulResult);
1497 // DWORD multiplication
1499 #define DWordMult ULongMult
1502 // DWORD_PTR multiplication
1504 #define DWordPtrMult ULongPtrMult
1507 // size_t multiplication
1509 #define SizeTMult UIntPtrMult
1512 // SIZE_T multiplication
1514 #define SIZETMult ULongPtrMult
1517 // ULONGLONG multiplication
1522 IN ULONGLONG ullMultiplicand,
1523 IN ULONGLONG ullMultiplier,
1524 OUT ULONGLONG* pullResult)
1526 HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
1528 ULONGLONG u64ResultHigh;
1529 ULONGLONG u64ResultLow;
1531 *pullResult = ULONGLONG_ERROR;
1533 u64ResultLow = UnsignedMultiply128(ullMultiplicand, ullMultiplier, &u64ResultHigh);
1534 if (u64ResultHigh == 0)
1536 *pullResult = u64ResultLow;
1540 // 64x64 into 128 is like 32.32 x 32.32.
1542 // a.b * c.d = a*(c.d) + .b*(c.d) = a*c + a*.d + .b*c + .b*.d
1543 // back in non-decimal notation where A=a*2^32 and C=c*2^32:
1544 // A*C + A*d + b*C + b*d
1545 // So there are four components to add together.
1546 // result = (a*c*2^64) + (a*d*2^32) + (b*c*2^32) + (b*d)
1548 // a * c must be 0 or there would be bits in the high 64-bits
1549 // a * d must be less than 2^32 or there would be bits in the high 64-bits
1550 // b * c must be less than 2^32 or there would be bits in the high 64-bits
1551 // then there must be no overflow of the resulting values summed up.
1560 ULONGLONG ullResult = 0;
1562 *pullResult = ULONGLONG_ERROR;
1564 dw_a = (ULONG)(ullMultiplicand >> 32);
1565 dw_c = (ULONG)(ullMultiplier >> 32);
1567 // common case -- if high dwords are both zero, no chance for overflow
1568 if ((dw_a == 0) && (dw_c == 0))
1570 dw_b = (DWORD)ullMultiplicand;
1571 dw_d = (DWORD)ullMultiplier;
1573 *pullResult = (((ULONGLONG)dw_b) * (ULONGLONG)dw_d);
1578 // a * c must be 0 or there would be bits set in the high 64-bits
1582 dw_d = (DWORD)ullMultiplier;
1584 // a * d must be less than 2^32 or there would be bits set in the high 64-bits
1585 ad = (((ULONGLONG)dw_a) * (ULONGLONG)dw_d);
1586 if ((ad & HIDWORD_MASK) == 0)
1588 dw_b = (DWORD)ullMultiplicand;
1590 // b * c must be less than 2^32 or there would be bits set in the high 64-bits
1591 bc = (((ULONGLONG)dw_b) * (ULONGLONG)dw_c);
1592 if ((bc & HIDWORD_MASK) == 0)
1594 // now sum them all up checking for overflow.
1595 // shifting is safe because we already checked for overflow above
1596 if (SUCCEEDED(ULongLongAdd(bc << 32, ad << 32, &ullResult)))
1599 bd = (((ULONGLONG)dw_b) * (ULONGLONG)dw_d);
1601 if (SUCCEEDED(ULongLongAdd(ullResult, bd, &ullResult)))
1603 *pullResult = ullResult;
1616 #endif // _INTSAFE_H_INCLUDED_