|
|
@@ -0,0 +1,1616 @@
|
|
|
+// Licensed to the .NET Foundation under one or more agreements.
|
|
|
+// The .NET Foundation licenses this file to you under the MIT license.
|
|
|
+// See the LICENSE file in the project root for more information.
|
|
|
+
|
|
|
+/******************************************************************
|
|
|
+* *
|
|
|
+* intsafe.h -- This module defines helper functions to prevent *
|
|
|
+* integer overflow issues. *
|
|
|
+* *
|
|
|
+* *
|
|
|
+******************************************************************/
|
|
|
+#ifndef _INTSAFE_H_INCLUDED_
|
|
|
+#define _INTSAFE_H_INCLUDED_
|
|
|
+
|
|
|
+#if _MSC_VER > 1000
|
|
|
+#pragma once
|
|
|
+#endif
|
|
|
+
|
|
|
+#include <specstrings.h> // for IN, etc.
|
|
|
+
|
|
|
+
|
|
|
+#if defined(_AMD64_)
|
|
|
+#ifdef __cplusplus
|
|
|
+extern "C" {
|
|
|
+#endif
|
|
|
+#define UnsignedMultiply128 _umul128
|
|
|
+ULONG64
|
|
|
+UnsignedMultiply128 (
|
|
|
+ IN ULONG64 Multiplier,
|
|
|
+ IN ULONG64 Multiplicand,
|
|
|
+ OUT ULONG64 *HighProduct
|
|
|
+ );
|
|
|
+#ifdef _MSC_VER
|
|
|
+#pragma intrinsic(_umul128)
|
|
|
+#endif // _MSC_VER
|
|
|
+#ifdef __cplusplus
|
|
|
+}
|
|
|
+#endif
|
|
|
+#endif // _AMD64_
|
|
|
+
|
|
|
+#ifndef FEATURE_PAL
|
|
|
+
|
|
|
+#ifdef _WIN64
|
|
|
+typedef unsigned __int64 size_t;
|
|
|
+typedef unsigned __int64 UINT_PTR;
|
|
|
+typedef unsigned __int64 ULONG_PTR;
|
|
|
+typedef unsigned __int64 DWORD_PTR;
|
|
|
+typedef unsigned __int64 SIZE_T;
|
|
|
+#else
|
|
|
+typedef __w64 unsigned int size_t;
|
|
|
+typedef __w64 unsigned int UINT_PTR;
|
|
|
+typedef __w64 unsigned long ULONG_PTR;
|
|
|
+typedef __w64 unsigned long DWORD_PTR;
|
|
|
+typedef __w64 unsigned long SIZE_T;
|
|
|
+#endif
|
|
|
+typedef char CHAR;
|
|
|
+typedef int INT;
|
|
|
+typedef long LONG;
|
|
|
+typedef unsigned char UCHAR;
|
|
|
+typedef unsigned short USHORT;
|
|
|
+typedef unsigned short WORD;
|
|
|
+typedef unsigned int UINT;
|
|
|
+typedef unsigned long ULONG;
|
|
|
+typedef unsigned long DWORD;
|
|
|
+typedef unsigned __int64 ULONGLONG;
|
|
|
+
|
|
|
+
|
|
|
+typedef LONG HRESULT;
|
|
|
+
|
|
|
+#ifndef SUCCEEDED
|
|
|
+#define SUCCEEDED(hr) (((HRESULT)(hr)) >= 0)
|
|
|
+#endif
|
|
|
+
|
|
|
+#ifndef FAILED
|
|
|
+#define FAILED(hr) (((HRESULT)(hr)) < 0)
|
|
|
+#endif
|
|
|
+
|
|
|
+#define S_OK ((HRESULT)0x00000000L)
|
|
|
+
|
|
|
+#endif // !FEATURE_PAL
|
|
|
+
|
|
|
+#define INTSAFE_E_ARITHMETIC_OVERFLOW ((HRESULT)0x80070216L) // 0x216 = 534 = ERROR_ARITHMETIC_OVERFLOW
|
|
|
+
|
|
|
+#ifndef LOWORD
|
|
|
+#define LOWORD(l) ((WORD)(((DWORD_PTR)(l)) & 0xffff))
|
|
|
+#endif
|
|
|
+
|
|
|
+#ifndef HIWORD
|
|
|
+#define HIWORD(l) ((WORD)(((DWORD_PTR)(l)) >> 16))
|
|
|
+#endif
|
|
|
+
|
|
|
+#define HIDWORD(_qw) ((ULONG)((_qw) >> 32))
|
|
|
+#define LODWORD(_qw) ((ULONG)(_qw))
|
|
|
+
|
|
|
+#if defined(MIDL_PASS) || defined(RC_INVOKED) || defined(_M_CEE_PURE) \
|
|
|
+ || defined(_68K_) || defined(_MPPC_) || defined(_PPC_) \
|
|
|
+ || defined(_M_IA64) || defined(_M_AMD64) || defined(__ARM_ARCH)
|
|
|
+
|
|
|
+#ifndef UInt32x32To64
|
|
|
+#define UInt32x32To64(a, b) ((unsigned __int64)((ULONG)(a)) * (unsigned __int64)((ULONG)(b)))
|
|
|
+#endif
|
|
|
+
|
|
|
+#elif defined(_M_IX86)
|
|
|
+
|
|
|
+#ifndef UInt32x32To64
|
|
|
+#define UInt32x32To64(a, b) (unsigned __int64)((unsigned __int64)(ULONG)(a) * (ULONG)(b))
|
|
|
+#endif
|
|
|
+
|
|
|
+#else
|
|
|
+
|
|
|
+#error Must define a target architecture.
|
|
|
+
|
|
|
+#endif
|
|
|
+
|
|
|
+#define INT_MAX 2147483647
|
|
|
+#define LONG_MAX 2147483647L
|
|
|
+#define USHRT_MAX 0xffff
|
|
|
+#define UINT_MAX 0xffffffff
|
|
|
+#define ULONG_MAX 0xffffffffUL
|
|
|
+#define DWORD_MAX 0xffffffffUL
|
|
|
+
|
|
|
+//
|
|
|
+// It is common for -1 to be used as an error value for various types
|
|
|
+//
|
|
|
+#define USHORT_ERROR (0xffff)
|
|
|
+#define INT_ERROR (-1)
|
|
|
+#define LONG_ERROR (-1L)
|
|
|
+#define UINT_ERROR (0xffffffff)
|
|
|
+#define ULONG_ERROR (0xffffffffUL)
|
|
|
+#ifdef _MSC_VER
|
|
|
+#define ULONGLONG_ERROR (0xffffffffffffffffui64)
|
|
|
+#define HIDWORD_MASK (0xffffffff00000000ui64)
|
|
|
+#else // _MSC_VER
|
|
|
+#define ULONGLONG_ERROR (0xffffffffffffffffULL)
|
|
|
+#define HIDWORD_MASK (0xffffffff00000000ULL)
|
|
|
+#endif // _MSC_VER
|
|
|
+#ifdef _WIN64
|
|
|
+#define SIZET_ERROR ULONGLONG_ERROR
|
|
|
+#else
|
|
|
+#define SIZET_ERROR ULONG_ERROR
|
|
|
+#endif
|
|
|
+
|
|
|
+//
|
|
|
+// We make some assumptions about the sizes of various types. Let's be
|
|
|
+// explicit about those assumptions and check them.
|
|
|
+//
|
|
|
+C_ASSERT(sizeof(unsigned short) == 2);
|
|
|
+C_ASSERT(sizeof(unsigned int) == 4);
|
|
|
+C_ASSERT(sizeof(ULONG) == 4);
|
|
|
+
|
|
|
+//
|
|
|
+// INT -> signed char conversion
|
|
|
+//
|
|
|
+__inline
|
|
|
+HRESULT
|
|
|
+IntToSignedChar(
|
|
|
+ IN INT iOperand,
|
|
|
+ OUT signed char* pch)
|
|
|
+{
|
|
|
+ HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
|
|
|
+ *pch = 0;
|
|
|
+
|
|
|
+ if ((iOperand >= -128) && (iOperand <= 127))
|
|
|
+ {
|
|
|
+ *pch = (signed char)iOperand;
|
|
|
+ hr = S_OK;
|
|
|
+ }
|
|
|
+
|
|
|
+ return hr;
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+// INT -> UCHAR conversion
|
|
|
+//
|
|
|
+__inline
|
|
|
+HRESULT
|
|
|
+IntToUChar(
|
|
|
+ IN INT iOperand,
|
|
|
+ OUT UCHAR* pch)
|
|
|
+{
|
|
|
+ HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
|
|
|
+ *pch = 0;
|
|
|
+
|
|
|
+ if ((iOperand >= 0) && (iOperand <= 255))
|
|
|
+ {
|
|
|
+ *pch = (UCHAR)iOperand;
|
|
|
+ hr = S_OK;
|
|
|
+ }
|
|
|
+
|
|
|
+ return hr;
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+// LONG -> UCHAR conversion
|
|
|
+//
|
|
|
+__inline
|
|
|
+HRESULT
|
|
|
+LongToUChar(
|
|
|
+ IN LONG lOperand,
|
|
|
+ OUT UCHAR* pch)
|
|
|
+{
|
|
|
+ HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
|
|
|
+ *pch = 0;
|
|
|
+
|
|
|
+ if ((lOperand >= 0) && (lOperand <= 255))
|
|
|
+ {
|
|
|
+ *pch = (UCHAR)lOperand;
|
|
|
+ hr = S_OK;
|
|
|
+ }
|
|
|
+
|
|
|
+ return hr;
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+// __inline is not sufficient. __forceinline is necessary.
|
|
|
+// If the function is not inlined and you link .objs compiled with different compiler switches,
|
|
|
+// you get one or the other function arbitrarily chosen.
|
|
|
+//
|
|
|
+// INT -> CHAR conversion
|
|
|
+//
|
|
|
+__forceinline
|
|
|
+HRESULT
|
|
|
+IntToChar(
|
|
|
+ IN INT iOperand,
|
|
|
+ OUT CHAR* pch)
|
|
|
+{
|
|
|
+#ifdef _CHAR_UNSIGNED
|
|
|
+ return IntToUChar(iOperand, (UCHAR*)pch);
|
|
|
+#else
|
|
|
+ return IntToSignedChar(iOperand, (signed char*)pch);
|
|
|
+#endif
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+// INT -> USHORT conversion
|
|
|
+//
|
|
|
+__inline
|
|
|
+HRESULT
|
|
|
+IntToUShort(
|
|
|
+ IN INT iOperand,
|
|
|
+ OUT USHORT* pusResult)
|
|
|
+{
|
|
|
+ HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
|
|
|
+ *pusResult = USHORT_ERROR;
|
|
|
+
|
|
|
+ if ((iOperand >= 0) && (iOperand <= USHRT_MAX))
|
|
|
+ {
|
|
|
+ *pusResult = (USHORT)iOperand;
|
|
|
+ hr = S_OK;
|
|
|
+ }
|
|
|
+
|
|
|
+ return hr;
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+// INT -> UINT conversion
|
|
|
+//
|
|
|
+__inline
|
|
|
+HRESULT
|
|
|
+IntToUInt(
|
|
|
+ IN INT iOperand,
|
|
|
+ OUT UINT* puResult)
|
|
|
+{
|
|
|
+ HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
|
|
|
+ *puResult = UINT_ERROR;
|
|
|
+
|
|
|
+ if (iOperand >= 0)
|
|
|
+ {
|
|
|
+ *puResult = (UINT)iOperand;
|
|
|
+ hr = S_OK;
|
|
|
+ }
|
|
|
+
|
|
|
+ return hr;
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+// INT -> ULONG conversion
|
|
|
+//
|
|
|
+__inline
|
|
|
+HRESULT
|
|
|
+IntToULong(
|
|
|
+ IN INT iOperand,
|
|
|
+ OUT ULONG* pulResult)
|
|
|
+{
|
|
|
+ HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
|
|
|
+ *pulResult = ULONG_ERROR;
|
|
|
+
|
|
|
+ if (iOperand >= 0)
|
|
|
+ {
|
|
|
+ *pulResult = (ULONG)iOperand;
|
|
|
+ hr = S_OK;
|
|
|
+ }
|
|
|
+
|
|
|
+ return hr;
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+// INT -> ULONGLONG conversion
|
|
|
+//
|
|
|
+__inline
|
|
|
+HRESULT
|
|
|
+IntToULongLong(
|
|
|
+ IN INT iOperand,
|
|
|
+ OUT ULONGLONG* pullResult)
|
|
|
+{
|
|
|
+ HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
|
|
|
+ *pullResult = ULONG_ERROR;
|
|
|
+
|
|
|
+ if (iOperand >= 0)
|
|
|
+ {
|
|
|
+ *pullResult = (ULONGLONG)iOperand;
|
|
|
+ hr = S_OK;
|
|
|
+ }
|
|
|
+
|
|
|
+ return hr;
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+// UINT -> signed char conversion
|
|
|
+//
|
|
|
+__inline
|
|
|
+HRESULT
|
|
|
+UIntToSignedChar(
|
|
|
+ IN UINT uOperand,
|
|
|
+ OUT signed char* pch)
|
|
|
+{
|
|
|
+ HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
|
|
|
+ *pch = 0;
|
|
|
+
|
|
|
+ if (uOperand <= 127)
|
|
|
+ {
|
|
|
+ *pch = (signed char)uOperand;
|
|
|
+ hr = S_OK;
|
|
|
+ }
|
|
|
+
|
|
|
+ return hr;
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+// UINT -> UCHAR conversion
|
|
|
+//
|
|
|
+__inline
|
|
|
+HRESULT
|
|
|
+UIntToUChar(
|
|
|
+ IN UINT uOperand,
|
|
|
+ OUT UCHAR* pch)
|
|
|
+{
|
|
|
+ HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
|
|
|
+ *pch = 0;
|
|
|
+
|
|
|
+ if (uOperand <= 255)
|
|
|
+ {
|
|
|
+ *pch = (UCHAR)uOperand;
|
|
|
+ hr = S_OK;
|
|
|
+ }
|
|
|
+
|
|
|
+ return hr;
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+// UINT -> BYTE conversion
|
|
|
+//
|
|
|
+#define UIntToByte UIntToUChar
|
|
|
+
|
|
|
+//
|
|
|
+// __inline is not sufficient. __forceinline is necessary.
|
|
|
+// If the function is not inlined and you link .objs compiled with different compiler switches,
|
|
|
+// you get one or the other function arbitrarily chosen.
|
|
|
+//
|
|
|
+// UINT -> CHAR conversion
|
|
|
+//
|
|
|
+__forceinline
|
|
|
+HRESULT
|
|
|
+UIntToChar(
|
|
|
+ IN UINT uOperand,
|
|
|
+ OUT CHAR* pch)
|
|
|
+{
|
|
|
+#ifdef _CHAR_UNSIGNED
|
|
|
+ return UIntToUChar(uOperand, (UCHAR*)pch);
|
|
|
+#else
|
|
|
+ return UIntToSignedChar(uOperand, (signed char*)pch);
|
|
|
+#endif // _CHAR_UNSIGNED
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+// UINT -> INT conversion
|
|
|
+//
|
|
|
+__inline
|
|
|
+HRESULT
|
|
|
+UIntToInt(
|
|
|
+ IN UINT uOperand,
|
|
|
+ OUT INT* piResult)
|
|
|
+{
|
|
|
+ HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
|
|
|
+ *piResult = INT_ERROR;
|
|
|
+
|
|
|
+ if (uOperand <= INT_MAX)
|
|
|
+ {
|
|
|
+ *piResult = (INT)uOperand;
|
|
|
+ hr = S_OK;
|
|
|
+ }
|
|
|
+
|
|
|
+ return hr;
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+// UINT -> LONG conversion
|
|
|
+//
|
|
|
+__inline
|
|
|
+HRESULT
|
|
|
+UIntToLong(
|
|
|
+ IN UINT Operand,
|
|
|
+ OUT LONG* Result)
|
|
|
+{
|
|
|
+ if (Operand <= LONG_MAX)
|
|
|
+ {
|
|
|
+ *Result = (LONG)Operand;
|
|
|
+ return S_OK;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ *Result = LONG_ERROR;
|
|
|
+ return INTSAFE_E_ARITHMETIC_OVERFLOW;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+// UINT -> ULONG conversion
|
|
|
+//
|
|
|
+__inline
|
|
|
+HRESULT
|
|
|
+UIntToULong(
|
|
|
+ IN UINT uOperand,
|
|
|
+ OUT ULONG* pulResult)
|
|
|
+{
|
|
|
+ *pulResult = (ULONG)uOperand;
|
|
|
+
|
|
|
+ return S_OK;
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+// ULONG -> UCHAR conversion
|
|
|
+//
|
|
|
+__inline
|
|
|
+HRESULT
|
|
|
+ULongToSignedChar(
|
|
|
+ IN ULONG ulOperand,
|
|
|
+ OUT signed char* pch)
|
|
|
+{
|
|
|
+ HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
|
|
|
+ *pch = 0;
|
|
|
+
|
|
|
+ if (ulOperand <= 127)
|
|
|
+ {
|
|
|
+ *pch = (signed char)ulOperand;
|
|
|
+ hr = S_OK;
|
|
|
+ }
|
|
|
+
|
|
|
+ return hr;
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+// ULONG -> UCHAR conversion
|
|
|
+//
|
|
|
+__inline
|
|
|
+HRESULT
|
|
|
+ULongToUChar(
|
|
|
+ IN ULONG ulOperand,
|
|
|
+ OUT unsigned char* pch)
|
|
|
+{
|
|
|
+ HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
|
|
|
+ *pch = 0;
|
|
|
+
|
|
|
+ if (ulOperand <= 255)
|
|
|
+ {
|
|
|
+ *pch = (unsigned char)ulOperand;
|
|
|
+ hr = S_OK;
|
|
|
+ }
|
|
|
+
|
|
|
+ return hr;
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+// __inline is not sufficient. __forceinline is necessary.
|
|
|
+// If the function is not inlined and you link .objs compiled with different compiler switches,
|
|
|
+// you get one or the other function arbitrarily chosen.
|
|
|
+//
|
|
|
+// ULONG -> CHAR conversion
|
|
|
+//
|
|
|
+__forceinline
|
|
|
+HRESULT
|
|
|
+ULongToChar(
|
|
|
+ IN ULONG ulOperand,
|
|
|
+ OUT CHAR* pch)
|
|
|
+{
|
|
|
+#ifdef _CHAR_UNSIGNED
|
|
|
+ return ULongToUChar(ulOperand, (unsigned char*)pch);
|
|
|
+#else
|
|
|
+ return ULongToSignedChar(ulOperand, (signed char*)pch);
|
|
|
+#endif // _CHAR_UNSIGNED
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+// ULONG -> USHORT conversion
|
|
|
+//
|
|
|
+__inline
|
|
|
+HRESULT
|
|
|
+ULongToUShort(
|
|
|
+ IN ULONG ulOperand,
|
|
|
+ OUT USHORT* pusResult)
|
|
|
+{
|
|
|
+ HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
|
|
|
+ *pusResult = USHORT_ERROR;
|
|
|
+
|
|
|
+ if (ulOperand <= USHRT_MAX)
|
|
|
+ {
|
|
|
+ *pusResult = (USHORT)ulOperand;
|
|
|
+ hr = S_OK;
|
|
|
+ }
|
|
|
+
|
|
|
+ return hr;
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+// ULONG -> INT conversion
|
|
|
+//
|
|
|
+__inline
|
|
|
+HRESULT
|
|
|
+ULongToInt(
|
|
|
+ IN ULONG ulOperand,
|
|
|
+ OUT INT* piResult)
|
|
|
+{
|
|
|
+ if (ulOperand <= INT_MAX)
|
|
|
+ {
|
|
|
+ *piResult = (INT)ulOperand;
|
|
|
+ return S_OK;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ *piResult = INT_ERROR;
|
|
|
+ return INTSAFE_E_ARITHMETIC_OVERFLOW;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+// ULONG -> UINT conversion
|
|
|
+//
|
|
|
+__inline
|
|
|
+HRESULT
|
|
|
+ULongToUInt(
|
|
|
+ IN ULONG ulOperand,
|
|
|
+ OUT UINT* puResult)
|
|
|
+{
|
|
|
+ *puResult = (UINT)ulOperand;
|
|
|
+
|
|
|
+ return S_OK;
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+// ULONG -> LONG conversion
|
|
|
+//
|
|
|
+__inline
|
|
|
+HRESULT
|
|
|
+ULongToLong(
|
|
|
+ IN ULONG Operand,
|
|
|
+ OUT LONG* Result)
|
|
|
+{
|
|
|
+ if (Operand <= LONG_MAX)
|
|
|
+ {
|
|
|
+ *Result = (LONG)Operand;
|
|
|
+ return S_OK;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ *Result = LONG_ERROR;
|
|
|
+ return INTSAFE_E_ARITHMETIC_OVERFLOW;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+// ULONGLONG -> INT conversion
|
|
|
+//
|
|
|
+__inline
|
|
|
+HRESULT
|
|
|
+ULongLongToInt(
|
|
|
+ IN ULONGLONG ullOperand,
|
|
|
+ OUT INT* piResult)
|
|
|
+{
|
|
|
+ if (ullOperand <= INT_MAX)
|
|
|
+ {
|
|
|
+ *piResult = (INT)ullOperand;
|
|
|
+ return S_OK;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ *piResult = INT_ERROR;
|
|
|
+ return INTSAFE_E_ARITHMETIC_OVERFLOW;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+// ULONGLONG -> LONG conversion
|
|
|
+//
|
|
|
+__inline
|
|
|
+HRESULT
|
|
|
+ULongLongToLong(
|
|
|
+ IN ULONGLONG Operand,
|
|
|
+ OUT LONG* Result)
|
|
|
+{
|
|
|
+ if (Operand <= LONG_MAX)
|
|
|
+ {
|
|
|
+ *Result = (LONG)Operand;
|
|
|
+ return S_OK;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ *Result = LONG_ERROR;
|
|
|
+ return INTSAFE_E_ARITHMETIC_OVERFLOW;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+// UINT -> USHORT conversion
|
|
|
+//
|
|
|
+__inline
|
|
|
+HRESULT
|
|
|
+UIntToUShort(
|
|
|
+ IN UINT uOperand,
|
|
|
+ OUT USHORT* pusResult)
|
|
|
+{
|
|
|
+ HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
|
|
|
+ *pusResult = USHORT_ERROR;
|
|
|
+
|
|
|
+ if (uOperand <= USHRT_MAX)
|
|
|
+ {
|
|
|
+ *pusResult = (USHORT)uOperand;
|
|
|
+ hr = S_OK;
|
|
|
+ }
|
|
|
+
|
|
|
+ return hr;
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+// ULONGLONG -> USHORT conversion
|
|
|
+//
|
|
|
+__inline
|
|
|
+HRESULT
|
|
|
+ULongLongToUShort(
|
|
|
+ IN ULONGLONG ullOperand,
|
|
|
+ OUT USHORT* pusResult)
|
|
|
+{
|
|
|
+ HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
|
|
|
+ USHORT usResult = USHORT_ERROR;
|
|
|
+
|
|
|
+ if (ullOperand <= USHRT_MAX)
|
|
|
+ {
|
|
|
+ usResult = (USHORT)ullOperand;
|
|
|
+ hr = S_OK;
|
|
|
+ }
|
|
|
+ *pusResult = usResult;
|
|
|
+
|
|
|
+ return hr;
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+// ULONGLONG -> ULONG conversion
|
|
|
+//
|
|
|
+__inline
|
|
|
+HRESULT
|
|
|
+ULongLongToULong(
|
|
|
+ IN ULONGLONG ullOperand,
|
|
|
+ OUT ULONG* pulResult)
|
|
|
+{
|
|
|
+ HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
|
|
|
+ *pulResult = ULONG_ERROR;
|
|
|
+
|
|
|
+ if (ullOperand <= ULONG_MAX)
|
|
|
+ {
|
|
|
+ *pulResult = (ULONG)ullOperand;
|
|
|
+ hr = S_OK;
|
|
|
+ }
|
|
|
+
|
|
|
+ return hr;
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+// UINT_PTR -> ULONG conversion
|
|
|
+// ULONG_PTR -> ULONG conversion
|
|
|
+//
|
|
|
+#ifdef _WIN64
|
|
|
+
|
|
|
+#define UIntPtrToULong ULongLongToULong
|
|
|
+#define ULongPtrToULong ULongLongToULong
|
|
|
+
|
|
|
+#else
|
|
|
+
|
|
|
+__inline
|
|
|
+HRESULT
|
|
|
+UIntPtrToULong(
|
|
|
+ IN UINT_PTR Operand,
|
|
|
+ OUT ULONG* pResult)
|
|
|
+{
|
|
|
+ *pResult = (ULONG)Operand;
|
|
|
+ return S_OK;
|
|
|
+}
|
|
|
+
|
|
|
+__inline
|
|
|
+HRESULT
|
|
|
+ULongPtrToULong(
|
|
|
+ IN ULONG_PTR Operand,
|
|
|
+ OUT ULONG* pResult)
|
|
|
+{
|
|
|
+ *pResult = (ULONG)Operand;
|
|
|
+ return S_OK;
|
|
|
+}
|
|
|
+
|
|
|
+#endif
|
|
|
+
|
|
|
+//
|
|
|
+// ULONGLONG -> UINT conversion
|
|
|
+//
|
|
|
+__inline
|
|
|
+HRESULT
|
|
|
+ULongLongToUInt(
|
|
|
+ IN ULONGLONG ullOperand,
|
|
|
+ OUT UINT* puResult)
|
|
|
+{
|
|
|
+ HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
|
|
|
+ *puResult = UINT_ERROR;
|
|
|
+
|
|
|
+ if (ullOperand <= UINT_MAX)
|
|
|
+ {
|
|
|
+ *puResult = (UINT)ullOperand;
|
|
|
+ hr = S_OK;
|
|
|
+ }
|
|
|
+
|
|
|
+ return hr;
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+// UINT_PTR -> UINT conversion
|
|
|
+// ULONG_PTR -> UINT conversion
|
|
|
+//
|
|
|
+#ifdef _WIN64
|
|
|
+
|
|
|
+#define UIntPtrToUInt ULongLongToUInt
|
|
|
+#define ULongPtrToUInt ULongLongToUInt
|
|
|
+
|
|
|
+#else
|
|
|
+
|
|
|
+__inline
|
|
|
+HRESULT
|
|
|
+UIntPtrToUInt(
|
|
|
+ IN UINT_PTR Operand,
|
|
|
+ OUT UINT* pResult)
|
|
|
+{
|
|
|
+ *pResult = (UINT)Operand;
|
|
|
+ return S_OK;
|
|
|
+}
|
|
|
+
|
|
|
+__inline
|
|
|
+HRESULT
|
|
|
+ULongPtrToUInt(
|
|
|
+ IN ULONG_PTR Operand,
|
|
|
+ OUT UINT* pResult)
|
|
|
+{
|
|
|
+ *pResult = (UINT)Operand;
|
|
|
+ return S_OK;
|
|
|
+}
|
|
|
+
|
|
|
+#endif
|
|
|
+
|
|
|
+//
|
|
|
+// * -> BYTE conversion (BYTE is always unsigned char)
|
|
|
+//
|
|
|
+#define IntToByte IntToUChar
|
|
|
+#define UIntToByte UIntToUChar
|
|
|
+#define LongToByte LongToUChar
|
|
|
+#define ULongToByte ULongToUChar
|
|
|
+
|
|
|
+//
|
|
|
+// * -> WORD conversion (WORD is always unsigned short)
|
|
|
+//
|
|
|
+#define IntToWord IntToUShort
|
|
|
+#define LongToWord LongToUShort
|
|
|
+#define LongLongToWord LongLongToUShort
|
|
|
+#define UIntToWord UIntToUShort
|
|
|
+#define ULongToWord ULongToUShort
|
|
|
+#define ULongLongToWord ULongLongToUShort
|
|
|
+#define UIntPtrToWord UIntPtrToUShort
|
|
|
+#define ULongPtrToWord ULongPtrToUShort
|
|
|
+#define SizeTToWord SizeTToUShort
|
|
|
+#define SIZETToWord SIZETToUShort
|
|
|
+
|
|
|
+//
|
|
|
+// WORD -> * conversion (WORD is always unsigned short)
|
|
|
+//
|
|
|
+#define WordToUChar UShortToUChar
|
|
|
+#define WordToByte UShortToByte
|
|
|
+#define WordToChar UShortToChar
|
|
|
+#define WordToSignedChar UShortToSignedChar
|
|
|
+#define WordToInt UShortToInt
|
|
|
+#define WordToLong UShortToLong
|
|
|
+#define WordToLongLong UShortToLongLong
|
|
|
+#define WordToIntPtr UShortToIntPtr
|
|
|
+#define WordToLongPtr UShortToLongPtr
|
|
|
+
|
|
|
+//
|
|
|
+// * -> DWORD conversion (DWORD is always ULONG)
|
|
|
+//
|
|
|
+#define CharToDWord CharToULong
|
|
|
+#define SignedCharToDWord SignedCharToULong
|
|
|
+#define ShortToDWord ShortToULong
|
|
|
+#define IntToDWord IntToULong
|
|
|
+#define LongToDWord LongToULong
|
|
|
+#define LongLongToDWord LongLongToULong
|
|
|
+#define UIntToDWord UIntToULong
|
|
|
+#define ULongLongToDWord ULongLongToULong
|
|
|
+#define IntPtrToDWord IntPtrToULong
|
|
|
+#define LongPtrToDWord LongPtrToULong
|
|
|
+#define UIntPtrToDWord UIntPtrToULong
|
|
|
+#define ULongPtrToDWord ULongPtrToULong
|
|
|
+#define SizeTToDWord SizeTToULong
|
|
|
+#define SIZETToDWord SIZETToULong
|
|
|
+
|
|
|
+//
|
|
|
+// DWORD -> * conversion (DWORD is always ULONG)
|
|
|
+//
|
|
|
+#define DWordToChar ULongToChar
|
|
|
+#define DWordToUChar ULongToUChar
|
|
|
+#define DWordToByte ULongToByte
|
|
|
+#define DWordToSignedChar ULongToSignedChar
|
|
|
+#define DWordToUShort ULongToUShort
|
|
|
+#define DWordToUInt ULongToUInt
|
|
|
+#define DWordToInt ULongToInt
|
|
|
+#define DWordToLong ULongToLong
|
|
|
+#define DWordToLongLong ULongToLongLong
|
|
|
+#define DWordToIntPtr ULongToIntPtr
|
|
|
+#define DWordToLongPtr ULongToLongPtr
|
|
|
+
|
|
|
+
|
|
|
+//
|
|
|
+// * -> UINT_PTR conversion (UINT_PTR is UINT on Win32, ULONGLONG on Win64)
|
|
|
+//
|
|
|
+#ifdef _WIN64
|
|
|
+#define CharToUIntPtr CharToULongLong
|
|
|
+#define SignedCharToUIntPtr SignedCharToULongLong
|
|
|
+#define ShortToUIntPtr ShortToULongLong
|
|
|
+#define IntToUIntPtr IntToULongLong
|
|
|
+#define LongToUIntPtr LongToULongLong
|
|
|
+#define LongLongToUIntPtr LongLongToULongLong
|
|
|
+#define IntPtrToUIntPtr IntPtrToULongLong
|
|
|
+#define LongPtrToUIntPtr LongPtrToULongLong
|
|
|
+#else
|
|
|
+#define CharToUIntPtr CharToUInt
|
|
|
+#define SignedCharToUIntPtr SignedCharToUInt
|
|
|
+#define ShortToUIntPtr ShortToUInt
|
|
|
+
|
|
|
+__inline
|
|
|
+HRESULT
|
|
|
+IntToUIntPtr(
|
|
|
+ IN INT iOperand,
|
|
|
+ OUT UINT_PTR* puResult)
|
|
|
+{
|
|
|
+ return IntToUInt(iOperand, (UINT*)puResult);
|
|
|
+}
|
|
|
+
|
|
|
+#define LongToUIntPtr LongToUInt
|
|
|
+#define LongLongToUIntPtr LongLongToUInt
|
|
|
+
|
|
|
+#define IntPtrToUIntPtr IntPtrToUInt
|
|
|
+#define LongPtrToUIntPtr LongPtrToUInt
|
|
|
+#endif
|
|
|
+
|
|
|
+__inline
|
|
|
+HRESULT
|
|
|
+ULongLongToUIntPtr(
|
|
|
+ IN ULONGLONG ullOperand,
|
|
|
+ OUT UINT_PTR* puResult)
|
|
|
+{
|
|
|
+#ifdef _WIN64
|
|
|
+ *puResult = ullOperand;
|
|
|
+ return S_OK;
|
|
|
+#else
|
|
|
+ return ULongLongToUInt(ullOperand, (UINT*)puResult);
|
|
|
+#endif
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+//
|
|
|
+// UINT_PTR -> * conversion (UINT_PTR is UINT on Win32, ULONGLONG on Win64)
|
|
|
+//
|
|
|
+#ifdef _WIN64
|
|
|
+#define UIntPtrToUShort ULongLongToUShort
|
|
|
+#define UIntPtrToInt ULongLongToInt
|
|
|
+#define UIntPtrToLong ULongLongToLong
|
|
|
+#define UIntPtrToLongLong ULongLongToLongLong
|
|
|
+#define UIntPtrToIntPtr ULongLongToIntPtr
|
|
|
+#define UIntPtrToLongPtr ULongLongToLongPtr
|
|
|
+#else
|
|
|
+
|
|
|
+__inline
|
|
|
+HRESULT
|
|
|
+UIntPtrToUShort(
|
|
|
+ IN UINT_PTR uOperand,
|
|
|
+ OUT USHORT* pusResult)
|
|
|
+{
|
|
|
+ return UIntToUShort((UINT)uOperand, pusResult);
|
|
|
+}
|
|
|
+
|
|
|
+__inline
|
|
|
+HRESULT
|
|
|
+UIntPtrToInt(
|
|
|
+ IN UINT_PTR uOperand,
|
|
|
+ OUT INT* piResult)
|
|
|
+{
|
|
|
+ return UIntToInt((UINT)uOperand, piResult);
|
|
|
+}
|
|
|
+
|
|
|
+__inline
|
|
|
+HRESULT
|
|
|
+UIntPtrToLong(
|
|
|
+ IN UINT_PTR Operand,
|
|
|
+ OUT LONG* Result)
|
|
|
+{
|
|
|
+ return UIntToLong((UINT)Operand, Result);
|
|
|
+}
|
|
|
+
|
|
|
+#define UIntPtrToLongLong UIntToLongLong
|
|
|
+#define UIntPtrToIntPtr UIntToIntPtr
|
|
|
+#define UIntPtrToLongPtr UIntToLongPtr
|
|
|
+#endif
|
|
|
+
|
|
|
+
|
|
|
+//
|
|
|
+// * -> ULONG_PTR conversion (ULONG_PTR is ULONG on Win32, ULONGLONG on Win64)
|
|
|
+//
|
|
|
+#ifdef _WIN64
|
|
|
+#define CharToULongPtr CharToULongLong
|
|
|
+#define SignedCharToULongPtr SignedCharToULongLong
|
|
|
+#define ShortToULongPtr ShortToULongLong
|
|
|
+#define IntToULongPtr IntToULongLong
|
|
|
+#define LongToULongPtr LongToULongLong
|
|
|
+#define LongLongToULongPtr LongLongToULongLong
|
|
|
+#define IntPtrToULongPtr IntPtrToULongLong
|
|
|
+#define LongPtrToULongPtr LongPtrToULongLong
|
|
|
+#else
|
|
|
+#define CharToULongPtr CharToULong
|
|
|
+#define SignedCharToULongPtr SignedCharToULong
|
|
|
+#define ShortToULongPtr ShortToULong
|
|
|
+
|
|
|
+__inline
|
|
|
+HRESULT
|
|
|
+IntToULongPtr(
|
|
|
+ IN INT iOperand,
|
|
|
+ OUT ULONG_PTR* pulResult)
|
|
|
+{
|
|
|
+ return IntToULong(iOperand, (ULONG*)pulResult);
|
|
|
+}
|
|
|
+
|
|
|
+#define LongToULongPtr LongToULong
|
|
|
+#define LongLongToULongPtr LongLongToULong
|
|
|
+
|
|
|
+#define IntPtrToULongPtr IntPtrToULong
|
|
|
+#define LongPtrToULongPtr LongPtrToULong
|
|
|
+#endif
|
|
|
+
|
|
|
+__inline
|
|
|
+HRESULT
|
|
|
+ULongLongToULongPtr(
|
|
|
+ IN ULONGLONG ullOperand,
|
|
|
+ OUT ULONG_PTR* pulResult)
|
|
|
+{
|
|
|
+#ifdef _WIN64
|
|
|
+ *pulResult = ullOperand;
|
|
|
+ return S_OK;
|
|
|
+#else
|
|
|
+ return ULongLongToULong(ullOperand, (ULONG*)pulResult);
|
|
|
+#endif
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+//
|
|
|
+// ULONG_PTR -> * conversion (ULONG_PTR is ULONG on Win32, ULONGLONG on Win64)
|
|
|
+//
|
|
|
+#ifdef _WIN64
|
|
|
+#define ULongPtrToUShort ULongLongToUShort
|
|
|
+#define ULongPtrToInt ULongLongToInt
|
|
|
+#define ULongPtrToLong ULongLongToLong
|
|
|
+#define ULongPtrToLongLong ULongLongToLongLong
|
|
|
+#define ULongPtrToIntPtr ULongLongToIntPtr
|
|
|
+#define ULongPtrToLongPtr ULongLongToLongPtr
|
|
|
+#else
|
|
|
+
|
|
|
+__inline
|
|
|
+HRESULT
|
|
|
+ULongPtrToUShort(
|
|
|
+ IN ULONG_PTR ulOperand,
|
|
|
+ OUT USHORT* pusResult)
|
|
|
+{
|
|
|
+ return ULongToUShort((ULONG)ulOperand, pusResult);
|
|
|
+}
|
|
|
+
|
|
|
+__inline
|
|
|
+HRESULT
|
|
|
+ULongPtrToInt(
|
|
|
+ IN ULONG_PTR ulOperand,
|
|
|
+ OUT INT* piResult)
|
|
|
+{
|
|
|
+ return ULongToInt((ULONG)ulOperand, piResult);
|
|
|
+}
|
|
|
+
|
|
|
+__inline
|
|
|
+HRESULT
|
|
|
+ULongPtrToLong(
|
|
|
+ IN ULONG_PTR Operand,
|
|
|
+ OUT LONG* Result)
|
|
|
+{
|
|
|
+ return ULongToLong((ULONG)Operand, Result);
|
|
|
+}
|
|
|
+
|
|
|
+#define ULongPtrToLongLong ULongToLongLong
|
|
|
+#define ULongPtrToIntPtr ULongToIntPtr
|
|
|
+#define ULongPtrToLongPtr ULongToLongPtr
|
|
|
+#endif
|
|
|
+
|
|
|
+//
|
|
|
+// * -> size_t conversion (size_t is always UINT_PTR)
|
|
|
+//
|
|
|
+#define CharToSizeT CharToUIntPtr
|
|
|
+#define SignedCharToSizeT SignedCharToUIntPtr
|
|
|
+#define ShortToSizeT ShortToUIntPtr
|
|
|
+#define IntToSizeT IntToUIntPtr
|
|
|
+#define LongToSizeT LongToUIntPtr
|
|
|
+#define LongLongToSizeT LongLongToUIntPtr
|
|
|
+#define ULongLongToSizeT ULongLongToUIntPtr
|
|
|
+#define IntPtrToSizeT IntPtrToUIntPtr
|
|
|
+#define LongPtrToSizeT LongPtrToUIntPtr
|
|
|
+
|
|
|
+//
|
|
|
+// size_t -> * conversion (size_t is always UINT_PTR)
|
|
|
+//
|
|
|
+#define SizeTToUShort UIntPtrToUShort
|
|
|
+#define SizeTToUInt UIntPtrToUInt
|
|
|
+#define SizeTToULong UIntPtrToULong
|
|
|
+#define SizeTToInt UIntPtrToInt
|
|
|
+#define SizeTToLong UIntPtrToLong
|
|
|
+#define SizeTToLongLong UIntPtrToLongLong
|
|
|
+#define SizeTToIntPtr UIntPtrToIntPtr
|
|
|
+#define SizeTToLongPtr UIntPtrToLongPtr
|
|
|
+
|
|
|
+//
|
|
|
+// * -> SIZE_T conversion (SIZE_T is always ULONG_PTR)
|
|
|
+//
|
|
|
+#define CharToSIZET CharToULongPtr
|
|
|
+#define SignedCharToSIZET SignedCharToULongPtr
|
|
|
+#define ShortToSIZET ShortToULongPtr
|
|
|
+#define IntToSIZET IntToULongPtr
|
|
|
+#define LongToSIZET LongToULongPtr
|
|
|
+#define LongLongToSIZET LongLongToULongPtr
|
|
|
+#define IntPtrToSIZET IntPtrToULongPtr
|
|
|
+#define LongPtrToSIZET LongPtrToULongPtr
|
|
|
+#define ULongLongToSIZET ULongLongToULongPtr
|
|
|
+
|
|
|
+//
|
|
|
+// SIZE_T -> * conversion (SIZE_T is always ULONG_PTR)
|
|
|
+//
|
|
|
+#define SIZETToUShort ULongPtrToUShort
|
|
|
+#define SIZETToUInt ULongPtrToUInt
|
|
|
+#define SIZETToULong ULongPtrToULong
|
|
|
+#define SIZETToUIntPtr ULongPtrToUIntPtr
|
|
|
+#define SIZETToULongPtr ULongPtrToULongPtr
|
|
|
+#define SIZETToInt ULongPtrToInt
|
|
|
+#define SIZETToLong ULongPtrToLong
|
|
|
+#define SIZETToLongLong ULongPtrToLongLong
|
|
|
+#define SIZETToIntPtr ULongPtrToIntPtr
|
|
|
+#define SIZETToLongPtr ULongPtrToLongPtr
|
|
|
+
|
|
|
+//
|
|
|
+// * -> DWORD_PTR conversion (DWORD_PTR is always ULONG_PTR)
|
|
|
+//
|
|
|
+#define CharToDWordPtr CharToULongPtr
|
|
|
+#define SignedCharToDWordPtr SignedCharToULongPtr
|
|
|
+#define ShortToDWordPtr ShortToULongPtr
|
|
|
+#define IntToDWordPtr IntToULongPtr
|
|
|
+#define LongToDWordPtr LongToULongPtr
|
|
|
+#define LongLongToDWordPtr LongLongToULongPtr
|
|
|
+#define ULongLongToDWordPtr ULongLongToULongPtr
|
|
|
+#define IntPtrToDWordPtr IntPtrToULongPtr
|
|
|
+#define LongPtrToDWordPtr LongPtrToULongPtr
|
|
|
+
|
|
|
+//
|
|
|
+// DWORD_PTR -> * conversion (DWORD_PTR is always ULONG_PTR)
|
|
|
+//
|
|
|
+#define DWordPtrToUShort ULongPtrToUShort
|
|
|
+#define DWordPtrToUInt ULongPtrToUInt
|
|
|
+#define DWordPtrToULong ULongPtrToULong
|
|
|
+#define DWordPtrToDWord ULongPtrToDWord
|
|
|
+#define DWordPtrToInt ULongPtrToInt
|
|
|
+#define DWordPtrToLong ULongPtrToLong
|
|
|
+#define DWordPtrToLongLong ULongPtrToLongLong
|
|
|
+#define DWordPtrToIntPtr ULongPtrToIntPtr
|
|
|
+#define DWordPtrToLongPtr ULongPtrToLongPtr
|
|
|
+
|
|
|
+//
|
|
|
+// USHORT addition
|
|
|
+//
|
|
|
+__inline
|
|
|
+HRESULT
|
|
|
+UShortAdd(
|
|
|
+ IN USHORT usAugend,
|
|
|
+ IN USHORT usAddend,
|
|
|
+ OUT USHORT* pusResult)
|
|
|
+{
|
|
|
+ HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
|
|
|
+ *pusResult = USHORT_ERROR;
|
|
|
+
|
|
|
+ if (((USHORT)(usAugend + usAddend)) >= usAugend)
|
|
|
+ {
|
|
|
+ *pusResult = (usAugend + usAddend);
|
|
|
+ hr = S_OK;
|
|
|
+ }
|
|
|
+
|
|
|
+ return hr;
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+// WORD addtition
|
|
|
+//
|
|
|
+#define WordAdd UShortAdd
|
|
|
+
|
|
|
+//
|
|
|
+// UINT addition
|
|
|
+//
|
|
|
+__inline
|
|
|
+HRESULT
|
|
|
+UIntAdd(
|
|
|
+ IN UINT uAugend,
|
|
|
+ IN UINT uAddend,
|
|
|
+ OUT UINT* puResult)
|
|
|
+{
|
|
|
+ HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
|
|
|
+ *puResult = UINT_ERROR;
|
|
|
+
|
|
|
+ if ((uAugend + uAddend) >= uAugend)
|
|
|
+ {
|
|
|
+ *puResult = (uAugend + uAddend);
|
|
|
+ hr = S_OK;
|
|
|
+ }
|
|
|
+
|
|
|
+ return hr;
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+// UINT_PTR addition
|
|
|
+//
|
|
|
+#define UIntPtrAdd SizeTAdd
|
|
|
+
|
|
|
+//
|
|
|
+// ULONG addition
|
|
|
+//
|
|
|
+__inline
|
|
|
+HRESULT
|
|
|
+ULongAdd(
|
|
|
+ IN ULONG ulAugend,
|
|
|
+ IN ULONG ulAddend,
|
|
|
+ OUT ULONG* pulResult)
|
|
|
+{
|
|
|
+ HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
|
|
|
+ *pulResult = ULONG_ERROR;
|
|
|
+
|
|
|
+ if ((ulAugend + ulAddend) >= ulAugend)
|
|
|
+ {
|
|
|
+ *pulResult = (ulAugend + ulAddend);
|
|
|
+ hr = S_OK;
|
|
|
+ }
|
|
|
+
|
|
|
+ return hr;
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+// ULONG_PTR addition
|
|
|
+//
|
|
|
+#ifdef _WIN64
|
|
|
+#define ULongPtrAdd ULongLongAdd
|
|
|
+#else
|
|
|
+__inline
|
|
|
+HRESULT
|
|
|
+ULongPtrAdd(
|
|
|
+ IN ULONG_PTR ulAugend,
|
|
|
+ IN ULONG_PTR ulAddend,
|
|
|
+ OUT ULONG_PTR* pulResult)
|
|
|
+{
|
|
|
+ return ULongAdd((ULONG)ulAugend, (ULONG)ulAddend, (ULONG*)pulResult);
|
|
|
+}
|
|
|
+#endif // _WIN64
|
|
|
+
|
|
|
+//
|
|
|
+// DWORD addition
|
|
|
+//
|
|
|
+#define DWordAdd ULongAdd
|
|
|
+
|
|
|
+//
|
|
|
+// DWORD_PTR addition
|
|
|
+//
|
|
|
+#define DWordPtrAdd ULongPtrAdd
|
|
|
+
|
|
|
+//
|
|
|
+// size_t addition
|
|
|
+//
|
|
|
+__inline
|
|
|
+HRESULT
|
|
|
+SizeTAdd(
|
|
|
+ IN size_t Augend,
|
|
|
+ IN size_t Addend,
|
|
|
+ OUT size_t* pResult)
|
|
|
+{
|
|
|
+ HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
|
|
|
+ *pResult = SIZET_ERROR;
|
|
|
+
|
|
|
+ if ((Augend + Addend) >= Augend)
|
|
|
+ {
|
|
|
+ *pResult = (Augend + Addend);
|
|
|
+ hr = S_OK;
|
|
|
+ }
|
|
|
+
|
|
|
+ return hr;
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+// SIZE_T addition
|
|
|
+//
|
|
|
+#define SIZETAdd ULongPtrAdd
|
|
|
+
|
|
|
+//
|
|
|
+// ULONGLONG addition
|
|
|
+//
|
|
|
+__inline
|
|
|
+HRESULT
|
|
|
+ULongLongAdd(
|
|
|
+ IN ULONGLONG ullAugend,
|
|
|
+ IN ULONGLONG ullAddend,
|
|
|
+ OUT ULONGLONG* pullResult)
|
|
|
+{
|
|
|
+ HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
|
|
|
+ *pullResult = ULONGLONG_ERROR;
|
|
|
+
|
|
|
+ if ((ullAugend + ullAddend) >= ullAugend)
|
|
|
+ {
|
|
|
+ *pullResult = (ullAugend + ullAddend);
|
|
|
+ hr = S_OK;
|
|
|
+ }
|
|
|
+
|
|
|
+ return hr;
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+// USHORT subtraction
|
|
|
+//
|
|
|
+__inline
|
|
|
+HRESULT
|
|
|
+UShortSub(
|
|
|
+ IN USHORT usMinuend,
|
|
|
+ IN USHORT usSubtrahend,
|
|
|
+ OUT USHORT* pusResult)
|
|
|
+{
|
|
|
+ HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
|
|
|
+ *pusResult = USHORT_ERROR;
|
|
|
+
|
|
|
+ if (usMinuend >= usSubtrahend)
|
|
|
+ {
|
|
|
+ *pusResult = (usMinuend - usSubtrahend);
|
|
|
+ hr = S_OK;
|
|
|
+ }
|
|
|
+
|
|
|
+ return hr;
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+// WORD subtraction
|
|
|
+//
|
|
|
+#define WordSub UShortSub
|
|
|
+
|
|
|
+
|
|
|
+//
|
|
|
+// UINT subtraction
|
|
|
+//
|
|
|
+__inline
|
|
|
+HRESULT
|
|
|
+UIntSub(
|
|
|
+ IN UINT uMinuend,
|
|
|
+ IN UINT uSubtrahend,
|
|
|
+ OUT UINT* puResult)
|
|
|
+{
|
|
|
+ HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
|
|
|
+ *puResult = UINT_ERROR;
|
|
|
+
|
|
|
+ if (uMinuend >= uSubtrahend)
|
|
|
+ {
|
|
|
+ *puResult = (uMinuend - uSubtrahend);
|
|
|
+ hr = S_OK;
|
|
|
+ }
|
|
|
+
|
|
|
+ return hr;
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+// UINT_PTR subtraction
|
|
|
+//
|
|
|
+#define UIntPtrSub SizeTSub
|
|
|
+
|
|
|
+//
|
|
|
+// ULONG subtraction
|
|
|
+//
|
|
|
+__inline
|
|
|
+HRESULT
|
|
|
+ULongSub(
|
|
|
+ IN ULONG ulMinuend,
|
|
|
+ IN ULONG ulSubtrahend,
|
|
|
+ OUT ULONG* pulResult)
|
|
|
+{
|
|
|
+ HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
|
|
|
+ *pulResult = ULONG_ERROR;
|
|
|
+
|
|
|
+ if (ulMinuend >= ulSubtrahend)
|
|
|
+ {
|
|
|
+ *pulResult = (ulMinuend - ulSubtrahend);
|
|
|
+ hr = S_OK;
|
|
|
+ }
|
|
|
+
|
|
|
+ return hr;
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+// ULONG_PTR subtraction
|
|
|
+//
|
|
|
+#ifdef _WIN64
|
|
|
+#define ULongPtrSub ULongLongSub
|
|
|
+#else
|
|
|
+__inline
|
|
|
+HRESULT
|
|
|
+ULongPtrSub(
|
|
|
+ IN ULONG_PTR ulMinuend,
|
|
|
+ IN ULONG_PTR ulSubtrahend,
|
|
|
+ OUT ULONG_PTR* pulResult)
|
|
|
+{
|
|
|
+ return ULongSub((ULONG)ulMinuend, (ULONG)ulSubtrahend, (ULONG*)pulResult);
|
|
|
+}
|
|
|
+#endif // _WIN64
|
|
|
+
|
|
|
+
|
|
|
+//
|
|
|
+// DWORD subtraction
|
|
|
+//
|
|
|
+#define DWordSub ULongSub
|
|
|
+
|
|
|
+//
|
|
|
+// DWORD_PTR subtraction
|
|
|
+//
|
|
|
+#define DWordPtrSub ULongPtrSub
|
|
|
+
|
|
|
+//
|
|
|
+// size_t subtraction
|
|
|
+//
|
|
|
+__inline
|
|
|
+HRESULT
|
|
|
+SizeTSub(
|
|
|
+ IN size_t Minuend,
|
|
|
+ IN size_t Subtrahend,
|
|
|
+ OUT size_t* pResult)
|
|
|
+{
|
|
|
+ HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
|
|
|
+ *pResult = SIZET_ERROR;
|
|
|
+
|
|
|
+ if (Minuend >= Subtrahend)
|
|
|
+ {
|
|
|
+ *pResult = (Minuend - Subtrahend);
|
|
|
+ hr = S_OK;
|
|
|
+ }
|
|
|
+
|
|
|
+ return hr;
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+// SIZE_T subtraction
|
|
|
+//
|
|
|
+#define SIZETSub ULongPtrSub
|
|
|
+
|
|
|
+//
|
|
|
+// ULONGLONG subtraction
|
|
|
+//
|
|
|
+__inline
|
|
|
+HRESULT
|
|
|
+ULongLongSub(
|
|
|
+ IN ULONGLONG ullMinuend,
|
|
|
+ IN ULONGLONG ullSubtrahend,
|
|
|
+ OUT ULONGLONG* pullResult)
|
|
|
+{
|
|
|
+ HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
|
|
|
+ *pullResult = ULONGLONG_ERROR;
|
|
|
+
|
|
|
+ if (ullMinuend >= ullSubtrahend)
|
|
|
+ {
|
|
|
+ *pullResult = (ullMinuend - ullSubtrahend);
|
|
|
+ hr = S_OK;
|
|
|
+ }
|
|
|
+
|
|
|
+ return hr;
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+// USHORT multiplication
|
|
|
+//
|
|
|
+__inline
|
|
|
+HRESULT
|
|
|
+UShortMult(
|
|
|
+ IN USHORT usMultiplicand,
|
|
|
+ IN USHORT usMultiplier,
|
|
|
+ OUT USHORT* pusResult)
|
|
|
+{
|
|
|
+ ULONG ulResult = ((ULONG)usMultiplicand) * (ULONG)usMultiplier;
|
|
|
+
|
|
|
+ return ULongToUShort(ulResult, pusResult);
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+// WORD multiplication
|
|
|
+//
|
|
|
+#define WordMult UShortMult
|
|
|
+
|
|
|
+//
|
|
|
+// UINT multiplication
|
|
|
+//
|
|
|
+__inline
|
|
|
+HRESULT
|
|
|
+UIntMult(
|
|
|
+ IN UINT uMultiplicand,
|
|
|
+ IN UINT uMultiplier,
|
|
|
+ OUT UINT* puResult)
|
|
|
+{
|
|
|
+ ULONGLONG ull64Result = UInt32x32To64(uMultiplicand, uMultiplier);
|
|
|
+
|
|
|
+ return ULongLongToUInt(ull64Result, puResult);
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+// UINT_PTR multiplication
|
|
|
+//
|
|
|
+#ifdef _WIN64
|
|
|
+#define UIntPtrMult ULongLongMult
|
|
|
+#else
|
|
|
+__inline
|
|
|
+HRESULT
|
|
|
+UIntPtrMult(
|
|
|
+ IN UINT_PTR ulMultiplicand,
|
|
|
+ IN UINT_PTR ulMultiplier,
|
|
|
+ OUT UINT_PTR* pulResult)
|
|
|
+{
|
|
|
+ return UIntMult((UINT)ulMultiplicand, (UINT)ulMultiplier, (UINT*)pulResult);
|
|
|
+}
|
|
|
+#endif // _WIN64
|
|
|
+
|
|
|
+//
|
|
|
+// ULONG multiplication
|
|
|
+//
|
|
|
+__inline
|
|
|
+HRESULT
|
|
|
+ULongMult(
|
|
|
+ IN ULONG ulMultiplicand,
|
|
|
+ IN ULONG ulMultiplier,
|
|
|
+ OUT ULONG* pulResult)
|
|
|
+{
|
|
|
+ ULONGLONG ull64Result = UInt32x32To64(ulMultiplicand, ulMultiplier);
|
|
|
+
|
|
|
+ return ULongLongToULong(ull64Result, pulResult);
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+// ULONG_PTR multiplication
|
|
|
+//
|
|
|
+#ifdef _WIN64
|
|
|
+#define ULongPtrMult ULongLongMult
|
|
|
+#else
|
|
|
+__inline
|
|
|
+HRESULT
|
|
|
+ULongPtrMult(
|
|
|
+ IN ULONG_PTR ulMultiplicand,
|
|
|
+ IN ULONG_PTR ulMultiplier,
|
|
|
+ OUT ULONG_PTR* pulResult)
|
|
|
+{
|
|
|
+ return ULongMult((ULONG)ulMultiplicand, (ULONG)ulMultiplier, (ULONG*)pulResult);
|
|
|
+}
|
|
|
+#endif // _WIN64
|
|
|
+
|
|
|
+
|
|
|
+//
|
|
|
+// DWORD multiplication
|
|
|
+//
|
|
|
+#define DWordMult ULongMult
|
|
|
+
|
|
|
+//
|
|
|
+// DWORD_PTR multiplication
|
|
|
+//
|
|
|
+#define DWordPtrMult ULongPtrMult
|
|
|
+
|
|
|
+//
|
|
|
+// size_t multiplication
|
|
|
+//
|
|
|
+#define SizeTMult UIntPtrMult
|
|
|
+
|
|
|
+//
|
|
|
+// SIZE_T multiplication
|
|
|
+//
|
|
|
+#define SIZETMult ULongPtrMult
|
|
|
+
|
|
|
+//
|
|
|
+// ULONGLONG multiplication
|
|
|
+//
|
|
|
+__inline
|
|
|
+HRESULT
|
|
|
+ULongLongMult(
|
|
|
+ IN ULONGLONG ullMultiplicand,
|
|
|
+ IN ULONGLONG ullMultiplier,
|
|
|
+ OUT ULONGLONG* pullResult)
|
|
|
+{
|
|
|
+ HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
|
|
|
+#ifdef _AMD64_
|
|
|
+ ULONGLONG u64ResultHigh;
|
|
|
+ ULONGLONG u64ResultLow;
|
|
|
+
|
|
|
+ *pullResult = ULONGLONG_ERROR;
|
|
|
+
|
|
|
+ u64ResultLow = UnsignedMultiply128(ullMultiplicand, ullMultiplier, &u64ResultHigh);
|
|
|
+ if (u64ResultHigh == 0)
|
|
|
+ {
|
|
|
+ *pullResult = u64ResultLow;
|
|
|
+ hr = S_OK;
|
|
|
+ }
|
|
|
+#else
|
|
|
+ // 64x64 into 128 is like 32.32 x 32.32.
|
|
|
+ //
|
|
|
+ // a.b * c.d = a*(c.d) + .b*(c.d) = a*c + a*.d + .b*c + .b*.d
|
|
|
+ // back in non-decimal notation where A=a*2^32 and C=c*2^32:
|
|
|
+ // A*C + A*d + b*C + b*d
|
|
|
+ // So there are four components to add together.
|
|
|
+ // result = (a*c*2^64) + (a*d*2^32) + (b*c*2^32) + (b*d)
|
|
|
+ //
|
|
|
+ // a * c must be 0 or there would be bits in the high 64-bits
|
|
|
+ // a * d must be less than 2^32 or there would be bits in the high 64-bits
|
|
|
+ // b * c must be less than 2^32 or there would be bits in the high 64-bits
|
|
|
+ // then there must be no overflow of the resulting values summed up.
|
|
|
+
|
|
|
+ ULONG dw_a;
|
|
|
+ ULONG dw_b;
|
|
|
+ ULONG dw_c;
|
|
|
+ ULONG dw_d;
|
|
|
+ ULONGLONG ad = 0;
|
|
|
+ ULONGLONG bc = 0;
|
|
|
+ ULONGLONG bd = 0;
|
|
|
+ ULONGLONG ullResult = 0;
|
|
|
+
|
|
|
+ *pullResult = ULONGLONG_ERROR;
|
|
|
+
|
|
|
+ dw_a = (ULONG)(ullMultiplicand >> 32);
|
|
|
+ dw_c = (ULONG)(ullMultiplier >> 32);
|
|
|
+
|
|
|
+ // common case -- if high dwords are both zero, no chance for overflow
|
|
|
+ if ((dw_a == 0) && (dw_c == 0))
|
|
|
+ {
|
|
|
+ dw_b = (DWORD)ullMultiplicand;
|
|
|
+ dw_d = (DWORD)ullMultiplier;
|
|
|
+
|
|
|
+ *pullResult = (((ULONGLONG)dw_b) * (ULONGLONG)dw_d);
|
|
|
+ hr = S_OK;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // a * c must be 0 or there would be bits set in the high 64-bits
|
|
|
+ if ((dw_a == 0) ||
|
|
|
+ (dw_c == 0))
|
|
|
+ {
|
|
|
+ dw_d = (DWORD)ullMultiplier;
|
|
|
+
|
|
|
+ // a * d must be less than 2^32 or there would be bits set in the high 64-bits
|
|
|
+ ad = (((ULONGLONG)dw_a) * (ULONGLONG)dw_d);
|
|
|
+ if ((ad & HIDWORD_MASK) == 0)
|
|
|
+ {
|
|
|
+ dw_b = (DWORD)ullMultiplicand;
|
|
|
+
|
|
|
+ // b * c must be less than 2^32 or there would be bits set in the high 64-bits
|
|
|
+ bc = (((ULONGLONG)dw_b) * (ULONGLONG)dw_c);
|
|
|
+ if ((bc & HIDWORD_MASK) == 0)
|
|
|
+ {
|
|
|
+ // now sum them all up checking for overflow.
|
|
|
+ // shifting is safe because we already checked for overflow above
|
|
|
+ if (SUCCEEDED(ULongLongAdd(bc << 32, ad << 32, &ullResult)))
|
|
|
+ {
|
|
|
+ // b * d
|
|
|
+ bd = (((ULONGLONG)dw_b) * (ULONGLONG)dw_d);
|
|
|
+
|
|
|
+ if (SUCCEEDED(ULongLongAdd(ullResult, bd, &ullResult)))
|
|
|
+ {
|
|
|
+ *pullResult = ullResult;
|
|
|
+ hr = S_OK;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+#endif // _AMD64_
|
|
|
+
|
|
|
+ return hr;
|
|
|
+}
|
|
|
+
|
|
|
+#endif // _INTSAFE_H_INCLUDED_
|