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/******************************************************************
6* *
7* intsafe.h -- This module defines helper functions to prevent *
8* integer overflow issues. *
9* *
10* *
11******************************************************************/
12#ifndef _INTSAFE_H_INCLUDED_
13#define _INTSAFE_H_INCLUDED_
14
15#if _MSC_VER > 1000
16#pragma once
17#endif
18
19#include <specstrings.h> // for IN, etc.
20
21#define INTSAFE_E_ARITHMETIC_OVERFLOW ((HRESULT)0x80070216L) // 0x216 = 534 = ERROR_ARITHMETIC_OVERFLOW
22
23#ifndef LOWORD
24#define LOWORD(l) ((WORD)(((DWORD_PTR)(l)) & 0xffff))
25#endif
26
27#ifndef HIWORD
28#define HIWORD(l) ((WORD)(((DWORD_PTR)(l)) >> 16))
29#endif
30
31#define HIDWORD(_qw) ((ULONG)((_qw) >> 32))
32#define LODWORD(_qw) ((ULONG)(_qw))
33
34#if defined(MIDL_PASS) || defined(RC_INVOKED) || defined(_M_CEE_PURE) \
35 || defined(_M_AMD64) || defined(__ARM_ARCH)
36
37#ifndef UInt32x32To64
38#define UInt32x32To64(a, b) ((unsigned __int64)((ULONG)(a)) * (unsigned __int64)((ULONG)(b)))
39#endif
40
41#elif defined(_M_IX86)
42
43#ifndef UInt32x32To64
44#define UInt32x32To64(a, b) (unsigned __int64)((unsigned __int64)(ULONG)(a) * (ULONG)(b))
45#endif
46
47#else
48
49#error Must define a target architecture.
50
51#endif
52
53#define INT_MAX 2147483647
54#define LONG_MAX 2147483647L
55#define USHRT_MAX 0xffff
56#define UINT_MAX 0xffffffff
57#define ULONG_MAX 0xffffffffUL
58#define DWORD_MAX 0xffffffffUL
59
60//
61// It is common for -1 to be used as an error value for various types
62//
63#define USHORT_ERROR (0xffff)
64#define INT_ERROR (-1)
65#define LONG_ERROR (-1L)
66#define UINT_ERROR (0xffffffff)
67#define ULONG_ERROR (0xffffffffUL)
68#ifdef _MSC_VER
69#define ULONGLONG_ERROR (0xffffffffffffffffui64)
70#define HIDWORD_MASK (0xffffffff00000000ui64)
71#else // _MSC_VER
72#define ULONGLONG_ERROR (0xffffffffffffffffULL)
73#define HIDWORD_MASK (0xffffffff00000000ULL)
74#endif // _MSC_VER
75#ifdef _WIN64
76#define SIZET_ERROR ULONGLONG_ERROR
77#else
78#define SIZET_ERROR ULONG_ERROR
79#endif
80
81//
82// We make some assumptions about the sizes of various types. Let's be
83// explicit about those assumptions and check them.
84//
85C_ASSERT(sizeof(unsigned short) == 2);
86C_ASSERT(sizeof(unsigned int) == 4);
87C_ASSERT(sizeof(ULONG) == 4);
88
89//
90// INT -> signed char conversion
91//
92__inline
93HRESULT
94IntToSignedChar(
95 IN INT iOperand,
96 OUT signed char* pch)
97{
98 HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
99 *pch = 0;
100
101 if ((iOperand >= -128) && (iOperand <= 127))
102 {
103 *pch = (signed char)iOperand;
104 hr = S_OK;
105 }
106
107 return hr;
108}
109
110//
111// INT -> UCHAR conversion
112//
113__inline
114HRESULT
115IntToUChar(
116 IN INT iOperand,
117 OUT UCHAR* pch)
118{
119 HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
120 *pch = 0;
121
122 if ((iOperand >= 0) && (iOperand <= 255))
123 {
124 *pch = (UCHAR)iOperand;
125 hr = S_OK;
126 }
127
128 return hr;
129}
130
131//
132// LONG -> UCHAR conversion
133//
134__inline
135HRESULT
136LongToUChar(
137 IN LONG lOperand,
138 OUT UCHAR* pch)
139{
140 HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
141 *pch = 0;
142
143 if ((lOperand >= 0) && (lOperand <= 255))
144 {
145 *pch = (UCHAR)lOperand;
146 hr = S_OK;
147 }
148
149 return hr;
150}
151
152//
153// __inline is not sufficient. __forceinline is necessary.
154// If the function is not inlined and you link .objs compiled with different compiler switches,
155// you get one or the other function arbitrarily chosen.
156//
157// INT -> CHAR conversion
158//
159__forceinline
160HRESULT
161IntToChar(
162 IN INT iOperand,
163 OUT CHAR* pch)
164{
165#ifdef _CHAR_UNSIGNED
166 return IntToUChar(iOperand, (UCHAR*)pch);
167#else
168 return IntToSignedChar(iOperand, (signed char*)pch);
169#endif
170}
171
172//
173// INT -> USHORT conversion
174//
175__inline
176HRESULT
177IntToUShort(
178 IN INT iOperand,
179 OUT USHORT* pusResult)
180{
181 HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
182 *pusResult = USHORT_ERROR;
183
184 if ((iOperand >= 0) && (iOperand <= USHRT_MAX))
185 {
186 *pusResult = (USHORT)iOperand;
187 hr = S_OK;
188 }
189
190 return hr;
191}
192
193//
194// INT -> UINT conversion
195//
196__inline
197HRESULT
198IntToUInt(
199 IN INT iOperand,
200 OUT UINT* puResult)
201{
202 HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
203 *puResult = UINT_ERROR;
204
205 if (iOperand >= 0)
206 {
207 *puResult = (UINT)iOperand;
208 hr = S_OK;
209 }
210
211 return hr;
212}
213
214//
215// INT -> ULONG conversion
216//
217__inline
218HRESULT
219IntToULong(
220 IN INT iOperand,
221 OUT ULONG* pulResult)
222{
223 HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
224 *pulResult = ULONG_ERROR;
225
226 if (iOperand >= 0)
227 {
228 *pulResult = (ULONG)iOperand;
229 hr = S_OK;
230 }
231
232 return hr;
233}
234
235//
236// INT -> ULONGLONG conversion
237//
238__inline
239HRESULT
240IntToULongLong(
241 IN INT iOperand,
242 OUT ULONGLONG* pullResult)
243{
244 HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
245 *pullResult = ULONG_ERROR;
246
247 if (iOperand >= 0)
248 {
249 *pullResult = (ULONGLONG)iOperand;
250 hr = S_OK;
251 }
252
253 return hr;
254}
255
256//
257// UINT -> signed char conversion
258//
259__inline
260HRESULT
261UIntToSignedChar(
262 IN UINT uOperand,
263 OUT signed char* pch)
264{
265 HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
266 *pch = 0;
267
268 if (uOperand <= 127)
269 {
270 *pch = (signed char)uOperand;
271 hr = S_OK;
272 }
273
274 return hr;
275}
276
277//
278// UINT -> UCHAR conversion
279//
280__inline
281HRESULT
282UIntToUChar(
283 IN UINT uOperand,
284 OUT UCHAR* pch)
285{
286 HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
287 *pch = 0;
288
289 if (uOperand <= 255)
290 {
291 *pch = (UCHAR)uOperand;
292 hr = S_OK;
293 }
294
295 return hr;
296}
297
298//
299// UINT -> BYTE conversion
300//
301#define UIntToByte UIntToUChar
302
303//
304// __inline is not sufficient. __forceinline is necessary.
305// If the function is not inlined and you link .objs compiled with different compiler switches,
306// you get one or the other function arbitrarily chosen.
307//
308// UINT -> CHAR conversion
309//
310__forceinline
311HRESULT
312UIntToChar(
313 IN UINT uOperand,
314 OUT CHAR* pch)
315{
316#ifdef _CHAR_UNSIGNED
317 return UIntToUChar(uOperand, (UCHAR*)pch);
318#else
319 return UIntToSignedChar(uOperand, (signed char*)pch);
320#endif // _CHAR_UNSIGNED
321}
322
323//
324// UINT -> INT conversion
325//
326__inline
327HRESULT
328UIntToInt(
329 IN UINT uOperand,
330 OUT INT* piResult)
331{
332 HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
333 *piResult = INT_ERROR;
334
335 if (uOperand <= INT_MAX)
336 {
337 *piResult = (INT)uOperand;
338 hr = S_OK;
339 }
340
341 return hr;
342}
343
344//
345// UINT -> LONG conversion
346//
347__inline
348HRESULT
349UIntToLong(
350 IN UINT Operand,
351 OUT LONG* Result)
352{
353 if (Operand <= LONG_MAX)
354 {
355 *Result = (LONG)Operand;
356 return S_OK;
357 }
358 else
359 {
360 *Result = LONG_ERROR;
361 return INTSAFE_E_ARITHMETIC_OVERFLOW;
362 }
363}
364
365//
366// UINT -> ULONG conversion
367//
368__inline
369HRESULT
370UIntToULong(
371 IN UINT uOperand,
372 OUT ULONG* pulResult)
373{
374 *pulResult = (ULONG)uOperand;
375
376 return S_OK;
377}
378
379//
380// ULONG -> UCHAR conversion
381//
382__inline
383HRESULT
384ULongToSignedChar(
385 IN ULONG ulOperand,
386 OUT signed char* pch)
387{
388 HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
389 *pch = 0;
390
391 if (ulOperand <= 127)
392 {
393 *pch = (signed char)ulOperand;
394 hr = S_OK;
395 }
396
397 return hr;
398}
399
400//
401// ULONG -> UCHAR conversion
402//
403__inline
404HRESULT
405ULongToUChar(
406 IN ULONG ulOperand,
407 OUT unsigned char* pch)
408{
409 HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
410 *pch = 0;
411
412 if (ulOperand <= 255)
413 {
414 *pch = (unsigned char)ulOperand;
415 hr = S_OK;
416 }
417
418 return hr;
419}
420
421//
422// __inline is not sufficient. __forceinline is necessary.
423// If the function is not inlined and you link .objs compiled with different compiler switches,
424// you get one or the other function arbitrarily chosen.
425//
426// ULONG -> CHAR conversion
427//
428__forceinline
429HRESULT
430ULongToChar(
431 IN ULONG ulOperand,
432 OUT CHAR* pch)
433{
434#ifdef _CHAR_UNSIGNED
435 return ULongToUChar(ulOperand, (unsigned char*)pch);
436#else
437 return ULongToSignedChar(ulOperand, (signed char*)pch);
438#endif // _CHAR_UNSIGNED
439}
440
441//
442// ULONG -> USHORT conversion
443//
444__inline
445HRESULT
446ULongToUShort(
447 IN ULONG ulOperand,
448 OUT USHORT* pusResult)
449{
450 HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
451 *pusResult = USHORT_ERROR;
452
453 if (ulOperand <= USHRT_MAX)
454 {
455 *pusResult = (USHORT)ulOperand;
456 hr = S_OK;
457 }
458
459 return hr;
460}
461
462//
463// ULONG -> INT conversion
464//
465__inline
466HRESULT
467ULongToInt(
468 IN ULONG ulOperand,
469 OUT INT* piResult)
470{
471 if (ulOperand <= INT_MAX)
472 {
473 *piResult = (INT)ulOperand;
474 return S_OK;
475 }
476 else
477 {
478 *piResult = INT_ERROR;
479 return INTSAFE_E_ARITHMETIC_OVERFLOW;
480 }
481}
482
483//
484// ULONG -> UINT conversion
485//
486__inline
487HRESULT
488ULongToUInt(
489 IN ULONG ulOperand,
490 OUT UINT* puResult)
491{
492 *puResult = (UINT)ulOperand;
493
494 return S_OK;
495}
496
497//
498// ULONG -> LONG conversion
499//
500__inline
501HRESULT
502ULongToLong(
503 IN ULONG Operand,
504 OUT LONG* Result)
505{
506 if (Operand <= LONG_MAX)
507 {
508 *Result = (LONG)Operand;
509 return S_OK;
510 }
511 else
512 {
513 *Result = LONG_ERROR;
514 return INTSAFE_E_ARITHMETIC_OVERFLOW;
515 }
516}
517
518//
519// ULONGLONG -> INT conversion
520//
521__inline
522HRESULT
523ULongLongToInt(
524 IN ULONGLONG ullOperand,
525 OUT INT* piResult)
526{
527 if (ullOperand <= INT_MAX)
528 {
529 *piResult = (INT)ullOperand;
530 return S_OK;
531 }
532 else
533 {
534 *piResult = INT_ERROR;
535 return INTSAFE_E_ARITHMETIC_OVERFLOW;
536 }
537}
538
539//
540// ULONGLONG -> LONG conversion
541//
542__inline
543HRESULT
544ULongLongToLong(
545 IN ULONGLONG Operand,
546 OUT LONG* Result)
547{
548 if (Operand <= LONG_MAX)
549 {
550 *Result = (LONG)Operand;
551 return S_OK;
552 }
553 else
554 {
555 *Result = LONG_ERROR;
556 return INTSAFE_E_ARITHMETIC_OVERFLOW;
557 }
558}
559
560//
561// UINT -> USHORT conversion
562//
563__inline
564HRESULT
565UIntToUShort(
566 IN UINT uOperand,
567 OUT USHORT* pusResult)
568{
569 HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
570 *pusResult = USHORT_ERROR;
571
572 if (uOperand <= USHRT_MAX)
573 {
574 *pusResult = (USHORT)uOperand;
575 hr = S_OK;
576 }
577
578 return hr;
579}
580
581//
582// ULONGLONG -> USHORT conversion
583//
584__inline
585HRESULT
586ULongLongToUShort(
587 IN ULONGLONG ullOperand,
588 OUT USHORT* pusResult)
589{
590 HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
591 USHORT usResult = USHORT_ERROR;
592
593 if (ullOperand <= USHRT_MAX)
594 {
595 usResult = (USHORT)ullOperand;
596 hr = S_OK;
597 }
598 *pusResult = usResult;
599
600 return hr;
601}
602
603//
604// ULONGLONG -> ULONG conversion
605//
606__inline
607HRESULT
608ULongLongToULong(
609 IN ULONGLONG ullOperand,
610 OUT ULONG* pulResult)
611{
612 HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
613 *pulResult = ULONG_ERROR;
614
615 if (ullOperand <= ULONG_MAX)
616 {
617 *pulResult = (ULONG)ullOperand;
618 hr = S_OK;
619 }
620
621 return hr;
622}
623
624//
625// UINT_PTR -> ULONG conversion
626// ULONG_PTR -> ULONG conversion
627//
628#ifdef _WIN64
629
630#define UIntPtrToULong ULongLongToULong
631#define ULongPtrToULong ULongLongToULong
632
633#else
634
635__inline
636HRESULT
637UIntPtrToULong(
638 IN UINT_PTR Operand,
639 OUT ULONG* pResult)
640{
641 *pResult = (ULONG)Operand;
642 return S_OK;
643}
644
645__inline
646HRESULT
647ULongPtrToULong(
648 IN ULONG_PTR Operand,
649 OUT ULONG* pResult)
650{
651 *pResult = (ULONG)Operand;
652 return S_OK;
653}
654
655#endif
656
657//
658// ULONGLONG -> UINT conversion
659//
660__inline
661HRESULT
662ULongLongToUInt(
663 IN ULONGLONG ullOperand,
664 OUT UINT* puResult)
665{
666 HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
667 *puResult = UINT_ERROR;
668
669 if (ullOperand <= UINT_MAX)
670 {
671 *puResult = (UINT)ullOperand;
672 hr = S_OK;
673 }
674
675 return hr;
676}
677
678//
679// UINT_PTR -> UINT conversion
680// ULONG_PTR -> UINT conversion
681//
682#ifdef _WIN64
683
684#define UIntPtrToUInt ULongLongToUInt
685#define ULongPtrToUInt ULongLongToUInt
686
687#else
688
689__inline
690HRESULT
691UIntPtrToUInt(
692 IN UINT_PTR Operand,
693 OUT UINT* pResult)
694{
695 *pResult = (UINT)Operand;
696 return S_OK;
697}
698
699__inline
700HRESULT
701ULongPtrToUInt(
702 IN ULONG_PTR Operand,
703 OUT UINT* pResult)
704{
705 *pResult = (UINT)Operand;
706 return S_OK;
707}
708
709#endif
710
711//
712// * -> BYTE conversion (BYTE is always unsigned char)
713//
714#define IntToByte IntToUChar
715#define UIntToByte UIntToUChar
716#define LongToByte LongToUChar
717#define ULongToByte ULongToUChar
718
719//
720// * -> WORD conversion (WORD is always unsigned short)
721//
722#define IntToWord IntToUShort
723#define LongToWord LongToUShort
724#define LongLongToWord LongLongToUShort
725#define UIntToWord UIntToUShort
726#define ULongToWord ULongToUShort
727#define ULongLongToWord ULongLongToUShort
728#define UIntPtrToWord UIntPtrToUShort
729#define ULongPtrToWord ULongPtrToUShort
730#define SizeTToWord SizeTToUShort
731#define SIZETToWord SIZETToUShort
732
733//
734// WORD -> * conversion (WORD is always unsigned short)
735//
736#define WordToUChar UShortToUChar
737#define WordToByte UShortToByte
738#define WordToChar UShortToChar
739#define WordToSignedChar UShortToSignedChar
740#define WordToInt UShortToInt
741#define WordToLong UShortToLong
742#define WordToLongLong UShortToLongLong
743#define WordToIntPtr UShortToIntPtr
744#define WordToLongPtr UShortToLongPtr
745
746//
747// * -> DWORD conversion (DWORD is always ULONG)
748//
749#define CharToDWord CharToULong
750#define SignedCharToDWord SignedCharToULong
751#define ShortToDWord ShortToULong
752#define IntToDWord IntToULong
753#define LongToDWord LongToULong
754#define LongLongToDWord LongLongToULong
755#define UIntToDWord UIntToULong
756#define ULongLongToDWord ULongLongToULong
757#define IntPtrToDWord IntPtrToULong
758#define LongPtrToDWord LongPtrToULong
759#define UIntPtrToDWord UIntPtrToULong
760#define ULongPtrToDWord ULongPtrToULong
761#define SizeTToDWord SizeTToULong
762#define SIZETToDWord SIZETToULong
763
764//
765// DWORD -> * conversion (DWORD is always ULONG)
766//
767#define DWordToChar ULongToChar
768#define DWordToUChar ULongToUChar
769#define DWordToByte ULongToByte
770#define DWordToSignedChar ULongToSignedChar
771#define DWordToUShort ULongToUShort
772#define DWordToUInt ULongToUInt
773#define DWordToInt ULongToInt
774#define DWordToLong ULongToLong
775#define DWordToLongLong ULongToLongLong
776#define DWordToIntPtr ULongToIntPtr
777#define DWordToLongPtr ULongToLongPtr
778
779
780//
781// * -> UINT_PTR conversion (UINT_PTR is UINT on Win32, ULONGLONG on Win64)
782//
783#ifdef _WIN64
784#define CharToUIntPtr CharToULongLong
785#define SignedCharToUIntPtr SignedCharToULongLong
786#define ShortToUIntPtr ShortToULongLong
787#define IntToUIntPtr IntToULongLong
788#define LongToUIntPtr LongToULongLong
789#define LongLongToUIntPtr LongLongToULongLong
790#define IntPtrToUIntPtr IntPtrToULongLong
791#define LongPtrToUIntPtr LongPtrToULongLong
792#else
793#define CharToUIntPtr CharToUInt
794#define SignedCharToUIntPtr SignedCharToUInt
795#define ShortToUIntPtr ShortToUInt
796
797__inline
798HRESULT
799IntToUIntPtr(
800 IN INT iOperand,
801 OUT UINT_PTR* puResult)
802{
803 return IntToUInt(iOperand, (UINT*)puResult);
804}
805
806#define LongToUIntPtr LongToUInt
807#define LongLongToUIntPtr LongLongToUInt
808
809#define IntPtrToUIntPtr IntPtrToUInt
810#define LongPtrToUIntPtr LongPtrToUInt
811#endif
812
813__inline
814HRESULT
815ULongLongToUIntPtr(
816 IN ULONGLONG ullOperand,
817 OUT UINT_PTR* puResult)
818{
819#ifdef _WIN64
820 *puResult = ullOperand;
821 return S_OK;
822#else
823 return ULongLongToUInt(ullOperand, (UINT*)puResult);
824#endif
825}
826
827
828//
829// UINT_PTR -> * conversion (UINT_PTR is UINT on Win32, ULONGLONG on Win64)
830//
831#ifdef _WIN64
832#define UIntPtrToUShort ULongLongToUShort
833#define UIntPtrToInt ULongLongToInt
834#define UIntPtrToLong ULongLongToLong
835#define UIntPtrToLongLong ULongLongToLongLong
836#define UIntPtrToIntPtr ULongLongToIntPtr
837#define UIntPtrToLongPtr ULongLongToLongPtr
838#else
839
840__inline
841HRESULT
842UIntPtrToUShort(
843 IN UINT_PTR uOperand,
844 OUT USHORT* pusResult)
845{
846 return UIntToUShort((UINT)uOperand, pusResult);
847}
848
849__inline
850HRESULT
851UIntPtrToInt(
852 IN UINT_PTR uOperand,
853 OUT INT* piResult)
854{
855 return UIntToInt((UINT)uOperand, piResult);
856}
857
858__inline
859HRESULT
860UIntPtrToLong(
861 IN UINT_PTR Operand,
862 OUT LONG* Result)
863{
864 return UIntToLong((UINT)Operand, Result);
865}
866
867#define UIntPtrToLongLong UIntToLongLong
868#define UIntPtrToIntPtr UIntToIntPtr
869#define UIntPtrToLongPtr UIntToLongPtr
870#endif
871
872
873//
874// * -> ULONG_PTR conversion (ULONG_PTR is ULONG on Win32, ULONGLONG on Win64)
875//
876#ifdef _WIN64
877#define CharToULongPtr CharToULongLong
878#define SignedCharToULongPtr SignedCharToULongLong
879#define ShortToULongPtr ShortToULongLong
880#define IntToULongPtr IntToULongLong
881#define LongToULongPtr LongToULongLong
882#define LongLongToULongPtr LongLongToULongLong
883#define IntPtrToULongPtr IntPtrToULongLong
884#define LongPtrToULongPtr LongPtrToULongLong
885#else
886#define CharToULongPtr CharToULong
887#define SignedCharToULongPtr SignedCharToULong
888#define ShortToULongPtr ShortToULong
889
890__inline
891HRESULT
892IntToULongPtr(
893 IN INT iOperand,
894 OUT ULONG_PTR* pulResult)
895{
896 return IntToULong(iOperand, (ULONG*)pulResult);
897}
898
899#define LongToULongPtr LongToULong
900#define LongLongToULongPtr LongLongToULong
901
902#define IntPtrToULongPtr IntPtrToULong
903#define LongPtrToULongPtr LongPtrToULong
904#endif
905
906__inline
907HRESULT
908ULongLongToULongPtr(
909 IN ULONGLONG ullOperand,
910 OUT ULONG_PTR* pulResult)
911{
912#ifdef _WIN64
913 *pulResult = ullOperand;
914 return S_OK;
915#else
916 return ULongLongToULong(ullOperand, (ULONG*)pulResult);
917#endif
918}
919
920
921//
922// ULONG_PTR -> * conversion (ULONG_PTR is ULONG on Win32, ULONGLONG on Win64)
923//
924#ifdef _WIN64
925#define ULongPtrToUShort ULongLongToUShort
926#define ULongPtrToInt ULongLongToInt
927#define ULongPtrToLong ULongLongToLong
928#define ULongPtrToLongLong ULongLongToLongLong
929#define ULongPtrToIntPtr ULongLongToIntPtr
930#define ULongPtrToLongPtr ULongLongToLongPtr
931#else
932
933__inline
934HRESULT
935ULongPtrToUShort(
936 IN ULONG_PTR ulOperand,
937 OUT USHORT* pusResult)
938{
939 return ULongToUShort((ULONG)ulOperand, pusResult);
940}
941
942__inline
943HRESULT
944ULongPtrToInt(
945 IN ULONG_PTR ulOperand,
946 OUT INT* piResult)
947{
948 return ULongToInt((ULONG)ulOperand, piResult);
949}
950
951__inline
952HRESULT
953ULongPtrToLong(
954 IN ULONG_PTR Operand,
955 OUT LONG* Result)
956{
957 return ULongToLong((ULONG)Operand, Result);
958}
959
960#define ULongPtrToLongLong ULongToLongLong
961#define ULongPtrToIntPtr ULongToIntPtr
962#define ULongPtrToLongPtr ULongToLongPtr
963#endif
964
965//
966// * -> size_t conversion (size_t is always UINT_PTR)
967//
968#define CharToSizeT CharToUIntPtr
969#define SignedCharToSizeT SignedCharToUIntPtr
970#define ShortToSizeT ShortToUIntPtr
971#define IntToSizeT IntToUIntPtr
972#define LongToSizeT LongToUIntPtr
973#define LongLongToSizeT LongLongToUIntPtr
974#define ULongLongToSizeT ULongLongToUIntPtr
975#define IntPtrToSizeT IntPtrToUIntPtr
976#define LongPtrToSizeT LongPtrToUIntPtr
977
978//
979// size_t -> * conversion (size_t is always UINT_PTR)
980//
981#define SizeTToUShort UIntPtrToUShort
982#define SizeTToUInt UIntPtrToUInt
983#define SizeTToULong UIntPtrToULong
984#define SizeTToInt UIntPtrToInt
985#define SizeTToLong UIntPtrToLong
986#define SizeTToLongLong UIntPtrToLongLong
987#define SizeTToIntPtr UIntPtrToIntPtr
988#define SizeTToLongPtr UIntPtrToLongPtr
989
990//
991// * -> SIZE_T conversion (SIZE_T is always ULONG_PTR)
992//
993#define CharToSIZET CharToULongPtr
994#define SignedCharToSIZET SignedCharToULongPtr
995#define ShortToSIZET ShortToULongPtr
996#define IntToSIZET IntToULongPtr
997#define LongToSIZET LongToULongPtr
998#define LongLongToSIZET LongLongToULongPtr
999#define IntPtrToSIZET IntPtrToULongPtr
1000#define LongPtrToSIZET LongPtrToULongPtr
1001#define ULongLongToSIZET ULongLongToULongPtr
1002
1003//
1004// SIZE_T -> * conversion (SIZE_T is always ULONG_PTR)
1005//
1006#define SIZETToUShort ULongPtrToUShort
1007#define SIZETToUInt ULongPtrToUInt
1008#define SIZETToULong ULongPtrToULong
1009#define SIZETToUIntPtr ULongPtrToUIntPtr
1010#define SIZETToULongPtr ULongPtrToULongPtr
1011#define SIZETToInt ULongPtrToInt
1012#define SIZETToLong ULongPtrToLong
1013#define SIZETToLongLong ULongPtrToLongLong
1014#define SIZETToIntPtr ULongPtrToIntPtr
1015#define SIZETToLongPtr ULongPtrToLongPtr
1016
1017//
1018// * -> DWORD_PTR conversion (DWORD_PTR is always ULONG_PTR)
1019//
1020#define CharToDWordPtr CharToULongPtr
1021#define SignedCharToDWordPtr SignedCharToULongPtr
1022#define ShortToDWordPtr ShortToULongPtr
1023#define IntToDWordPtr IntToULongPtr
1024#define LongToDWordPtr LongToULongPtr
1025#define LongLongToDWordPtr LongLongToULongPtr
1026#define ULongLongToDWordPtr ULongLongToULongPtr
1027#define IntPtrToDWordPtr IntPtrToULongPtr
1028#define LongPtrToDWordPtr LongPtrToULongPtr
1029
1030//
1031// DWORD_PTR -> * conversion (DWORD_PTR is always ULONG_PTR)
1032//
1033#define DWordPtrToUShort ULongPtrToUShort
1034#define DWordPtrToUInt ULongPtrToUInt
1035#define DWordPtrToULong ULongPtrToULong
1036#define DWordPtrToDWord ULongPtrToDWord
1037#define DWordPtrToInt ULongPtrToInt
1038#define DWordPtrToLong ULongPtrToLong
1039#define DWordPtrToLongLong ULongPtrToLongLong
1040#define DWordPtrToIntPtr ULongPtrToIntPtr
1041#define DWordPtrToLongPtr ULongPtrToLongPtr
1042
1043//
1044// USHORT addition
1045//
1046__inline
1047HRESULT
1048UShortAdd(
1049 IN USHORT usAugend,
1050 IN USHORT usAddend,
1051 OUT USHORT* pusResult)
1052{
1053 HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
1054 *pusResult = USHORT_ERROR;
1055
1056 if (((USHORT)(usAugend + usAddend)) >= usAugend)
1057 {
1058 *pusResult = (usAugend + usAddend);
1059 hr = S_OK;
1060 }
1061
1062 return hr;
1063}
1064
1065//
1066// WORD addtition
1067//
1068#define WordAdd UShortAdd
1069
1070//
1071// UINT addition
1072//
1073__inline
1074HRESULT
1075UIntAdd(
1076 IN UINT uAugend,
1077 IN UINT uAddend,
1078 OUT UINT* puResult)
1079{
1080 HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
1081 *puResult = UINT_ERROR;
1082
1083 if ((uAugend + uAddend) >= uAugend)
1084 {
1085 *puResult = (uAugend + uAddend);
1086 hr = S_OK;
1087 }
1088
1089 return hr;
1090}
1091
1092//
1093// UINT_PTR addition
1094//
1095#define UIntPtrAdd SizeTAdd
1096
1097//
1098// ULONG addition
1099//
1100__inline
1101HRESULT
1102ULongAdd(
1103 IN ULONG ulAugend,
1104 IN ULONG ulAddend,
1105 OUT ULONG* pulResult)
1106{
1107 HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
1108 *pulResult = ULONG_ERROR;
1109
1110 if ((ulAugend + ulAddend) >= ulAugend)
1111 {
1112 *pulResult = (ulAugend + ulAddend);
1113 hr = S_OK;
1114 }
1115
1116 return hr;
1117}
1118
1119//
1120// ULONG_PTR addition
1121//
1122#ifdef _WIN64
1123#define ULongPtrAdd ULongLongAdd
1124#else
1125__inline
1126HRESULT
1127ULongPtrAdd(
1128 IN ULONG_PTR ulAugend,
1129 IN ULONG_PTR ulAddend,
1130 OUT ULONG_PTR* pulResult)
1131{
1132 return ULongAdd((ULONG)ulAugend, (ULONG)ulAddend, (ULONG*)pulResult);
1133}
1134#endif // _WIN64
1135
1136//
1137// DWORD addition
1138//
1139#define DWordAdd ULongAdd
1140
1141//
1142// DWORD_PTR addition
1143//
1144#define DWordPtrAdd ULongPtrAdd
1145
1146//
1147// size_t addition
1148//
1149__inline
1150HRESULT
1151SizeTAdd(
1152 IN size_t Augend,
1153 IN size_t Addend,
1154 OUT size_t* pResult)
1155{
1156 HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
1157 *pResult = SIZET_ERROR;
1158
1159 if ((Augend + Addend) >= Augend)
1160 {
1161 *pResult = (Augend + Addend);
1162 hr = S_OK;
1163 }
1164
1165 return hr;
1166}
1167
1168//
1169// SIZE_T addition
1170//
1171#define SIZETAdd ULongPtrAdd
1172
1173//
1174// ULONGLONG addition
1175//
1176__inline
1177HRESULT
1178ULongLongAdd(
1179 IN ULONGLONG ullAugend,
1180 IN ULONGLONG ullAddend,
1181 OUT ULONGLONG* pullResult)
1182{
1183 HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
1184 *pullResult = ULONGLONG_ERROR;
1185
1186 if ((ullAugend + ullAddend) >= ullAugend)
1187 {
1188 *pullResult = (ullAugend + ullAddend);
1189 hr = S_OK;
1190 }
1191
1192 return hr;
1193}
1194
1195//
1196// USHORT subtraction
1197//
1198__inline
1199HRESULT
1200UShortSub(
1201 IN USHORT usMinuend,
1202 IN USHORT usSubtrahend,
1203 OUT USHORT* pusResult)
1204{
1205 HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
1206 *pusResult = USHORT_ERROR;
1207
1208 if (usMinuend >= usSubtrahend)
1209 {
1210 *pusResult = (usMinuend - usSubtrahend);
1211 hr = S_OK;
1212 }
1213
1214 return hr;
1215}
1216
1217//
1218// WORD subtraction
1219//
1220#define WordSub UShortSub
1221
1222
1223//
1224// UINT subtraction
1225//
1226__inline
1227HRESULT
1228UIntSub(
1229 IN UINT uMinuend,
1230 IN UINT uSubtrahend,
1231 OUT UINT* puResult)
1232{
1233 HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
1234 *puResult = UINT_ERROR;
1235
1236 if (uMinuend >= uSubtrahend)
1237 {
1238 *puResult = (uMinuend - uSubtrahend);
1239 hr = S_OK;
1240 }
1241
1242 return hr;
1243}
1244
1245//
1246// UINT_PTR subtraction
1247//
1248#define UIntPtrSub SizeTSub
1249
1250//
1251// ULONG subtraction
1252//
1253__inline
1254HRESULT
1255ULongSub(
1256 IN ULONG ulMinuend,
1257 IN ULONG ulSubtrahend,
1258 OUT ULONG* pulResult)
1259{
1260 HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
1261 *pulResult = ULONG_ERROR;
1262
1263 if (ulMinuend >= ulSubtrahend)
1264 {
1265 *pulResult = (ulMinuend - ulSubtrahend);
1266 hr = S_OK;
1267 }
1268
1269 return hr;
1270}
1271
1272//
1273// ULONG_PTR subtraction
1274//
1275#ifdef _WIN64
1276#define ULongPtrSub ULongLongSub
1277#else
1278__inline
1279HRESULT
1280ULongPtrSub(
1281 IN ULONG_PTR ulMinuend,
1282 IN ULONG_PTR ulSubtrahend,
1283 OUT ULONG_PTR* pulResult)
1284{
1285 return ULongSub((ULONG)ulMinuend, (ULONG)ulSubtrahend, (ULONG*)pulResult);
1286}
1287#endif // _WIN64
1288
1289
1290//
1291// DWORD subtraction
1292//
1293#define DWordSub ULongSub
1294
1295//
1296// DWORD_PTR subtraction
1297//
1298#define DWordPtrSub ULongPtrSub
1299
1300//
1301// size_t subtraction
1302//
1303__inline
1304HRESULT
1305SizeTSub(
1306 IN size_t Minuend,
1307 IN size_t Subtrahend,
1308 OUT size_t* pResult)
1309{
1310 HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
1311 *pResult = SIZET_ERROR;
1312
1313 if (Minuend >= Subtrahend)
1314 {
1315 *pResult = (Minuend - Subtrahend);
1316 hr = S_OK;
1317 }
1318
1319 return hr;
1320}
1321
1322//
1323// SIZE_T subtraction
1324//
1325#define SIZETSub ULongPtrSub
1326
1327//
1328// ULONGLONG subtraction
1329//
1330__inline
1331HRESULT
1332ULongLongSub(
1333 IN ULONGLONG ullMinuend,
1334 IN ULONGLONG ullSubtrahend,
1335 OUT ULONGLONG* pullResult)
1336{
1337 HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
1338 *pullResult = ULONGLONG_ERROR;
1339
1340 if (ullMinuend >= ullSubtrahend)
1341 {
1342 *pullResult = (ullMinuend - ullSubtrahend);
1343 hr = S_OK;
1344 }
1345
1346 return hr;
1347}
1348
1349//
1350// USHORT multiplication
1351//
1352__inline
1353HRESULT
1354UShortMult(
1355 IN USHORT usMultiplicand,
1356 IN USHORT usMultiplier,
1357 OUT USHORT* pusResult)
1358{
1359 ULONG ulResult = ((ULONG)usMultiplicand) * (ULONG)usMultiplier;
1360
1361 return ULongToUShort(ulResult, pusResult);
1362}
1363
1364//
1365// WORD multiplication
1366//
1367#define WordMult UShortMult
1368
1369//
1370// UINT multiplication
1371//
1372__inline
1373HRESULT
1374UIntMult(
1375 IN UINT uMultiplicand,
1376 IN UINT uMultiplier,
1377 OUT UINT* puResult)
1378{
1379 ULONGLONG ull64Result = UInt32x32To64(uMultiplicand, uMultiplier);
1380
1381 return ULongLongToUInt(ull64Result, puResult);
1382}
1383
1384//
1385// ULONG multiplication
1386//
1387__inline
1388HRESULT
1389ULongMult(
1390 IN ULONG ulMultiplicand,
1391 IN ULONG ulMultiplier,
1392 OUT ULONG* pulResult)
1393{
1394 ULONGLONG ull64Result = UInt32x32To64(ulMultiplicand, ulMultiplier);
1395
1396 return ULongLongToULong(ull64Result, pulResult);
1397}
1398
1399//
1400// DWORD multiplication
1401//
1402#define DWordMult ULongMult
1403
1404//
1405// DWORD_PTR multiplication
1406//
1407#define DWordPtrMult ULongPtrMult
1408
1409#endif // _INTSAFE_H_INCLUDED_
1410