added Linux specific files

This commit is contained in:
Hadis Kakanejadi Fard 2017-01-25 10:49:09 -08:00
parent 7ff6b40fc0
commit 9714d94cd5
16 changed files with 15246 additions and 0 deletions

View file

@ -0,0 +1,2805 @@
//-----------------------------------------------------------------------------
// File: FormattedPrint.cpp
//
//
// Contents: Contains functions for handling Windows format strings
// and UTF-16 on non-Windows platforms
//
// Microsoft Drivers 4.0 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the ""Software""),
// to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and / or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions :
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//---------------------------------------------------------------------------------------------------------------------------------
#include <FormattedPrint.h>
#include <errno.h>
#if !defined(_MSC_VER)
#include <iconv.h>
#endif
#include "StringFunctions.h"
// XPLAT_ODBC_TODO VSTS 819733 - MPlat: Reconcile std c++ usage between platforms
#ifdef MPLAT_UNIX
// #include <sal_undef.h>
#elif defined(MPLAT_WWOWH)
# define _ASSERTE assert
# include <malloc.h>
# undef _M_IX86
# undef min
# undef max
#endif
#include <vector>
#include <algorithm>
#ifdef MPLAT_UNIX
#include <sal.h>
#endif
#ifdef __linux__
#define PTR_IS_INT64 1
#else
#define PTR_IS_INT64 0
#endif
#ifndef _MSC_VER
// SQL Server does not have a long double type
#define LONGDOUBLE_IS_DOUBLE 1
typedef double _LONGDOUBLE;
#endif
// XPLAT_ODBC_TODO VSTS VSTS 718708 Localization
#define _SAFECRT_IMPL
#if !defined(_countof)
#define _countof(_Array) (sizeof(_Array) / sizeof(_Array[0]))
#endif // _countof
#ifndef _VALIDATE_RETURN
#define _VALIDATE_RETURN( expr, errorcode, retexpr ) \
{ \
int _Expr_val=!!(expr); \
if ( !( _Expr_val ) ) \
{ \
assert(false); \
errno = errorcode; \
return ( retexpr ); \
} \
}
#endif /* _VALIDATE_RETURN */
static const char *__nullstring = "(null)"; /* string to print on null ptr */
static const wchar_t *__wnullstring = L"(null)";/* string to print on null ptr */
#define BUFFERSIZE 512
#define MAXPRECISION BUFFERSIZE
#define _CVTBUFSIZE (309+40) /* # of digits in max. dp value + slop */
/* flag definitions */
#define FL_SIGN 0x00001 /* put plus or minus in front */
#define FL_SIGNSP 0x00002 /* put space or minus in front */
#define FL_LEFT 0x00004 /* left justify */
#define FL_LEADZERO 0x00008 /* pad with leading zeros */
#define FL_LONG 0x00010 /* long value given */
#define FL_SHORT 0x00020 /* short value given */
#define FL_SIGNED 0x00040 /* signed data given */
#define FL_ALTERNATE 0x00080 /* alternate form requested */
#define FL_NEGATIVE 0x00100 /* value is negative */
#define FL_FORCEOCTAL 0x00200 /* force leading '0' for octals */
#define FL_LONGDOUBLE 0x00400 /* long double value given */
#define FL_WIDECHAR 0x00800 /* wide characters */
#define FL_LONGLONG 0x01000 /* long long value given */
#define FL_I64 0x08000 /* __int64 value given */
/* state definitions */
enum STATE {
ST_NORMAL, /* normal state; outputting literal chars */
ST_PERCENT, /* just read '%' */
ST_FLAG, /* just read flag character */
ST_WIDTH, /* just read width specifier */
ST_DOT, /* just read '.' */
ST_PRECIS, /* just read precision specifier */
ST_SIZE, /* just read size specifier */
ST_TYPE /* just read type specifier */
,ST_INVALID /* Invalid format */
};
#define NUMSTATES (ST_INVALID + 1)
/* character type values */
enum CHARTYPE {
CH_OTHER, /* character with no special meaning */
CH_PERCENT, /* '%' */
CH_DOT, /* '.' */
CH_STAR, /* '*' */
CH_ZERO, /* '0' */
CH_DIGIT, /* '1'..'9' */
CH_FLAG, /* ' ', '+', '-', '#' */
CH_SIZE, /* 'h', 'l', 'L', 'N', 'F', 'w' */
CH_TYPE /* type specifying character */
};
static const unsigned char __lookuptable_s[] = {
/* ' ' */ 0x06,
/* '!' */ 0x80,
/* '"' */ 0x80,
/* '#' */ 0x86,
/* '$' */ 0x80,
/* '%' */ 0x81,
/* '&' */ 0x80,
/* ''' */ 0x00,
/* '(' */ 0x00,
/* ')' */ 0x10,
/* '*' */ 0x03,
/* '+' */ 0x86,
/* ',' */ 0x80,
/* '-' */ 0x86,
/* '.' */ 0x82,
/* '/' */ 0x80,
/* '0' */ 0x14,
/* '1' */ 0x05,
/* '2' */ 0x05,
/* '3' */ 0x45,
/* '4' */ 0x45,
/* '5' */ 0x45,
/* '6' */ 0x85,
/* '7' */ 0x85,
/* '8' */ 0x85,
/* '9' */ 0x05,
/* ':' */ 0x00,
/* ';' */ 0x00,
/* '<' */ 0x30,
/* '=' */ 0x30,
/* '>' */ 0x80,
/* '?' */ 0x50,
/* '@' */ 0x80,
#if defined (_SAFECRT_IMPL)
/* 'A' */ 0x80, // Disable %A format
#else /* defined (_SAFECRT_IMPL) */
/* 'A' */ 0x88,
#endif /* defined (_SAFECRT_IMPL) */
/* 'B' */ 0x00,
/* 'C' */ 0x08,
/* 'D' */ 0x00,
/* 'E' */ 0x28,
/* 'F' */ 0x27,
/* 'G' */ 0x38,
/* 'H' */ 0x50,
/* 'I' */ 0x57,
/* 'J' */ 0x80,
/* 'K' */ 0x00,
/* 'L' */ 0x07,
/* 'M' */ 0x00,
/* 'N' */ 0x37,
/* 'O' */ 0x30,
/* 'P' */ 0x30,
/* 'Q' */ 0x50,
/* 'R' */ 0x50,
/* 'S' */ 0x88,
/* 'T' */ 0x00,
/* 'U' */ 0x00,
/* 'V' */ 0x00,
/* 'W' */ 0x20,
/* 'X' */ 0x28,
/* 'Y' */ 0x80,
/* 'Z' */ 0x88,
/* '[' */ 0x80,
/* '\' */ 0x80,
/* ']' */ 0x00,
/* '^' */ 0x00,
/* '_' */ 0x00,
/* '`' */ 0x60,
#if defined (_SAFECRT_IMPL)
/* 'a' */ 0x60, // Disable %a format
#else /* defined (_SAFECRT_IMPL) */
/* 'a' */ 0x68,
#endif /* defined (_SAFECRT_IMPL) */
/* 'b' */ 0x60,
/* 'c' */ 0x68,
/* 'd' */ 0x68,
/* 'e' */ 0x68,
/* 'f' */ 0x08,
/* 'g' */ 0x08,
/* 'h' */ 0x07,
/* 'i' */ 0x78,
/* 'j' */ 0x70,
/* 'k' */ 0x70,
/* 'l' */ 0x77,
/* 'm' */ 0x70,
/* 'n' */ 0x70,
/* 'o' */ 0x08,
/* 'p' */ 0x08,
/* 'q' */ 0x00,
/* 'r' */ 0x00,
/* 's' */ 0x08,
/* 't' */ 0x00,
/* 'u' */ 0x08,
/* 'v' */ 0x00,
/* 'w' */ 0x07,
/* 'x' */ 0x08
};
static inline CHARTYPE GetCharType( WCHAR wch )
{
return ((wch < (L' ') || wch > (L'x')) ? CH_OTHER : (enum CHARTYPE)(__lookuptable_s[wch - (L' ')] & 0xF));
}
static inline CHARTYPE GetCharType( char ch )
{
return ((ch < (' ') || ch > ('x')) ? CH_OTHER : (enum CHARTYPE)(__lookuptable_s[ch - (' ')] & 0xF));
}
static inline STATE GetState( CHARTYPE type, STATE oldState )
{
return (enum STATE)(__lookuptable_s[type * NUMSTATES + oldState] >> 4);
}
static bool isleadbyte(unsigned char ch)
{
return (FALSE != IsDBCSLeadByte(ch) );
}
static bool isleadwchar(WCHAR ch)
{
return ((ch & 0xFC00) == 0xD800);
}
static bool _isleadbyte_l(unsigned char ch, _locale_t loc)
{
// XPLAT_ODBC_TODO VSTS 718708 Localization
return ( FALSE != IsDBCSLeadByte(ch) );
}
#define _WCTOMB_S mplat_wctomb_s
errno_t mplat_wctomb_s(
int *pRetValue,
char *mbchar,
size_t sizeInBytes,
WCHAR wchar
)
{
DWORD rc;
size_t cch = SystemLocale::FromUtf16( CP_ACP, &wchar, 1, mbchar, sizeInBytes, NULL, &rc );
*pRetValue = (int)cch;
return (ERROR_SUCCESS == rc ? 0 : -1);
}
#define _MBTOWC mplat_mbtowc
int mplat_mbtowc(
WCHAR * pwchar,
const char * pmb,
size_t n
)
{
size_t cch = SystemLocale::NextChar( CP_ACP, pmb ) - pmb;
if ( 0 < cch )
{
size_t cchActual = SystemLocale::ToUtf16( CP_ACP, pmb, cch, pwchar, 1, NULL );
assert( cch == cchActual );
}
return (int)cch;
}
// Floating point print routines
void _CFLTCVT( double * dbl, char * buf, int bufSize, char fmt, int precision, int caps, _locale_t loc = NULL )
{
const size_t local_bufsize = 8;
char local_fmt[local_bufsize];
if ( 0 != caps )
{
fmt -= ('a') - ('A'); /* convert format char to upper */
}
int chars_printed = snprintf( local_fmt, local_bufsize, "%%.%d%c", precision-1, fmt );
assert( 0 < chars_printed && (size_t)chars_printed < local_bufsize );
// We want to use the platform version of snprintf so temporarily undef.
// Formatting of floating pt values is complex so we didn't implement it here.
// Even porting the CRT code would've been difficult. Instead, we can use the
// platform's snprintf for just floating pt values. We have to undef to prevent
// recursing right back to here.
# undef snprintf
# if defined(MPLAT_WWOWH)
# undef _snprintf
# define snprintf _snprintf
# endif
chars_printed = snprintf( buf, bufSize, local_fmt, *dbl );
assert( 0 < chars_printed && chars_printed < bufSize );
# if defined(MPLAT_WWOWH)
# undef snprintf
# define _snprintf mplat_snprintf
# endif
# define snprintf mplat_snprintf
}
#if !LONGDOUBLE_IS_DOUBLE
// SQL Server does not support the long double data type so this should never be called.
// It will be compiled out on Linux.
void _CLDCVT( _LONGDOUBLE * dbl, char * buf, int bufSize, char fmt, int precision, int caps )
{
assert(false);
}
#endif
static enum STATE ProcessSizeA( char sizeCh, char fmt_ch, char next_fmt_ch, int * advance, int * flags )
{
*advance = 0;
switch (sizeCh)
{
case 'l':
/*
* In order to handle the ll case, we depart from the
* simple deterministic state machine.
*/
if ( 'l' == fmt_ch )
{
*advance = 1;
*flags |= FL_LONGLONG;
}
else
{
*flags |= FL_LONG;
}
break;
case 'I':
/*
* In order to handle the I, I32, and I64 size modifiers, we
* depart from the simple deterministic state machine. The
* code below scans for characters following the 'I',
* and defaults to 64 bit on WIN64 and 32 bit on WIN32
*/
#if PTR_IS_INT64
*flags |= FL_I64; /* 'I' => __int64 on WIN64 systems */
#endif /* PTR_IS_INT64 */
if ( '6' == fmt_ch && '4' == next_fmt_ch )
{
*advance = 2;
*flags |= FL_I64; /* I64 => __int64 */
}
else if ( '3' == fmt_ch && '2' == next_fmt_ch )
{
*advance = 2;
*flags &= ~FL_I64; /* I32 => __int32 */
}
else if (
(fmt_ch == 'd') ||
(fmt_ch == 'i') ||
(fmt_ch == 'o') ||
(fmt_ch == 'u') ||
(fmt_ch == 'x') ||
(fmt_ch == 'X') )
{
/*
* Nothing further needed. %Id (et al) is
* handled just like %d, except that it defaults to 64 bits
* on WIN64. Fall through to the next iteration.
*/
}
else
{
return ST_NORMAL;
}
break;
case 'h':
*flags |= FL_SHORT;
break;
case 'w':
*flags |= FL_WIDECHAR;
}
return ST_SIZE;
}
static enum STATE ProcessSizeW( WCHAR sizeCh, WCHAR fmt_ch, WCHAR next_fmt_ch, int * advance, int * flags )
{
*advance = 0;
switch (sizeCh)
{
case L'l':
/*
* In order to handle the ll case, we depart from the
* simple deterministic state machine.
*/
if ( L'l' == fmt_ch )
{
*advance = 1;
*flags |= FL_LONGLONG;
}
else
{
*flags |= FL_LONG;
}
break;
case L'I':
/*
* In order to handle the I, I32, and I64 size modifiers, we
* depart from the simple deterministic state machine. The
* code below scans for characters following the 'I',
* and defaults to 64 bit on WIN64 and 32 bit on WIN32
*/
#if PTR_IS_INT64
*flags |= FL_I64; /* 'I' => __int64 on WIN64 systems */
#endif /* PTR_IS_INT64 */
if ( L'6' == fmt_ch && L'4' == next_fmt_ch )
{
*advance = 2;
*flags |= FL_I64; /* I64 => __int64 */
}
else if ( L'3' == fmt_ch && L'2' == next_fmt_ch )
{
*advance = 2;
*flags &= ~FL_I64; /* I32 => __int32 */
}
else if (
(fmt_ch == L'd') ||
(fmt_ch == L'i') ||
(fmt_ch == L'o') ||
(fmt_ch == L'u') ||
(fmt_ch == L'x') ||
(fmt_ch == L'X') )
{
/*
* Nothing further needed. %Id (et al) is
* handled just like %d, except that it defaults to 64 bits
* on WIN64. Fall through to the next iteration.
*/
}
else
{
return ST_NORMAL;
}
break;
case L'h':
*flags |= FL_SHORT;
break;
case L'w':
*flags |= FL_WIDECHAR;
}
return ST_SIZE;
}
STATE ProcessSize( WCHAR sizeCh, const WCHAR * format, int * advance, int * flags )
{
WCHAR formatCh = *format;
WCHAR next_formatCh = (L'\0' == formatCh ? L'\0' : *(format+1));
return ProcessSizeW( sizeCh, formatCh, next_formatCh, advance, flags );
}
STATE ProcessSize( char sizeCh, const char * format, int * advance, int * flags )
{
char formatCh = *format;
char next_formatCh = ('\0' == formatCh ? '\0' : *(format+1));
return ProcessSizeA( sizeCh, formatCh, next_formatCh, advance, flags );
}
// Tools\vc\src\crt\amd64\output.c
int FormattedPrintA( IFormattedPrintOutput<char> * output, const char *format, va_list argptr )
{
int hexadd=0; /* offset to add to number to get 'a'..'f' */
char ch; /* character just read */
int flags=0; /* flag word -- see #defines above for flag values */
enum STATE state; /* current state */
enum CHARTYPE chclass; /* class of current character */
int radix; /* current conversion radix */
int charsout; /* characters currently written so far, -1 = IO error */
int fldwidth = 0; /* selected field width -- 0 means default */
int precision = 0; /* selected precision -- -1 means default */
char prefix[2]; /* numeric prefix -- up to two characters */
int prefixlen=0; /* length of prefix -- 0 means no prefix */
int capexp=0; /* non-zero = 'E' exponent signifient, zero = 'e' or unused */
int no_output=0; /* non-zero = prodcue no output for this specifier */
union {
char *sz; /* pointer text to be printed, not zero terminated */
WCHAR *wz;
} text;
int textlen; /* length of the text in bytes/wchars to be printed.
textlen is in multibyte or wide chars if _UNICODE */
union {
char sz[BUFFERSIZE];
} buffer;
WCHAR wchar; /* temp wchar_t */
int buffersize; /* size of text.sz (used only for the call to _cfltcvt) */
int bufferiswide=0; /* non-zero = buffer contains wide chars already */
#ifndef _SAFECRT_IMPL
_LocaleUpdate _loc_update(plocinfo);
#endif /* _SAFECRT_IMPL */
char *heapbuf = NULL; /* non-zero = test.sz using heap buffer to be freed */
int advance; /* count of how much helper fxns need format ptr incremented */
_VALIDATE_RETURN( ((output != NULL) && (format != NULL)), EINVAL, -1);
charsout = 0; /* no characters written yet */
textlen = 0; /* no text yet */
state = ST_NORMAL; /* starting state */
heapbuf = NULL; /* not using heap-allocated buffer */
buffersize = 0;
/* main loop -- loop while format character exist and no I/O errors */
while ((ch = *format++) != '\0' && charsout >= 0) {
// Find char class and next state
chclass = GetCharType( ch );
state = GetState( chclass, state );
/* execute code for each state */
switch (state) {
case ST_INVALID:
// "Incorrect format specifier"
assert( false );
errno = EINVAL;
return -1;
case ST_NORMAL:
NORMAL_STATE:
/* normal state -- just write character */
bufferiswide = 0;
#ifdef _SAFECRT_IMPL
if (isleadbyte((unsigned char)ch)) {
#else /* _SAFECRT_IMPL */
if (_isleadbyte_l((unsigned char)ch, _loc_update.GetLocaleT())) {
#endif /* _SAFECRT_IMPL */
// XPLAT_ODBC_TODO VSTS 718708 Localization
// Deal with more than 2 storage units per character
output->WRITE_CHAR(ch, &charsout);
ch = *format++;
/* don't fall off format string */
_VALIDATE_RETURN( (ch != '\0'), EINVAL, -1);
}
output->WRITE_CHAR(ch, &charsout);
break;
case ST_PERCENT:
/* set default value of conversion parameters */
prefixlen = fldwidth = no_output = capexp = 0;
flags = 0;
precision = -1;
bufferiswide = 0; /* default */
break;
case ST_FLAG:
/* set flag based on which flag character */
switch (ch) {
case ('-'):
flags |= FL_LEFT; /* '-' => left justify */
break;
case ('+'):
flags |= FL_SIGN; /* '+' => force sign indicator */
break;
case (' '):
flags |= FL_SIGNSP; /* ' ' => force sign or space */
break;
case ('#'):
flags |= FL_ALTERNATE; /* '#' => alternate form */
break;
case ('0'):
flags |= FL_LEADZERO; /* '0' => pad with leading zeros */
break;
}
break;
case ST_WIDTH:
/* update width value */
if (ch == ('*')) {
/* get width from arg list */
fldwidth = va_arg(argptr, int);
if (fldwidth < 0) {
/* ANSI says neg fld width means '-' flag and pos width */
flags |= FL_LEFT;
fldwidth = -fldwidth;
}
}
else {
/* add digit to current field width */
fldwidth = fldwidth * 10 + (ch - ('0'));
}
break;
case ST_DOT:
/* zero the precision, since dot with no number means 0
not default, according to ANSI */
precision = 0;
break;
case ST_PRECIS:
/* update precison value */
if (ch == ('*')) {
/* get precision from arg list */
precision = va_arg(argptr, int);
if (precision < 0)
precision = -1; /* neg precision means default */
}
else {
/* add digit to current precision */
precision = precision * 10 + (ch - ('0'));
}
break;
case ST_SIZE:
/* just read a size specifier, set the flags based on it */
state = ProcessSize( ch, format, &advance, &flags );
format += advance;
if ( ST_NORMAL == state )
{
goto NORMAL_STATE;
}
break;
case ST_TYPE:
/* we have finally read the actual type character, so we */
/* now format and "print" the output. We use a big switch */
/* statement that sets 'text' to point to the text that should */
/* be printed, and 'textlen' to the length of this text. */
/* Common code later on takes care of justifying it and */
/* other miscellaneous chores. Note that cases share code, */
/* in particular, all integer formatting is done in one place. */
/* Look at those funky goto statements! */
switch (ch) {
case ('C'): /* ISO wide character */
if (!(flags & (FL_SHORT|FL_LONG|FL_WIDECHAR)))
flags |= FL_WIDECHAR; /* ISO std. */
/* fall into 'c' case */
case ('c'): {
/* print a single character specified by int argument */
if (flags & (FL_LONG|FL_WIDECHAR)) {
errno_t e = 0;
wchar = (WCHAR) va_arg(argptr, int);
/* convert to multibyte character */
e = _WCTOMB_S(&textlen, buffer.sz, _countof(buffer.sz), wchar);
/* check that conversion was successful */
if (e != 0)
no_output = 1;
} else {
/* format multibyte character */
/* this is an extension of ANSI */
unsigned short temp;
temp = (unsigned short) va_arg(argptr, int);
{
buffer.sz[0] = (char) temp;
textlen = 1;
}
}
text.sz = buffer.sz;
}
break;
case ('Z'): {
// 'Z' format specifier disabled
_VALIDATE_RETURN(0, EINVAL, -1);
}
break;
case ('S'): /* ISO wide character string */
if (!(flags & (FL_SHORT|FL_LONG|FL_WIDECHAR)))
flags |= FL_WIDECHAR;
case ('s'): {
/* print a string -- */
/* ANSI rules on how much of string to print: */
/* all if precision is default, */
/* min(precision, length) if precision given. */
/* prints '(null)' if a null string is passed */
int i;
char *p; /* temps */
WCHAR *pwch;
/* At this point it is tempting to use strlen(), but */
/* if a precision is specified, we're not allowed to */
/* scan past there, because there might be no null */
/* at all. Thus, we must do our own scan. */
i = (precision == -1) ? INT_MAX : precision;
text.sz = (char *)va_arg(argptr, void *);
/* scan for null upto i characters */
if (flags & (FL_LONG|FL_WIDECHAR)) {
if (text.wz == NULL) /* NULL passed, use special string */
text.wz = (WCHAR *)__wnullstring;
bufferiswide = 1;
pwch = text.wz;
while ( i-- && *pwch )
++pwch;
textlen = (int)(pwch - text.wz);
/* textlen now contains length in wide chars */
} else {
if (text.sz == NULL) /* NULL passed, use special string */
text.sz = (char*) __nullstring;
p = text.sz;
while (i-- && *p)
++p;
textlen = (int)(p - text.sz); /* length of the string */
}
}
break;
case ('n'): {
// We will not support %n
_VALIDATE_RETURN(0, EINVAL, -1);
}
break;
case ('E'):
case ('G'):
case ('A'):
capexp = 1; /* capitalize exponent */
ch += ('a') - ('A'); /* convert format char to lower */
/* DROP THROUGH */
case ('e'):
case ('f'):
case ('g'):
case ('a'): {
/* floating point conversion -- we call cfltcvt routines */
/* to do the work for us. */
flags |= FL_SIGNED; /* floating point is signed conversion */
text.sz = buffer.sz; /* put result in buffer */
buffersize = BUFFERSIZE;
/* compute the precision value */
if (precision < 0)
precision = 6; /* default precision: 6 */
else if (precision == 0 && ch == ('g'))
precision = 1; /* ANSI specified */
else if (precision > MAXPRECISION)
precision = MAXPRECISION;
if (precision > BUFFERSIZE - _CVTBUFSIZE) {
/* conversion will potentially overflow local buffer */
/* so we need to use a heap-allocated buffer. */
heapbuf = (char *)malloc(_CVTBUFSIZE + precision);
if (heapbuf != NULL)
{
text.sz = heapbuf;
buffersize = _CVTBUFSIZE + precision;
}
else
/* malloc failed, cap precision further */
precision = BUFFERSIZE - _CVTBUFSIZE;
}
#ifdef _SAFECRT_IMPL
/* for safecrt, we pass along the FL_ALTERNATE flag to _safecrt_cfltcvt */
if (flags & FL_ALTERNATE)
{
capexp |= FL_ALTERNATE;
}
#endif /* _SAFECRT_IMPL */
#if !LONGDOUBLE_IS_DOUBLE
/* do the conversion */
if (flags & FL_LONGDOUBLE) {
_LONGDOUBLE tmp;
tmp=va_arg(argptr, _LONGDOUBLE);
/* Note: assumes ch is in ASCII range */
_CLDCVT(&tmp, text.sz, buffersize, (char)ch, precision, capexp);
} else
#endif /* !LONGDOUBLE_IS_DOUBLE */
{
double tmp;
tmp=va_arg(argptr, double);
/* Note: assumes ch is in ASCII range */
/* In safecrt, we provide a special version of _cfltcvt which internally calls printf (see safecrt_output_s.c) */
#ifndef _SAFECRT_IMPL
_cfltcvt_l(&tmp, text.sz, buffersize, (char)ch, precision, capexp, _loc_update.GetLocaleT());
#else /* _SAFECRT_IMPL */
_CFLTCVT(&tmp, text.sz, buffersize, (char)ch, precision, capexp);
#endif /* _SAFECRT_IMPL */
}
#ifndef _SAFECRT_IMPL
/* For safecrt, this is done already in _safecrt_cfltcvt */
/* '#' and precision == 0 means force a decimal point */
if ((flags & FL_ALTERNATE) && precision == 0)
{
_forcdecpt_l(text.sz, _loc_update.GetLocaleT());
}
/* 'g' format means crop zero unless '#' given */
if (ch == ('g') && !(flags & FL_ALTERNATE))
{
_cropzeros_l(text.sz, _loc_update.GetLocaleT());
}
#endif /* _SAFECRT_IMPL */
/* check if result was negative, save '-' for later */
/* and point to positive part (this is for '0' padding) */
if (*text.sz == '-') {
flags |= FL_NEGATIVE;
++text.sz;
}
textlen = (int)strlen(text.sz); /* compute length of text */
}
break;
case ('d'):
case ('i'):
/* signed decimal output */
flags |= FL_SIGNED;
radix = 10;
goto COMMON_INT;
case ('u'):
radix = 10;
goto COMMON_INT;
case ('p'):
/* write a pointer -- this is like an integer or long */
/* except we force precision to pad with zeros and */
/* output in big hex. */
precision = 2 * sizeof(void *); /* number of hex digits needed */
#if PTR_IS_INT64
flags |= FL_I64; /* assume we're converting an int64 */
#endif /* !PTR_IS_INT */
/* DROP THROUGH to hex formatting */
case ('X'):
/* unsigned upper hex output */
hexadd = ('A') - ('9') - 1; /* set hexadd for uppercase hex */
goto COMMON_HEX;
case ('x'):
/* unsigned lower hex output */
hexadd = ('a') - ('9') - 1; /* set hexadd for lowercase hex */
/* DROP THROUGH TO COMMON_HEX */
COMMON_HEX:
radix = 16;
if (flags & FL_ALTERNATE) {
/* alternate form means '0x' prefix */
prefix[0] = ('0');
prefix[1] = (char)(('x') - ('a') + ('9') + 1 + hexadd); /* 'x' or 'X' */
prefixlen = 2;
}
goto COMMON_INT;
case ('o'):
/* unsigned octal output */
radix = 8;
if (flags & FL_ALTERNATE) {
/* alternate form means force a leading 0 */
flags |= FL_FORCEOCTAL;
}
/* DROP THROUGH to COMMON_INT */
COMMON_INT: {
/* This is the general integer formatting routine. */
/* Basically, we get an argument, make it positive */
/* if necessary, and convert it according to the */
/* correct radix, setting text and textlen */
/* appropriately. */
ULONGLONG number; /* number to convert */
int digit; /* ascii value of digit */
LONGLONG l; /* temp long value */
/* 1. read argument into l, sign extend as needed */
if (flags & FL_I64)
l = va_arg(argptr, LONGLONG);
else if (flags & FL_LONGLONG)
l = va_arg(argptr, LONGLONG);
else
if (flags & FL_SHORT) {
if (flags & FL_SIGNED)
l = (short) va_arg(argptr, int); /* sign extend */
else
l = (unsigned short) va_arg(argptr, int); /* zero-extend*/
} else
{
if (flags & FL_SIGNED)
l = (int)va_arg(argptr, int); /* sign extend */
else
l = (unsigned int) va_arg(argptr, int); /* zero-extend*/
}
/* 2. check for negative; copy into number */
if ( (flags & FL_SIGNED) && l < 0) {
number = -l;
flags |= FL_NEGATIVE; /* remember negative sign */
} else {
number = l;
}
if ( (flags & FL_I64) == 0 && (flags & FL_LONGLONG) == 0 ) {
/*
* Unless printing a full 64-bit value, insure values
* here are not in cananical longword format to prevent
* the sign extended upper 32-bits from being printed.
*/
number &= 0xffffffff;
}
/* 3. check precision value for default; non-default */
/* turns off 0 flag, according to ANSI. */
if (precision < 0)
precision = 1; /* default precision */
else {
flags &= ~FL_LEADZERO;
if (precision > MAXPRECISION)
precision = MAXPRECISION;
}
/* 4. Check if data is 0; if so, turn off hex prefix */
if (number == 0)
prefixlen = 0;
/* 5. Convert data to ASCII -- note if precision is zero */
/* and number is zero, we get no digits at all. */
text.sz = &buffer.sz[BUFFERSIZE-1]; /* last digit at end of buffer */
while (precision-- > 0 || number != 0) {
digit = (int)(number % radix) + '0';
number /= radix; /* reduce number */
if (digit > '9') {
/* a hex digit, make it a letter */
digit += hexadd;
}
*text.sz-- = (char)digit; /* store the digit */
}
textlen = (int)((char *)&buffer.sz[BUFFERSIZE-1] - text.sz); /* compute length of number */
++text.sz; /* text points to first digit now */
/* 6. Force a leading zero if FORCEOCTAL flag set */
if ((flags & FL_FORCEOCTAL) && (textlen == 0 || text.sz[0] != '0')) {
*--text.sz = '0';
++textlen; /* add a zero */
}
}
break;
}
/* At this point, we have done the specific conversion, and */
/* 'text' points to text to print; 'textlen' is length. Now we */
/* justify it, put on prefixes, leading zeros, and then */
/* print it. */
if (!no_output) {
int padding; /* amount of padding, negative means zero */
if (flags & FL_SIGNED) {
if (flags & FL_NEGATIVE) {
/* prefix is a '-' */
prefix[0] = ('-');
prefixlen = 1;
}
else if (flags & FL_SIGN) {
/* prefix is '+' */
prefix[0] = ('+');
prefixlen = 1;
}
else if (flags & FL_SIGNSP) {
/* prefix is ' ' */
prefix[0] = (' ');
prefixlen = 1;
}
}
/* calculate amount of padding -- might be negative, */
/* but this will just mean zero */
padding = fldwidth - textlen - prefixlen;
/* put out the padding, prefix, and text, in the correct order */
if (!(flags & (FL_LEFT | FL_LEADZERO))) {
/* pad on left with blanks */
output->WRITE_MULTI_CHAR((' '), padding, &charsout);
}
/* write prefix */
output->WRITE_STRING(prefix, prefixlen, &charsout);
if ((flags & FL_LEADZERO) && !(flags & FL_LEFT)) {
/* write leading zeros */
output->WRITE_MULTI_CHAR(('0'), padding, &charsout);
}
/* write text */
if (bufferiswide && (textlen > 0)) {
WCHAR *p;
int retval, count;
errno_t e = 0;
char L_buffer[MB_LEN_MAX+1];
p = text.wz;
count = textlen;
while (count--) {
e = _WCTOMB_S(&retval, L_buffer, _countof(L_buffer), *p++);
if (e != 0 || retval == 0) {
charsout = -1;
break;
}
output->WRITE_STRING(L_buffer, retval, &charsout);
}
} else {
output->WRITE_STRING(text.sz, textlen, &charsout);
}
if (charsout >= 0 && (flags & FL_LEFT)) {
/* pad on right with blanks */
output->WRITE_MULTI_CHAR((' '), padding, &charsout);
}
/* we're done! */
}
if (heapbuf) {
free(heapbuf);
heapbuf = NULL;
}
break;
}
}
/* The format string shouldn't be incomplete - i.e. when we are finished
with the format string, the last thing we should have encountered
should have been a regular char to be output or a type specifier. Else
the format string was incomplete */
_VALIDATE_RETURN(((state == ST_NORMAL) || (state == ST_TYPE)), EINVAL, -1);
return charsout; /* return value = number of characters written */
}
// Tools\vc\src\crt\amd64\output.c
int FormattedPrintW( IFormattedPrintOutput<WCHAR> * output, const WCHAR *format, va_list argptr )
{
int hexadd=0; /* offset to add to number to get 'a'..'f' */
WCHAR ch; /* character just read */
int flags=0; /* flag word -- see #defines above for flag values */
enum STATE state; /* current state */
enum CHARTYPE chclass; /* class of current character */
int radix; /* current conversion radix */
int charsout; /* characters currently written so far, -1 = IO error */
int fldwidth = 0; /* selected field width -- 0 means default */
int precision = 0; /* selected precision -- -1 means default */
WCHAR prefix[2]; /* numeric prefix -- up to two characters */
int prefixlen=0; /* length of prefix -- 0 means no prefix */
int capexp=0; /* non-zero = 'E' exponent signifient, zero = 'e' or unused */
int no_output=0; /* non-zero = prodcue no output for this specifier */
union {
char *sz; /* pointer text to be printed, not zero terminated */
WCHAR *wz;
} text;
int textlen; /* length of the text in bytes/wchars to be printed.
textlen is in multibyte or wide chars if _UNICODE */
union {
char sz[BUFFERSIZE];
WCHAR wz[BUFFERSIZE];
} buffer;
WCHAR wchar; /* temp wchar_t */
int buffersize; /* size of text.sz (used only for the call to _cfltcvt) */
int bufferiswide=0; /* non-zero = buffer contains wide chars already */
#ifndef _SAFECRT_IMPL
_LocaleUpdate _loc_update(plocinfo);
#endif /* _SAFECRT_IMPL */
char *heapbuf = NULL; /* non-zero = test.sz using heap buffer to be freed */
int advance; /* count of how much helper fxns need format ptr incremented */
_VALIDATE_RETURN( ((output != NULL) && (format != NULL)), EINVAL, -1);
charsout = 0; /* no characters written yet */
textlen = 0; /* no text yet */
state = ST_NORMAL; /* starting state */
heapbuf = NULL; /* not using heap-allocated buffer */
buffersize = 0;
/* main loop -- loop while format character exist and no I/O errors */
while ((ch = *format++) != L'\0' && charsout >= 0) {
// Find char class and next state
chclass = GetCharType( ch );
state = GetState( chclass, state );
/* execute code for each state */
switch (state) {
case ST_INVALID:
// "Incorrect format specifier"
assert( false );
errno = EINVAL;
return -1;
case ST_NORMAL:
NORMAL_STATE:
/* normal state -- just write character */
bufferiswide = 1;
if (isleadwchar(ch)) {
// Deal with more than 2 storage units per character
output->WRITE_CHAR(ch, &charsout);
ch = *format++;
/* don't fall off format string */
_VALIDATE_RETURN( (ch != L'\0'), EINVAL, -1);
}
output->WRITE_CHAR(ch, &charsout);
break;
case ST_PERCENT:
/* set default value of conversion parameters */
prefixlen = fldwidth = no_output = capexp = 0;
flags = 0;
precision = -1;
bufferiswide = 0; /* default */
break;
case ST_FLAG:
/* set flag based on which flag character */
switch (ch) {
case L'-':
flags |= FL_LEFT; /* '-' => left justify */
break;
case L'+':
flags |= FL_SIGN; /* '+' => force sign indicator */
break;
case L' ':
flags |= FL_SIGNSP; /* ' ' => force sign or space */
break;
case L'#':
flags |= FL_ALTERNATE; /* '#' => alternate form */
break;
case L'0':
flags |= FL_LEADZERO; /* '0' => pad with leading zeros */
break;
}
break;
case ST_WIDTH:
/* update width value */
if (ch == L'*') {
/* get width from arg list */
fldwidth = va_arg(argptr, int);
if (fldwidth < 0) {
/* ANSI says neg fld width means '-' flag and pos width */
flags |= FL_LEFT;
fldwidth = -fldwidth;
}
}
else {
/* add digit to current field width */
fldwidth = fldwidth * 10 + (ch - L'0');
}
break;
case ST_DOT:
/* zero the precision, since dot with no number means 0
not default, according to ANSI */
precision = 0;
break;
case ST_PRECIS:
/* update precison value */
if (ch == L'*') {
/* get precision from arg list */
precision = va_arg(argptr, int);
if (precision < 0)
precision = -1; /* neg precision means default */
}
else {
/* add digit to current precision */
precision = precision * 10 + (ch - L'0');
}
break;
case ST_SIZE:
/* just read a size specifier, set the flags based on it */
state = ProcessSize( ch, format, &advance, &flags );
format += advance;
if ( ST_NORMAL == state )
{
goto NORMAL_STATE;
}
break;
case ST_TYPE:
/* we have finally read the actual type character, so we */
/* now format and "print" the output. We use a big switch */
/* statement that sets 'text' to point to the text that should */
/* be printed, and 'textlen' to the length of this text. */
/* Common code later on takes care of justifying it and */
/* other miscellaneous chores. Note that cases share code, */
/* in particular, all integer formatting is done in one place. */
/* Look at those funky goto statements! */
switch (ch) {
case L'C': /* ISO wide character */
if (!(flags & (FL_SHORT|FL_LONG|FL_WIDECHAR)))
flags |= FL_SHORT;
/* fall into 'c' case */
case L'c': {
/* print a single character specified by int argument */
bufferiswide = 1;
wchar = (WCHAR) va_arg(argptr, int);
if (flags & FL_SHORT) {
/* format multibyte character */
/* this is an extension of ANSI */
char tempchar[2];
{
tempchar[0] = (char)(wchar & 0x00ff);
tempchar[1] = '\0';
}
#ifdef _SAFECRT_IMPL
if (_MBTOWC(buffer.wz,tempchar, MB_CUR_MAX) < 0)
#else /* _SAFECRT_IMPL */
if (_mbtowc_l(buffer.wz,
tempchar,
_loc_update.GetLocaleT()->locinfo->mb_cur_max,
_loc_update.GetLocaleT()) < 0)
#endif /* _SAFECRT_IMPL */
{
/* ignore if conversion was unsuccessful */
no_output = 1;
}
} else {
buffer.wz[0] = wchar;
}
text.wz = buffer.wz;
textlen = 1; /* print just a single character */
}
break;
case L'Z': {
// 'Z' format specifier disabled
_VALIDATE_RETURN(0, EINVAL, -1);
}
break;
case L'S': /* ISO wide character string */
if (!(flags & (FL_SHORT|FL_LONG|FL_WIDECHAR)))
flags |= FL_SHORT;
case L's': {
/* print a string -- */
/* ANSI rules on how much of string to print: */
/* all if precision is default, */
/* min(precision, length) if precision given. */
/* prints '(null)' if a null string is passed */
int i;
char *p; /* temps */
WCHAR *pwch;
/* At this point it is tempting to use strlen(), but */
/* if a precision is specified, we're not allowed to */
/* scan past there, because there might be no null */
/* at all. Thus, we must do our own scan. */
i = (precision == -1) ? INT_MAX : precision;
text.sz = (char *)va_arg(argptr, void *);
/* scan for null upto i characters */
if (flags & FL_SHORT) {
if (text.sz == NULL) /* NULL passed, use special string */
text.sz = (char*) __nullstring;
p = text.sz;
for (textlen=0; textlen<i && *p; textlen++) {
#ifdef _SAFECRT_IMPL
if (isleadbyte((unsigned char)(*p)))
#else /* _SAFECRT_IMPL */
if (_isleadbyte_l((unsigned char)(*p), _loc_update.GetLocaleT()))
#endif /* _SAFECRT_IMPL */
++p;
++p;
}
/* textlen now contains length in multibyte chars */
} else {
if (text.wz == NULL) /* NULL passed, use special string */
text.wz = (WCHAR *)__wnullstring;
bufferiswide = 1;
pwch = text.wz;
while (i-- && *pwch)
++pwch;
textlen = (int)(pwch - text.wz); /* in wchar_ts */
/* textlen now contains length in wide chars */
}
}
break;
case L'n': {
// 'n' format specifier disabled
_VALIDATE_RETURN(0, EINVAL, -1);
}
break;
case L'E':
case L'G':
case L'A':
capexp = 1; /* capitalize exponent */
ch += L'a' - L'A'; /* convert format char to lower */
/* DROP THROUGH */
case L'e':
case L'f':
case L'g':
case L'a': {
/* floating point conversion -- we call cfltcvt routines */
/* to do the work for us. */
flags |= FL_SIGNED; /* floating point is signed conversion */
text.sz = buffer.sz; /* put result in buffer */
buffersize = BUFFERSIZE;
/* compute the precision value */
if (precision < 0)
precision = 6; /* default precision: 6 */
else if (precision == 0 && ch == L'g')
precision = 1; /* ANSI specified */
else if (precision > MAXPRECISION)
precision = MAXPRECISION;
if (precision > BUFFERSIZE - _CVTBUFSIZE) {
/* conversion will potentially overflow local buffer */
/* so we need to use a heap-allocated buffer. */
heapbuf = (char *)malloc(_CVTBUFSIZE + precision);
if (heapbuf != NULL)
{
text.sz = heapbuf;
buffersize = _CVTBUFSIZE + precision;
}
else
/* malloc failed, cap precision further */
precision = BUFFERSIZE - _CVTBUFSIZE;
}
#ifdef _SAFECRT_IMPL
/* for safecrt, we pass along the FL_ALTERNATE flag to _safecrt_cfltcvt */
if (flags & FL_ALTERNATE)
{
capexp |= FL_ALTERNATE;
}
#endif /* _SAFECRT_IMPL */
#if !LONGDOUBLE_IS_DOUBLE
/* do the conversion */
if (flags & FL_LONGDOUBLE) {
_LONGDOUBLE tmp;
tmp=va_arg(argptr, _LONGDOUBLE);
/* Note: assumes ch is in ASCII range */
_CLDCVT(&tmp, text.sz, buffersize, (char)ch, precision, capexp);
} else
#endif /* !LONGDOUBLE_IS_DOUBLE */
{
double tmp;
tmp=va_arg(argptr, double);
/* Note: assumes ch is in ASCII range */
/* In safecrt, we provide a special version of _cfltcvt which internally calls printf (see safecrt_output_s.c) */
#ifndef _SAFECRT_IMPL
_cfltcvt_l(&tmp, text.sz, buffersize, (char)ch, precision, capexp, _loc_update.GetLocaleT());
#else /* _SAFECRT_IMPL */
_CFLTCVT(&tmp, text.sz, buffersize, (char)ch, precision, capexp);
#endif /* _SAFECRT_IMPL */
}
#ifndef _SAFECRT_IMPL
/* For safecrt, this is done already in _safecrt_cfltcvt */
/* '#' and precision == 0 means force a decimal point */
if ((flags & FL_ALTERNATE) && precision == 0)
{
_forcdecpt_l(text.sz, _loc_update.GetLocaleT());
}
/* 'g' format means crop zero unless '#' given */
if (ch == L'g' && !(flags & FL_ALTERNATE))
{
_cropzeros_l(text.sz, _loc_update.GetLocaleT());
}
#endif /* _SAFECRT_IMPL */
/* check if result was negative, save '-' for later */
/* and point to positive part (this is for '0' padding) */
if (*text.sz == '-') {
flags |= FL_NEGATIVE;
++text.sz;
}
textlen = (int)strlen(text.sz); /* compute length of text */
}
break;
case L'd':
case L'i':
/* signed decimal output */
flags |= FL_SIGNED;
radix = 10;
goto COMMON_INT;
case L'u':
radix = 10;
goto COMMON_INT;
case L'p':
/* write a pointer -- this is like an integer or long */
/* except we force precision to pad with zeros and */
/* output in big hex. */
precision = 2 * sizeof(void *); /* number of hex digits needed */
#if PTR_IS_INT64
flags |= FL_I64; /* assume we're converting an int64 */
#endif /* !PTR_IS_INT */
/* DROP THROUGH to hex formatting */
case L'X':
/* unsigned upper hex output */
hexadd = L'A' - L'9' - 1; /* set hexadd for uppercase hex */
goto COMMON_HEX;
case L'x':
/* unsigned lower hex output */
hexadd = L'a' - L'9' - 1; /* set hexadd for lowercase hex */
/* DROP THROUGH TO COMMON_HEX */
COMMON_HEX:
radix = 16;
if (flags & FL_ALTERNATE) {
/* alternate form means '0x' prefix */
prefix[0] = L'0';
prefix[1] = (WCHAR)(L'x' - L'a' + L'9' + 1 + hexadd); /* 'x' or 'X' */
prefixlen = 2;
}
goto COMMON_INT;
case L'o':
/* unsigned octal output */
radix = 8;
if (flags & FL_ALTERNATE) {
/* alternate form means force a leading 0 */
flags |= FL_FORCEOCTAL;
}
/* DROP THROUGH to COMMON_INT */
COMMON_INT: {
/* This is the general integer formatting routine. */
/* Basically, we get an argument, make it positive */
/* if necessary, and convert it according to the */
/* correct radix, setting text and textlen */
/* appropriately. */
ULONGLONG number; /* number to convert */
int digit; /* ascii value of digit */
LONGLONG l; /* temp long value */
/* 1. read argument into l, sign extend as needed */
if (flags & FL_I64)
l = va_arg(argptr, LONGLONG);
else if (flags & FL_LONGLONG)
l = va_arg(argptr, LONGLONG);
else
if (flags & FL_SHORT) {
if (flags & FL_SIGNED)
l = (short) va_arg(argptr, int); /* sign extend */
else
l = (unsigned short) va_arg(argptr, int); /* zero-extend*/
} else
{
if (flags & FL_SIGNED)
l = (int)va_arg(argptr, int); /* sign extend */
else
l = (unsigned int) va_arg(argptr, int); /* zero-extend*/
}
/* 2. check for negative; copy into number */
if ( (flags & FL_SIGNED) && l < 0) {
number = -l;
flags |= FL_NEGATIVE; /* remember negative sign */
} else {
number = l;
}
if ( (flags & FL_I64) == 0 && (flags & FL_LONGLONG) == 0 ) {
/*
* Unless printing a full 64-bit value, insure values
* here are not in cananical longword format to prevent
* the sign extended upper 32-bits from being printed.
*/
number &= 0xffffffff;
}
/* 3. check precision value for default; non-default */
/* turns off 0 flag, according to ANSI. */
if (precision < 0)
precision = 1; /* default precision */
else {
flags &= ~FL_LEADZERO;
if (precision > MAXPRECISION)
precision = MAXPRECISION;
}
/* 4. Check if data is 0; if so, turn off hex prefix */
if (number == 0)
prefixlen = 0;
/* 5. Convert data to ASCII -- note if precision is zero */
/* and number is zero, we get no digits at all. */
text.sz = &buffer.sz[BUFFERSIZE-1]; /* last digit at end of buffer */
while (precision-- > 0 || number != 0) {
digit = (int)(number % radix) + '0';
number /= radix; /* reduce number */
if (digit > '9') {
/* a hex digit, make it a letter */
digit += hexadd;
}
*text.sz-- = (char)digit; /* store the digit */
}
textlen = (int)((char *)&buffer.sz[BUFFERSIZE-1] - text.sz); /* compute length of number */
++text.sz; /* text points to first digit now */
/* 6. Force a leading zero if FORCEOCTAL flag set */
if ((flags & FL_FORCEOCTAL) && (textlen == 0 || text.sz[0] != '0')) {
*--text.sz = '0';
++textlen; /* add a zero */
}
}
break;
}
/* At this point, we have done the specific conversion, and */
/* 'text' points to text to print; 'textlen' is length. Now we */
/* justify it, put on prefixes, leading zeros, and then */
/* print it. */
if (!no_output) {
int padding; /* amount of padding, negative means zero */
if (flags & FL_SIGNED) {
if (flags & FL_NEGATIVE) {
/* prefix is a '-' */
prefix[0] = L'-';
prefixlen = 1;
}
else if (flags & FL_SIGN) {
/* prefix is '+' */
prefix[0] = L'+';
prefixlen = 1;
}
else if (flags & FL_SIGNSP) {
/* prefix is ' ' */
prefix[0] = L' ';
prefixlen = 1;
}
}
/* calculate amount of padding -- might be negative, */
/* but this will just mean zero */
padding = fldwidth - textlen - prefixlen;
/* put out the padding, prefix, and text, in the correct order */
if (!(flags & (FL_LEFT | FL_LEADZERO))) {
/* pad on left with blanks */
output->WRITE_MULTI_CHAR(L' ', padding, &charsout);
}
/* write prefix */
output->WRITE_STRING(prefix, prefixlen, &charsout);
if ((flags & FL_LEADZERO) && !(flags & FL_LEFT)) {
/* write leading zeros */
output->WRITE_MULTI_CHAR(L'0', padding, &charsout);
}
/* write text */
if (!bufferiswide && textlen > 0) {
char *p;
int retval, count;
p = text.sz;
count = textlen;
while (count-- > 0) {
#ifdef _SAFECRT_IMPL
retval = _MBTOWC(&wchar, p, MB_CUR_MAX);
#else /* _SAFECRT_IMPL */
retval = _mbtowc_l(&wchar,
p,
_loc_update.GetLocaleT()->locinfo->mb_cur_max,
_loc_update.GetLocaleT());
#endif /* _SAFECRT_IMPL */
if (retval <= 0) {
charsout = -1;
break;
}
output->WRITE_CHAR(wchar, &charsout);
p += retval;
}
} else {
output->WRITE_STRING(text.wz, textlen, &charsout);
}
if (charsout >= 0 && (flags & FL_LEFT)) {
/* pad on right with blanks */
output->WRITE_MULTI_CHAR(L' ', padding, &charsout);
}
/* we're done! */
}
if (heapbuf) {
free(heapbuf);
heapbuf = NULL;
}
break;
}
}
/* The format string shouldn't be incomplete - i.e. when we are finished
with the format string, the last thing we should have encountered
should have been a regular char to be output or a type specifier. Else
the format string was incomplete */
_VALIDATE_RETURN(((state == ST_NORMAL) || (state == ST_TYPE)), EINVAL, -1);
return charsout; /* return value = number of characters written */
}
// Used for holding the size and value of a variable argument.
// Uses INT and LONGLONG to hold all possible values. Each is just a buffer to hold the right number of bits.
struct vararg_t
{
enum ArgType_e
{
Unknown,
Int32,
Int64,
ShouldBeInt32,
ShouldBeInt64
};
vararg_t() : int64Val(0), int32Val(0), argType(vararg_t::Unknown) {}
vararg_t( INT val ) : int64Val(0), int32Val(val), argType(vararg_t::Int32) {}
vararg_t( LONGLONG ptr ) : int64Val(ptr), int32Val(0), argType(vararg_t::Int64) {}
ArgType_e Type() const { return argType; }
INT Int32Value() const { return int32Val; }
LONGLONG Int64Value() const { return int64Val; }
void * PtrValue() const
{
#if PTR_IS_INT64
return reinterpret_cast<void *>(int64Val);
#else
return reinterpret_cast<void *>(int32Val);
#endif
}
void SetForInt32()
{
assert( vararg_t::Unknown == argType );
argType = vararg_t::ShouldBeInt32;
}
void SetForInt64()
{
assert( vararg_t::Unknown == argType );
argType = vararg_t::ShouldBeInt64;
}
void SetForPtr()
{
#if PTR_IS_INT64
SetForInt64();
#else
SetForInt32();
#endif
}
void Int32Value( INT val )
{
assert( vararg_t::Unknown == argType || vararg_t::ShouldBeInt32 == argType );
assert( 0 == int64Val );
argType = vararg_t::Int32;
int32Val = val;
}
void Int64Value( LONGLONG val )
{
assert( vararg_t::Unknown == argType || vararg_t::ShouldBeInt64 == argType );
assert( 0 == int32Val );
argType = vararg_t::Int64;
int64Val = val;
}
private:
LONGLONG int64Val;
INT int32Val;
ArgType_e argType;
};
// Caches the var arg values in the supplied vector. Types are determined by inspecting the format string.
// On error, sets errno and returns false
static bool GetFormatMessageArgsA( const char * format, std::vector< vararg_t > * argcache, va_list * Arguments )
{
if ( NULL == format )
{
errno = EINVAL;
return false;
}
const char *p = format;
char fmt_ch;
while( '\0' != (fmt_ch = *p++) )
{
if ( '%' != fmt_ch )
{
// continue to next format spec
}
else if ( '0' == *p || '\0' == *p )
{
// %0 or null term means end formatting
break;
}
else if ( *p < '1' || '9' < *p )
{
// Escaped char, skip and keep going
++p;
}
else
{
// Integer must be [1..99]
size_t argPos = *p++ - '0';
if ( '0' <= *p && *p <= '9' )
{
argPos *= 10;
argPos += *p++ - '0';
}
assert( 0 < argPos && argPos < 100 );
if ( argcache->size() < argPos )
{
// Haven't processed this arg, yet
argcache->resize( argPos );
}
if ( vararg_t::Unknown == argcache->at(argPos-1).Type() )
{
if ( '!' != *p )
{
// Assume %s as per spec
argcache->at(argPos-1).SetForPtr();
}
else
{
// Step over the initial '!' and process format specification
++p;
char ch;
int flags = 0;
int advance = 0;
enum CHARTYPE chclass;
enum STATE state = ST_PERCENT;
bool found_terminator = false;
while ( !found_terminator && ('\0' != (ch = *p++)) )
{
chclass = GetCharType( ch );
state = GetState( chclass, state );
switch ( state )
{
case ST_DOT:
case ST_FLAG:
break;
case ST_WIDTH:
case ST_PRECIS:
if ( '*' == ch )
{
argcache->at(argPos-1).SetForInt32();
++argPos;
if ( argcache->size() < argPos )
{
argcache->resize( argPos );
}
}
break;
case ST_SIZE:
state = ProcessSize( ch, p, &advance, &flags );
p += advance;
if ( ST_SIZE != state )
{
// Size and type flags were inconsistent
errno = EINVAL;
return false;
}
break;
case ST_TYPE:
// Group into 32-bit and 64-bit sized args
assert( vararg_t::Unknown == argcache->at(argPos-1).Type() );
switch ( ch )
{
case 'C': // chars
case 'c':
argcache->at(argPos-1).SetForInt32();
break;
case 'd': // ints
case 'i':
case 'u':
case 'X':
case 'x':
case 'o':
// INT args
if ( (flags & FL_I64) || (flags & FL_LONGLONG) )
argcache->at(argPos-1).SetForInt64();
else
argcache->at(argPos-1).SetForInt32();
break;
case 'S': // strings
case 's':
case 'p': // pointer
argcache->at(argPos-1).SetForPtr();
break;
case 'E': // doubles (not supported as per spec)
case 'e':
case 'G':
case 'g':
case 'A':
case 'a':
case 'f':
default:
errno = EINVAL;
return false;
}
break;
case ST_NORMAL:
if ( '!' == ch )
{
found_terminator = true;
break;
}
// Fall thru to error, missing terminating '!'
default:
errno = EINVAL;
return false;
}
}
if ( !found_terminator )
{
// End of string before trailing '!' was found
errno = EINVAL;
return false;
}
}
}
}
}
if ( 0 < argcache->size() && NULL == Arguments )
{
errno = EINVAL;
return false;
}
// Cache var arg values now that we know the number and sizes
for ( std::vector< vararg_t >::iterator arg = argcache->begin(); arg != argcache->end(); ++arg )
{
if ( vararg_t::Unknown == arg->Type() )
{
// Arg not referenced in format string so assume ptr sized.
// This is a decent assumption since every arg gets ptr-size bytes to ensure alignment
// of later arg values. Verified this behavior with both Windows and Linux.
arg->SetForPtr();
}
vararg_t::ArgType_e argtype = arg->Type();
assert( vararg_t::ShouldBeInt32 == argtype || vararg_t::ShouldBeInt64 == argtype );
if ( vararg_t::ShouldBeInt32 == argtype )
{
arg->Int32Value( (INT)va_arg(*Arguments, INT) );
}
else
{
arg->Int64Value( (LONGLONG)va_arg(*Arguments, LONGLONG) );
}
}
return true;
}
// Caches the var arg values in the supplied vector. Types are determined by inspecting the format string.
// On error, sets errno and returns false
static bool GetFormatMessageArgsW( const WCHAR * format, std::vector< vararg_t > * argcache, va_list * Arguments )
{
if ( NULL == format )
{
errno = EINVAL;
return false;
}
const WCHAR *p = format;
WCHAR fmt_ch;
while( L'\0' != (fmt_ch = *p++) )
{
if ( L'%' != fmt_ch )
{
// continue to next format spec
}
else if ( L'0' == *p || L'\0' == *p )
{
// %0 or null term means end formatting
break;
}
else if ( *p < L'1' || L'9' < *p )
{
// Escaped char, skip and keep going
++p;
}
else
{
// Integer must be [1..99]
size_t argPos = *p++ - L'0';
if ( L'0' <= *p && *p <= L'9' )
{
argPos *= 10;
argPos += *p++ - L'0';
}
assert( 0 < argPos && argPos < 100 );
if ( argcache->size() < argPos )
{
// Haven't processed this arg, yet
argcache->resize( argPos );
}
if ( vararg_t::Unknown == argcache->at(argPos-1).Type() )
{
if ( L'!' != *p )
{
// Assume %s as per spec
argcache->at(argPos-1).SetForPtr();
}
else
{
// Step over the initial '!' and process format specification
++p;
WCHAR ch;
int flags = 0;
int advance = 0;
enum CHARTYPE chclass;
enum STATE state = ST_PERCENT;
bool found_terminator = false;
while ( !found_terminator && (L'\0' != (ch = *p++)) )
{
chclass = GetCharType( ch );
state = GetState( chclass, state );
switch ( state )
{
case ST_DOT:
case ST_FLAG:
break;
case ST_WIDTH:
case ST_PRECIS:
if ( L'*' == ch )
{
argcache->at(argPos-1).SetForInt32();
++argPos;
if ( argcache->size() < argPos )
{
argcache->resize( argPos );
}
}
break;
case ST_SIZE:
state = ProcessSize( ch, p, &advance, &flags );
p += advance;
if ( ST_SIZE != state )
{
// Size and type flags were inconsistent
errno = EINVAL;
return false;
}
break;
case ST_TYPE:
// Group into 32-bit and 64-bit sized args
assert( vararg_t::Unknown == argcache->at(argPos-1).Type() );
switch ( ch )
{
case L'C': // chars
case L'c':
argcache->at(argPos-1).SetForInt32();
break;
case L'd': // ints
case L'i':
case L'u':
case L'X':
case L'x':
case L'o':
// INT args
if ( (flags & FL_I64) || (flags & FL_LONGLONG) )
argcache->at(argPos-1).SetForInt64();
else
argcache->at(argPos-1).SetForInt32();
break;
case L'S': // strings
case L's':
case L'p': // pointer
argcache->at(argPos-1).SetForPtr();
break;
case L'E': // doubles (not supported as per spec)
case L'e':
case L'G':
case L'g':
case L'A':
case L'a':
case L'f':
default:
errno = EINVAL;
return false;
}
break;
case ST_NORMAL:
if ( L'!' == ch )
{
found_terminator = true;
break;
}
// Fall thru to error, missing terminating '!'
default:
errno = EINVAL;
return false;
}
}
if ( !found_terminator )
{
// End of string before trailing '!' was found
errno = EINVAL;
return false;
}
}
}
}
}
if ( 0 < argcache->size() && NULL == Arguments )
{
errno = EINVAL;
return false;
}
// Cache var arg values now that we know the number and sizes
for ( std::vector< vararg_t >::iterator arg = argcache->begin(); arg != argcache->end(); ++arg )
{
if ( vararg_t::Unknown == arg->Type() )
{
// Arg not referenced in format string so assume ptr sized.
// This is a decent assumption since every arg gets ptr-size bytes to ensure alignment
// of later arg values. Verified this behavior with both Windows and Linux.
arg->SetForPtr();
}
vararg_t::ArgType_e argtype = arg->Type();
assert( vararg_t::ShouldBeInt32 == argtype || vararg_t::ShouldBeInt64 == argtype );
if ( vararg_t::ShouldBeInt32 == argtype )
{
arg->Int32Value( (INT)va_arg(*Arguments, INT) );
}
else
{
arg->Int64Value( (LONGLONG)va_arg(*Arguments, LONGLONG) );
}
}
return true;
}
// On success, returns the number of chars written into the buffer excluding null terminator.
// On error, sets errno and returns zero.
static DWORD FormatMessageToBufferA( const char * format, char * buffer, DWORD bufferWCharSize, const std::vector< vararg_t > & args )
{
char * msg = buffer;
DWORD bufsize = std::min(bufferWCharSize, (DWORD)64000);
DWORD msg_pos = 0;
const DWORD fmtsize = 32;
char fmt[fmtsize];
DWORD fmt_pos;
char fmt_ch;
const char * p = format;
while( msg_pos < bufsize && '\0' != (fmt_ch = *p++) )
{
if ( '%' != fmt_ch )
{
msg[msg_pos++] = fmt_ch;
}
else if ( '0' == *p || '\0' == *p )
{
// %0 or null term means end formatting
break;
}
else if ( *p < '1' || '9' < *p )
{
// Escaped char, print and keep going
// Eg. "%n" == '\n'
switch ( *p )
{
case 'a': msg[msg_pos++] = '\a'; break;
case 'b': msg[msg_pos++] = '\b'; break;
case 'f': msg[msg_pos++] = '\f'; break;
case 'n': msg[msg_pos++] = '\n'; break;
case 'r': msg[msg_pos++] = '\r'; break;
case 't': msg[msg_pos++] = '\t'; break;
case 'v': msg[msg_pos++] = '\v'; break;
default: msg[msg_pos++] = *p; break;
}
++p;
}
else
{
// Integer must be [1..99]
size_t argPos = *p++ - '0';
if ( '0' <= *p && *p <= '9' )
{
argPos *= 10;
argPos += *p++ - '0';
}
assert( 0 < argPos && argPos < 100 );
fmt_pos = 0;
fmt[fmt_pos++] = '%';
if ( '!' != *p )
{
// Assume %s as per spec
fmt[fmt_pos++] = 's';
fmt[fmt_pos] = '\0';
int chars_printed = mplat_snprintf_s( &msg[msg_pos], bufsize-msg_pos, bufsize-msg_pos, fmt, args[argPos-1].PtrValue() );
if ( chars_printed < 0 )
{
errno = EINVAL;
return 0;
}
msg_pos += chars_printed;
}
else
{
// Skip over '!' and build format string
++p;
char ch;
int flags = 0;
int advance = 0;
enum CHARTYPE chclass;
enum STATE state = ST_PERCENT;
bool found_terminator = false;
while ( fmt_pos < fmtsize && !found_terminator && ('\0' != (ch = *p++)) )
{
chclass = GetCharType( ch );
state = GetState( chclass, state );
switch ( state )
{
case ST_SIZE:
state = ProcessSize( ch, p, &advance, &flags );
fmt[fmt_pos++] = ch;
while ( fmt_pos < fmtsize && 0 < advance-- )
{
fmt[fmt_pos++] = *p++;
}
break;
case ST_NORMAL:
assert( '!' == ch );
found_terminator = true;
break;
case ST_INVALID:
case ST_PERCENT:
errno = EINVAL;
return 0;
default:
fmt[fmt_pos++] = ch;
break;
}
}
if ( fmtsize <= fmt_pos )
{
// Should not have a format string longer than 31 chars
// It can happen but shouldn't (eg. a bunch of size mods like %llllllllllllllld)
errno = EINVAL;
return 0;
}
fmt[fmt_pos] = '\0';
// Format string might need up to 3 args (eg. %*.*d )
// If more than one arg, then the first ones must be 32-bit ints
// Hence, first 64-bit arg tells us the last arg we need to send.
int chars_printed = 0;
if ( vararg_t::Int64 == args[argPos-1].Type() )
{
chars_printed = mplat_snprintf_s( &msg[msg_pos], bufsize-msg_pos, bufsize-msg_pos, fmt, args[argPos-1].Int64Value() );
}
else if ( args.size() == argPos )
{
// No more args so send the one Int
chars_printed = mplat_snprintf_s( &msg[msg_pos], bufsize-msg_pos, bufsize-msg_pos, fmt, args[argPos-1].Int32Value() );
}
else if ( vararg_t::Int64 == args[argPos].Type() )
{
chars_printed = mplat_snprintf_s( &msg[msg_pos], bufsize-msg_pos, bufsize-msg_pos, fmt, args[argPos-1].Int32Value(), args[argPos].Int64Value() );
}
else if ( args.size() == (argPos+1) )
{
// No more args so send the two Ints
chars_printed = mplat_snprintf_s( &msg[msg_pos], bufsize-msg_pos, bufsize-msg_pos, fmt, args[argPos-1].Int32Value(), args[argPos-1].Int32Value() );
}
else if ( vararg_t::Int64 == args[argPos+1].Type() )
{
chars_printed = mplat_snprintf_s( &msg[msg_pos], bufsize-msg_pos, bufsize-msg_pos, fmt, args[argPos-1].Int32Value(), args[argPos].Int32Value(), args[argPos+1].Int64Value() );
}
else
{
chars_printed = mplat_snprintf_s( &msg[msg_pos], bufsize-msg_pos, bufsize-msg_pos, fmt, args[argPos-1].Int32Value(), args[argPos].Int32Value(), args[argPos+1].Int32Value() );
}
if ( chars_printed < 0 )
{
errno = EINVAL;
return 0;
}
msg_pos += chars_printed;
}
}
}
if ( bufsize <= msg_pos )
{
errno = ERANGE;
return 0;
}
msg[msg_pos] = '\0';
return msg_pos;
}
// On success, returns the number of chars written into the buffer excluding null terminator.
// On error, sets errno and returns zero.
static DWORD FormatMessageToBufferW( const WCHAR * format, WCHAR * buffer, DWORD bufferWCharSize, const std::vector< vararg_t > & args )
{
WCHAR * msg = buffer;
DWORD bufsize = std::min(bufferWCharSize, (DWORD)64000);
DWORD msg_pos = 0;
const DWORD fmtsize = 32;
WCHAR fmt[fmtsize];
DWORD fmt_pos;
WCHAR fmt_ch;
const WCHAR * p = format;
while( msg_pos < bufsize && L'\0' != (fmt_ch = *p++) )
{
if ( L'%' != fmt_ch )
{
msg[msg_pos++] = fmt_ch;
}
else if ( L'0' == *p || L'\0' == *p )
{
// %0 or null term means end formatting
break;
}
else if ( *p < L'1' || L'9' < *p )
{
// Escaped char, print and keep going
// Eg. "%n" == '\n'
switch ( *p )
{
case L'a': msg[msg_pos++] = L'\a'; break;
case L'b': msg[msg_pos++] = L'\b'; break;
case L'f': msg[msg_pos++] = L'\f'; break;
case L'n': msg[msg_pos++] = L'\n'; break;
case L'r': msg[msg_pos++] = L'\r'; break;
case L't': msg[msg_pos++] = L'\t'; break;
case L'v': msg[msg_pos++] = L'\v'; break;
default: msg[msg_pos++] = *p; break;
}
++p;
}
else
{
// Integer must be [1..99]
size_t argPos = *p++ - L'0';
if ( L'0' <= *p && *p <= L'9' )
{
argPos *= 10;
argPos += *p++ - L'0';
}
assert( 0 < argPos && argPos < 100 );
fmt_pos = 0;
fmt[fmt_pos++] = L'%';
if ( L'!' != *p )
{
// Assume %s as per spec
fmt[fmt_pos++] = L's';
fmt[fmt_pos] = L'\0';
int chars_printed = mplat_snwprintf_s( &msg[msg_pos], bufsize-msg_pos, bufsize-msg_pos, fmt, args[argPos-1].PtrValue() );
if ( chars_printed < 0 )
{
errno = EINVAL;
return 0;
}
msg_pos += chars_printed;
}
else
{
// Skip over '!' and build format string
++p;
WCHAR ch;
int flags = 0;
int advance = 0;
enum CHARTYPE chclass;
enum STATE state = ST_PERCENT;
bool found_terminator = false;
while ( fmt_pos < fmtsize && !found_terminator && (L'\0' != (ch = *p++)) )
{
chclass = GetCharType( ch );
state = GetState( chclass, state );
switch ( state )
{
case ST_SIZE:
state = ProcessSize( ch, p, &advance, &flags );
fmt[fmt_pos++] = ch;
while ( fmt_pos < fmtsize && 0 < advance-- )
{
fmt[fmt_pos++] = *p++;
}
break;
case ST_NORMAL:
assert( L'!' == ch );
found_terminator = true;
break;
case ST_INVALID:
case ST_PERCENT:
errno = EINVAL;
return 0;
default:
fmt[fmt_pos++] = ch;
break;
}
}
if ( fmtsize <= fmt_pos )
{
// Should not have a format string longer than 31 chars
// It can happen but shouldn't (eg. a bunch of size mods like %llllllllllllllld)
errno = EINVAL;
return 0;
}
fmt[fmt_pos] = L'\0';
// Format string might need up to 3 args (eg. %*.*d )
// If more than one arg, then the first ones must be 32-bit ints
// Hence, first 64-bit arg tells us the last arg we need to send.
int chars_printed = 0;
if ( vararg_t::Int64 == args[argPos-1].Type() )
{
chars_printed = mplat_snwprintf_s( &msg[msg_pos], bufsize-msg_pos, bufsize-msg_pos, fmt, args[argPos-1].Int64Value() );
}
else if ( args.size() == argPos )
{
// No more args so send the one Int
chars_printed = mplat_snwprintf_s( &msg[msg_pos], bufsize-msg_pos, bufsize-msg_pos, fmt, args[argPos-1].Int32Value() );
}
else if ( vararg_t::Int64 == args[argPos].Type() )
{
chars_printed = mplat_snwprintf_s( &msg[msg_pos], bufsize-msg_pos, bufsize-msg_pos, fmt, args[argPos-1].Int32Value(), args[argPos].Int64Value() );
}
else if ( args.size() == (argPos+1) )
{
// No more args so send the two Ints
chars_printed = mplat_snwprintf_s( &msg[msg_pos], bufsize-msg_pos, bufsize-msg_pos, fmt, args[argPos-1].Int32Value(), args[argPos-1].Int32Value() );
}
else if ( vararg_t::Int64 == args[argPos+1].Type() )
{
chars_printed = mplat_snwprintf_s( &msg[msg_pos], bufsize-msg_pos, bufsize-msg_pos, fmt, args[argPos-1].Int32Value(), args[argPos].Int32Value(), args[argPos+1].Int64Value() );
}
else
{
chars_printed = mplat_snwprintf_s( &msg[msg_pos], bufsize-msg_pos, bufsize-msg_pos, fmt, args[argPos-1].Int32Value(), args[argPos].Int32Value(), args[argPos+1].Int32Value() );
}
if ( chars_printed < 0 )
{
errno = EINVAL;
return 0;
}
msg_pos += chars_printed;
}
}
}
if ( bufsize <= msg_pos )
{
errno = ERANGE;
return 0;
}
msg[msg_pos] = L'\0';
return msg_pos;
}
DWORD FormatMessageA(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, DWORD dwLanguageId, LPTSTR lpBuffer, DWORD nSize, va_list *Arguments)
{
DWORD chars_printed = 0;
// XPLAT_ODBC_TODO VSTS 718708 Localization by handling FORMAT_MESSAGE_FROM_HMODULE and dwLanguageId param
if ( dwFlags & FORMAT_MESSAGE_FROM_STRING )
{
// Format specification allows for reordering of insertions relative to var arg position
// This means we need to walk thru the format specification to find the types of the var args in var arg order
// We extract the var args in order based on the identified types
// Finally, we re-walk the format specfication and perform the insertions
// First pass thru the format string to determine all args and their types
// This first pass also validates the format string and will return an error
// if it is invalid. This allows FormatMessageToBuffer to have less error
// checking.
std::vector< vararg_t > args;
// Based on quick scan of RC files, the largest arg count was 7 so reserve 8 slots to reduce allocations
args.reserve(8);
if ( GetFormatMessageArgsA( reinterpret_cast<const char *>(lpSource), &args, Arguments ) )
{
if ( dwFlags == (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING) )
{
*((char**)lpBuffer) = NULL;
const DWORD max_size = 64000;
char local_buf[max_size];
chars_printed = FormatMessageToBufferA( reinterpret_cast<const char *>(lpSource), local_buf, max_size, args );
if ( 0 < chars_printed )
{
size_t buf_size = std::min( max_size, std::max(nSize, (chars_printed+1)) );
char * return_buf = (char *)LocalAlloc(0, buf_size * sizeof(char));
if ( NULL == return_buf )
{
errno = ENOMEM;
}
else
{
mplat_cscpy(return_buf, local_buf);
*((char**)lpBuffer) = return_buf;
}
}
}
else if ( dwFlags == FORMAT_MESSAGE_FROM_STRING )
{
chars_printed = FormatMessageToBufferA( reinterpret_cast<const char *>(lpSource), lpBuffer, std::min(nSize, (DWORD)64000), args );
}
}
}
else if ( dwFlags & FORMAT_MESSAGE_FROM_SYSTEM )
{
// Since we don't have the Windows system error messages available use a fixed message
// Can not use a message ID for this since this same code is used by driver and tools,
// each having their own RLL file. Don't think we should be reserving an ID across all RLLs.
const char systemMsg[] = "Error code 0x%X";
if ( dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER )
{
*((char**)lpBuffer) = NULL;
// Add 9 for up to 8 hex digits plus null term (ignore removal of format specs)
const size_t msgsize = (9 + sizeof(systemMsg)/sizeof(systemMsg[0]));
char * return_buf = (char *)LocalAlloc(0, msgsize * sizeof(char));
if ( NULL == return_buf )
{
errno = ENOMEM;
}
else
{
chars_printed = mplat_snprintf_s( return_buf, msgsize, msgsize, systemMsg, dwMessageId );
// Assert that we did our buffer size math right
assert( chars_printed < msgsize );
if ( 0 < chars_printed )
{
*((char**)lpBuffer) = return_buf;
}
else
{
LocalFree( return_buf );
errno = EINVAL;
}
}
}
else
{
chars_printed = mplat_snprintf_s( lpBuffer, nSize, nSize, systemMsg, dwMessageId );
}
}
return chars_printed;
}
// FormatMessage implementation details (see MSDN for more info)
//
// The Windows FormatMessage API is very rich, complex. This is not an exact duplication of that function.
// Instead, the most important aspects of this function have been implemented here along with constraints to
// match how we use it within SNAC, BCP, and SQLCMD.
//
// Only these combinations of dwFlags are supported:
// FORMAT_MESSAGE_FROM_STRING
// Writes formatted message into supplied buffer
// FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING
// Allocates a buffer, writes formatted message into that buffer, returns buffer in lpBufffer
// FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS
// Writes fixed, English message into the supplied buffer (do not have Windows resources to get real message)
// FORMAT_MESSAGE_FROM_HMODULE
// SQLCMD uses this to read strings from the RLL that have not been translated to the current lang
//
// dwLanguageId is ignored for FORMAT_MESSAGE_FROM_STRING as per spec
// For FORMAT_MESSAGE_FROM_SYSTEM, we don't have Windows resources so language is irrelevant
DWORD FormatMessageW(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, DWORD dwLanguageId, LPWSTR lpBuffer, DWORD nSize, va_list *Arguments)
{
DWORD chars_printed = 0;
// XPLAT_ODBC_TODO VSTS 718708 Localization by handling FORMAT_MESSAGE_FROM_HMODULE and dwLanguageId param
if ( dwFlags & FORMAT_MESSAGE_FROM_STRING )
{
// Format specification allows for reordering of insertions relative to var arg position
// This means we need to walk thru the format specification to find the types of the var args in var arg order
// We extract the var args in order based on the identified types
// Finally, we re-walk the format specfication and perform the insertions
// First pass thru the format string to determine all args and their types
// This first pass also validates the format string and will return an error
// if it is invalid. This allows FormatMessageToBuffer to have less error
// checking.
std::vector< vararg_t > args;
// Based on quick scan of RC files, the largest arg count was 7 so reserve 8 slots to reduce allocations
args.reserve(8);
if ( GetFormatMessageArgsW( reinterpret_cast<const WCHAR *>(lpSource), &args, Arguments ) )
{
if ( dwFlags == (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING) )
{
*((WCHAR**)lpBuffer) = NULL;
const DWORD max_size = 64000;
WCHAR local_buf[max_size];
chars_printed = FormatMessageToBufferW( reinterpret_cast<const WCHAR *>(lpSource), local_buf, max_size, args );
if ( 0 < chars_printed )
{
size_t buf_size = std::min( max_size, std::max(nSize, (chars_printed+1)) );
WCHAR * return_buf = (WCHAR *)LocalAlloc(0, buf_size * sizeof(WCHAR));
if ( NULL == return_buf )
{
errno = ENOMEM;
}
else
{
mplat_wcscpy(return_buf, local_buf);
*((WCHAR**)lpBuffer) = return_buf;
}
}
}
else if ( dwFlags == FORMAT_MESSAGE_FROM_STRING )
{
chars_printed = FormatMessageToBufferW( reinterpret_cast<const WCHAR *>(lpSource), lpBuffer, std::min(nSize, (DWORD)64000), args );
}
}
}
else if ( dwFlags & FORMAT_MESSAGE_FROM_SYSTEM )
{
// Since we don't have the Windows system error messages available use a fixed message
// Can not use a message ID for this since this same code is used by driver and tools,
// each having their own RLL file. Don't think we should be reserving an ID across all RLLs.
const wchar_t systemMsg[] = L"Error code 0x%X";
if ( dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER )
{
*((WCHAR**)lpBuffer) = NULL;
// Add 9 for up to 8 hex digits plus null term (ignore removal of format specs)
const size_t msgsize = (9 + sizeof(systemMsg)/sizeof(systemMsg[0]));
WCHAR * return_buf = (WCHAR *)LocalAlloc(0, msgsize * sizeof(WCHAR));
if ( NULL == return_buf )
{
errno = ENOMEM;
}
else
{
chars_printed = mplat_snwprintf_s( return_buf, msgsize, msgsize, (WCHAR *)systemMsg, dwMessageId );
// Assert that we did our buffer size math right
assert( chars_printed < msgsize );
if ( 0 < chars_printed )
{
*((WCHAR**)lpBuffer) = return_buf;
}
else
{
LocalFree( return_buf );
errno = EINVAL;
}
}
}
else
{
chars_printed = mplat_snwprintf_s( lpBuffer, nSize, nSize, (WCHAR *)systemMsg, dwMessageId );
}
}
return chars_printed;
}
//--------Other definitions from xplat stub sources--------------
BOOL IsDBCSLeadByte(__inn BYTE TestChar)
{
// XPLAT_ODBC_TODO: This is to allow BatchParser to function
// BatchParser will single step thru utf8 code points
// BatchParser needs to become utf8-aware
// VSTS 718708 Localization
if ( CP_UTF8 == SystemLocale::Singleton().AnsiCP() )
return FALSE;
// XPLAT_ODBC_TODO
return IsDBCSLeadByteEx(SystemLocale::Singleton().AnsiCP(), TestChar);
}
BOOL IsDBCSLeadByteEx(
__inn UINT CodePage,
__inn BYTE TestChar)
{
if ( 1 == SystemLocale::MaxCharCchSize(CodePage) )
return FALSE;
// Lead byte ranges for code pages, inclusive:
// CP932
// 0x81-0x9f, 0xe0-0xfc
// CP936, CP949, CP950
// 0x81-0xfe
assert( 932 == CodePage || 936 == CodePage || 949 == CodePage || 950 == CodePage );
if ( 932 == CodePage )
{
if ( TestChar < (unsigned char)0x81
|| (unsigned char)0xfc < TestChar
|| ((unsigned char)0x9f < TestChar && TestChar < (unsigned char)0xe0) )
{
return FALSE;
}
}
else if ( TestChar < (unsigned char)0x81 || TestChar == (unsigned char)0xff )
return FALSE;
return TRUE;
}
int mplat_vsnwprintf( WCHAR * buffer, size_t count, const WCHAR * format, va_list args )
{
BufferOutput<WCHAR> output( buffer, count );
return FormattedPrintW( &output, format, args );
}
int mplat_snwprintf_s( WCHAR *buffer, size_t bufsize, size_t count, const WCHAR *format, ... )
{
va_list args;
va_start( args, format );
int retcode = mplat_vsnwprintf( buffer, std::min(bufsize, count), format, args );
va_end( args );
return retcode;
}
int mplat_vsnprintf( char * buffer, size_t count, const char * format, va_list args )
{
BufferOutput<char> output( buffer, count );
return FormattedPrintA( &output, format, args );
}
int mplat_snprintf_s( char *buffer, size_t bufsize, size_t count, const char *format, ... )
{
va_list args;
va_start( args, format );
int retcode = mplat_vsnprintf( buffer, std::min(bufsize, count), format, args );
va_end( args );
return retcode;
}
// Tools\vc\src\crt\amd64\wcscat.c
WCHAR * mplat_wcscpy( WCHAR * dst, const WCHAR * src )
{
WCHAR * cp = dst;
while( (*cp++ = *src++) )
; /* Copy src over dst */
return( dst );
}
char * mplat_cscpy( char * dst, const char * src )
{
char * cp = dst;
while( (*cp++ = *src++) )
; /* Copy src over dst */
return( dst );
}
size_t mplat_wcslen( const WCHAR * str )
{
const WCHAR * eos = str;
while( *eos++ )
{
}
return( (size_t)(eos - str- 1) );
}
HLOCAL LocalAlloc(UINT uFlags, SIZE_T uBytes)
{
assert(uFlags == 0); // For now
return malloc(uBytes);
}
HLOCAL LocalFree(HLOCAL hMem)
{
assert(hMem != NULL);
free(hMem);
return NULL;
}

View file

@ -0,0 +1,231 @@
//-----------------------------------------------------------------------------
// File: FormattedPrint.h
//
// Contents: Contains functions for handling Windows format strings
// and UTF-16 on non-Windows platforms
//
// Microsoft Drivers 4.0 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the ""Software""),
// to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and / or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions :
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//---------------------------------------------------------------------------------------------------------------------------------
#ifndef _FORMATTEDPRINT_H_
#define _FORMATTEDPRINT_H_
#include "winnls.h"
#include "localization.hpp"
inline bool __ascii_iswalpha(WCHAR c) { return( ('A' <= (c) && (c) <= 'Z') || ( 'a' <= (c) && (c) <= 'z') ); }
inline WCHAR __ascii_towupper(WCHAR c) { return( (((c) >= L'a') && ((c) <= L'z')) ? (WCHAR)((c) - L'a' + L'A') : (c) ); }
inline char __ascii_toupper(char c) { return( (((c) >= 'a') && ((c) <= 'z')) ? ((c) - 'a' + 'A') : (c) ); }
template< typename T >
struct IFormattedPrintOutput
{
/*
Method names are all CAPS to match the original code for formatted print from the Windows CRT.
pCumulativeOutputCount
Used to track running total of output storage units.
Note that the count is the memory size in sizeof(TCHAR) and not the display char count.
For example, a UTF-8 char+diacritical mark is two chars in memory but only one for display
so pCumulativeOutputCount will be incremented by 2 after output.
If an error is encountered, then set this to -1.
If the value is -1 upon entry of any callback, simply return and don't output anything.
*/
// Writes a single character to the output.
virtual void WRITE_CHAR( T ch , int * pCumulativeOutputCount ) = 0;
// Repeatedly writes a single character to the output. If there isn't enough room, writes to end of buffer.
// If repeatCount is <=0, then don't output anything and leave pCumulativeOutputCount as is.
virtual void WRITE_MULTI_CHAR( T ch, int repeatCount, int * pCumulativeOutputCount ) = 0;
// Writes the supplied string to the output. If there isn't enough room, writes to end of buffer.
// If count is <=0, then don't output anything and leave pCumulativeOutputCount as is.
virtual void WRITE_STRING( const T * pch, int count, int * pCumulativeOutputCount ) = 0;
// Ensure dtors are virtual
virtual ~IFormattedPrintOutput() { }
};
template< typename T >
class FormattedOutput : public IFormattedPrintOutput<T>
{
protected:
bool ShouldOutput( const int * pCumulativeOutputCount, int count ) const
{
assert( NULL != pCumulativeOutputCount );
return ( (0 <= *pCumulativeOutputCount) && (0 < count) );
}
};
int FormattedPrintA( IFormattedPrintOutput<char> * output, const char *format, va_list argptr );
int FormattedPrintW( IFormattedPrintOutput<WCHAR> * output, const WCHAR *format, va_list argptr );
template< typename T >
class BufferOutput : public FormattedOutput<T>
{
T * m_buffer;
size_t m_countRemainingInBuffer;
bool CanOutput() const
{
return ( 0 < m_countRemainingInBuffer );
}
// Stop these from being available
BufferOutput();
BufferOutput( const BufferOutput & );
BufferOutput & operator=( const BufferOutput & );
public:
BufferOutput( T * pcb, size_t bufsize )
: m_buffer( pcb ),
m_countRemainingInBuffer( bufsize )
{
assert( NULL != m_buffer );
if ( m_countRemainingInBuffer < INT_MAX )
{
memset( m_buffer, 0, m_countRemainingInBuffer * sizeof(T) );
}
}
virtual void WRITE_CHAR(T ch, int * pCumulativeOutputCount)
{
if ( FormattedOutput<T>::ShouldOutput( pCumulativeOutputCount, 1 ) )
{
if ( CanOutput() )
{
++(*pCumulativeOutputCount);
--m_countRemainingInBuffer;
*m_buffer++ = ch;
}
else
{
*pCumulativeOutputCount = -1;
}
}
}
virtual void WRITE_MULTI_CHAR(T ch, int repeatCount, int * pCumulativeOutputCount)
{
if ( FormattedOutput<T>::ShouldOutput( pCumulativeOutputCount, repeatCount ) )
{
if ( CanOutput() )
{
while ( 0 != m_countRemainingInBuffer && 0 != repeatCount )
{
*m_buffer++ = ch;
--m_countRemainingInBuffer;
--repeatCount;
++(*pCumulativeOutputCount);
}
if ( 0 != repeatCount )
{
// Not enough room in buffer
*pCumulativeOutputCount = -1;
}
}
else
{
*pCumulativeOutputCount = -1;
}
}
}
virtual void WRITE_STRING(const T * pch, int count, int * pCumulativeOutputCount)
{
assert( NULL != pch );
if ( FormattedOutput<T>::ShouldOutput( pCumulativeOutputCount, count ) )
{
if ( CanOutput() )
{
while ( 0 != m_countRemainingInBuffer && 0 != count )
{
*m_buffer++ = *pch++;
--m_countRemainingInBuffer;
--count;
++(*pCumulativeOutputCount);
}
if ( 0 != count )
{
// Not enough room in buffer
*pCumulativeOutputCount = -1;
}
}
else
{
*pCumulativeOutputCount = -1;
}
}
}
};
template< typename T >
class FileOutput : public FormattedOutput<T>
{
FILE * m_file;
// Stop these from being available
FileOutput();
FileOutput( const FileOutput & );
FileOutput & operator=( const FileOutput & );
public:
FileOutput( FILE * file )
: m_file( file )
{
assert( NULL != m_file );
}
virtual void WRITE_CHAR(T ch, int * pCumulativeOutputCount)
{
if ( FormattedOutput<T>::ShouldOutput( pCumulativeOutputCount, 1 ) )
{
++(*pCumulativeOutputCount);
if ( fputc( ch, m_file ) != ch )
*pCumulativeOutputCount = -1;
}
}
virtual void WRITE_MULTI_CHAR(T ch, int repeatCount, int * pCumulativeOutputCount)
{
if ( FormattedOutput<T>::ShouldOutput( pCumulativeOutputCount, repeatCount ) )
{
*pCumulativeOutputCount += repeatCount;
while ( 0 < repeatCount-- )
{
if ( fputc( ch, m_file ) != ch )
{
*pCumulativeOutputCount = -1;
return;
}
}
}
}
virtual void WRITE_STRING(const T * pch, int count, int * pCumulativeOutputCount)
{
if ( FormattedOutput<T>::ShouldOutput( pCumulativeOutputCount, count ) )
{
assert( NULL != pch );
*pCumulativeOutputCount += count;
if ( (size_t)count != fwrite( pch, sizeof(T), count, m_file ) )
*pCumulativeOutputCount = -1;
}
}
};
#endif // _FORMATTEDPRINT_H_

View file

@ -0,0 +1,145 @@
//---------------------------------------------------------------------------------------------------------------------------------
// File: StringFunctions.cpp
//
// Contents: Contains functions for handling UTF-16 on non-Windows platforms
//
// Microsoft Drivers 4.0 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the ""Software""),
// to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and / or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions :
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//---------------------------------------------------------------------------------------------------------------------------------
#include "StringFunctions.h"
// Tools\vc\src\crt\amd64\memcpy_s.c
int mplat_memcpy_s( void * dest, size_t destSize, const void * src, size_t count )
{
if ( 0 == count )
{
// nothing to do
return 0;
}
// validation section
if ( NULL == dest )
{
errno = EINVAL;
return EINVAL;
}
if ( src == NULL || destSize < count )
{
// zeroes the destination buffer
memset(dest, 0, destSize*sizeof(char));
if ( NULL == src )
{
errno = EINVAL;
return EINVAL;
}
if ( destSize < count )
{
errno = ERANGE;
return ERANGE;
}
return EINVAL;
}
memcpy(dest, src, count*sizeof(char));
return 0;
}
// Tools\vc\src\crt\amd64\strcpy_s.c
int mplat_strcpy_s( char * dest, size_t destSize, const char * src )
{
char * p;
size_t available;
// validation section
if ( NULL == dest || 0 == destSize )
{
errno = EINVAL;
return EINVAL;
}
if ( NULL == src )
{
*dest = 0;
errno = EINVAL;
return EINVAL;
}
p = dest;
available = destSize;
while ( (*p++ = *src++) != 0 && --available > 0 )
{
}
if ( 0 == available )
{
*dest = 0;
errno = ERANGE;
return ERANGE;
}
return 0;
}
// Tools\vc\src\crt\amd64\strcat_s.c
int mplat_strcat_s( char * dest, size_t destSize, const char * src )
{
char *p;
size_t available;
// validation section
if ( NULL == dest || 0 == destSize )
{
errno = EINVAL;
return EINVAL;
}
if ( NULL == src )
{
*dest = 0;
errno = EINVAL;
return EINVAL;
}
p = dest;
available = destSize;
while (available > 0 && *p != 0)
{
p++;
available--;
}
if (available == 0)
{
*dest = 0;
errno = EINVAL;
return EINVAL;
}
while ((*p++ = *src++) != 0 && --available > 0)
{
}
if (available == 0)
{
*dest = 0;
errno = ERANGE;
return ERANGE;
}
*p = 0;
return 0;
}
//
// End copy functions
//----------------------------------------------------------------------------

View file

@ -0,0 +1,39 @@
//---------------------------------------------------------------------------------------------------------------------------------
// File: StringFunctions.h
//
// Contents: Contains functions for handling UTF-16 on non-Windows platforms
//
// Microsoft Drivers 4.0 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the ""Software""),
// to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and / or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions :
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//---------------------------------------------------------------------------------------------------------------------------------
#if !defined(_STRINGFUNCTIONS_H_)
#define _STRINGFUNCTIONS_H_
#include "winnls.h"
// ---------------------------------------------------------------------------
// Declare internal versions of string handling functions
// Only the functions implemented are declared here
// Copy
int mplat_memcpy_s(void *_S1, size_t _N1, const void *_S2, size_t _N);
int mplat_strcat_s( char *strDestination, size_t numberOfElements, const char *strSource );
int mplat_strcpy_s(char * _Dst, size_t _SizeInBytes, const char * _Src);
// Copy
#define memcpy_s mplat_memcpy_s
#define strcat_s mplat_strcat_s
#define strcpy_s mplat_strcpy_s
#endif // _STRINGFUNCTIONS_H_

View file

@ -0,0 +1,517 @@
//---------------------------------------------------------------------------------------------------------------------------------
// File: Globalization.h
//
// Contents: Contains functions for handling Windows format strings
// and UTF-16 on non-Windows platforms
//
// Microsoft Drivers 4.0 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the ""Software""),
// to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and / or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions :
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//---------------------------------------------------------------------------------------------------------------------------------
#if !defined(_GLOBALIZATION_H_)
#define _GLOBALIZATION_H_
#include "xplat.h"
#include "typedefs_for_linux.h"
#include <errno.h>
#if defined(MPLAT_UNIX)
#include <iconv.h>
const iconv_t INVALID_ICONV = (iconv_t)(-1);
class IConvCache : public SLIST_ENTRY
{
iconv_t m_iconv;
// Prevent copying
IConvCache( const IConvCache & );
IConvCache & operator=( const IConvCache & );
public:
IConvCache( int dstIdx, int srcIdx );
~IConvCache();
iconv_t GetIConv() const
{
return m_iconv;
}
};
#endif
class EncodingConverter
{
UINT m_dstCodePage;
UINT m_srcCodePage;
#if defined(MPLAT_UNIX)
const IConvCache * m_pCvtCache;
bool IsValidIConv() const
{
return (NULL != m_pCvtCache && INVALID_ICONV != m_pCvtCache->GetIConv());
}
template< typename T >
struct iconv_buffer
{
char * m_pBytes;
size_t m_nBytesLeft;
iconv_buffer( char * buffer, size_t cchSize )
: m_pBytes(buffer), m_nBytesLeft(sizeof(T)*cchSize) {}
~iconv_buffer() {}
void Reset( char * buffer, size_t cchSize )
{
m_pBytes = buffer;
m_nBytesLeft = cchSize*sizeof(T);
}
void SkipSingleCh()
{
assert( sizeof(T) <= m_nBytesLeft );
m_nBytesLeft -= sizeof(T);
m_pBytes += sizeof(T);
}
void SkipDoubleCh()
{
SkipSingleCh();
// Only skip second half if there's bytes left and it is non-NULL
if ( m_nBytesLeft && 0 != *(UNALIGNED T *)m_pBytes )
SkipSingleCh();
}
void SkipUtf8Ch()
{
assert( 1 == sizeof(T) );
const char * pNext = SystemLocale::NextChar( CP_UTF8, m_pBytes, m_nBytesLeft );
assert( m_pBytes < pNext && (size_t)(pNext-m_pBytes) <= SystemLocale::MaxCharCchSize(CP_UTF8) );
UINT toTrim = (UINT)(pNext - m_pBytes);
assert( toTrim <= m_nBytesLeft );
assert( 0 < toTrim );
m_nBytesLeft -= toTrim;
m_pBytes += toTrim;
}
static char DefaultChar( UINT srcDataCP )
{
return 0x3f;
}
static WCHAR DefaultWChar( UINT srcDataCP )
{
return (CP_UTF8 == srcDataCP ? 0xfffd // Unicode to Unicode, use Unicode default char
: (932 == srcDataCP ? 0x30fb // 932 to Unicode has special default char
: 0x003f)); // WCP source, use '?'
}
void AssignDefault( UINT srcDataCP )
{
assert( sizeof(T) <= m_nBytesLeft );
if ( 1 == sizeof(T) )
{
*m_pBytes = DefaultChar( srcDataCP );
--m_nBytesLeft;
++m_pBytes;
}
else
{
*(UNALIGNED T *)m_pBytes = DefaultWChar( srcDataCP );
m_nBytesLeft -= sizeof(T);
m_pBytes += sizeof(T);
}
}
bool AssignDefaultUtf8( UINT srcDataCP )
{
// This is a utf8 buffer so T must be char
assert( 1 == sizeof(T) );
if ( CP_UTF16 == srcDataCP )
{
// If source codepage is UTF16 then use Unicode default char
// UTF8 default char is 3 bytes long
if ( m_nBytesLeft < 3 )
return false;
*m_pBytes++ = (T)0xef;
*m_pBytes++ = (T)0xbf;
*m_pBytes++ = (T)0xbd;
m_nBytesLeft -= 3;
}
else if ( 932 == srcDataCP )
{
// If source codepage is 932 then use special default char
// UTF8 default char for 932 is 3 bytes long
if ( m_nBytesLeft < 3 )
return false;
*m_pBytes++ = (T)0xe3;
*m_pBytes++ = (T)0x83;
*m_pBytes++ = (T)0xbb;
m_nBytesLeft -= 3;
}
else
{
*m_pBytes = DefaultChar( srcDataCP );
++m_pBytes;
--m_nBytesLeft;
}
return true;
}
// Prevent compiler from generating these
iconv_buffer();
iconv_buffer( const iconv_buffer & other );
iconv_buffer & operator=( const iconv_buffer & other );
};
template< class DestType >
bool AddDefault( iconv_buffer<DestType> * dest, bool * pHasLoss, DWORD * pErrorCode ) const
{
if ( NULL != pHasLoss )
*pHasLoss = true;
if ( CP_UTF8 != m_dstCodePage )
dest->AssignDefault( m_srcCodePage );
else if ( !dest->AssignDefaultUtf8(m_srcCodePage) )
{
// Not enough room for the default char
if ( NULL != pErrorCode )
*pErrorCode = ERROR_INSUFFICIENT_BUFFER;
return false;
}
return true;
}
template< class DestType, class SrcType >
size_t Convert(
iconv_buffer<DestType> & dest,
iconv_buffer<SrcType> & src,
bool failIfLossy = false, bool * pHasLoss = NULL, DWORD * pErrorCode = NULL ) const
{
if ( !IsValidIConv() )
return 0;
size_t iconv_ret;
size_t cchDest = dest.m_nBytesLeft/sizeof(DestType);
if ( NULL != pHasLoss )
*pHasLoss = false;
if ( NULL != pErrorCode )
*pErrorCode = ERROR_SUCCESS;
while ( 0 < dest.m_nBytesLeft && 0 < src.m_nBytesLeft )
{
// First clear any intermediate state left over from previous conversions
iconv_ret = iconv( m_pCvtCache->GetIConv(), NULL, NULL, NULL, NULL );
assert( 0 == iconv_ret );
// Now attempt conversion
iconv_ret = iconv( m_pCvtCache->GetIConv(), &src.m_pBytes, &src.m_nBytesLeft, &dest.m_pBytes, &dest.m_nBytesLeft );
if ( iconv_ret == (size_t)(-1) )
{
// If there's no dest bytes left, then treat as E2BIG even if the error
// is EILSEQ, etc. We want E2BIG to take precedence like Windows.
int err = (0 < dest.m_nBytesLeft ? errno : E2BIG);
if ( E2BIG != err && failIfLossy )
{
if ( NULL != pErrorCode )
*pErrorCode = ERROR_NO_UNICODE_TRANSLATION;
return 0;
}
switch ( err )
{
case EILSEQ: // Invalid multibyte sequence in input
if ( CP_UTF8 == m_srcCodePage )
src.SkipUtf8Ch();
else if ( 1 == sizeof(SrcType) )
src.SkipDoubleCh(); // DBCS
else
src.SkipSingleCh(); // utf32 or incomplate utf16 surrogate
if ( !AddDefault(&dest, pHasLoss, pErrorCode) )
return 0;
break;
case EINVAL: // Incomplete multibyte sequence in input
if ( CP_UTF8 == m_srcCodePage )
src.SkipUtf8Ch();
else
src.SkipSingleCh();
if ( !AddDefault(&dest, pHasLoss, pErrorCode) )
return 0;
break;
case E2BIG: // Output buffer is out of room
if ( NULL != pErrorCode )
*pErrorCode = ERROR_INSUFFICIENT_BUFFER;
return 0;
default:
if ( NULL != pErrorCode )
*pErrorCode = ERROR_INVALID_PARAMETER;
return 0;
}
}
}
return cchDest - (dest.m_nBytesLeft / sizeof(DestType));
}
#elif defined(MPLAT_WWOWH)
size_t ReturnCchResult( int cch, DWORD * pErrorCode ) const
{
if ( cch < 0 )
cch = 0;
if ( NULL != pErrorCode )
*pErrorCode = (0 == cch ? GetLastError() : ERROR_SUCCESS);
return cch;
}
#endif // defined(MPLAT_WWOWH)
public:
EncodingConverter( UINT dstCodePage, UINT srcCodePage );
~EncodingConverter();
bool Initialize();
// Performs an encoding conversion.
// Returns the number of dest chars written.
// Input and output buffers should not overlap.
template< class DestType, class SrcType, class AllocT >
size_t Convert(
DestType ** destBuffer,
const SrcType * srcBuffer, size_t cchSource,
bool failIfLossy = false, bool * pHasLoss = NULL, DWORD * pErrorCode = NULL ) const
{
#if defined(MPLAT_UNIX)
if ( !IsValidIConv() )
return 0;
iconv_buffer<SrcType> src(
reinterpret_cast< char * >( const_cast< SrcType * >(srcBuffer) ),
cchSource );
size_t cchDest = cchSource;
AutoArray< DestType, AllocT > newDestBuffer( cchDest );
iconv_buffer<DestType> dest(
reinterpret_cast< char * >(newDestBuffer.m_ptr),
cchDest );
size_t cchPrevCvt = 0;
DWORD rcCvt;
while ( true )
{
size_t cchCvt = Convert( dest, src, failIfLossy, pHasLoss, &rcCvt );
if ( 0 == cchCvt )
{
if ( ERROR_INSUFFICIENT_BUFFER == rcCvt )
{
// Alloc more and continue
cchPrevCvt = cchDest;
cchDest *= 2;
if ( !newDestBuffer.Realloc(cchDest) )
{
if ( NULL != pErrorCode )
*pErrorCode = ERROR_NOT_ENOUGH_MEMORY;
return 0;
}
// Fill newly allocated part of buffer
dest.Reset( reinterpret_cast< char * >(newDestBuffer.m_ptr+cchPrevCvt), cchDest );
}
else
{
if ( NULL != pErrorCode )
*pErrorCode = rcCvt;
return 0;
}
}
else
{
if ( NULL != pErrorCode )
*pErrorCode = rcCvt;
*destBuffer = newDestBuffer.Detach();
return cchPrevCvt + cchCvt;
}
}
#elif defined(MPLAT_WWOWH)
// WWOWH unit testing code
// Can only convert between ansi and utf16
if ( 1 == sizeof(DestType) && 2 == sizeof(SrcType) )
{
// utf16 to ansi
const wchar_t * srcPtr = reinterpret_cast< const wchar_t * >( srcBuffer );
BOOL loss = FALSE;
int converted = WideCharToMultiByte(
m_dstCodePage, 0,
srcPtr, (int)cchSource,
NULL, 0,
NULL, &loss );
if ( 0 < converted )
{
AutoArray< char, AllocT > newDestBuffer( converted );
char * dstPtr = newDestBuffer.m_ptr;
converted = WideCharToMultiByte(
m_dstCodePage, 0,
srcPtr, (int)cchSource,
newDestBuffer.m_ptr, converted,
NULL, &loss );
if ( 0 < converted )
*destBuffer = newDestBuffer.Detach();
if ( NULL != pHasLoss )
*pHasLoss = (FALSE != loss);
}
return ReturnCchResult( converted, pErrorCode );
}
else if ( 2 == sizeof(DestType) && 1 == sizeof(SrcType) )
{
// ansi to utf16
const char * srcPtr = reinterpret_cast< const char * >( srcBuffer );
int converted = MultiByteToWideChar(
m_srcCodePage, (failIfLossy ? MB_ERR_INVALID_CHARS : 0),
srcPtr, (int)cchSource,
NULL, 0 );
if ( 0 < converted )
{
AutoArray< WCHAR, AllocT > newDestBuffer( converted );
converted = MultiByteToWideChar(
m_srcCodePage, (failIfLossy ? MB_ERR_INVALID_CHARS : 0),
srcPtr, (int)cchSource,
newDestBuffer.m_ptr, converted );
if ( 0 < converted )
*destBuffer = newDestBuffer.Detach();
if ( NULL != pHasLoss )
*pHasLoss = false;
}
return ReturnCchResult( converted, pErrorCode );
}
else
{
assert( false );
if ( NULL != pErrorCode )
*pErrorCode = ERROR_NOT_SUPPORTED;
return 0;
}
#endif // defined(MPLAT_WWOWH)
}
// Performs an encoding conversion.
// Returns the number of dest chars written.
// Input and output buffers should not overlap.
template< class DestType, class SrcType >
size_t Convert(
DestType * destBuffer, size_t cchDest,
const SrcType * srcBuffer, size_t cchSource,
bool failIfLossy = false, bool * pHasLoss = NULL, DWORD * pErrorCode = NULL ) const
{
#if defined(MPLAT_UNIX)
if ( !IsValidIConv() )
return 0;
iconv_buffer<SrcType> src(
reinterpret_cast< char * >( const_cast< SrcType * >(srcBuffer) ),
cchSource );
if ( 0 < cchDest )
{
iconv_buffer<DestType> dest(
reinterpret_cast< char * >(destBuffer),
cchDest );
return Convert( dest, src, failIfLossy, pHasLoss, pErrorCode );
}
else
{
// Use fixed size buffer iteratively to determine final required length
const size_t CCH_FIXED_SIZE = 256;
char fixed_buf[ CCH_FIXED_SIZE*sizeof(DestType) ];
iconv_buffer<DestType> dest(
&fixed_buf[0],
CCH_FIXED_SIZE );
bool hasLoss = false;
DWORD rcCvt = ERROR_SUCCESS;
size_t cchOnce = 0;
size_t cchCumulative = 0;
while ( 0 < src.m_nBytesLeft
&& 0 == (cchOnce = Convert(dest, src, failIfLossy, &hasLoss, &rcCvt))
&& ERROR_INSUFFICIENT_BUFFER == rcCvt )
{
cchCumulative += CCH_FIXED_SIZE;
cchCumulative -= dest.m_nBytesLeft;
dest.Reset( &fixed_buf[0], CCH_FIXED_SIZE );
}
if ( 0 < cchOnce )
cchCumulative += cchOnce;
if ( NULL != pErrorCode )
*pErrorCode = (0 < cchCumulative ? ERROR_SUCCESS : rcCvt);
if ( NULL != pHasLoss )
*pHasLoss |= hasLoss;
return cchCumulative;
}
#elif defined(MPLAT_WWOWH)
// WWOWH unit testing code
// Can only convert between ansi and utf16
if ( 1 == sizeof(DestType) && 2 == sizeof(SrcType) )
{
// utf16 to ansi
char * dstPtr = reinterpret_cast< char * >( destBuffer );
const wchar_t * srcPtr = reinterpret_cast< const wchar_t * >( srcBuffer );
BOOL loss = FALSE;
int converted = WideCharToMultiByte(
m_dstCodePage, 0,
srcPtr, (int)cchSource,
dstPtr, (int)cchDest,
NULL, &loss );
if ( NULL != pHasLoss )
*pHasLoss = (FALSE != loss);
return ReturnCchResult( converted, pErrorCode );
}
else if ( 2 == sizeof(DestType) && 1 == sizeof(SrcType) )
{
// ansi to utf16
wchar_t * dstPtr = reinterpret_cast< wchar_t * >( destBuffer );
const char * srcPtr = reinterpret_cast< const char * >( srcBuffer );
int converted = MultiByteToWideChar(
m_srcCodePage, (failIfLossy ? MB_ERR_INVALID_CHARS : 0),
srcPtr, (int)cchSource,
dstPtr, (int)cchDest );
if ( NULL != pHasLoss )
*pHasLoss = false;
return ReturnCchResult( converted, pErrorCode );
}
else
{
assert( false );
if ( NULL != pErrorCode )
*pErrorCode = ERROR_NOT_SUPPORTED;
return 0;
}
#endif // defined(MPLAT_WWOWH)
}
};
#endif // _GLOBALIZATION_H_

View file

@ -0,0 +1,62 @@
//---------------------------------------------------------------------------------------------------------------------------------
// File: InterlockedAtomic.h
//
// Contents: Contains a portable abstraction for interlocked, atomic
// operations on int32_t and pointer types.
//
// Microsoft Drivers 4.0 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the ""Software""),
// to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and / or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions :
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//---------------------------------------------------------------------------------------------------------------------------------
#ifndef __INTERLOCKEDATOMIC_H__
#define __INTERLOCKEDATOMIC_H__
// Forward references and contract specifications
//
// Increments and returns new value
LONG InterlockedIncrement( LONG volatile * atomic );
// Decrements and returns new value
LONG InterlockedDecrement( LONG volatile * atomic );
// Always returns old value
// Sets to new value if old value equals compareTo
LONG InterlockedCompareExchange( LONG volatile * atomic, LONG newValue, LONG compareTo );
// Sets to new value and returns old value
LONG InterlockedExchange( LONG volatile * atomic, LONG newValue );
// Sets to new value and returns old value
PVOID InterlockedExchangePointer( PVOID volatile * atomic, PVOID newValue);
// Adds the amount and returns the old value
LONG InterlockedExchangeAdd( LONG volatile * atomic, LONG add );
// Always returns the old value
// Sets the new value if old value equals compareTo
PVOID InterlockedCompareExchangePointer( PVOID volatile * atomic, PVOID newValue, PVOID compareTo );
// Use conditional compilation to load the implementation
//
#if defined(_MSC_VER)
#include "InterlockedAtomic_WwoWH.h"
#elif defined(__GNUC__)
#include "interlockedatomic_gcc.h"
#else
#error "Unsupported compiler"
#endif
#endif // __INTERLOCKEDATOMIC_H__

View file

@ -0,0 +1,63 @@
//---------------------------------------------------------------------------------------------------------------------------------
// File: InterlockedAtomic_gcc.h
//
// Contents: Contains a portable abstraction for interlocked, atomic
// operations on int32_t and pointer types.
//
// Microsoft Drivers 4.0 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the ""Software""),
// to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and / or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions :
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//---------------------------------------------------------------------------------------------------------------------------------
#ifndef __INTERLOCKEDATOMIC_GCC_H__
#define __INTERLOCKEDATOMIC_GCC_H__
#if !defined(__GNUC__)
#error "Incorrect compiler configuration in InterlockedAtomic.h. Was expecting GCC."
#endif
inline LONG InterlockedIncrement( LONG volatile * atomic )
{
return __sync_add_and_fetch( atomic, 1 );
}
inline LONG InterlockedDecrement( LONG volatile * atomic )
{
return __sync_sub_and_fetch( atomic, 1 );
}
inline LONG InterlockedCompareExchange( LONG volatile * atomic, LONG newValue, LONG compareTo )
{
return __sync_val_compare_and_swap( atomic, compareTo, newValue );
}
inline LONG InterlockedExchange( LONG volatile * atomic, LONG newValue )
{
return __sync_lock_test_and_set( atomic, newValue );
}
inline PVOID InterlockedExchangePointer( PVOID volatile * atomic, PVOID newValue)
{
return __sync_lock_test_and_set( atomic, newValue );
}
inline LONG InterlockedExchangeAdd( LONG volatile * atomic, LONG add )
{
return __sync_fetch_and_add( atomic, add );
}
inline PVOID InterlockedCompareExchangePointer( PVOID volatile * atomic, PVOID newValue, PVOID compareTo )
{
return __sync_val_compare_and_swap( atomic, compareTo, newValue );
}
#endif // __INTERLOCKEDATOMIC_GCC_H__

View file

@ -0,0 +1,142 @@
//---------------------------------------------------------------------------------------------------------------------------------
// File: InterlockedSList.h
//
// Contents: Contains a portable abstraction for interlocked, singly
// linked list.
//
// Microsoft Drivers 4.0 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the ""Software""),
// to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and / or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions :
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//---------------------------------------------------------------------------------------------------------------------------------
#ifndef __INTERLOCKEDSLIST_H__
#define __INTERLOCKEDSLIST_H__
#include "interlockedatomic.h"
#define SLIST_ENTRY SINGLE_LIST_ENTRY
#define PSLIST_ENTRY PSINGLE_LIST_ENTRY
typedef struct _SINGLE_LIST_ENTRY {
// Want a volatile pointer to non-volatile data so place after all type info
struct _SINGLE_LIST_ENTRY * volatile Next;
} SINGLE_LIST_ENTRY, *PSINGLE_LIST_ENTRY;
typedef union _SLIST_HEADER {
// Provides 8 byte alignment for 32-bit builds. Technically, not needed for
// current implementation below but leaving for future use.
ULONGLONG Alignment;
struct {
// Want a volatile pointer to non-volatile data so place after all type info
PSLIST_ENTRY volatile Head;
volatile LONG Depth;
volatile LONG Mutex;
} List;
} SLIST_HEADER, *PSLIST_HEADER;
inline VOID InitializeSListHead( PSLIST_HEADER slist )
{
assert( NULL != slist );
slist->List.Head = NULL;
slist->List.Depth = 0;
slist->List.Mutex = 0;
}
inline PSLIST_ENTRY InterlockedPopEntrySList( PSLIST_HEADER slist )
{
assert( NULL != slist );
// Exit prior to 'mutex' if we think it is empty
// Some callers (like sqlncli/msdart/dll/dynslist.h) rely on a NULL
// result from Pop to indicate the list is empty. This early exit
// is an optimization and not technically needed for correctness.
PSLIST_ENTRY oldHead = slist->List.Head;
if ( NULL == oldHead )
{
return NULL;
}
while ( 0 != slist->List.Mutex || 0 != InterlockedCompareExchange( &slist->List.Mutex, 1, 0 ) )
{
// Spin until 'mutex' is free
}
// We have the 'mutex' so proceed with update
oldHead = slist->List.Head;
if ( NULL != oldHead )
{
slist->List.Head = oldHead->Next;
--(slist->List.Depth);
assert( 0 <= slist->List.Depth );
}
// Free the 'mutex'
slist->List.Mutex = 0;
return oldHead;
}
inline PSLIST_ENTRY InterlockedPushEntrySList( PSLIST_HEADER slist, PSLIST_ENTRY newEntry )
{
assert( NULL != slist );
while ( 0 != slist->List.Mutex || 0 != InterlockedCompareExchange( &slist->List.Mutex, 1, 0 ) )
{
// Spin until 'mutex' is free
}
// We have the 'mutex' so proceed with update
PSLIST_ENTRY oldHead = slist->List.Head;
newEntry->Next = oldHead;
slist->List.Head = newEntry;
++(slist->List.Depth);
// Free the 'mutex'
slist->List.Mutex = 0;
return oldHead;
}
inline PSLIST_ENTRY InterlockedFlushSList( PSLIST_HEADER slist )
{
assert( NULL != slist );
while ( 0 != slist->List.Mutex || 0 != InterlockedCompareExchange( &slist->List.Mutex, 1, 0 ) )
{
// Spin until 'mutex' is free
}
// We have the 'mutex' so proceed with update
PSLIST_ENTRY oldHead = slist->List.Head;
slist->List.Head = NULL;
slist->List.Depth = 0;
// Free the 'mutex'
slist->List.Mutex = 0;
return oldHead;
}
// If the list has more than USHORT nodes then this method
// will not return reliable results.
inline USHORT QueryDepthSList( PSLIST_HEADER slist )
{
assert( NULL != slist );
return static_cast<USHORT>(slist->List.Depth);
}
#endif // __INTERLOCKEDSLIST_H__

7635
source/shared/intsafe.h Normal file
View file

@ -0,0 +1,7635 @@
//---------------------------------------------------------------------------------------------------------------------------------
// File: intsafe.h
//
// Contents: This module defines helper functions to prevent
// integer overflow bugs.
//
// Microsoft Drivers 4.0 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the ""Software""),
// to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and / or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions :
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//---------------------------------------------------------------------------------------------------------------------------------
#ifndef XPLAT_INTSAFE_H
#define XPLAT_INTSAFE_H
#if (_MSC_VER > 1000)
#pragma once
#endif
#if !defined(_W64)
#if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && (_MSC_VER >= 1300)
#define _W64 __w64
#else
#define _W64
#endif
#endif
#include "sal.h"
#include <limits.h>
//
// typedefs
//
typedef char CHAR;
typedef signed char INT8;
typedef unsigned char UCHAR;
typedef unsigned char UINT8;
typedef unsigned char BYTE;
typedef short SHORT;
typedef signed short INT16;
typedef unsigned short USHORT;
typedef unsigned short UINT16;
typedef unsigned short WORD;
typedef int INT;
typedef signed int INT32;
typedef unsigned int UINT;
typedef unsigned int UINT32;
typedef windowsLong_t LONG;
typedef windowsULong_t DWORD;
typedef windowsLongLong_t LONGLONG;
typedef windowsLongLong_t LONG64;
typedef windowsLongLong_t INT64;
typedef windowsULongLong_t ULONGLONG;
typedef windowsULongLong_t DWORDLONG;
typedef windowsULongLong_t ULONG64;
typedef windowsULongLong_t DWORD64;
typedef windowsULongLong_t UINT64;
#if (__midl > 501)
typedef [public] __int3264 INT_PTR;
typedef [public] unsigned __int3264 UINT_PTR;
typedef [public] __int3264 LONG_PTR;
typedef [public] unsigned __int3264 ULONG_PTR;
#else
#ifdef _WIN64
typedef __int64 INT_PTR, *PINT_PTR;
typedef unsigned __int64 UINT_PTR, *PUINT_PTR;
typedef __int64 LONG_PTR, *PLONG_PTR;
typedef unsigned __int64 ULONG_PTR, *PULONG_PTR;
#else
typedef _W64 int INT_PTR, *PINT_PTR;
typedef _W64 unsigned int UINT_PTR, *PUINT_PTR;
typedef _W64 windowsLong_t LONG_PTR, *PLONG_PTR;
typedef _W64 windowsULong_t ULONG_PTR, *PULONG_PTR;
#endif // WIN64
#endif // (__midl > 501)
typedef ULONG_PTR DWORD_PTR;
typedef LONG_PTR SSIZE_T;
typedef ULONG_PTR SIZE_T;
#if defined(_AMD64_)
#ifdef __cplusplus
extern "C" {
#endif
#define UnsignedMultiply128 _umul128
ULONG64
UnsignedMultiply128 (
__inn ULONG64 Multiplier,
__inn ULONG64 Multiplicand,
__outt __deref_out_range(==,Multiplier * Multiplicand) ULONG64 *HighProduct
);
#pragma intrinsic(_umul128)
#ifdef __cplusplus
}
#endif
#endif // _AMD64_
typedef __success(return >= 0) windowsLong_t HRESULT;
#define SUCCEEDED(hr) (((HRESULT)(hr)) >= 0)
#define FAILED(hr) (((HRESULT)(hr)) < 0)
#define S_OK ((HRESULT)0L)
#define INTSAFE_E_ARITHMETIC_OVERFLOW ((HRESULT)0x80070216L) // 0x216 = 534 = ERROR_ARITHMETIC_OVERFLOW
#ifndef SORTPP_PASS
// compiletime asserts (failure results in error C2118: negative subscript)
#define C_ASSERT(e) typedef char __C_ASSERT__[(e)?1:-1]
#else
#define C_ASSERT(e)
#endif
//
// UInt32x32To64 macro
//
#define UInt32x32To64(a, b) ((windowsULongLong_t)(((windowsULongLong_t)(a)) * ((windowsULong_t)(b))))
//
// Min/Max type values
//
//#define INT8_MIN (-127 - 1)
#define SHORT_MIN (-32768)
//#define INT16_MIN (-32767 - 1)
//#define INT_MIN (-2147483647 - 1)
//#define INT32_MIN (-2147483647l - 1)
//#define LONG_MIN (-2147483647L - 1)
#define LONGLONG_MIN (-9223372036854775807ll - 1)
#define LONG64_MIN (-9223372036854775807ll - 1)
//#define INT64_MIN (-9223372036854775807ll - 1)
#define INT128_MIN (-170141183460469231731687303715884105727i128 - 1)
#ifdef _WIN64
#define INT_PTR_MIN (-9223372036854775807ll - 1)
#define LONG_PTR_MIN (-9223372036854775807ll - 1)
#define PTRDIFF_T_MIN (-9223372036854775807ll - 1)
#define SSIZE_T_MIN (-9223372036854775807ll - 1)
#else
#define INT_PTR_MIN (-2147483647 - 1)
#define LONG_PTR_MIN (-2147483647L - 1)
#define PTRDIFF_T_MIN (-2147483647 - 1)
#define SSIZE_T_MIN (-2147483647L - 1)
#endif
//#define INT8_MAX 127
//#define UINT8_MAX 0xff
#define BYTE_MAX 0xff
#define SHORT_MAX 32767
//#define INT16_MAX 32767
#define USHORT_MAX 0xffff
//#define UINT16_MAX 0xffff
#define WORD_MAX 0xffff
//#define INT_MAX 2147483647
//#define INT32_MAX 2147483647l
//#define UINT_MAX 0xffffffff
//#define UINT32_MAX 0xfffffffful
//#define LONG_MAX 2147483647L
//#define ULONG_MAX 0xffffffffUL
#define DWORD_MAX 0xffffffffUL
#define LONGLONG_MAX 9223372036854775807ll
#define LONG64_MAX 9223372036854775807ll
//#define INT64_MAX 9223372036854775807ll
#define ULONGLONG_MAX 0xffffffffffffffffull
#define DWORDLONG_MAX 0xffffffffffffffffull
#define ULONG64_MAX 0xffffffffffffffffull
#define DWORD64_MAX 0xffffffffffffffffull
//#define UINT64_MAX 0xffffffffffffffffull
#define INT128_MAX 170141183460469231731687303715884105727i128
#define UINT128_MAX 0xffffffffffffffffffffffffffffffffui128
#ifndef _I64_MIN
#define _I64_MIN INT64_MIN
#define _I64_MAX INT64_MAX
#define _UI64_MIN UINT64_MIN
#define _UI64_MAX UINT64_MAX
#endif
#undef SIZE_T_MAX
#ifdef _WIN64
#define INT_PTR_MAX 9223372036854775807ll
#define UINT_PTR_MAX 0xffffffffffffffffull
#define LONG_PTR_MAX 9223372036854775807ll
#define ULONG_PTR_MAX 0xffffffffffffffffull
#define DWORD_PTR_MAX 0xffffffffffffffffull
#define PTRDIFF_T_MAX 9223372036854775807ll
#define SIZE_T_MAX 0xffffffffffffffffull
#define SSIZE_T_MAX 9223372036854775807ll
#define _SIZE_T_MAX 0xffffffffffffffffull
#else
#define INT_PTR_MAX 2147483647
#define UINT_PTR_MAX 0xffffffff
#define LONG_PTR_MAX 2147483647L
#define ULONG_PTR_MAX 0xffffffffUL
#define DWORD_PTR_MAX 0xffffffffUL
#define PTRDIFF_T_MAX 2147483647
#define SIZE_T_MAX 0xffffffff
#define SSIZE_T_MAX 2147483647L
#define _SIZE_T_MAX 0xffffffffUL
#endif
//
// It is common for -1 to be used as an error value
//
#define INT8_ERROR (-1)
#define UINT8_ERROR 0xff
#define BYTE_ERROR 0xff
#define SHORT_ERROR (-1)
#define INT16_ERROR (-1)
#define USHORT_ERROR 0xffff
#define UINT16_ERROR 0xffff
#define WORD_ERROR 0xffff
#define INT_ERROR (-1)
#define INT32_ERROR (-1l)
#define UINT_ERROR 0xffffffff
#define UINT32_ERROR 0xfffffffful
#define LONG_ERROR (-1L)
#define ULONG_ERROR 0xffffffffUL
#define DWORD_ERROR 0xffffffffUL
#define LONGLONG_ERROR (-1ll)
#define LONG64_ERROR (-1ll)
#define INT64_ERROR (-1ll)
#define ULONGLONG_ERROR 0xffffffffffffffffull
#define DWORDLONG_ERROR 0xffffffffffffffffull
#define ULONG64_ERROR 0xffffffffffffffffull
#define UINT64_ERROR 0xffffffffffffffffull
#ifdef _WIN64
#define INT_PTR_ERROR (-1ll)
#define UINT_PTR_ERROR 0xffffffffffffffffull
#define LONG_PTR_ERROR (-1ll)
#define ULONG_PTR_ERROR 0xffffffffffffffffull
#define DWORD_PTR_ERROR 0xffffffffffffffffull
#define PTRDIFF_T_ERROR (-1ll)
#define SIZE_T_ERROR 0xffffffffffffffffull
#define SSIZE_T_ERROR (-1ll)
#define _SIZE_T_ERROR 0xffffffffffffffffull
#else
#define INT_PTR_ERROR (-1)
#define UINT_PTR_ERROR 0xffffffff
#define LONG_PTR_ERROR (-1L)
#define ULONG_PTR_ERROR 0xffffffffUL
#define DWORD_PTR_ERROR 0xffffffffUL
#define PTRDIFF_T_ERROR (-1)
#define SIZE_T_ERROR 0xffffffff
#define SSIZE_T_ERROR (-1L)
#define _SIZE_T_ERROR 0xffffffffUL
#endif
//
// We make some assumptions about the sizes of various types. Let's be
// explicit about those assumptions and check them.
//
C_ASSERT(sizeof(USHORT) == 2);
C_ASSERT(sizeof(INT) == 4);
C_ASSERT(sizeof(UINT) == 4);
C_ASSERT(sizeof(LONG) == 4);
C_ASSERT(sizeof(ULONG) == 8);
C_ASSERT(sizeof(UINT_PTR) == sizeof(ULONG_PTR));
//=============================================================================
// Conversion functions
//
// There are three reasons for having conversion functions:
//
// 1. We are converting from a signed type to an unsigned type of the same
// size, or vice-versa.
//
// Since we only have unsigned math functions, this allows people to convert
// to unsigned, do the math, and then convert back to signed.
//
// 2. We are converting to a smaller type, and we could therefore possibly
// overflow.
//
// 3. We are converting to a bigger type, and we are signed and the type we are
// converting to is unsigned.
//
//=============================================================================
//
// INT8 -> UCHAR conversion
//
__inline
HRESULT
Int8ToUChar(
__inn INT8 i8Operand,
__outt __deref_out_range(==,i8Operand) UCHAR* pch)
{
HRESULT hr;
if (i8Operand >= 0)
{
*pch = (UCHAR)i8Operand;
hr = S_OK;
}
else
{
*pch = '\0';
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// INT8 -> UINT8 conversion
//
__inline
HRESULT
Int8ToUInt8(
__inn INT8 i8Operand,
__outt __deref_out_range(==,i8Operand) UINT8* pu8Result)
{
HRESULT hr;
if (i8Operand >= 0)
{
*pu8Result = (UINT8)i8Operand;
hr = S_OK;
}
else
{
*pu8Result = UINT8_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// INT8 -> BYTE conversion
//
#define Int8ToByte Int8ToUInt8
//
// INT8 -> USHORT conversion
//
__inline
HRESULT
Int8ToUShort(
__inn INT8 i8Operand,
__outt __deref_out_range(==,i8Operand) USHORT* pusResult)
{
HRESULT hr;
if (i8Operand >= 0)
{
*pusResult = (USHORT)i8Operand;
hr = S_OK;
}
else
{
*pusResult = USHORT_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// INT8 -> UINT16 conversion
//
#define Int8ToUInt16 Int8ToUShort
//
// INT8 -> WORD conversion
//
#define Int8ToWord Int8ToUShort
//
// INT8 -> UINT conversion
//
__inline
HRESULT
Int8ToUInt(
__inn INT8 i8Operand,
__outt __deref_out_range(==,i8Operand) UINT* puResult)
{
HRESULT hr;
if (i8Operand >= 0)
{
*puResult = (UINT)i8Operand;
hr = S_OK;
}
else
{
*puResult = UINT_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// INT8 -> UINT32 conversion
//
#define Int8ToUInt32 Int8ToUInt
//
// INT8 -> UINT_PTR conversion
//
__inline
HRESULT
Int8ToUIntPtr(
__inn INT8 i8Operand,
__outt __deref_out_range(==,i8Operand) UINT_PTR* puResult)
{
HRESULT hr;
if (i8Operand >= 0)
{
*puResult = (UINT_PTR)i8Operand;
hr = S_OK;
}
else
{
*puResult = UINT_PTR_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// INT8 -> ULONG conversion
//
__inline
HRESULT
Int8ToULong(
__inn INT8 i8Operand,
__outt __deref_out_range(==,i8Operand) ULONG* pulResult)
{
HRESULT hr;
if (i8Operand >= 0)
{
*pulResult = (ULONG)i8Operand;
hr = S_OK;
}
else
{
*pulResult = ULONG_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// INT8 -> ULONG_PTR conversion
//
__inline
HRESULT
Int8ToULongPtr(
__inn INT8 i8Operand,
__outt __deref_out_range(==,i8Operand) ULONG_PTR* pulResult)
{
HRESULT hr;
if (i8Operand >= 0)
{
*pulResult = (ULONG_PTR)i8Operand;
hr = S_OK;
}
else
{
*pulResult = ULONG_PTR_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// INT8 -> DWORD conversion
//
#define Int8ToDWord Int8ToULong
//
// INT8 -> DWORD_PTR conversion
//
#define Int8ToDWordPtr Int8ToULongPtr
//
// INT8 -> ULONGLONG conversion
//
__inline
HRESULT
Int8ToULongLong(
__inn INT8 i8Operand,
__outt __deref_out_range(==,i8Operand) ULONGLONG* pullResult)
{
HRESULT hr;
if (i8Operand >= 0)
{
*pullResult = (ULONGLONG)i8Operand;
hr = S_OK;
}
else
{
*pullResult = ULONGLONG_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// INT8 -> DWORDLONG conversion
//
#define Int8ToDWordLong Int8ToULongLong
//
// INT8 -> ULONG64 conversion
//
#define Int8ToULong64 Int8ToULongLong
//
// INT8 -> DWORD64 conversion
//
#define Int8ToDWord64 Int8ToULongLong
//
// INT8 -> UINT64 conversion
//
#define Int8ToUInt64 Int8ToULongLong
//
// INT8 -> size_t conversion
//
#define Int8ToSizeT Int8ToUIntPtr
//
// INT8 -> SIZE_T conversion
//
#define Int8ToSIZET Int8ToULongPtr
//
// UINT8 -> INT8 conversion
//
__inline
HRESULT
UInt8ToInt8(
__inn UINT8 u8Operand,
__outt __deref_out_range(==,u8Operand) INT8* pi8Result)
{
HRESULT hr;
if (u8Operand <= INT8_MAX)
{
*pi8Result = (INT8)u8Operand;
hr = S_OK;
}
else
{
*pi8Result = INT8_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// UINT8 -> CHAR conversion
//
__forceinline
HRESULT
UInt8ToChar(
__inn UINT8 u8Operand,
__outt __deref_out_range(==,u8Operand) CHAR* pch)
{
#ifdef _CHAR_UNSIGNED
*pch = (CHAR)u8Operand;
return S_OK;
#else
return UInt8ToInt8(u8Operand, (INT8*)pch);
#endif
}
//
// BYTE -> INT8 conversion
//
__inline
HRESULT
ByteToInt8(
__inn BYTE bOperand,
__outt __deref_out_range(==,bOperand) INT8* pi8Result)
{
HRESULT hr;
if (bOperand <= INT8_MAX)
{
*pi8Result = (INT8)bOperand;
hr = S_OK;
}
else
{
*pi8Result = INT8_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// BYTE -> CHAR conversion
//
__forceinline
HRESULT
ByteToChar(
__inn BYTE bOperand,
__outt __deref_out_range(==,bOperand) CHAR* pch)
{
#ifdef _CHAR_UNSIGNED
*pch = (CHAR)bOperand;
return S_OK;
#else
return ByteToInt8(bOperand, (INT8*)pch);
#endif
}
//
// SHORT -> INT8 conversion
//
__inline
HRESULT
ShortToInt8(
__inn SHORT sOperand,
__outt __deref_out_range(==,sOperand) INT8* pi8Result)
{
HRESULT hr;
if ((sOperand >= INT8_MIN) && (sOperand <= INT8_MAX))
{
*pi8Result = (INT8)sOperand;
hr = S_OK;
}
else
{
*pi8Result = INT8_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// SHORT -> UCHAR conversion
//
__inline
HRESULT
ShortToUChar(
__inn SHORT sOperand,
__outt __deref_out_range(==,sOperand) UCHAR* pch)
{
HRESULT hr;
if ((sOperand >= 0) && (sOperand <= 255))
{
*pch = (UCHAR)sOperand;
hr = S_OK;
}
else
{
*pch = '\0';
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// SHORT -> CHAR conversion
//
__forceinline
HRESULT
ShortToChar(
__inn SHORT sOperand,
__outt __deref_out_range(==,sOperand) CHAR* pch)
{
#ifdef _CHAR_UNSIGNED
return ShortToUChar(sOperand, (UCHAR*)pch);
#else
return ShortToInt8(sOperand, (INT8*)pch);
#endif // _CHAR_UNSIGNED
}
//
// SHORT -> UINT8 conversion
//
__inline
HRESULT
ShortToUInt8(
__inn SHORT sOperand,
__outt __deref_out_range(==,sOperand) UINT8* pui8Result)
{
HRESULT hr;
if ((sOperand >= 0) && (sOperand <= UINT8_MAX))
{
*pui8Result = (UINT8)sOperand;
hr = S_OK;
}
else
{
*pui8Result = UINT8_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// SHORT -> BYTE conversion
//
#define ShortToByte ShortToUInt8
//
// SHORT -> USHORT conversion
//
__inline
HRESULT
ShortToUShort(
__inn SHORT sOperand,
__outt __deref_out_range(==,sOperand) USHORT* pusResult)
{
HRESULT hr;
if (sOperand >= 0)
{
*pusResult = (USHORT)sOperand;
hr = S_OK;
}
else
{
*pusResult = USHORT_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// SHORT -> UINT16 conversion
//
#define ShortToUInt16 ShortToUShort
//
// SHORT -> WORD conversion
//
#define ShortToWord ShortToUShort
//
// SHORT -> UINT conversion
//
__inline
HRESULT
ShortToUInt(
__inn SHORT sOperand,
__outt __deref_out_range(==,sOperand) UINT* puResult)
{
HRESULT hr;
if (sOperand >= 0)
{
*puResult = (UINT)sOperand;
hr = S_OK;
}
else
{
*puResult = UINT_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// SHORT -> UINT32 conversion
//
#define ShortToUInt32 ShortToUInt
//
// SHORT -> UINT_PTR conversion
//
__inline
HRESULT
ShortToUIntPtr(
__inn SHORT sOperand,
__outt __deref_out_range(==,sOperand) UINT_PTR* puResult)
{
HRESULT hr;
if (sOperand >= 0)
{
*puResult = (UINT_PTR)sOperand;
hr = S_OK;
}
else
{
*puResult = UINT_PTR_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// SHORT -> ULONG conversion
//
__inline
HRESULT
ShortToULong(
__inn SHORT sOperand,
__outt __deref_out_range(==,sOperand) ULONG* pulResult)
{
HRESULT hr;
if (sOperand >= 0)
{
*pulResult = (ULONG)sOperand;
hr = S_OK;
}
else
{
*pulResult = ULONG_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// SHORT -> ULONG_PTR conversion
//
__inline
HRESULT
ShortToULongPtr(
__inn SHORT sOperand,
__outt __deref_out_range(==,sOperand) ULONG_PTR* pulResult)
{
HRESULT hr;
if (sOperand >= 0)
{
*pulResult = (ULONG_PTR)sOperand;
hr = S_OK;
}
else
{
*pulResult = ULONG_PTR_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// SHORT -> DWORD conversion
//
#define ShortToDWord ShortToULong
//
// SHORT -> DWORD_PTR conversion
//
__inline
HRESULT
ShortToDWordPtr(
__inn SHORT sOperand,
__outt __deref_out_range(==,sOperand) DWORD_PTR* pdwResult)
{
HRESULT hr;
if (sOperand >= 0)
{
*pdwResult = (DWORD_PTR)sOperand;
hr = S_OK;
}
else
{
*pdwResult = DWORD_PTR_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// SHORT -> ULONGLONG conversion
//
__inline
HRESULT
ShortToULongLong(
__inn SHORT sOperand,
__outt __deref_out_range(==,sOperand) ULONGLONG* pullResult)
{
HRESULT hr;
if (sOperand >= 0)
{
*pullResult = (ULONGLONG)sOperand;
hr = S_OK;
}
else
{
*pullResult = ULONGLONG_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// SHORT -> DWORDLONG conversion
//
#define ShortToDWordLong ShortToULongLong
//
// SHORT -> ULONG64 conversion
//
#define ShortToULong64 ShortToULongLong
//
// SHORT -> DWORD64 conversion
//
#define ShortToDWord64 ShortToULongLong
//
// SHORT -> UINT64 conversion
//
#define ShortToUInt64 ShortToULongLong
//
// SHORT -> size_t conversion
//
#define ShortToSizeT ShortToUIntPtr
//
// SHORT -> SIZE_T conversion
//
#define ShortToSIZET ShortToULongPtr
//
// INT16 -> CHAR conversion
//
#define Int16ToChar ShortToChar
//
// INT16 -> INT8 conversion
//
#define Int16ToInt8 ShortToInt8
//
// INT16 -> UCHAR conversion
//
#define Int16ToUChar ShortToUChar
//
// INT16 -> UINT8 conversion
//
#define Int16ToUInt8 ShortToUInt8
//
// INT16 -> BYTE conversion
//
#define Int16ToByte ShortToUInt8
//
// INT16 -> USHORT conversion
//
#define Int16ToUShort ShortToUShort
//
// INT16 -> UINT16 conversion
//
#define Int16ToUInt16 ShortToUShort
//
// INT16 -> WORD conversion
//
#define Int16ToWord ShortToUShort
//
// INT16 -> UINT conversion
//
#define Int16ToUInt ShortToUInt
//
// INT16 -> UINT32 conversion
//
#define Int16ToUInt32 ShortToUInt
//
// INT16 -> UINT_PTR conversion
//
#define Int16ToUIntPtr ShortToUIntPtr
//
// INT16 -> ULONG conversion
//
#define Int16ToULong ShortToULong
//
// INT16 -> ULONG_PTR conversion
//
#define Int16ToULongPtr ShortToULongPtr
//
// INT16 -> DWORD conversion
//
#define Int16ToDWord ShortToULong
//
// INT16 -> DWORD_PTR conversion
//
#define Int16ToDWordPtr ShortToULongPtr
//
// INT16 -> ULONGLONG conversion
//
#define Int16ToULongLong ShortToULongLong
//
// INT16 -> DWORDLONG conversion
//
#define Int16ToDWordLong ShortToULongLong
//
// INT16 -> ULONG64 conversion
//
#define Int16ToULong64 ShortToULongLong
//
// INT16 -> DWORD64 conversion
//
#define Int16ToDWord64 ShortToULongLong
//
// INT16 -> UINT64 conversion
//
#define Int16ToUInt64 ShortToULongLong
//
// INT16 -> size_t conversion
//
#define Int16ToSizeT ShortToUIntPtr
//
// INT16 -> SIZE_T conversion
//
#define Int16ToSIZET ShortToULongPtr
//
// USHORT -> INT8 conversion
//
__inline
HRESULT
UShortToInt8(
__inn USHORT usOperand,
__outt __deref_out_range(==,usOperand) INT8* pi8Result)
{
HRESULT hr;
if (usOperand <= INT8_MAX)
{
*pi8Result = (INT8)usOperand;
hr = S_OK;
}
else
{
*pi8Result = INT8_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// USHORT -> UCHAR conversion
//
__inline
HRESULT
UShortToUChar(
__inn USHORT usOperand,
__outt __deref_out_range(==,usOperand) UCHAR* pch)
{
HRESULT hr;
if (usOperand <= 255)
{
*pch = (UCHAR)usOperand;
hr = S_OK;
}
else
{
*pch = '\0';
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// USHORT -> CHAR conversion
//
__forceinline
HRESULT
UShortToChar(
__inn USHORT usOperand,
__outt __deref_out_range(==,usOperand) CHAR* pch)
{
#ifdef _CHAR_UNSIGNED
return UShortToUChar(usOperand, (UCHAR*)pch);
#else
return UShortToInt8(usOperand, (INT8*)pch);
#endif // _CHAR_UNSIGNED
}
//
// USHORT -> UINT8 conversion
//
__inline
HRESULT
UShortToUInt8(
__inn USHORT usOperand,
__outt __deref_out_range(==,usOperand) UINT8* pui8Result)
{
HRESULT hr;
if (usOperand <= UINT8_MAX)
{
*pui8Result = (UINT8)usOperand;
hr = S_OK;
}
else
{
*pui8Result = UINT8_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// USHORT -> BYTE conversion
//
#define UShortToByte UShortToUInt8
//
// USHORT -> SHORT conversion
//
__inline
HRESULT
UShortToShort(
__inn USHORT usOperand,
__outt __deref_out_range(==,usOperand) SHORT* psResult)
{
HRESULT hr;
if (usOperand <= SHORT_MAX)
{
*psResult = (SHORT)usOperand;
hr = S_OK;
}
else
{
*psResult = SHORT_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// USHORT -> INT16 conversion
//
#define UShortToInt16 UShortToShort
//
// UINT16 -> CHAR conversion
//
#define UInt16ToChar UShortToChar
//
// UINT16 -> INT8 conversion
//
#define UInt16ToInt8 UShortToInt8
//
// UINT16 -> UCHAR conversion
//
#define UInt16ToUChar UShortToUChar
//
// UINT16 -> UINT8 conversion
//
#define UInt16ToUInt8 UShortToUInt8
//
// UINT16 -> BYTE conversion
//
#define UInt16ToByte UShortToUInt8
//
// UINT16 -> SHORT conversion
//
#define UInt16ToShort UShortToShort
//
// UINT16 -> INT16 conversion
//
#define UInt16ToInt16 UShortToShort
//
// WORD -> INT8 conversion
//
#define WordToInt8 UShortToInt8
//
// WORD -> CHAR conversion
//
#define WordToChar UShortToChar
//
// WORD -> UCHAR conversion
//
#define WordToUChar UShortToUChar
//
// WORD -> UINT8 conversion
//
#define WordToUInt8 UShortToUInt8
//
// WORD -> BYTE conversion
//
#define WordToByte UShortToUInt8
//
// WORD -> SHORT conversion
//
#define WordToShort UShortToShort
//
// WORD -> INT16 conversion
//
#define WordToInt16 UShortToShort
//
// INT -> INT8 conversion
//
__inline
HRESULT
IntToInt8(
__inn INT iOperand,
__outt __deref_out_range(==,iOperand) INT8* pi8Result)
{
HRESULT hr;
if ((iOperand >= INT8_MIN) && (iOperand <= INT8_MAX))
{
*pi8Result = (INT8)iOperand;
hr = S_OK;
}
else
{
*pi8Result = INT8_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// INT -> UCHAR conversion
//
__inline
HRESULT
IntToUChar(
__inn INT iOperand,
__outt __deref_out_range(==,iOperand) UCHAR* pch)
{
HRESULT hr;
if ((iOperand >= 0) && (iOperand <= 255))
{
*pch = (UCHAR)iOperand;
hr = S_OK;
}
else
{
*pch = '\0';
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// INT -> CHAR conversion
//
__forceinline
HRESULT
IntToChar(
__inn INT iOperand,
__outt __deref_out_range(==,iOperand) CHAR* pch)
{
#ifdef _CHAR_UNSIGNED
return IntToUChar(iOperand, (UCHAR*)pch);
#else
return IntToInt8(iOperand, (INT8*)pch);
#endif // _CHAR_UNSIGNED
}
//
// INT -> BYTE conversion
//
#define IntToByte IntToUInt8
//
// INT -> UINT8 conversion
//
__inline
HRESULT
IntToUInt8(
__inn INT iOperand,
__outt __deref_out_range(==,iOperand) UINT8* pui8Result)
{
HRESULT hr;
if ((iOperand >= 0) && (iOperand <= UINT8_MAX))
{
*pui8Result = (UINT8)iOperand;
hr = S_OK;
}
else
{
*pui8Result = UINT8_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// INT -> SHORT conversion
//
__inline
HRESULT
IntToShort(
__inn INT iOperand,
__outt __deref_out_range(==,iOperand) SHORT* psResult)
{
HRESULT hr;
if ((iOperand >= SHORT_MIN) && (iOperand <= SHORT_MAX))
{
*psResult = (SHORT)iOperand;
hr = S_OK;
}
else
{
*psResult = SHORT_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// INT -> INT16 conversion
//
#define IntToInt16 IntToShort
//
// INT -> USHORT conversion
//
__inline
HRESULT
IntToUShort(
__inn INT iOperand,
__outt __deref_out_range(==,iOperand) USHORT* pusResult)
{
HRESULT hr;
if ((iOperand >= 0) && (iOperand <= USHORT_MAX))
{
*pusResult = (USHORT)iOperand;
hr = S_OK;
}
else
{
*pusResult = USHORT_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// INT -> UINT16 conversion
//
#define IntToUInt16 IntToUShort
//
// INT -> WORD conversion
//
#define IntToWord IntToUShort
//
// INT -> UINT conversion
//
__inline
HRESULT
IntToUInt(
__inn INT iOperand,
__outt __deref_out_range(==,iOperand) UINT* puResult)
{
HRESULT hr;
if (iOperand >= 0)
{
*puResult = (UINT)iOperand;
hr = S_OK;
}
else
{
*puResult = UINT_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// INT -> UINT_PTR conversion
//
#ifdef _WIN64
#define IntToUIntPtr IntToULongLong
#else
#define IntToUIntPtr IntToUInt
#endif
//
// INT -> ULONG conversion
//
__inline
HRESULT
IntToULong(
__inn INT iOperand,
__outt __deref_out_range(==,iOperand) ULONG* pulResult)
{
HRESULT hr;
if (iOperand >= 0)
{
*pulResult = (ULONG)iOperand;
hr = S_OK;
}
else
{
*pulResult = ULONG_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// INT -> ULONG_PTR conversion
//
#ifdef _WIN64
#define IntToULongPtr IntToULongLong
#else
#define IntToULongPtr IntToULong
#endif
//
// INT -> DWORD conversion
//
#define IntToDWord IntToULong
//
// INT -> DWORD_PTR conversion
//
#define IntToDWordPtr IntToULongPtr
//
// INT -> ULONGLONG conversion
//
__inline
HRESULT
IntToULongLong(
__inn INT iOperand,
__outt __deref_out_range(==,iOperand) ULONGLONG* pullResult)
{
HRESULT hr;
if (iOperand >= 0)
{
*pullResult = (ULONGLONG)iOperand;
hr = S_OK;
}
else
{
*pullResult = ULONGLONG_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// INT -> DWORDLONG conversion
//
#define IntToDWordLong IntToULongLong
//
// INT -> ULONG64 conversion
//
#define IntToULong64 IntToULongLong
//
// INT -> DWORD64 conversion
//
#define IntToDWord64 IntToULongLong
//
// INT -> UINT64 conversion
//
#define IntToUInt64 IntToULongLong
//
// INT -> size_t conversion
//
#define IntToSizeT IntToUIntPtr
//
// INT -> SIZE_T conversion
//
#define IntToSIZET IntToULongPtr
//
// INT32 -> CHAR conversion
//
#define Int32ToChar IntToChar
//
// INT32 -> INT328 conversion
//
#define Int32ToInt8 IntToInt8
//
// INT32 -> UCHAR conversion
//
#define Int32ToUChar IntToUChar
//
// INT32 -> BYTE conversion
//
#define Int32ToByte IntToUInt8
//
// INT32 -> UINT8 conversion
//
#define Int32ToUInt8 IntToUInt8
//
// INT32 -> SHORT conversion
//
#define Int32ToShort IntToShort
//
// INT32 -> INT16 conversion
//
#define Int32ToInt16 IntToShort
//
// INT32 -> USHORT conversion
//
#define Int32ToUShort IntToUShort
//
// INT32 -> UINT16 conversion
//
#define Int32ToUInt16 IntToUShort
//
// INT32 -> WORD conversion
//
#define Int32ToWord IntToUShort
//
// INT32 -> UINT conversion
//
#define Int32ToUInt IntToUInt
//
// INT32 -> UINT32 conversion
//
#define Int32ToUInt32 IntToUInt
//
// INT32 -> UINT_PTR conversion
//
#define Int32ToUIntPtr IntToUIntPtr
//
// INT32 -> ULONG conversion
//
#define Int32ToULong IntToULong
//
// INT32 -> ULONG_PTR conversion
//
#define Int32ToULongPtr IntToULongPtr
//
// INT32 -> DWORD conversion
//
#define Int32ToDWord IntToULong
//
// INT32 -> DWORD_PTR conversion
//
#define Int32ToDWordPtr IntToULongPtr
//
// INT32 -> ULONGLONG conversion
//
#define Int32ToULongLong IntToULongLong
//
// INT32 -> DWORDLONG conversion
//
#define Int32ToDWordLong IntToULongLong
//
// INT32 -> ULONG64 conversion
//
#define Int32ToULong64 IntToULongLong
//
// INT32 -> DWORD64 conversion
//
#define Int32ToDWord64 IntToULongLong
//
// INT32 -> UINT64 conversion
//
#define Int32ToUInt64 IntToULongLong
//
// INT32 -> size_t conversion
//
#define Int32ToSizeT IntToUIntPtr
//
// INT32 -> SIZE_T conversion
//
#define Int32ToSIZET IntToULongPtr
//
// INT_PTR -> INT8 conversion
//
__inline
HRESULT
IntPtrToInt8(
__inn INT_PTR iOperand,
__outt __deref_out_range(==,iOperand) INT8* pi8Result)
{
HRESULT hr;
if ((iOperand >= INT8_MIN) && (iOperand <= INT8_MAX))
{
*pi8Result = (INT8)iOperand;
hr = S_OK;
}
else
{
*pi8Result = INT8_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// INT_PTR -> UCHAR conversion
//
__inline
HRESULT
IntPtrToUChar(
__inn INT_PTR iOperand,
__outt __deref_out_range(==,iOperand) UCHAR* pch)
{
HRESULT hr;
if ((iOperand >= 0) && (iOperand <= 255))
{
*pch = (UCHAR)iOperand;
hr = S_OK;
}
else
{
*pch = '\0';
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// INT_PTR -> CHAR conversion
//
__forceinline
HRESULT
IntPtrToChar(
__inn INT_PTR iOperand,
__outt __deref_out_range(==,iOperand) CHAR* pch)
{
#ifdef _CHAR_UNSIGNED
return IntPtrToUChar(iOperand, (UCHAR*)pch);
#else
return IntPtrToInt8(iOperand, (INT8*)pch);
#endif // _CHAR_UNSIGNED
}
//
// INT_PTR -> UINT8 conversion
//
__inline
HRESULT
IntPtrToUInt8(
__inn INT_PTR iOperand,
__outt __deref_out_range(==,iOperand) UINT8* pui8Result)
{
HRESULT hr;
if ((iOperand >= 0) && (iOperand <= UINT8_MAX))
{
*pui8Result = (UINT8)iOperand;
hr = S_OK;
}
else
{
*pui8Result = UINT8_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// INT_PTR -> BYTE conversion
//
#define IntPtrToByte IntPtrToUInt8
//
// INT_PTR -> SHORT conversion
//
__inline
HRESULT
IntPtrToShort(
__inn INT_PTR iOperand,
__outt __deref_out_range(==,iOperand) SHORT* psResult)
{
HRESULT hr;
if ((iOperand >= SHORT_MIN) && (iOperand <= SHORT_MAX))
{
*psResult = (SHORT)iOperand;
hr = S_OK;
}
else
{
*psResult = SHORT_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// INT_PTR -> INT16 conversion
//
#define IntPtrToInt16 IntPtrToShort
//
// INT_PTR -> USHORT conversion
//
__inline
HRESULT
IntPtrToUShort(
__inn INT_PTR iOperand,
__outt __deref_out_range(==,iOperand) USHORT* pusResult)
{
HRESULT hr;
if ((iOperand >= 0) && (iOperand <= USHORT_MAX))
{
*pusResult = (USHORT)iOperand;
hr = S_OK;
}
else
{
*pusResult = USHORT_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// INT_PTR -> UINT16 conversion
//
#define IntPtrToUInt16 IntPtrToUShort
//
// INT_PTR -> WORD conversion
//
#define IntPtrToWord IntPtrToUShort
//
// INT_PTR -> INT conversion
//
#ifdef _WIN64
#define IntPtrToInt LongLongToInt
#else
__inline
HRESULT
IntPtrToInt(
__inn INT_PTR iOperand,
__outt __deref_out_range(==,iOperand) INT* piResult)
{
*piResult = (INT)iOperand;
return S_OK;
}
#endif
//
// INT_PTR -> INT32 conversion
//
#define IntPtrToInt32 IntPtrToInt
//
// INT_PTR -> UINT conversion
//
#ifdef _WIN64
#define IntPtrToUInt LongLongToUInt
#else
__inline
HRESULT
IntPtrToUInt(
__inn INT_PTR iOperand,
__outt __deref_out_range(==,iOperand) UINT* puResult)
{
HRESULT hr;
if (iOperand >= 0)
{
*puResult = (UINT)iOperand;
hr = S_OK;
}
else
{
*puResult = UINT_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
#endif
//
// INT_PTR -> UINT32 conversion
//
#define IntPtrToUInt32 IntPtrToUInt
//
// INT_PTR -> UINT_PTR conversion
//
#ifdef _WIN64
#define IntPtrToUIntPtr LongLongToULongLong
#else
__inline
HRESULT
IntPtrToUIntPtr(
__inn INT_PTR iOperand,
__outt __deref_out_range(==,iOperand) UINT_PTR* puResult)
{
HRESULT hr;
if (iOperand >= 0)
{
*puResult = (UINT_PTR)iOperand;
hr = S_OK;
}
else
{
*puResult = UINT_PTR_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
#endif
//
// INT_PTR -> LONG conversion
//
#ifdef _WIN64
#define IntPtrToLong LongLongToLong
#else
__inline
HRESULT
IntPtrToLong(
__inn INT_PTR iOperand,
__outt __deref_out_range(==,iOperand) LONG* plResult)
{
*plResult = (LONG)iOperand;
return S_OK;
}
#endif
//
// INT_PTR -> LONG_PTR conversion
//
__inline
HRESULT
IntPtrToLongPtr(
__inn INT_PTR iOperand,
__outt __deref_out_range(==,iOperand) LONG_PTR* plResult)
{
*plResult = (LONG_PTR)iOperand;
return S_OK;
}
//
// INT_PTR -> ULONG conversion
//
#ifdef _WIN64
#define IntPtrToULong LongLongToULong
#else
__inline
HRESULT
IntPtrToULong(
__inn INT_PTR iOperand,
__outt __deref_out_range(==,iOperand) ULONG* pulResult)
{
HRESULT hr;
if (iOperand >= 0)
{
*pulResult = (ULONG)iOperand;
hr = S_OK;
}
else
{
*pulResult = ULONG_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
#endif
//
// INT_PTR -> ULONG_PTR conversion
//
#ifdef _WIN64
#define IntPtrToULongPtr LongLongToULongLong
#else
__inline
HRESULT
IntPtrToULongPtr(
__inn INT_PTR iOperand,
__outt __deref_out_range(==,iOperand) ULONG_PTR* pulResult)
{
HRESULT hr;
if (iOperand >= 0)
{
*pulResult = (ULONG_PTR)iOperand;
hr = S_OK;
}
else
{
*pulResult = ULONG_PTR_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
#endif
//
// INT_PTR -> DWORD conversion
//
#define IntPtrToDWord IntPtrToULong
//
// INT_PTR -> DWORD_PTR conversion
//
#define IntPtrToDWordPtr IntPtrToULongPtr
//
// INT_PTR -> ULONGLONG conversion
//
#ifdef _WIN64
#define IntPtrToULongLong LongLongToULongLong
#else
__inline
HRESULT
IntPtrToULongLong(
__inn INT_PTR iOperand,
__outt __deref_out_range(==,iOperand) ULONGLONG* pullResult)
{
HRESULT hr;
if (iOperand >= 0)
{
*pullResult = (ULONGLONG)iOperand;
hr = S_OK;
}
else
{
*pullResult = ULONGLONG_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
#endif
//
// INT_PTR -> DWORDLONG conversion
//
#define IntPtrToDWordLong IntPtrToULongLong
//
// INT_PTR -> ULONG64 conversion
//
#define IntPtrToULong64 IntPtrToULongLong
//
// INT_PTR -> DWORD64 conversion
//
#define IntPtrToDWord64 IntPtrToULongLong
//
// INT_PTR -> UINT64 conversion
//
#define IntPtrToUInt64 IntPtrToULongLong
//
// INT_PTR -> size_t conversion
//
#define IntPtrToSizeT IntPtrToUIntPtr
//
// INT_PTR -> SIZE_T conversion
//
#define IntPtrToSIZET IntPtrToULongPtr
//
// UINT -> INT8 conversion
//
__inline
HRESULT
UIntToInt8(
__inn UINT uOperand,
__outt __deref_out_range(==,uOperand) INT8* pi8Result)
{
HRESULT hr;
if (uOperand <= INT8_MAX)
{
*pi8Result = (INT8)uOperand;
hr = S_OK;
}
else
{
*pi8Result = INT8_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// UINT -> UCHAR conversion
//
__inline
HRESULT
UIntToUChar(
__inn UINT uOperand,
__outt __deref_out_range(==,uOperand) UCHAR* pch)
{
HRESULT hr;
if (uOperand <= 255)
{
*pch = (UCHAR)uOperand;
hr = S_OK;
}
else
{
*pch = '\0';
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// UINT -> CHAR conversion
//
__forceinline
HRESULT
UIntToChar(
__inn UINT uOperand,
__outt __deref_out_range(==,uOperand) CHAR* pch)
{
#ifdef _CHAR_UNSIGNED
return UIntToUChar(uOperand, (UCHAR*)pch);
#else
return UIntToInt8(uOperand, (INT8*)pch);
#endif
}
//
// UINT -> UINT8 conversion
//
__inline
HRESULT
UIntToUInt8(
__inn UINT uOperand,
__outt __deref_out_range(==,uOperand) UINT8* pui8Result)
{
HRESULT hr;
if (uOperand <= UINT8_MAX)
{
*pui8Result = (UINT8)uOperand;
hr = S_OK;
}
else
{
*pui8Result = UINT8_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// UINT -> BYTE conversion
//
#define UIntToByte UIntToUInt8
//
// UINT -> SHORT conversion
//
__inline
HRESULT
UIntToShort(
__inn UINT uOperand,
__outt __deref_out_range(==,uOperand) SHORT* psResult)
{
HRESULT hr;
if (uOperand <= SHORT_MAX)
{
*psResult = (SHORT)uOperand;
hr = S_OK;
}
else
{
*psResult = SHORT_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// UINT -> INT16 conversion
//
#define UIntToInt16 UIntToShort
//
// UINT -> USHORT conversion
//
__inline
HRESULT
UIntToUShort(
__inn UINT uOperand,
__outt __deref_out_range(==,uOperand) USHORT* pusResult)
{
HRESULT hr;
if (uOperand <= USHORT_MAX)
{
*pusResult = (USHORT)uOperand;
hr = S_OK;
}
else
{
*pusResult = USHORT_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// UINT -> UINT16 conversion
//
#define UIntToUInt16 UIntToUShort
//
// UINT -> WORD conversion
//
#define UIntToWord UIntToUShort
//
// UINT -> INT conversion
//
__inline
HRESULT
UIntToInt(
__inn UINT uOperand,
__outt __deref_out_range(==,uOperand) INT* piResult)
{
HRESULT hr;
if (uOperand <= INT_MAX)
{
*piResult = (INT)uOperand;
hr = S_OK;
}
else
{
*piResult = INT_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// UINT -> INT32 conversion
//
#define UIntToInt32 UIntToInt
//
// UINT -> INT_PTR conversion
//
#ifdef _WIN64
__inline
HRESULT
UIntToIntPtr(
__inn UINT uOperand,
__outt __deref_out_range(==,uOperand) INT_PTR* piResult)
{
*piResult = uOperand;
return S_OK;
}
#else
#define UIntToIntPtr UIntToInt
#endif
//
// UINT -> LONG conversion
//
__inline
HRESULT
UIntToLong(
__inn UINT uOperand,
__outt __deref_out_range(==,uOperand) LONG* plResult)
{
HRESULT hr;
if (uOperand <= INT32_MAX)
{
*plResult = (LONG)uOperand;
hr = S_OK;
}
else
{
*plResult = LONG_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// UINT -> LONG_PTR conversion
//
#ifdef _WIN64
__inline
HRESULT
UIntToLongPtr(
__inn UINT uOperand,
__outt __deref_out_range(==,uOperand) LONG_PTR* plResult)
{
*plResult = uOperand;
return S_OK;
}
#else
#define UIntToLongPtr UIntToLong
#endif
//
// UINT -> ptrdiff_t conversion
//
#define UIntToPtrdiffT UIntToIntPtr
//
// UINT -> SSIZE_T conversion
//
#define UIntToSSIZET UIntToLongPtr
//
// UINT32 -> CHAR conversion
//
#define UInt32ToChar UIntToChar
//
// UINT32 -> INT8 conversion
//
#define UInt32ToInt8 UIntToInt8
//
// UINT32 -> UCHAR conversion
//
#define UInt32ToUChar UIntToUChar
//
// UINT32 -> UINT8 conversion
//
#define UInt32ToUInt8 UIntToUInt8
//
// UINT32 -> BYTE conversion
//
#define UInt32ToByte UInt32ToUInt8
//
// UINT32 -> SHORT conversion
//
#define UInt32ToShort UIntToShort
//
// UINT32 -> INT16 conversion
//
#define UInt32ToInt16 UIntToShort
//
// UINT32 -> USHORT conversion
//
#define UInt32ToUShort UIntToUShort
//
// UINT32 -> UINT16 conversion
//
#define UInt32ToUInt16 UIntToUShort
//
// UINT32 -> WORD conversion
//
#define UInt32ToWord UIntToUShort
//
// UINT32 -> INT conversion
//
#define UInt32ToInt UIntToInt
//
// UINT32 -> INT_PTR conversion
//
#define UInt32ToIntPtr UIntToIntPtr
//
// UINT32 -> INT32 conversion
//
#define UInt32ToInt32 UIntToInt
//
// UINT32 -> LONG conversion
//
#define UInt32ToLong UIntToLong
//
// UINT32 -> LONG_PTR conversion
//
#define UInt32ToLongPtr UIntToLongPtr
//
// UINT32 -> ptrdiff_t conversion
//
#define UInt32ToPtrdiffT UIntToPtrdiffT
//
// UINT32 -> SSIZE_T conversion
//
#define UInt32ToSSIZET UIntToSSIZET
//
// UINT_PTR -> INT8 conversion
//
__inline
HRESULT
UIntPtrToInt8(
__inn UINT_PTR uOperand,
__outt __deref_out_range(==,uOperand) INT8* pi8Result)
{
HRESULT hr;
if (uOperand <= INT8_MAX)
{
*pi8Result = (INT8)uOperand;
hr = S_OK;
}
else
{
*pi8Result = INT8_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// UINT_PTR -> UCHAR conversion
//
__inline
HRESULT
UIntPtrToUChar(
__inn UINT_PTR uOperand,
__outt __deref_out_range(==,uOperand) UCHAR* pch)
{
HRESULT hr;
if (uOperand <= 255)
{
*pch = (UCHAR)uOperand;
hr = S_OK;
}
else
{
*pch = '\0';
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// UINT_PTR -> CHAR conversion
//
__forceinline
HRESULT
UIntPtrToChar(
__inn UINT_PTR uOperand,
__outt __deref_out_range(==,uOperand) CHAR* pch)
{
#ifdef _CHAR_UNSIGNED
return UIntPtrToUChar(uOperand, (UCHAR*)pch);
#else
return UIntPtrToInt8(uOperand, (INT8*)pch);
#endif
}
//
// UINT_PTR -> UINT8 conversion
//
__inline
HRESULT
UIntPtrToUInt8(
__inn UINT_PTR uOperand,
__outt __deref_out_range(==,uOperand) UINT8* pu8Result)
{
HRESULT hr;
if (uOperand <= UINT8_MAX)
{
*pu8Result = (UINT8)uOperand;
hr = S_OK;
}
else
{
*pu8Result = UINT8_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// UINT_PTR -> BYTE conversion
//
#define UIntPtrToByte UIntPtrToUInt8
//
// UINT_PTR -> SHORT conversion
//
__inline
HRESULT
UIntPtrToShort(
__inn UINT_PTR uOperand,
__outt __deref_out_range(==,uOperand) SHORT* psResult)
{
HRESULT hr;
if (uOperand <= SHORT_MAX)
{
*psResult = (SHORT)uOperand;
hr = S_OK;
}
else
{
*psResult = SHORT_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// UINT_PTR -> INT16 conversion
//
__inline
HRESULT
UIntPtrToInt16(
__inn UINT_PTR uOperand,
__outt __deref_out_range(==,uOperand) INT16* pi16Result)
{
HRESULT hr;
if (uOperand <= INT16_MAX)
{
*pi16Result = (INT16)uOperand;
hr = S_OK;
}
else
{
*pi16Result = INT16_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// UINT_PTR -> USHORT conversion
//
__inline
HRESULT
UIntPtrToUShort(
__inn UINT_PTR uOperand,
__outt __deref_out_range(==,uOperand) USHORT* pusResult)
{
HRESULT hr;
if (uOperand <= USHORT_MAX)
{
*pusResult = (USHORT)uOperand;
hr = S_OK;
}
else
{
*pusResult = USHORT_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// UINT_PTR -> UINT16 conversion
//
__inline
HRESULT
UIntPtrToUInt16(
__inn UINT_PTR uOperand,
__outt __deref_out_range(==,uOperand) UINT16* pu16Result)
{
HRESULT hr;
if (uOperand <= UINT16_MAX)
{
*pu16Result = (UINT16)uOperand;
hr = S_OK;
}
else
{
*pu16Result = UINT16_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// UINT_PTR -> WORD conversion
//
#define UIntPtrToWord UIntPtrToUShort
//
// UINT_PTR -> INT conversion
//
__inline
HRESULT
UIntPtrToInt(
__inn UINT_PTR uOperand,
__outt __deref_out_range(==,uOperand) INT* piResult)
{
HRESULT hr;
if (uOperand <= INT_MAX)
{
*piResult = (INT)uOperand;
hr = S_OK;
}
else
{
*piResult = INT_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// UINT_PTR -> INT32 conversion
//
#define UIntPtrToInt32 UIntPtrToInt
//
// UINT_PTR -> INT_PTR conversion
//
__inline
HRESULT
UIntPtrToIntPtr(
__inn UINT_PTR uOperand,
__outt __deref_out_range(==,uOperand) INT_PTR* piResult)
{
HRESULT hr;
if (uOperand <= INT_PTR_MAX)
{
*piResult = (INT_PTR)uOperand;
hr = S_OK;
}
else
{
*piResult = INT_PTR_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// UINT_PTR -> UINT conversion
//
#ifdef _WIN64
#define UIntPtrToUInt ULongLongToUInt
#else
__inline
HRESULT
UIntPtrToUInt(
__inn UINT_PTR uOperand,
__outt __deref_out_range(==,uOperand) UINT* puResult)
{
*puResult = (UINT)uOperand;
return S_OK;
}
#endif
//
// UINT_PTR -> UINT32 conversion
//
#define UIntPtrToUInt32 UIntPtrToUInt
//
// UINT_PTR -> LONG conversion
//
__inline
HRESULT
UIntPtrToLong(
__inn UINT_PTR uOperand,
__outt __deref_out_range(==,uOperand) LONG* plResult)
{
HRESULT hr;
if (uOperand <= INT32_MAX)
{
*plResult = (LONG)uOperand;
hr = S_OK;
}
else
{
*plResult = LONG_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// UINT_PTR -> LONG_PTR conversion
//
__inline
HRESULT
UIntPtrToLongPtr(
__inn UINT_PTR uOperand,
__outt __deref_out_range(==,uOperand) LONG_PTR* plResult)
{
HRESULT hr;
if (uOperand <= LONG_PTR_MAX)
{
*plResult = (LONG_PTR)uOperand;
hr = S_OK;
}
else
{
*plResult = LONG_PTR_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// UINT_PTR -> ULONG conversion
//
#ifdef _WIN64
#define UIntPtrToULong ULongLongToULong
#else
__inline
HRESULT
UIntPtrToULong(
__inn UINT_PTR uOperand,
__outt __deref_out_range(==,uOperand) ULONG* pulResult)
{
*pulResult = (ULONG)uOperand;
return S_OK;
}
#endif
//
// UINT_PTR -> DWORD conversion
//
#define UIntPtrToDWord UIntPtrToULong
//
// UINT_PTR -> LONGLONG conversion
//
#ifdef _WIN64
#define UIntPtrToLongLong ULongLongToLongLong
#else
__inline
HRESULT
UIntPtrToLongLong(
__inn UINT_PTR uOperand,
__outt __deref_out_range(==,uOperand) LONGLONG* pllResult)
{
*pllResult = (LONGLONG)uOperand;
return S_OK;
}
#endif
//
// UINT_PTR -> LONG64 conversion
//
#define UIntPtrToLong64 UIntPtrToLongLong
//
// UINT_PTR -> INT64 conversion
//
#define UIntPtrToInt64 UIntPtrToLongLong
//
// UINT_PTR -> ptrdiff_t conversion
//
#define UIntPtrToPtrdiffT UIntPtrToIntPtr
//
// UINT_PTR -> SSIZE_T conversion
//
#define UIntPtrToSSIZET UIntPtrToLongPtr
//
// LONG -> INT8 conversion
//
__inline
HRESULT
LongToInt8(
__inn LONG lOperand,
__outt __deref_out_range(==,lOperand) INT8* pi8Result)
{
HRESULT hr;
if ((lOperand >= INT8_MIN) && (lOperand <= INT8_MAX))
{
*pi8Result = (INT8)lOperand;
hr = S_OK;
}
else
{
*pi8Result = INT8_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// LONG -> UCHAR conversion
//
__inline
HRESULT
LongToUChar(
__inn LONG lOperand,
__outt __deref_out_range(==,lOperand) UCHAR* pch)
{
HRESULT hr;
if ((lOperand >= 0) && (lOperand <= 255))
{
*pch = (UCHAR)lOperand;
hr = S_OK;
}
else
{
*pch = '\0';
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// LONG -> CHAR conversion
//
__forceinline
HRESULT
LongToChar(
__inn LONG lOperand,
__outt __deref_out_range(==,lOperand) CHAR* pch)
{
#ifdef _CHAR_UNSIGNED
return LongToUChar(lOperand, (UCHAR*)pch);
#else
return LongToInt8(lOperand, (INT8*)pch);
#endif
}
//
// LONG -> UINT8 conversion
//
__inline
HRESULT
LongToUInt8(
__inn LONG lOperand,
__outt __deref_out_range(==,lOperand) UINT8* pui8Result)
{
HRESULT hr;
if ((lOperand >= 0) && (lOperand <= UINT8_MAX))
{
*pui8Result = (UINT8)lOperand;
hr = S_OK;
}
else
{
*pui8Result = UINT8_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// LONG -> BYTE conversion
//
#define LongToByte LongToUInt8
//
// LONG -> SHORT conversion
//
__inline
HRESULT
LongToShort(
__inn LONG lOperand,
__outt __deref_out_range(==,lOperand) SHORT* psResult)
{
HRESULT hr;
if ((lOperand >= SHORT_MIN) && (lOperand <= SHORT_MAX))
{
*psResult = (SHORT)lOperand;
hr = S_OK;
}
else
{
*psResult = SHORT_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// LONG -> INT16 conversion
//
#define LongToInt16 LongToShort
//
// LONG -> USHORT conversion
//
__inline
HRESULT
LongToUShort(
__inn LONG lOperand,
__outt __deref_out_range(==,lOperand) USHORT* pusResult)
{
HRESULT hr;
if ((lOperand >= 0) && (lOperand <= USHORT_MAX))
{
*pusResult = (USHORT)lOperand;
hr = S_OK;
}
else
{
*pusResult = USHORT_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// LONG -> UINT16 conversion
//
#define LongToUInt16 LongToUShort
//
// LONG -> WORD conversion
//
#define LongToWord LongToUShort
//
// LONG -> INT conversion
//
__inline
HRESULT
LongToInt(
__inn LONG lOperand,
__outt __deref_out_range(==,lOperand) INT* piResult)
{
C_ASSERT(sizeof(INT) == sizeof(LONG));
*piResult = (INT)lOperand;
return S_OK;
}
//
// LONG -> INT32 conversion
//
#define LongToInt32 LongToInt
//
// LONG -> INT_PTR conversion
//
#ifdef _WIN64
__inline
HRESULT
LongToIntPtr(
__inn LONG lOperand,
__outt __deref_out_range(==,lOperand) INT_PTR* piResult)
{
*piResult = lOperand;
return S_OK;
}
#else
#define LongToIntPtr LongToInt
#endif
//
// LONG -> UINT conversion
//
__inline
HRESULT
LongToUInt(
__inn LONG lOperand,
__outt __deref_out_range(==,lOperand) UINT* puResult)
{
HRESULT hr;
if (lOperand >= 0)
{
*puResult = (UINT)lOperand;
hr = S_OK;
}
else
{
*puResult = UINT_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// LONG -> UINT32 conversion
//
#define LongToUInt32 LongToUInt
//
// LONG -> UINT_PTR conversion
//
#ifdef _WIN64
__inline
HRESULT
LongToUIntPtr(
__inn LONG lOperand,
__outt __deref_out_range(==,lOperand) UINT_PTR* puResult)
{
HRESULT hr;
if (lOperand >= 0)
{
*puResult = (UINT_PTR)lOperand;
hr = S_OK;
}
else
{
*puResult = UINT_PTR_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
#else
#define LongToUIntPtr LongToUInt
#endif
//
// LONG -> ULONG conversion
//
__inline
HRESULT
LongToULong(
__inn LONG lOperand,
__outt __deref_out_range(==,lOperand) ULONG* pulResult)
{
HRESULT hr;
if (lOperand >= 0)
{
*pulResult = (ULONG)lOperand;
hr = S_OK;
}
else
{
*pulResult = ULONG_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// LONG -> ULONG_PTR conversion
//
#ifdef _WIN64
__inline
HRESULT
LongToULongPtr(
__inn LONG lOperand,
__outt __deref_out_range(==,lOperand) ULONG_PTR* pulResult)
{
HRESULT hr;
if (lOperand >= 0)
{
*pulResult = (ULONG_PTR)lOperand;
hr = S_OK;
}
else
{
*pulResult = ULONG_PTR_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
#else
#define LongToULongPtr LongToULong
#endif
//
// LONG -> DWORD conversion
//
#define LongToDWord LongToULong
//
// LONG -> DWORD_PTR conversion
//
#define LongToDWordPtr LongToULongPtr
//
// LONG -> ULONGLONG conversion
//
__inline
HRESULT
LongToULongLong(
__inn LONG lOperand,
__outt __deref_out_range(==,lOperand) ULONGLONG* pullResult)
{
HRESULT hr;
if (lOperand >= 0)
{
*pullResult = (ULONGLONG)lOperand;
hr = S_OK;
}
else
{
*pullResult = ULONGLONG_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// LONG -> DWORDLONG conversion
//
#define LongToDWordLong LongToULongLong
//
// LONG -> ULONG64 conversion
//
#define LongToULong64 LongToULongLong
//
// LONG -> DWORD64 conversion
//
#define LongToDWord64 LongToULongLong
//
// LONG -> UINT64 conversion
//
#define LongToUInt64 LongToULongLong
//
// LONG -> ptrdiff_t conversion
//
#define LongToPtrdiffT LongToIntPtr
//
// LONG -> size_t conversion
//
#define LongToSizeT LongToUIntPtr
//
// LONG -> SIZE_T conversion
//
#define LongToSIZET LongToULongPtr
//
// LONG_PTR -> INT8 conversion
//
__inline
HRESULT
LongPtrToInt8(
__inn LONG_PTR lOperand,
__outt __deref_out_range(==,lOperand) INT8* pi8Result)
{
HRESULT hr;
if ((lOperand >= INT8_MIN) && (lOperand <= INT8_MAX))
{
*pi8Result = (INT8)lOperand;
hr = S_OK;
}
else
{
*pi8Result = INT8_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// LONG_PTR -> UCHAR conversion
//
__inline
HRESULT
LongPtrToUChar(
__inn LONG_PTR lOperand,
__outt __deref_out_range(==,lOperand) UCHAR* pch)
{
HRESULT hr;
if ((lOperand >= 0) && (lOperand <= 255))
{
*pch = (UCHAR)lOperand;
hr = S_OK;
}
else
{
*pch = '\0';
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// LONG_PTR -> CHAR conversion
//
__forceinline
HRESULT
LongPtrToChar(
__inn LONG_PTR lOperand,
__outt __deref_out_range(==,lOperand) CHAR* pch)
{
#ifdef _CHAR_UNSIGNED
return LongPtrToUChar(lOperand, (UCHAR*)pch);
#else
return LongPtrToInt8(lOperand, (INT8*)pch);
#endif
}
//
// LONG_PTR -> UINT8 conversion
//
__inline
HRESULT
LongPtrToUInt8(
__inn LONG_PTR lOperand,
__outt __deref_out_range(==,lOperand) UINT8* pui8Result)
{
HRESULT hr;
if ((lOperand >= 0) && (lOperand <= UINT8_MAX))
{
*pui8Result = (UINT8)lOperand;
hr = S_OK;
}
else
{
*pui8Result = UINT8_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// LONG_PTR -> BYTE conversion
//
#define LongPtrToByte LongPtrToUInt8
//
// LONG_PTR -> SHORT conversion
//
__inline
HRESULT
LongPtrToShort(
__inn LONG_PTR lOperand,
__outt __deref_out_range(==,lOperand) SHORT* psResult)
{
HRESULT hr;
if ((lOperand >= SHORT_MIN) && (lOperand <= SHORT_MAX))
{
*psResult = (SHORT)lOperand;
hr = S_OK;
}
else
{
*psResult = SHORT_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// LONG_PTR -> INT16 conversion
//
#define LongPtrToInt16 LongPtrToShort
//
// LONG_PTR -> USHORT conversion
//
__inline
HRESULT
LongPtrToUShort(
__inn LONG_PTR lOperand,
__outt __deref_out_range(==,lOperand) USHORT* pusResult)
{
HRESULT hr;
if ((lOperand >= 0) && (lOperand <= USHORT_MAX))
{
*pusResult = (USHORT)lOperand;
hr = S_OK;
}
else
{
*pusResult = USHORT_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// LONG_PTR -> UINT16 conversion
//
#define LongPtrToUInt16 LongPtrToUShort
//
// LONG_PTR -> WORD conversion
//
#define LongPtrToWord LongPtrToUShort
//
// LONG_PTR -> INT conversion
//
#ifdef _WIN64
#define LongPtrToInt LongLongToInt
#else
__inline
HRESULT
LongPtrToInt(
__inn LONG_PTR lOperand,
__outt __deref_out_range(==,lOperand) INT* piResult)
{
C_ASSERT(sizeof(INT) == sizeof(LONG_PTR));
*piResult = (INT)lOperand;
return S_OK;
}
#endif
//
// LONG_PTR -> INT32 conversion
//
#define LongPtrToInt32 LongPtrToInt
//
// LONG_PTR -> INT_PTR conversion
//
__inline
HRESULT
LongPtrToIntPtr(
__inn LONG_PTR lOperand,
__outt __deref_out_range(==,lOperand) INT_PTR* piResult)
{
C_ASSERT(sizeof(LONG_PTR) == sizeof(INT_PTR));
*piResult = (INT_PTR)lOperand;
return S_OK;
}
//
// LONG_PTR -> UINT conversion
//
#ifdef _WIN64
#define LongPtrToUInt LongLongToUInt
#else
__inline
HRESULT
LongPtrToUInt(
__inn LONG_PTR lOperand,
__outt __deref_out_range(==,lOperand) UINT* puResult)
{
HRESULT hr;
if (lOperand >= 0)
{
*puResult = (UINT)lOperand;
hr = S_OK;
}
else
{
*puResult = UINT_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
#endif
//
// LONG_PTR -> UINT32 conversion
//
#define LongPtrToUInt32 LongPtrToUInt
//
// LONG_PTR -> UINT_PTR conversion
//
__inline
HRESULT
LongPtrToUIntPtr(
__inn LONG_PTR lOperand,
__outt __deref_out_range(==,lOperand) UINT_PTR* puResult)
{
HRESULT hr;
if (lOperand >= 0)
{
*puResult = (UINT_PTR)lOperand;
hr = S_OK;
}
else
{
*puResult = UINT_PTR_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// LONG_PTR -> LONG conversion
//
#ifdef _WIN64
#define LongPtrToLong LongLongToLong
#else
__inline
HRESULT
LongPtrToLong(
__inn LONG_PTR lOperand,
__outt __deref_out_range(==,lOperand) LONG* plResult)
{
*plResult = (LONG)lOperand;
return S_OK;
}
#endif
//
// LONG_PTR -> ULONG conversion
//
#ifdef _WIN64
#define LongPtrToULong LongLongToULong
#else
__inline
HRESULT
LongPtrToULong(
__inn LONG_PTR lOperand,
__outt __deref_out_range(==,lOperand) ULONG* pulResult)
{
HRESULT hr;
if (lOperand >= 0)
{
*pulResult = (ULONG)lOperand;
hr = S_OK;
}
else
{
*pulResult = ULONG_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
#endif
//
// LONG_PTR -> ULONG_PTR conversion
//
__inline
HRESULT
LongPtrToULongPtr(
__inn LONG_PTR lOperand,
__outt __deref_out_range(==,lOperand) ULONG_PTR* pulResult)
{
HRESULT hr;
if (lOperand >= 0)
{
*pulResult = (ULONG_PTR)lOperand;
hr = S_OK;
}
else
{
*pulResult = ULONG_PTR_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// LONG_PTR -> DWORD conversion
//
#define LongPtrToDWord LongPtrToULong
//
// LONG_PTR -> DWORD_PTR conversion
//
#define LongPtrToDWordPtr LongPtrToULongPtr
//
// LONG_PTR -> ULONGLONG conversion
//
__inline
HRESULT
LongPtrToULongLong(
__inn LONG_PTR lOperand,
__outt __deref_out_range(==,lOperand) ULONGLONG* pullResult)
{
HRESULT hr;
if (lOperand >= 0)
{
*pullResult = (ULONGLONG)lOperand;
hr = S_OK;
}
else
{
*pullResult = ULONGLONG_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// LONG_PTR -> DWORDLONG conversion
//
#define LongPtrToDWordLong LongPtrToULongLong
//
// LONG_PTR -> ULONG64 conversion
//
#define LongPtrToULong64 LongPtrToULongLong
//
// LONG_PTR -> DWORD64 conversion
//
#define LongPtrToDWord64 LongPtrToULongLong
//
// LONG_PTR -> UINT64 conversion
//
#define LongPtrToUInt64 LongPtrToULongLong
//
// LONG_PTR -> size_t conversion
//
#define LongPtrToSizeT LongPtrToUIntPtr
//
// LONG_PTR -> SIZE_T conversion
//
#define LongPtrToSIZET LongPtrToULongPtr
//
// ULONG -> INT8 conversion
//
__inline
HRESULT
ULongToInt8(
__inn ULONG ulOperand,
__outt __deref_out_range(==,ulOperand) INT8* pi8Result)
{
HRESULT hr;
if (ulOperand <= INT8_MAX)
{
*pi8Result = (INT8)ulOperand;
hr = S_OK;
}
else
{
*pi8Result = INT8_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// ULONG -> UCHAR conversion
//
__inline
HRESULT
ULongToUChar(
__inn ULONG ulOperand,
__outt __deref_out_range(==,ulOperand) UCHAR* pch)
{
HRESULT hr;
if (ulOperand <= 255)
{
*pch = (UCHAR)ulOperand;
hr = S_OK;
}
else
{
*pch = '\0';
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// ULONG -> CHAR conversion
//
__forceinline
HRESULT
ULongToChar(
__inn ULONG ulOperand,
__outt __deref_out_range(==,ulOperand) CHAR* pch)
{
#ifdef _CHAR_UNSIGNED
return ULongToUChar(ulOperand, (UCHAR*)pch);
#else
return ULongToInt8(ulOperand, (INT8*)pch);
#endif
}
//
// ULONG -> UINT8 conversion
//
__inline
HRESULT
ULongToUInt8(
__inn ULONG ulOperand,
__outt __deref_out_range(==,ulOperand) UINT8* pui8Result)
{
HRESULT hr;
if (ulOperand <= UINT8_MAX)
{
*pui8Result = (UINT8)ulOperand;
hr = S_OK;
}
else
{
*pui8Result = UINT8_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// ULONG -> BYTE conversion
//
#define ULongToByte ULongToUInt8
//
// ULONG -> SHORT conversion
//
__inline
HRESULT
ULongToShort(
__inn ULONG ulOperand,
__outt __deref_out_range(==,ulOperand) SHORT* psResult)
{
HRESULT hr;
if (ulOperand <= SHORT_MAX)
{
*psResult = (SHORT)ulOperand;
hr = S_OK;
}
else
{
*psResult = SHORT_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// ULONG -> INT16 conversion
//
#define ULongToInt16 ULongToShort
//
// ULONG -> USHORT conversion
//
__inline
HRESULT
ULongToUShort(
__inn ULONG ulOperand,
__outt __deref_out_range(==,ulOperand) USHORT* pusResult)
{
HRESULT hr;
if (ulOperand <= USHORT_MAX)
{
*pusResult = (USHORT)ulOperand;
hr = S_OK;
}
else
{
*pusResult = USHORT_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// ULONG -> UINT16 conversion
//
#define ULongToUInt16 ULongToUShort
//
// ULONG -> WORD conversion
//
#define ULongToWord ULongToUShort
//
// ULONG -> INT conversion
//
__inline
HRESULT
ULongToInt(
__inn ULONG ulOperand,
__outt __deref_out_range(==,ulOperand) INT* piResult)
{
HRESULT hr;
if (ulOperand <= INT_MAX)
{
*piResult = (INT)ulOperand;
hr = S_OK;
}
else
{
*piResult = INT_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// ULONG -> INT32 conversion
//
#define ULongToInt32 ULongToInt
//
// ULONG -> INT_PTR conversion
//
#ifdef _WIN64
__inline
HRESULT
ULongToIntPtr(
__inn ULONG ulOperand,
__outt __deref_out_range(==,ulOperand) INT_PTR* piResult)
{
*piResult = (INT_PTR)ulOperand;
return S_OK;
}
#else
#define ULongToIntPtr ULongToInt
#endif
//
// ULONG -> UINT conversion
//
__inline
HRESULT
ULongToUInt(
__inn ULONG ulOperand,
__outt __deref_out_range(==,ulOperand) UINT* puResult)
{
//C_ASSERT(sizeof(ULONG) == sizeof(UINT));
*puResult = (UINT)ulOperand;
return S_OK;
}
//
// ULONG -> UINT32 conversion
//
#define ULongToUInt32 ULongToUInt
//
// ULONG -> UINT_PTR conversion
//
#ifdef _WIN64
__inline
HRESULT
ULongToUIntPtr(
__inn ULONG ulOperand,
__outt __deref_out_range(==,ulOperand) UINT_PTR* puiResult)
{
C_ASSERT(sizeof(UINT_PTR) > sizeof(ULONG));
*puiResult = (UINT_PTR)ulOperand;
return S_OK;
}
#else
#define ULongToUIntPtr ULongToUInt
#endif
//
// ULONG -> LONG conversion
//
__inline
HRESULT
ULongToLong(
__inn ULONG ulOperand,
__outt __deref_out_range(==,ulOperand) LONG* plResult)
{
HRESULT hr;
if (ulOperand <= INT32_MAX)
{
*plResult = (LONG)ulOperand;
hr = S_OK;
}
else
{
*plResult = LONG_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// ULONG -> LONG_PTR conversion
//
#ifdef _WIN64
__inline
HRESULT
ULongToLongPtr(
__inn ULONG ulOperand,
__outt __deref_out_range(==,ulOperand) LONG_PTR* plResult)
{
C_ASSERT(sizeof(LONG_PTR) > sizeof(ULONG));
*plResult = (LONG_PTR)ulOperand;
return S_OK;
}
#else
#define ULongToLongPtr ULongToLong
#endif
//
// ULONG -> ptrdiff_t conversion
//
#define ULongToPtrdiffT ULongToIntPtr
//
// ULONG -> SSIZE_T conversion
//
#define ULongToSSIZET ULongToLongPtr
//
// ULONG_PTR -> INT8 conversion
//
__inline
HRESULT
ULongPtrToInt8(
__inn ULONG_PTR ulOperand,
__outt __deref_out_range(==,ulOperand) INT8* pi8Result)
{
HRESULT hr;
if (ulOperand <= INT8_MAX)
{
*pi8Result = (INT8)ulOperand;
hr = S_OK;
}
else
{
*pi8Result = INT8_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// ULONG_PTR -> UCHAR conversion
//
__inline
HRESULT
ULongPtrToUChar(
__inn ULONG_PTR ulOperand,
__outt __deref_out_range(==,ulOperand) UCHAR* pch)
{
HRESULT hr;
if (ulOperand <= 255)
{
*pch = (UCHAR)ulOperand;
hr = S_OK;
}
else
{
*pch = '\0';
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// ULONG_PTR -> CHAR conversion
//
__forceinline
HRESULT
ULongPtrToChar(
__inn ULONG_PTR ulOperand,
__outt __deref_out_range(==,ulOperand) CHAR* pch)
{
#ifdef _CHAR_UNSIGNED
return ULongPtrToUChar(ulOperand, (UCHAR*)pch);
#else
return ULongPtrToInt8(ulOperand, (INT8*)pch);
#endif
}
//
// ULONG_PTR -> UINT8 conversion
//
__inline
HRESULT
ULongPtrToUInt8(
__inn ULONG_PTR ulOperand,
__outt __deref_out_range(==,ulOperand) UINT8* pui8Result)
{
HRESULT hr;
if (ulOperand <= UINT8_MAX)
{
*pui8Result = (UINT8)ulOperand;
hr = S_OK;
}
else
{
*pui8Result = UINT8_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// ULONG_PTR -> BYTE conversion
//
#define ULongPtrToByte ULongPtrToUInt8
//
// ULONG_PTR -> SHORT conversion
//
__inline
HRESULT
ULongPtrToShort(
__inn ULONG_PTR ulOperand,
__outt __deref_out_range(==,ulOperand) SHORT* psResult)
{
HRESULT hr;
if (ulOperand <= SHORT_MAX)
{
*psResult = (SHORT)ulOperand;
hr = S_OK;
}
else
{
*psResult = SHORT_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// ULONG_PTR -> INT16 conversion
//
#define ULongPtrToInt16 ULongPtrToShort
//
// ULONG_PTR -> USHORT conversion
//
__inline
HRESULT
ULongPtrToUShort(
__inn ULONG_PTR ulOperand,
__outt __deref_out_range(==,ulOperand) USHORT* pusResult)
{
HRESULT hr;
if (ulOperand <= USHORT_MAX)
{
*pusResult = (USHORT)ulOperand;
hr = S_OK;
}
else
{
*pusResult = USHORT_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// ULONG_PTR -> UINT16 conversion
//
#define ULongPtrToUInt16 ULongPtrToUShort
//
// ULONG_PTR -> WORD conversion
//
#define ULongPtrToWord ULongPtrToUShort
//
// ULONG_PTR -> INT conversion
//
__inline
HRESULT
ULongPtrToInt(
__inn ULONG_PTR ulOperand,
__outt __deref_out_range(==,ulOperand) INT* piResult)
{
HRESULT hr;
if (ulOperand <= INT_MAX)
{
*piResult = (INT)ulOperand;
hr = S_OK;
}
else
{
*piResult = INT_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// ULONG_PTR -> INT32 conversion
//
#define ULongPtrToInt32 ULongPtrToInt
//
// ULONG_PTR -> INT_PTR conversion
//
__inline
HRESULT
ULongPtrToIntPtr(
__inn ULONG_PTR ulOperand,
__outt __deref_out_range(==,ulOperand) INT_PTR* piResult)
{
HRESULT hr;
if (ulOperand <= INT_PTR_MAX)
{
*piResult = (INT_PTR)ulOperand;
hr = S_OK;
}
else
{
*piResult = INT_PTR_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// ULONG_PTR -> UINT conversion
//
#ifdef _WIN64
#define ULongPtrToUInt ULongLongToUInt
#else
__inline
HRESULT
ULongPtrToUInt(
__inn ULONG_PTR ulOperand,
__outt __deref_out_range(==,ulOperand) UINT* puResult)
{
C_ASSERT(sizeof(ULONG_PTR) == sizeof(UINT));
*puResult = (UINT)ulOperand;
return S_OK;
}
#endif
//
// ULONG_PTR -> UINT32 conversion
//
#define ULongPtrToUInt32 ULongPtrToUInt
//
// ULONG_PTR -> UINT_PTR conversion
//
__inline
HRESULT
ULongPtrToUIntPtr(
__inn ULONG_PTR ulOperand,
__outt __deref_out_range(==,ulOperand) UINT_PTR* puResult)
{
*puResult = (UINT_PTR)ulOperand;
return S_OK;
}
//
// ULONG_PTR -> LONG conversion
//
__inline
HRESULT
ULongPtrToLong(
__inn ULONG_PTR ulOperand,
__outt __deref_out_range(==,ulOperand) LONG* plResult)
{
HRESULT hr;
if (ulOperand <= INT32_MAX)
{
*plResult = (LONG)ulOperand;
hr = S_OK;
}
else
{
*plResult = LONG_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// ULONG_PTR -> LONG_PTR conversion
//
__inline
HRESULT
ULongPtrToLongPtr(
__inn ULONG_PTR ulOperand,
__outt __deref_out_range(==,ulOperand) LONG_PTR* plResult)
{
HRESULT hr;
if (ulOperand <= LONG_PTR_MAX)
{
*plResult = (LONG_PTR)ulOperand;
hr = S_OK;
}
else
{
*plResult = LONG_PTR_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// ULONG_PTR -> ULONG conversion
//
#ifdef _WIN64
#define ULongPtrToULong ULongLongToULong
#else
__inline
HRESULT
ULongPtrToULong(
__inn ULONG_PTR ulOperand,
__outt __deref_out_range(==,ulOperand) ULONG* pulResult)
{
*pulResult = (ULONG)ulOperand;
return S_OK;
}
#endif
//
// ULONG_PTR -> DWORD conversion
//
#define ULongPtrToDWord ULongPtrToULong
//
// ULONG_PTR -> LONGLONG conversion
//
#ifdef _WIN64
#define ULongPtrToLongLong ULongLongToLongLong
#else
__inline
HRESULT
ULongPtrToLongLong(
__inn ULONG_PTR ulOperand,
__outt __deref_out_range(==,ulOperand) LONGLONG* pllResult)
{
*pllResult = (LONGLONG)ulOperand;
return S_OK;
}
#endif
//
// ULONG_PTR -> LONG64 conversion
//
#define ULongPtrToLong64 ULongPtrToLongLong
//
// ULONG_PTR -> INT64
//
#define ULongPtrToInt64 ULongPtrToLongLong
//
// ULONG_PTR -> ptrdiff_t conversion
//
#define ULongPtrToPtrdiffT ULongPtrToIntPtr
//
// ULONG_PTR -> SSIZE_T conversion
//
#define ULongPtrToSSIZET ULongPtrToLongPtr
//
// DWORD -> INT8 conversion
//
#define DWordToInt8 ULongToInt8
//
// DWORD -> CHAR conversion
//
#define DWordToChar ULongToChar
//
// DWORD -> UCHAR conversion
//
#define DWordToUChar ULongToUChar
//
// DWORD -> UINT8 conversion
//
#define DWordToUInt8 ULongToUInt8
//
// DWORD -> BYTE conversion
//
#define DWordToByte ULongToUInt8
//
// DWORD -> SHORT conversion
//
#define DWordToShort ULongToShort
//
// DWORD -> INT16 conversion
//
#define DWordToInt16 ULongToShort
//
// DWORD -> USHORT conversion
//
#define DWordToUShort ULongToUShort
//
// DWORD -> UINT16 conversion
//
#define DWordToUInt16 ULongToUShort
//
// DWORD -> WORD conversion
//
#define DWordToWord ULongToUShort
//
// DWORD -> INT conversion
//
#define DWordToInt ULongToInt
//
// DWORD -> INT32 conversion
//
#define DWordToInt32 ULongToInt
//
// DWORD -> INT_PTR conversion
//
#define DWordToIntPtr ULongToIntPtr
//
// DWORD -> UINT conversion
//
#define DWordToUInt ULongToUInt
//
// DWORD -> UINT32 conversion
//
#define DWordToUInt32 ULongToUInt
//
// DWORD -> UINT_PTR conversion
//
#define DWordToUIntPtr ULongToUIntPtr
//
// DWORD -> LONG conversion
//
#define DWordToLong ULongToLong
//
// DWORD -> LONG_PTR conversion
//
#define DWordToLongPtr ULongToLongPtr
//
// DWORD -> ptrdiff_t conversion
//
#define DWordToPtrdiffT ULongToIntPtr
//
// DWORD -> SSIZE_T conversion
//
#define DWordToSSIZET ULongToLongPtr
//
// DWORD_PTR -> INT8 conversion
//
#define DWordPtrToInt8 ULongPtrToInt8
//
// DWORD_PTR -> UCHAR conversion
//
#define DWordPtrToUChar ULongPtrToUChar
//
// DWORD_PTR -> CHAR conversion
//
#define DWordPtrToChar ULongPtrToChar
//
// DWORD_PTR -> UINT8 conversion
//
#define DWordPtrToUInt8 ULongPtrToUInt8
//
// DWORD_PTR -> BYTE conversion
//
#define DWordPtrToByte ULongPtrToUInt8
//
// DWORD_PTR -> SHORT conversion
//
#define DWordPtrToShort ULongPtrToShort
//
// DWORD_PTR -> INT16 conversion
//
#define DWordPtrToInt16 ULongPtrToShort
//
// DWORD_PTR -> USHORT conversion
//
#define DWordPtrToUShort ULongPtrToUShort
//
// DWORD_PTR -> UINT16 conversion
//
#define DWordPtrToUInt16 ULongPtrToUShort
//
// DWORD_PTR -> WORD conversion
//
#define DWordPtrToWord ULongPtrToUShort
//
// DWORD_PTR -> INT conversion
//
#define DWordPtrToInt ULongPtrToInt
//
// DWORD_PTR -> INT32 conversion
//
#define DWordPtrToInt32 ULongPtrToInt
//
// DWORD_PTR -> INT_PTR conversion
//
#define DWordPtrToIntPtr ULongPtrToIntPtr
//
// DWORD_PTR -> UINT conversion
//
#define DWordPtrToUInt ULongPtrToUInt
//
// DWORD_PTR -> UINT32 conversion
//
#define DWordPtrToUInt32 ULongPtrToUInt
//
// DWODR_PTR -> UINT_PTR conversion
//
#define DWordPtrToUIntPtr ULongPtrToUIntPtr
//
// DWORD_PTR -> LONG conversion
//
#define DWordPtrToLong ULongPtrToLong
//
// DWORD_PTR -> LONG_PTR conversion
//
#define DWordPtrToLongPtr ULongPtrToLongPtr
//
// DWORD_PTR -> ULONG conversion
//
#define DWordPtrToULong ULongPtrToULong
//
// DWORD_PTR -> DWORD conversion
//
#define DWordPtrToDWord ULongPtrToULong
//
// DWORD_PTR -> LONGLONG conversion
//
#define DWordPtrToLongLong ULongPtrToLongLong
//
// DWORD_PTR -> LONG64 conversion
//
#define DWordPtrToLong64 ULongPtrToLongLong
//
// DWORD_PTR -> INT64 conversion
//
#define DWordPtrToInt64 ULongPtrToLongLong
//
// DWORD_PTR -> ptrdiff_t conversion
//
#define DWordPtrToPtrdiffT ULongPtrToIntPtr
//
// DWORD_PTR -> SSIZE_T conversion
//
#define DWordPtrToSSIZET ULongPtrToLongPtr
//
// LONGLONG -> INT8 conversion
//
__inline
HRESULT
LongLongToInt8(
__inn LONGLONG llOperand,
__outt __deref_out_range(==,llOperand) INT8* pi8Result)
{
HRESULT hr;
if ((llOperand >= INT8_MIN) && (llOperand <= INT8_MAX))
{
*pi8Result = (INT8)llOperand;
hr = S_OK;
}
else
{
*pi8Result = INT8_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// LONGLONG -> UCHAR conversion
//
__inline
HRESULT
LongLongToUChar(
__inn LONGLONG llOperand,
__outt __deref_out_range(==,llOperand) UCHAR* pch)
{
HRESULT hr;
if ((llOperand >= 0) && (llOperand <= 255))
{
*pch = (UCHAR)llOperand;
hr = S_OK;
}
else
{
*pch = '\0';
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// LONGLONG -> CHAR conversion
//
__forceinline
HRESULT
LongLongToChar(
__inn LONGLONG llOperand,
__outt __deref_out_range(==,llOperand) CHAR* pch)
{
#ifdef _CHAR_UNSIGNED
return LongLongToUChar(llOperand, (UCHAR*)pch);
#else
return LongLongToInt8(llOperand, (INT8*)pch);
#endif
}
//
// LONGLONG -> UINT8 conversion
//
__inline
HRESULT
LongLongToUInt8(
__inn LONGLONG llOperand,
__outt __deref_out_range(==,llOperand) UINT8* pu8Result)
{
HRESULT hr;
if ((llOperand >= 0) && (llOperand <= UINT8_MAX))
{
*pu8Result = (UINT8)llOperand;
hr = S_OK;
}
else
{
*pu8Result = UINT8_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// LONGLONG -> BYTE conversion
//
#define LongLongToByte LongLongToUInt8
//
// LONGLONG -> SHORT conversion
//
__inline
HRESULT
LongLongToShort(
__inn LONGLONG llOperand,
__outt __deref_out_range(==,llOperand) SHORT* psResult)
{
HRESULT hr;
if ((llOperand >= SHORT_MIN) && (llOperand <= SHORT_MAX))
{
*psResult = (SHORT)llOperand;
hr = S_OK;
}
else
{
*psResult = SHORT_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// LONGLONG -> INT16 conversion
//
#define LongLongToInt16 LongLongToShort
//
// LONGLONG -> USHORT conversion
//
__inline
HRESULT
LongLongToUShort(
__inn LONGLONG llOperand,
__outt __deref_out_range(==,llOperand) USHORT* pusResult)
{
HRESULT hr;
if ((llOperand >= 0) && (llOperand <= USHORT_MAX))
{
*pusResult = (USHORT)llOperand;
hr = S_OK;
}
else
{
*pusResult = USHORT_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// LONGLONG -> UINT16 conversion
//
#define LongLongToUInt16 LongLongToUShort
//
// LONGLONG -> WORD conversion
//
#define LongLongToWord LongLongToUShort
//
// LONGLONG -> INT conversion
//
__inline
HRESULT
LongLongToInt(
__inn LONGLONG llOperand,
__outt __deref_out_range(==,llOperand) INT* piResult)
{
HRESULT hr;
if ((llOperand >= INT_MIN) && (llOperand <= INT_MAX))
{
*piResult = (INT)llOperand;
hr = S_OK;
}
else
{
*piResult = INT_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// LONGLONG -> INT32 conversion
//
#define LongLongToInt32 LongLongToInt
//
// LONGLONG -> INT_PTR conversion
//
#ifdef _WIN64
__inline
HRESULT
LongLongToIntPtr(
__inn LONGLONG llOperand,
__outt __deref_out_range(==,llOperand) INT_PTR* piResult)
{
*piResult = llOperand;
return S_OK;
}
#else
#define LongLongToIntPtr LongLongToInt
#endif
//
// LONGLONG -> UINT conversion
//
__inline
HRESULT
LongLongToUInt(
__inn LONGLONG llOperand,
__outt __deref_out_range(==,llOperand) UINT* puResult)
{
HRESULT hr;
if ((llOperand >= 0) && (llOperand <= UINT_MAX))
{
*puResult = (UINT)llOperand;
hr = S_OK;
}
else
{
*puResult = UINT_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// LONGLONG -> UINT32 conversion
//
#define LongLongToUInt32 LongLongToUInt
//
// LONGLONG -> UINT_PTR conversion
//
#ifdef _WIN64
#define LongLongToUIntPtr LongLongToULongLong
#else
#define LongLongToUIntPtr LongLongToUInt
#endif
//
// LONGLONG -> LONG conversion
//
__inline
HRESULT
LongLongToLong(
__inn LONGLONG llOperand,
__outt __deref_out_range(==,llOperand) LONG* plResult)
{
HRESULT hr;
if ((llOperand >= INT32_MIN) && (llOperand <= INT32_MAX))
{
*plResult = (LONG)llOperand;
hr = S_OK;
}
else
{
*plResult = LONG_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// LONGLONG -> LONG_PTR conversion
//
#ifdef _WIN64
__inline
HRESULT
LongLongToLongPtr(
__inn LONGLONG llOperand,
__outt __deref_out_range(==,llOperand) LONG_PTR* plResult)
{
*plResult = (LONG_PTR)llOperand;
return S_OK;
}
#else
#define LongLongToLongPtr LongLongToLong
#endif
//
// LONGLONG -> ULONG conversion
//
__inline
HRESULT
LongLongToULong(
__inn LONGLONG llOperand,
__outt __deref_out_range(==,llOperand) ULONG* pulResult)
{
HRESULT hr;
if ((llOperand >= 0) && (llOperand <= (LONGLONG)(ULONGLONG)UINT32_MAX))
{
*pulResult = (ULONG)llOperand;
hr = S_OK;
}
else
{
*pulResult = ULONG_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// LONGLONG -> ULONG_PTR conversion
//
#ifdef _WIN64
#define LongLongToULongPtr LongLongToULongLong
#else
#define LongLongToULongPtr LongLongToULong
#endif
//
// LONGLONG -> DWORD conversion
//
#define LongLongToDWord LongLongToULong
//
// LONGLONG -> DWORD_PTR conversion
//
#define LongLongToDWordPtr LongLongToULongPtr
//
// LONGLONG -> ULONGLONG conversion
//
__inline
HRESULT
LongLongToULongLong(
__inn LONGLONG llOperand,
__outt __deref_out_range(==,llOperand) ULONGLONG* pullResult)
{
HRESULT hr;
if (llOperand >= 0)
{
*pullResult = (ULONGLONG)llOperand;
hr = S_OK;
}
else
{
*pullResult = ULONGLONG_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// LONGLONG -> DWORDLONG conversion
//
#define LongLongToDWordLong LongLongToULongLong
//
// LONGLONG -> ULONG64 conversion
//
#define LongLongToULong64 LongLongToULongLong
//
// LONGLONG -> DWORD64 conversion
//
#define LongLongToDWord64 LongLongToULongLong
//
// LONGLONG -> UINT64 conversion
//
#define LongLongToUInt64 LongLongToULongLong
//
// LONGLONG -> ptrdiff_t conversion
//
#define LongLongToPtrdiffT LongLongToIntPtr
//
// LONGLONG -> size_t conversion
//
#define LongLongToSizeT LongLongToUIntPtr
//
// LONGLONG -> SSIZE_T conversion
//
#define LongLongToSSIZET LongLongToLongPtr
//
// LONGLONG -> SIZE_T conversion
//
#define LongLongToSIZET LongLongToULongPtr
//
// LONG64 -> CHAR conversion
//
#define Long64ToChar LongLongToChar
//
// LONG64 -> INT8 conversion
//
#define Long64ToInt8 LongLongToInt8
//
// LONG64 -> UCHAR conversion
//
#define Long64ToUChar LongLongToUChar
//
// LONG64 -> UINT8 conversion
//
#define Long64ToUInt8 LongLongToUInt8
//
// LONG64 -> BYTE conversion
//
#define Long64ToByte LongLongToUInt8
//
// LONG64 -> SHORT conversion
//
#define Long64ToShort LongLongToShort
//
// LONG64 -> INT16 conversion
//
#define Long64ToInt16 LongLongToShort
//
// LONG64 -> USHORT conversion
//
#define Long64ToUShort LongLongToUShort
//
// LONG64 -> UINT16 conversion
//
#define Long64ToUInt16 LongLongToUShort
//
// LONG64 -> WORD conversion
//
#define Long64ToWord LongLongToUShort
//
// LONG64 -> INT conversion
//
#define Long64ToInt LongLongToInt
//
// LONG64 -> INT32 conversion
//
#define Long64ToInt32 LongLongToInt
//
// LONG64 -> INT_PTR conversion
//
#define Long64ToIntPtr LongLongToIntPtr
//
// LONG64 -> UINT conversion
//
#define Long64ToUInt LongLongToUInt
//
// LONG64 -> UINT32 conversion
//
#define Long64ToUInt32 LongLongToUInt
//
// LONG64 -> UINT_PTR conversion
//
#define Long64ToUIntPtr LongLongToUIntPtr
//
// LONG64 -> LONG conversion
//
#define Long64ToLong LongLongToLong
//
// LONG64 -> LONG_PTR conversion
//
#define Long64ToLongPtr LongLongToLongPtr
//
// LONG64 -> ULONG conversion
//
#define Long64ToULong LongLongToULong
//
// LONG64 -> ULONG_PTR conversion
//
#define Long64ToULongPtr LongLongToULongPtr
//
// LONG64 -> DWORD conversion
//
#define Long64ToDWord LongLongToULong
//
// LONG64 -> DWORD_PTR conversion
//
#define Long64ToDWordPtr LongLongToULongPtr
//
// LONG64 -> ULONGLONG conversion
//
#define Long64ToULongLong LongLongToULongLong
//
// LONG64 -> ptrdiff_t conversion
//
#define Long64ToPtrdiffT LongLongToIntPtr
//
// LONG64 -> size_t conversion
//
#define Long64ToSizeT LongLongToUIntPtr
//
// LONG64 -> SSIZE_T conversion
//
#define Long64ToSSIZET LongLongToLongPtr
//
// LONG64 -> SIZE_T conversion
//
#define Long64ToSIZET LongLongToULongPtr
//
// INT64 -> CHAR conversion
//
#define Int64ToChar LongLongToChar
//
// INT64 -> INT8 conversion
//
#define Int64ToInt8 LongLongToInt8
//
// INT64 -> UCHAR conversion
//
#define Int64ToUChar LongLongToUChar
//
// INT64 -> UINT8 conversion
//
#define Int64ToUInt8 LongLongToUInt8
//
// INT64 -> BYTE conversion
//
#define Int64ToByte LongLongToUInt8
//
// INT64 -> SHORT conversion
//
#define Int64ToShort LongLongToShort
//
// INT64 -> INT16 conversion
//
#define Int64ToInt16 LongLongToShort
//
// INT64 -> USHORT conversion
//
#define Int64ToUShort LongLongToUShort
//
// INT64 -> UINT16 conversion
//
#define Int64ToUInt16 LongLongToUShort
//
// INT64 -> WORD conversion
//
#define Int64ToWord LongLongToUShort
//
// INT64 -> INT conversion
//
#define Int64ToInt LongLongToInt
//
// INT64 -> INT32 conversion
//
#define Int64ToInt32 LongLongToInt
//
// INT64 -> INT_PTR conversion
//
#define Int64ToIntPtr LongLongToIntPtr
//
// INT64 -> UINT conversion
//
#define Int64ToUInt LongLongToUInt
//
// INT64 -> UINT32 conversion
//
#define Int64ToUInt32 LongLongToUInt
//
// INT64 -> UINT_PTR conversion
//
#define Int64ToUIntPtr LongLongToUIntPtr
//
// INT64 -> LONG conversion
//
#define Int64ToLong LongLongToLong
//
// INT64 -> LONG_PTR conversion
//
#define Int64ToLongPtr LongLongToLongPtr
//
// INT64 -> ULONG conversion
//
#define Int64ToULong LongLongToULong
//
// INT64 -> ULONG_PTR conversion
//
#define Int64ToULongPtr LongLongToULongPtr
//
// INT64 -> DWORD conversion
//
#define Int64ToDWord LongLongToULong
//
// INT64 -> DWORD_PTR conversion
//
#define Int64ToDWordPtr LongLongToULongPtr
//
// INT64 -> ULONGLONG conversion
//
#define Int64ToULongLong LongLongToULongLong
//
// INT64 -> DWORDLONG conversion
//
#define Int64ToDWordLong LongLongToULongLong
//
// INT64 -> ULONG64 conversion
//
#define Int64ToULong64 LongLongToULongLong
//
// INT64 -> DWORD64 conversion
//
#define Int64ToDWord64 LongLongToULongLong
//
// INT64 -> UINT64 conversion
//
#define Int64ToUInt64 LongLongToULongLong
//
// INT64 -> ptrdiff_t conversion
//
#define Int64ToPtrdiffT LongLongToIntPtr
//
// INT64 -> size_t conversion
//
#define Int64ToSizeT LongLongToUIntPtr
//
// INT64 -> SSIZE_T conversion
//
#define Int64ToSSIZET LongLongToLongPtr
//
// INT64 -> SIZE_T conversion
//
#define Int64ToSIZET LongLongToULongPtr
//
// ULONGLONG -> INT8 conversion
//
__inline
HRESULT
ULongLongToInt8(
__inn ULONGLONG ullOperand,
__outt __deref_out_range(==,ullOperand) INT8* pi8Result)
{
HRESULT hr;
if (ullOperand <= INT8_MAX)
{
*pi8Result = (INT8)ullOperand;
hr = S_OK;
}
else
{
*pi8Result = INT8_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// ULONGLONG -> UCHAR conversion
//
__inline
HRESULT
ULongLongToUChar(
__inn ULONGLONG ullOperand,
__outt __deref_out_range(==,ullOperand) UCHAR* pch)
{
HRESULT hr;
if (ullOperand <= 255)
{
*pch = (UCHAR)ullOperand;
hr = S_OK;
}
else
{
*pch = '\0';
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// ULONGLONG -> CHAR conversion
//
__forceinline
HRESULT
ULongLongToChar(
__inn ULONGLONG ullOperand,
__outt __deref_out_range(==,ullOperand) CHAR* pch)
{
#ifdef _CHAR_UNSIGNED
return ULongLongToUChar(ullOperand, (UCHAR*)pch);
#else
return ULongLongToInt8(ullOperand, (INT8*)pch);
#endif
}
//
// ULONGLONG -> UINT8 conversion
//
__inline
HRESULT
ULongLongToUInt8(
__inn ULONGLONG ullOperand,
__outt __deref_out_range(==,ullOperand) UINT8* pu8Result)
{
HRESULT hr;
if (ullOperand <= UINT8_MAX)
{
*pu8Result = (UINT8)ullOperand;
hr = S_OK;
}
else
{
*pu8Result = UINT8_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// ULONGLONG -> BYTE conversion
//
#define ULongLongToByte ULongLongToUInt8
//
// ULONGLONG -> SHORT conversion
//
__inline
HRESULT
ULongLongToShort(
__inn ULONGLONG ullOperand,
__outt __deref_out_range(==,ullOperand) SHORT* psResult)
{
HRESULT hr;
if (ullOperand <= SHORT_MAX)
{
*psResult = (SHORT)ullOperand;
hr = S_OK;
}
else
{
*psResult = SHORT_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// ULONGLONG -> INT16 conversion
//
#define ULongLongToInt16 ULongLongToShort
//
// ULONGLONG -> USHORT conversion
//
__inline
HRESULT
ULongLongToUShort(
__inn ULONGLONG ullOperand,
__outt __deref_out_range(==,ullOperand) USHORT* pusResult)
{
HRESULT hr;
if (ullOperand <= USHORT_MAX)
{
*pusResult = (USHORT)ullOperand;
hr = S_OK;
}
else
{
*pusResult = USHORT_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// ULONGLONG -> UINT16 conversion
//
#define ULongLongToUInt16 ULongLongToUShort
//
// ULONGLONG -> WORD conversion
//
#define ULongLongToWord ULongLongToUShort
//
// ULONGLONG -> INT conversion
//
__inline
HRESULT
ULongLongToInt(
__inn ULONGLONG ullOperand,
__outt __deref_out_range(==,ullOperand) INT* piResult)
{
HRESULT hr;
if (ullOperand <= INT_MAX)
{
*piResult = (INT)ullOperand;
hr = S_OK;
}
else
{
*piResult = INT_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// ULONGLONG -> INT32 conversion
//
#define ULongLongToInt32 ULongLongToInt
//
// ULONGLONG -> INT_PTR conversion
//
#ifdef _WIN64
#define ULongLongToIntPtr ULongLongToLongLong
#else
#define ULongLongToIntPtr ULongLongToInt
#endif
//
// ULONGLONG -> UINT conversion
//
__inline
HRESULT
ULongLongToUInt(
__inn ULONGLONG ullOperand,
__outt __deref_out_range(==,ullOperand) UINT* puResult)
{
HRESULT hr;
if (ullOperand <= UINT_MAX)
{
*puResult = (UINT)ullOperand;
hr = S_OK;
}
else
{
*puResult = UINT_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// ULONGLONG -> UINT32 conversion
//
#define ULongLongToUInt32 ULongLongToUInt
//
// ULONGLONG -> UINT_PTR conversion
//
#ifdef _WIN64
__inline
HRESULT
ULongLongToUIntPtr(
__inn ULONGLONG ullOperand,
__outt __deref_out_range(==,ullOperand) UINT_PTR* puResult)
{
*puResult = ullOperand;
return S_OK;
}
#else
#define ULongLongToUIntPtr ULongLongToUInt
#endif
//
// ULONGLONG -> LONG conversion
//
__inline
HRESULT
ULongLongToLong(
__inn ULONGLONG ullOperand,
__outt __deref_out_range(==,ullOperand) LONG* plResult)
{
HRESULT hr;
if (ullOperand <= INT32_MAX)
{
*plResult = (LONG)ullOperand;
hr = S_OK;
}
else
{
*plResult = LONG_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// ULONGLONG -> LONG_PTR conversion
//
__inline
HRESULT
ULongLongToLongPtr(
__inn ULONGLONG ullOperand,
__outt __deref_out_range(==,ullOperand) LONG_PTR* plResult)
{
HRESULT hr;
if (ullOperand <= LONG_PTR_MAX)
{
*plResult = (LONG_PTR)ullOperand;
hr = S_OK;
}
else
{
*plResult = LONG_PTR_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// ULONGLONG -> ULONG conversion
//
__inline
HRESULT
ULongLongToULong(
__inn ULONGLONG ullOperand,
__outt __deref_out_range(==,ullOperand) ULONG* pulResult)
{
HRESULT hr;
if (ullOperand <= UINT32_MAX)
{
*pulResult = (ULONG)ullOperand;
hr = S_OK;
}
else
{
*pulResult = ULONG_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// ULONGLONG -> ULONG_PTR conversion
//
#ifdef _WIN64
__inline
HRESULT
ULongLongToULongPtr(
__inn ULONGLONG ullOperand,
__outt __deref_out_range(==,ullOperand) ULONG_PTR* pulResult)
{
*pulResult = ullOperand;
return S_OK;
}
#else
#define ULongLongToULongPtr ULongLongToULong
#endif
//
// ULONGLONG -> DWORD conversion
//
#define ULongLongToDWord ULongLongToULong
//
// ULONGLONG -> DWORD_PTR conversion
//
#define ULongLongToDWordPtr ULongLongToULongPtr
//
// ULONGLONG -> LONGLONG conversion
//
__inline
HRESULT
ULongLongToLongLong(
__inn ULONGLONG ullOperand,
__outt __deref_out_range(==,ullOperand) LONGLONG* pllResult)
{
HRESULT hr;
if (ullOperand <= LONGLONG_MAX)
{
*pllResult = (LONGLONG)ullOperand;
hr = S_OK;
}
else
{
*pllResult = LONGLONG_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// ULONGLONG -> INT64 conversion
//
#define ULongLongToInt64 ULongLongToLongLong
//
// ULONGLONG -> LONG64 conversion
//
#define ULongLongToLong64 ULongLongToLongLong
//
// ULONGLONG -> ptrdiff_t conversion
//
#define ULongLongToPtrdiffT ULongLongToIntPtr
//
// ULONGLONG -> size_t conversion
//
#define ULongLongToSizeT ULongLongToUIntPtr
//
// ULONGLONG -> SSIZE_T conversion
//
#define ULongLongToSSIZET ULongLongToLongPtr
//
// ULONGLONG -> SIZE_T conversion
//
#define ULongLongToSIZET ULongLongToULongPtr
//
// DWORDLONG -> CHAR conversion
//
#define DWordLongToChar ULongLongToChar
//
// DWORDLONG -> INT8 conversion
//
#define DWordLongToInt8 ULongLongToInt8
//
// DWORDLONG -> UCHAR conversion
//
#define DWordLongToUChar ULongLongToUChar
//
// DWORDLONG -> UINT8 conversion
//
#define DWordLongToUInt8 ULongLongToUInt8
//
// DWORDLONG -> BYTE conversion
//
#define DWordLongToByte ULongLongToUInt8
//
// DWORDLONG -> SHORT conversion
//
#define DWordLongToShort ULongLongToShort
//
// DWORDLONG -> INT16 conversion
//
#define DWordLongToInt16 ULongLongToShort
//
// DWORDLONG -> USHORT conversion
//
#define DWordLongToUShort ULongLongToUShort
//
// DWORDLONG -> UINT16 conversion
//
#define DWordLongToUInt16 ULongLongToUShort
//
// DWORDLONG -> WORD conversion
//
#define DWordLongToWord ULongLongToUShort
//
// DWORDLONG -> INT conversion
//
#define DWordLongToInt ULongLongToInt
//
// DWORDLONG -> INT32 conversion
//
#define DWordLongToInt32 ULongLongToInt
//
// DWORDLONG -> INT_PTR conversion
//
#define DWordLongToIntPtr ULongLongToIntPtr
//
// DWORDLONG -> UINT conversion
//
#define DWordLongToUInt ULongLongToUInt
//
// DWORDLONG -> UINT32 conversion
//
#define DWordLongToUInt32 ULongLongToUInt
//
// DWORDLONG -> UINT_PTR conversion
//
#define DWordLongToUIntPtr ULongLongToUIntPtr
//
// DWORDLONG -> LONG conversion
//
#define DWordLongToLong ULongLongToLong
//
// DWORDLONG -> LONG_PTR conversion
//
#define DWordLongToLongPtr ULongLongToLongPtr
//
// DWORDLONG -> ULONG conversion
//
#define DWordLongToULong ULongLongToULong
//
// DWORDLONG -> ULONG_PTR conversion
//
#define DWordLongToULongPtr ULongLongToULongPtr
//
// DWORDLONG -> DWORD conversion
//
#define DWordLongToDWord ULongLongToULong
//
// DWORDLONG -> DWORD_PTR conversion
//
#define DWordLongToDWordPtr ULongLongToULongPtr
//
// DWORDLONG -> LONGLONG conversion
//
#define DWordLongToLongLong ULongLongToLongLong
//
// DWORDLONG -> LONG64 conversion
//
#define DWordLongToLong64 ULongLongToLongLong
//
// DWORDLONG -> INT64 conversion
//
#define DWordLongToInt64 ULongLongToLongLong
//
// DWORDLONG -> ptrdiff_t conversion
//
#define DWordLongToPtrdiffT ULongLongToIntPtr
//
// DWORDLONG -> size_t conversion
//
#define DWordLongToSizeT ULongLongToUIntPtr
//
// DWORDLONG -> SSIZE_T conversion
//
#define DWordLongToSSIZET ULongLongToLongPtr
//
// DWORDLONG -> SIZE_T conversion
//
#define DWordLongToSIZET ULongLongToULongPtr
//
// ULONG64 -> CHAR conversion
//
#define ULong64ToChar ULongLongToChar
//
// ULONG64 -> INT8 conversion
//
#define ULong64ToInt8 ULongLongToInt8
//
// ULONG64 -> UCHAR conversion
//
#define ULong64ToUChar ULongLongToUChar
//
// ULONG64 -> UINT8 conversion
//
#define ULong64ToUInt8 ULongLongToUInt8
//
// ULONG64 -> BYTE conversion
//
#define ULong64ToByte ULongLongToUInt8
//
// ULONG64 -> SHORT conversion
//
#define ULong64ToShort ULongLongToShort
//
// ULONG64 -> INT16 conversion
//
#define ULong64ToInt16 ULongLongToShort
//
// ULONG64 -> USHORT conversion
//
#define ULong64ToUShort ULongLongToUShort
//
// ULONG64 -> UINT16 conversion
//
#define ULong64ToUInt16 ULongLongToUShort
//
// ULONG64 -> WORD conversion
//
#define ULong64ToWord ULongLongToUShort
//
// ULONG64 -> INT conversion
//
#define ULong64ToInt ULongLongToInt
//
// ULONG64 -> INT32 conversion
//
#define ULong64ToInt32 ULongLongToInt
//
// ULONG64 -> INT_PTR conversion
//
#define ULong64ToIntPtr ULongLongToIntPtr
//
// ULONG64 -> UINT conversion
//
#define ULong64ToUInt ULongLongToUInt
//
// ULONG64 -> UINT32 conversion
//
#define ULong64ToUInt32 ULongLongToUInt
//
// ULONG64 -> UINT_PTR conversion
//
#define ULong64ToUIntPtr ULongLongToUIntPtr
//
// ULONG64 -> LONG conversion
//
#define ULong64ToLong ULongLongToLong
//
// ULONG64 -> LONG_PTR conversion
//
#define ULong64ToLongPtr ULongLongToLongPtr
//
// ULONG64 -> ULONG conversion
//
#define ULong64ToULong ULongLongToULong
//
// ULONG64 -> ULONG_PTR conversion
//
#define ULong64ToULongPtr ULongLongToULongPtr
//
// ULONG64 -> DWORD conversion
//
#define ULong64ToDWord ULongLongToULong
//
// ULONG64 -> DWORD_PTR conversion
//
#define ULong64ToDWordPtr ULongLongToULongPtr
//
// ULONG64 -> LONGLONG conversion
//
#define ULong64ToLongLong ULongLongToLongLong
//
// ULONG64 -> LONG64 conversion
//
#define ULong64ToLong64 ULongLongToLongLong
//
// ULONG64 -> INT64 conversion
//
#define ULong64ToInt64 ULongLongToLongLong
//
// ULONG64 -> ptrdiff_t conversion
//
#define ULong64ToPtrdiffT ULongLongToIntPtr
//
// ULONG64 -> size_t conversion
//
#define ULong64ToSizeT ULongLongToUIntPtr
//
// ULONG64 -> SSIZE_T conversion
//
#define ULong64ToSSIZET ULongLongToLongPtr
//
// ULONG64 -> SIZE_T conversion
//
#define ULong64ToSIZET ULongLongToULongPtr
//
// DWORD64 -> CHAR conversion
//
#define DWord64ToChar ULongLongToChar
//
// DWORD64 -> INT8 conversion
//
#define DWord64ToInt8 ULongLongToInt8
//
// DWORD64 -> UCHAR conversion
//
#define DWord64ToUChar ULongLongToUChar
//
// DWORD64 -> UINT8 conversion
//
#define DWord64ToUInt8 ULongLongToUInt8
//
// DWORD64 -> BYTE conversion
//
#define DWord64ToByte ULongLongToUInt8
//
// DWORD64 -> SHORT conversion
//
#define DWord64ToShort ULongLongToShort
//
// DWORD64 -> INT16 conversion
//
#define DWord64ToInt16 ULongLongToShort
//
// DWORD64 -> USHORT conversion
//
#define DWord64ToUShort ULongLongToUShort
//
// DWORD64 -> UINT16 conversion
//
#define DWord64ToUInt16 ULongLongToUShort
//
// DWORD64 -> WORD conversion
//
#define DWord64ToWord ULongLongToUShort
//
// DWORD64 -> INT conversion
//
#define DWord64ToInt ULongLongToInt
//
// DWORD64 -> INT32 conversion
//
#define DWord64ToInt32 ULongLongToInt
//
// DWORD64 -> INT_PTR conversion
//
#define DWord64ToIntPtr ULongLongToIntPtr
//
// DWORD64 -> UINT conversion
//
#define DWord64ToUInt ULongLongToUInt
//
// DWORD64 -> UINT32 conversion
//
#define DWord64ToUInt32 ULongLongToUInt
//
// DWORD64 -> UINT_PTR conversion
//
#define DWord64ToUIntPtr ULongLongToUIntPtr
//
// DWORD64 -> LONG conversion
//
#define DWord64ToLong ULongLongToLong
//
// DWORD64 -> LONG_PTR conversion
//
#define DWord64ToLongPtr ULongLongToLongPtr
//
// DWORD64 -> ULONG conversion
//
#define DWord64ToULong ULongLongToULong
//
// DWORD64 -> ULONG_PTR conversion
//
#define DWord64ToULongPtr ULongLongToULongPtr
//
// DWORD64 -> DWORD conversion
//
#define DWord64ToDWord ULongLongToULong
//
// DWORD64 -> DWORD_PTR conversion
//
#define DWord64ToDWordPtr ULongLongToULongPtr
//
// DWORD64 -> LONGLONG conversion
//
#define DWord64ToLongLong ULongLongToLongLong
//
// DWORD64 -> LONG64 conversion
//
#define DWord64ToLong64 ULongLongToLongLong
//
// DWORD64 -> INT64 conversion
//
#define DWord64ToInt64 ULongLongToLongLong
//
// DWORD64 -> ptrdiff_t conversion
//
#define DWord64ToPtrdiffT ULongLongToIntPtr
//
// DWORD64 -> size_t conversion
//
#define DWord64ToSizeT ULongLongToUIntPtr
//
// DWORD64 -> SSIZE_T conversion
//
#define DWord64ToSSIZET ULongLongToLongPtr
//
// DWORD64 -> SIZE_T conversion
//
#define DWord64ToSIZET ULongLongToULongPtr
//
// UINT64 -> CHAR conversion
//
#define UInt64ToChar ULongLongToChar
//
// UINT64 -> INT8 conversion
//
#define UInt64ToInt8 ULongLongToInt8
//
// UINT64 -> UCHAR conversion
//
#define UInt64ToUChar ULongLongToUChar
//
// UINT64 -> UINT8 conversion
//
#define UInt64ToUInt8 ULongLongToUInt8
//
// UINT64 -> BYTE conversion
//
#define UInt64ToByte ULongLongToUInt8
//
// UINT64 -> SHORT conversion
//
#define UInt64ToShort ULongLongToShort
//
// UINT64 -> INT16 conversion
//
//
#define UInt64ToInt16 ULongLongToShort
//
// UINT64 -> USHORT conversion
//
#define UInt64ToUShort ULongLongToUShort
//
// UINT64 -> UINT16 conversion
//
#define UInt64ToUInt16 ULongLongToUShort
//
// UINT64 -> WORD conversion
//
#define UInt64ToWord ULongLongToUShort
//
// UINT64 -> INT conversion
//
#define UInt64ToInt ULongLongToInt
//
// UINT64 -> INT32 conversion
//
#define UInt64ToInt32 ULongLongToInt
//
// UINT64 -> INT_PTR conversion
//
#define UInt64ToIntPtr ULongLongToIntPtr
//
// UINT64 -> UINT conversion
//
#define UInt64ToUInt ULongLongToUInt
//
// UINT64 -> UINT32 conversion
//
#define UInt64ToUInt32 ULongLongToUInt
//
// UINT64 -> UINT_PTR conversion
//
#define UInt64ToUIntPtr ULongLongToUIntPtr
//
// UINT64 -> LONG conversion
//
#define UInt64ToLong ULongLongToLong
//
// UINT64 -> LONG_PTR conversion
//
#define UInt64ToLongPtr ULongLongToLongPtr
//
// UINT64 -> ULONG conversion
//
#define UInt64ToULong ULongLongToULong
//
// UINT64 -> ULONG_PTR conversion
//
#define UInt64ToULongPtr ULongLongToULongPtr
//
// UINT64 -> DWORD conversion
//
#define UInt64ToDWord ULongLongToULong
//
// UINT64 -> DWORD_PTR conversion
//
#define UInt64ToDWordPtr ULongLongToULongPtr
//
// UINT64 -> LONGLONG conversion
//
#define UInt64ToLongLong ULongLongToLongLong
//
// UINT64 -> LONG64 conversion
//
#define UInt64ToLong64 ULongLongToLongLong
//
// UINT64 -> INT64 conversion
//
#define UInt64ToInt64 ULongLongToLongLong
//
// UINT64 -> ptrdiff_t conversion
//
#define UInt64ToPtrdiffT ULongLongToIntPtr
//
// UINT64 -> size_t conversion
//
#define UInt64ToSizeT ULongLongToUIntPtr
//
// UINT64 -> SSIZE_T conversion
//
#define UInt64ToSSIZET ULongLongToLongPtr
//
// UINT64 -> SIZE_T conversion
//
#define UInt64ToSIZET ULongLongToULongPtr
//
// ptrdiff_t -> CHAR conversion
//
#define PtrdiffTToChar IntPtrToChar
//
// ptrdiff_t -> INT8 conversion
//
#define PtrdiffTToInt8 IntPtrToInt8
//
// ptrdiff_t -> UCHAR conversion
//
#define PtrdiffTToUChar IntPtrToUChar
//
// ptrdiff_t -> UINT8 conversion
//
#define PtrdiffTToUInt8 IntPtrToUInt8
//
// ptrdiff_t -> BYTE conversion
//
#define PtrdiffTToByte IntPtrToUInt8
//
// ptrdiff_t -> SHORT conversion
//
#define PtrdiffTToShort IntPtrToShort
//
// ptrdiff_t -> INT16 conversion
//
#define PtrdiffTToInt16 IntPtrToShort
//
// ptrdiff_t -> USHORT conversion
//
#define PtrdiffTToUShort IntPtrToUShort
//
// ptrdiff_t -> UINT16 conversion
//
#define PtrdiffTToUInt16 IntPtrToUShort
//
// ptrdiff_t -> WORD conversion
//
#define PtrdiffTToWord IntPtrToUShort
//
// ptrdiff_t -> INT conversion
//
#define PtrdiffTToInt IntPtrToInt
//
// ptrdiff_t -> INT32 conversion
//
#define PtrdiffTToInt32 IntPtrToInt
//
// ptrdiff_t -> UINT conversion
//
#define PtrdiffTToUInt IntPtrToUInt
//
// ptrdiff_t -> UINT32 conversion
//
#define PtrdiffTToUInt32 IntPtrToUInt
//
// ptrdiff_t -> UINT_PTR conversion
//
#define PtrdiffTToUIntPtr IntPtrToUIntPtr
//
// ptrdiff_t -> LONG conversion
//
#define PtrdiffTToLong IntPtrToLong
//
// ptrdiff_t -> LONG_PTR conversion
//
#define PtrdiffTToLongPtr IntPtrToLongPtr
//
// ptrdiff_t -> ULONG conversion
//
#define PtrdiffTToULong IntPtrToULong
//
// ptrdiff_t -> ULONG_PTR conversion
//
#define PtrdiffTToULongPtr IntPtrToULongPtr
//
// ptrdiff_t -> DWORD conversion
//
#define PtrdiffTToDWord IntPtrToULong
//
// ptrdiff_t -> DWORD_PTR conversion
//
#define PtrdiffTToDWordPtr IntPtrToULongPtr
//
// ptrdiff_t -> ULONGLONG conversion
//
#define PtrdiffTToULongLong IntPtrToULongLong
//
// ptrdiff_t -> DWORDLONG conversion
//
#define PtrdiffTToDWordLong IntPtrToULongLong
//
// ptrdiff_t -> ULONG64 conversion
//
#define PtrdiffTToULong64 IntPtrToULongLong
//
// ptrdiff_t -> DWORD64 conversion
//
#define PtrdiffTToDWord64 IntPtrToULongLong
//
// ptrdiff_t -> UINT64 conversion
//
#define PtrdiffTToUInt64 IntPtrToULongLong
//
// ptrdiff_t -> size_t conversion
//
#define PtrdiffTToSizeT IntPtrToUIntPtr
//
// ptrdiff_t -> SIZE_T conversion
//
#define PtrdiffTToSIZET IntPtrToULongPtr
//
// size_t -> INT8 conversion
//
#define SizeTToInt8 UIntPtrToInt8
//
// size_t -> UCHAR conversion
//
#define SizeTToUChar UIntPtrToUChar
//
// size_t -> CHAR conversion
//
#define SizeTToChar UIntPtrToChar
//
// size_t -> UINT8 conversion
//
#define SizeTToUInt8 UIntPtrToUInt8
//
// size_t -> BYTE conversion
//
#define SizeTToByte UIntPtrToUInt8
//
// size_t -> SHORT conversion
//
#define SizeTToShort UIntPtrToShort
//
// size_t -> INT16 conversion
//
#define SizeTToInt16 UIntPtrToShort
//
// size_t -> USHORT conversion
//
#define SizeTToUShort UIntPtrToUShort
//
// size_t -> UINT16 conversion
//
#define SizeTToUInt16 UIntPtrToUShort
//
// size_t -> WORD
//
#define SizeTToWord UIntPtrToUShort
//
// size_t -> INT conversion
//
#define SizeTToInt UIntPtrToInt
//
// size_t -> INT32 conversion
//
#define SizeTToInt32 UIntPtrToInt
//
// size_t -> INT_PTR conversion
//
#define SizeTToIntPtr UIntPtrToIntPtr
//
// size_t -> UINT conversion
//
#define SizeTToUInt UIntPtrToUInt
//
// size_t -> UINT32 conversion
//
#define SizeTToUInt32 UIntPtrToUInt
//
// size_t -> LONG conversion
//
#define SizeTToLong UIntPtrToLong
//
// size_t -> LONG_PTR conversion
//
#define SizeTToLongPtr UIntPtrToLongPtr
//
// size_t -> ULONG conversion
//
#define SizeTToULong UIntPtrToULong
//
// size_t -> DWORD conversion
//
#define SizeTToDWord UIntPtrToULong
//
// size_t -> LONGLONG conversion
//
#define SizeTToLongLong UIntPtrToLongLong
//
// size_t -> LONG64 conversion
//
#define SizeTToLong64 UIntPtrToLongLong
//
// size_t -> INT64
//
#define SizeTToInt64 UIntPtrToLongLong
//
// size_t -> ptrdiff_t conversion
//
#define SizeTToPtrdiffT UIntPtrToIntPtr
//
// size_t -> SSIZE_T conversion
//
#define SizeTToSSIZET UIntPtrToLongPtr
//
// SSIZE_T -> INT8 conversion
//
#define SSIZETToInt8 LongPtrToInt8
//
// SSIZE_T -> UCHAR conversion
//
#define SSIZETToUChar LongPtrToUChar
//
// SSIZE_T -> CHAR conversion
//
#define SSIZETToChar LongPtrToChar
//
// SSIZE_T -> UINT8 conversion
//
#define SSIZETToUInt8 LongPtrToUInt8
//
// SSIZE_T -> BYTE conversion
//
#define SSIZETToByte LongPtrToUInt8
//
// SSIZE_T -> SHORT conversion
//
#define SSIZETToShort LongPtrToShort
//
// SSIZE_T -> INT16 conversion
//
#define SSIZETToInt16 LongPtrToShort
//
// SSIZE_T -> USHORT conversion
//
#define SSIZETToUShort LongPtrToUShort
//
// SSIZE_T -> UINT16 conversion
//
#define SSIZETToUInt16 LongPtrToUShort
//
// SSIZE_T -> WORD conversion
//
#define SSIZETToWord LongPtrToUShort
//
// SSIZE_T -> INT conversion
//
#define SSIZETToInt LongPtrToInt
//
// SSIZE_T -> INT32 conversion
//
#define SSIZETToInt32 LongPtrToInt
//
// SSIZE_T -> INT_PTR conversion
//
#define SSIZETToIntPtr LongPtrToIntPtr
//
// SSIZE_T -> UINT conversion
//
#define SSIZETToUInt LongPtrToUInt
//
// SSIZE_T -> UINT32 conversion
//
#define SSIZETToUInt32 LongPtrToUInt
//
// SSIZE_T -> UINT_PTR conversion
//
#define SSIZETToUIntPtr LongPtrToUIntPtr
//
// SSIZE_T -> LONG conversion
//
#define SSIZETToLong LongPtrToLong
//
// SSIZE_T -> ULONG conversion
//
#define SSIZETToULong LongPtrToULong
//
// SSIZE_T -> ULONG_PTR conversion
//
#define SSIZETToULongPtr LongPtrToULongPtr
//
// SSIZE_T -> DWORD conversion
//
#define SSIZETToDWord LongPtrToULong
//
// SSIZE_T -> DWORD_PTR conversion
//
#define SSIZETToDWordPtr LongPtrToULongPtr
//
// SSIZE_T -> ULONGLONG conversion
//
#define SSIZETToULongLong LongPtrToULongLong
//
// SSIZE_T -> DWORDLONG conversion
//
#define SSIZETToDWordLong LongPtrToULongLong
//
// SSIZE_T -> ULONG64 conversion
//
#define SSIZETToULong64 LongPtrToULongLong
//
// SSIZE_T -> DWORD64 conversion
//
#define SSIZETToDWord64 LongPtrToULongLong
//
// SSIZE_T -> UINT64 conversion
//
#define SSIZETToUInt64 LongPtrToULongLong
//
// SSIZE_T -> size_t conversion
//
#define SSIZETToSizeT LongPtrToUIntPtr
//
// SSIZE_T -> SIZE_T conversion
//
#define SSIZETToSIZET LongPtrToULongPtr
//
// SIZE_T -> INT8 conversion
//
#define SIZETToInt8 ULongPtrToInt8
//
// SIZE_T -> UCHAR conversion
//
#define SIZETToUChar ULongPtrToUChar
//
// SIZE_T -> CHAR conversion
//
#define SIZETToChar ULongPtrToChar
//
// SIZE_T -> UINT8 conversion
//
#define SIZETToUInt8 ULongPtrToUInt8
//
// SIZE_T -> BYTE conversion
//
#define SIZETToByte ULongPtrToUInt8
//
// SIZE_T -> SHORT conversion
//
#define SIZETToShort ULongPtrToShort
//
// SIZE_T -> INT16 conversion
//
#define SIZETToInt16 ULongPtrToShort
//
// SIZE_T -> USHORT conversion
//
#define SIZETToUShort ULongPtrToUShort
//
// SIZE_T -> UINT16 conversion
//
#define SIZETToUInt16 ULongPtrToUShort
//
// SIZE_T -> WORD
//
#define SIZETToWord ULongPtrToUShort
//
// SIZE_T -> INT conversion
//
#define SIZETToInt ULongPtrToInt
//
// SIZE_T -> INT32 conversion
//
#define SIZETToInt32 ULongPtrToInt
//
// SIZE_T -> INT_PTR conversion
//
#define SIZETToIntPtr ULongPtrToIntPtr
//
// SIZE_T -> UINT conversion
//
#define SIZETToUInt ULongPtrToUInt
//
// SIZE_T -> UINT32 conversion
//
#define SIZETToUInt32 ULongPtrToUInt
//
// SIZE_T -> UINT_PTR conversion
//
#define SIZETToUIntPtr ULongPtrToUIntPtr
//
// SIZE_T -> LONG conversion
//
#define SIZETToLong ULongPtrToLong
//
// SIZE_T -> LONG_PTR conversion
//
#define SIZETToLongPtr ULongPtrToLongPtr
//
// SIZE_T -> ULONG conversion
//
#define SIZETToULong ULongPtrToULong
//
// SIZE_T -> DWORD conversion
//
#define SIZETToDWord ULongPtrToULong
//
// SIZE_T -> LONGLONG conversion
//
#define SIZETToLongLong ULongPtrToLongLong
//
// SIZE_T -> LONG64 conversion
//
#define SIZETToLong64 ULongPtrToLongLong
//
// SIZE_T -> INT64
//
#define SIZETToInt64 ULongPtrToLongLong
//
// SIZE_T -> ptrdiff_t conversion
//
#define SIZETToPtrdiffT ULongPtrToIntPtr
//
// SIZE_T -> SSIZE_T conversion
//
#define SIZETToSSIZET ULongPtrToLongPtr
//=============================================================================
// Addition functions
//=============================================================================
//
// UINT8 addition
//
__inline
HRESULT
UInt8Add(
__inn UINT8 u8Augend,
__inn UINT8 u8Addend,
__outt __deref_out_range(==,u8Augend + u8Addend) UINT8* pu8Result)
{
HRESULT hr;
if (((UINT8)(u8Augend + u8Addend)) >= u8Augend)
{
*pu8Result = (UINT8)(u8Augend + u8Addend);
hr = S_OK;
}
else
{
*pu8Result = UINT8_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// USHORT addition
//
__inline
HRESULT
UShortAdd(
__inn USHORT usAugend,
__inn USHORT usAddend,
__outt __deref_out_range(==,usAugend + usAddend) USHORT* pusResult)
{
HRESULT hr;
if (((USHORT)(usAugend + usAddend)) >= usAugend)
{
*pusResult = (USHORT)(usAugend + usAddend);
hr = S_OK;
}
else
{
*pusResult = USHORT_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// UINT16 addition
//
#define UInt16Add UShortAdd
//
// WORD addtition
//
#define WordAdd UShortAdd
//
// UINT addition
//
__inline
HRESULT
UIntAdd(
__inn UINT uAugend,
__inn UINT uAddend,
__outt __deref_out_range(==,uAugend + uAddend) UINT* puResult)
{
HRESULT hr;
if ((uAugend + uAddend) >= uAugend)
{
*puResult = (uAugend + uAddend);
hr = S_OK;
}
else
{
*puResult = UINT_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// UINT32 addition
//
#define UInt32Add UIntAdd
//
// UINT_PTR addition
//
#ifdef _WIN64
#define UIntPtrAdd ULongLongAdd
#else
__inline
HRESULT
UIntPtrAdd(
__inn UINT_PTR uAugend,
__inn UINT_PTR uAddend,
__outt __deref_out_range(==,uAugend + uAddend) UINT_PTR* puResult)
{
HRESULT hr;
if ((uAugend + uAddend) >= uAugend)
{
*puResult = (uAugend + uAddend);
hr = S_OK;
}
else
{
*puResult = UINT_PTR_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
#endif // _WIN64
//
// ULONG addition
//
__inline
HRESULT
ULongAdd(
__inn ULONG ulAugend,
__inn ULONG ulAddend,
__outt __deref_out_range(==,ulAugend + ulAddend) ULONG* pulResult)
{
HRESULT hr;
if ((ulAugend + ulAddend) >= ulAugend)
{
*pulResult = (ulAugend + ulAddend);
hr = S_OK;
}
else
{
*pulResult = ULONG_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// ULONG_PTR addition
//
#ifdef _WIN64
#define ULongPtrAdd ULongLongAdd
#else
__inline
HRESULT
ULongPtrAdd(
__inn ULONG_PTR ulAugend,
__inn ULONG_PTR ulAddend,
__outt __deref_out_range(==,ulAugend + ulAddend) ULONG_PTR* pulResult)
{
HRESULT hr;
if ((ulAugend + ulAddend) >= ulAugend)
{
*pulResult = (ulAugend + ulAddend);
hr = S_OK;
}
else
{
*pulResult = ULONG_PTR_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
#endif // _WIN64
//
// DWORD addition
//
#define DWordAdd ULongAdd
//
// DWORD_PTR addition
//
#ifdef _WIN64
#define DWordPtrAdd ULongLongAdd
#else
__inline
HRESULT
DWordPtrAdd(
__inn DWORD_PTR dwAugend,
__inn DWORD_PTR dwAddend,
__outt __deref_out_range(==,dwAugend + dwAddend) DWORD_PTR* pdwResult)
{
HRESULT hr;
if ((dwAugend + dwAddend) >= dwAugend)
{
*pdwResult = (dwAugend + dwAddend);
hr = S_OK;
}
else
{
*pdwResult = DWORD_PTR_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
#endif // _WIN64
//
// size_t addition
//
__inline
HRESULT
SizeTAdd(
__inn size_t Augend,
__inn size_t Addend,
__outt __deref_out_range(==,Augend + Addend) size_t* pResult)
{
HRESULT hr;
if ((Augend + Addend) >= Augend)
{
*pResult = (Augend + Addend);
hr = S_OK;
}
else
{
*pResult = SIZE_T_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// SIZE_T addition
//
#ifdef _WIN64
#define SIZETAdd ULongLongAdd
#else
__inline
HRESULT
SIZETAdd(
__inn SIZE_T Augend,
__inn SIZE_T Addend,
__outt __deref_out_range(==,Augend + Addend) SIZE_T* pResult)
{
HRESULT hr;
if ((Augend + Addend) >= Augend)
{
*pResult = (Augend + Addend);
hr = S_OK;
}
else
{
*pResult = _SIZE_T_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
#endif // _WIN64
//
// ULONGLONG addition
//
__inline
HRESULT
ULongLongAdd(
__inn ULONGLONG ullAugend,
__inn ULONGLONG ullAddend,
__outt __deref_out_range(==,ullAugend + ullAddend) ULONGLONG* pullResult)
{
HRESULT hr;
if ((ullAugend + ullAddend) >= ullAugend)
{
*pullResult = (ullAugend + ullAddend);
hr = S_OK;
}
else
{
*pullResult = ULONGLONG_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// DWORDLONG addition
//
#define DWordLongAdd ULongLongAdd
//
// ULONG64 addition
//
#define ULong64Add ULongLongAdd
//
// DWORD64 addition
//
#define DWord64Add ULongLongAdd
//
// UINT64 addition
//
#define UInt64Add ULongLongAdd
//=============================================================================
// Subtraction functions
//=============================================================================
//
// UINT8 subtraction
//
__inline
HRESULT
UInt8Sub(
__inn UINT8 u8Minuend,
__inn UINT8 u8Subtrahend,
__outt __deref_out_range(==,u8Minuend - u8Subtrahend) UINT8* pu8Result)
{
HRESULT hr;
if (u8Minuend >= u8Subtrahend)
{
*pu8Result = (UINT8)(u8Minuend - u8Subtrahend);
hr = S_OK;
}
else
{
*pu8Result = UINT8_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// USHORT subtraction
//
__inline
HRESULT
UShortSub(
__inn USHORT usMinuend,
__inn USHORT usSubtrahend,
__outt __deref_out_range(==,usMinuend - usSubtrahend) USHORT* pusResult)
{
HRESULT hr;
if (usMinuend >= usSubtrahend)
{
*pusResult = (USHORT)(usMinuend - usSubtrahend);
hr = S_OK;
}
else
{
*pusResult = USHORT_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// UINT16 subtraction
//
#define UInt16Sub UShortSub
//
// WORD subtraction
//
#define WordSub UShortSub
//
// UINT subtraction
//
__inline
HRESULT
UIntSub(
__inn UINT uMinuend,
__inn UINT uSubtrahend,
__outt __deref_out_range(==,uMinuend - uSubtrahend) UINT* puResult)
{
HRESULT hr;
if (uMinuend >= uSubtrahend)
{
*puResult = (uMinuend - uSubtrahend);
hr = S_OK;
}
else
{
*puResult = UINT_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// UINT32 subtraction
//
#define UInt32Sub UIntSub
//
// UINT_PTR subtraction
//
#ifdef _WIN64
#define UIntPtrSub ULongLongSub
#else
__inline
HRESULT
UIntPtrSub(
__inn UINT_PTR uMinuend,
__inn UINT_PTR uSubtrahend,
__outt __deref_out_range(==,uMinuend - uSubtrahend) UINT_PTR* puResult)
{
HRESULT hr;
if (uMinuend >= uSubtrahend)
{
*puResult = (uMinuend - uSubtrahend);
hr = S_OK;
}
else
{
*puResult = UINT_PTR_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
#endif // _WIN64
//
// ULONG subtraction
//
__inline
HRESULT
ULongSub(
__inn ULONG ulMinuend,
__inn ULONG ulSubtrahend,
__outt __deref_out_range(==,ulMinuend - ulSubtrahend) ULONG* pulResult)
{
HRESULT hr;
if (ulMinuend >= ulSubtrahend)
{
*pulResult = (ulMinuend - ulSubtrahend);
hr = S_OK;
}
else
{
*pulResult = ULONG_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// ULONG_PTR subtraction
//
#ifdef _WIN64
#define ULongPtrSub ULongLongSub
#else
__inline
HRESULT
ULongPtrSub(
__inn ULONG_PTR ulMinuend,
__inn ULONG_PTR ulSubtrahend,
__outt __deref_out_range(==,ulMinuend - ulSubtrahend) ULONG_PTR* pulResult)
{
HRESULT hr;
if (ulMinuend >= ulSubtrahend)
{
*pulResult = (ulMinuend - ulSubtrahend);
hr = S_OK;
}
else
{
*pulResult = ULONG_PTR_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
#endif // _WIN64
//
// DWORD subtraction
//
#define DWordSub ULongSub
//
// DWORD_PTR subtraction
//
#ifdef _WIN64
#define DWordPtrSub ULongLongSub
#else
__inline
HRESULT
DWordPtrSub(
__inn DWORD_PTR dwMinuend,
__inn DWORD_PTR dwSubtrahend,
__outt __deref_out_range(==,dwMinuend - dwSubtrahend) DWORD_PTR* pdwResult)
{
HRESULT hr;
if (dwMinuend >= dwSubtrahend)
{
*pdwResult = (dwMinuend - dwSubtrahend);
hr = S_OK;
}
else
{
*pdwResult = DWORD_PTR_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
#endif // _WIN64
//
// size_t subtraction
//
__inline
HRESULT
SizeTSub(
__inn size_t Minuend,
__inn size_t Subtrahend,
__outt __deref_out_range(==,Minuend - Subtrahend) size_t* pResult)
{
HRESULT hr;
if (Minuend >= Subtrahend)
{
*pResult = (Minuend - Subtrahend);
hr = S_OK;
}
else
{
*pResult = SIZE_T_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// SIZE_T subtraction
//
#ifdef _WIN64
#define SIZETSub ULongLongSub
#else
__inline
HRESULT
SIZETSub(
__inn SIZE_T Minuend,
__inn SIZE_T Subtrahend,
__outt __deref_out_range(==,Minuend - Subtrahend) SIZE_T* pResult)
{
HRESULT hr;
if (Minuend >= Subtrahend)
{
*pResult = (Minuend - Subtrahend);
hr = S_OK;
}
else
{
*pResult = _SIZE_T_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
#endif // _WIN64
//
// ULONGLONG subtraction
//
__inline
HRESULT
ULongLongSub(
__inn ULONGLONG ullMinuend,
__inn ULONGLONG ullSubtrahend,
__outt __deref_out_range(==,ullMinuend - ullSubtrahend) ULONGLONG* pullResult)
{
HRESULT hr;
if (ullMinuend >= ullSubtrahend)
{
*pullResult = (ullMinuend - ullSubtrahend);
hr = S_OK;
}
else
{
*pullResult = ULONGLONG_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
return hr;
}
//
// DWORDLONG subtraction
//
#define DWordLongSub ULongLongSub
//
// ULONG64 subtraction
//
#define ULong64Sub ULongLongSub
//
// DWORD64 subtraction
//
#define DWord64Sub ULongLongSub
//
// UINT64 subtraction
//
#define UInt64Sub ULongLongSub
//=============================================================================
// Multiplication functions
//=============================================================================
//
// UINT8 multiplication
//
__inline
HRESULT
UInt8Mult(
__inn UINT8 u8Multiplicand,
__inn UINT8 u8Multiplier,
__outt __deref_out_range(==,u8Multiplier * u8Multiplicand) UINT8* pu8Result)
{
UINT uResult = ((UINT)u8Multiplicand) * ((UINT)u8Multiplier);
return UIntToUInt8(uResult, pu8Result);
}
//
// USHORT multiplication
//
__inline
HRESULT
UShortMult(
__inn USHORT usMultiplicand,
__inn USHORT usMultiplier,
__outt __deref_out_range(==,usMultiplier * usMultiplicand)USHORT* pusResult)
{
ULONG ulResult = ((ULONG)usMultiplicand) * ((ULONG)usMultiplier);
return ULongToUShort(ulResult, pusResult);
}
//
// UINT16 multiplication
//
#define UInt16Mult UShortMult
//
// WORD multiplication
//
#define WordMult UShortMult
//
// UINT multiplication
//
__inline
HRESULT
UIntMult(
__inn UINT uMultiplicand,
__inn UINT uMultiplier,
__outt __deref_out_range(==,uMultiplier * uMultiplicand) UINT* puResult)
{
ULONGLONG ull64Result = UInt32x32To64(uMultiplicand, uMultiplier);
return ULongLongToUInt(ull64Result, puResult);
}
//
// UINT32 multiplication
//
#define UInt32Mult UIntMult
//
// UINT_PTR multiplication
//
#ifdef _WIN64
#define UIntPtrMult ULongLongMult
#else
__inline
HRESULT
UIntPtrMult(
__inn UINT_PTR uMultiplicand,
__inn UINT_PTR uMultiplier,
__outt __deref_out_range(==,uMultiplier * uMultiplicand) UINT_PTR* puResult)
{
ULONGLONG ull64Result = UInt32x32To64(uMultiplicand, uMultiplier);
return ULongLongToUIntPtr(ull64Result, puResult);
}
#endif // _WIN64
//
// ULONG multiplication
//
__inline
HRESULT
ULongMult(
__inn ULONG ulMultiplicand,
__inn ULONG ulMultiplier,
__outt __deref_out_range(==,ulMultiplier * ulMultiplicand) ULONG* pulResult)
{
ULONGLONG ull64Result = UInt32x32To64(ulMultiplicand, ulMultiplier);
return ULongLongToULong(ull64Result, pulResult);
}
//
// ULONG_PTR multiplication
//
#ifdef _WIN64
#define ULongPtrMult ULongLongMult
#else
__inline
HRESULT
ULongPtrMult(
__inn ULONG_PTR ulMultiplicand,
__inn ULONG_PTR ulMultiplier,
__outt __deref_out_range(==,ulMultiplier * ulMultiplicand) ULONG_PTR* pulResult)
{
ULONGLONG ull64Result = UInt32x32To64(ulMultiplicand, ulMultiplier);
return ULongLongToULongPtr(ull64Result, (unsigned long *)pulResult);
}
#endif // _WIN64
//
// DWORD multiplication
//
#define DWordMult ULongMult
//
// DWORD_PTR multiplication
//
#ifdef _WIN64
#define DWordPtrMult ULongLongMult
#else
__inline
HRESULT
DWordPtrMult(
__inn DWORD_PTR dwMultiplicand,
__inn DWORD_PTR dwMultiplier,
__outt __deref_out_range(==,dwMultiplier * dwMultiplicand) DWORD_PTR* pdwResult)
{
ULONGLONG ull64Result = UInt32x32To64(dwMultiplicand, dwMultiplier);
return ULongLongToDWordPtr(ull64Result, (unsigned long *)pdwResult);
}
#endif // _WIN64
//
// size_t multiplication
//
#ifdef _WIN64
#define SizeTMult ULongLongMult
#else
__inline
HRESULT
SizeTMult(
__inn size_t Multiplicand,
__inn size_t Multiplier,
__outt __deref_out_range(==,Multiplier * Multiplicand) UINT* pResult)
{
ULONGLONG ull64Result = UInt32x32To64(Multiplicand, Multiplier);
return ULongLongToSizeT(ull64Result, pResult);
}
#endif // _WIN64
//
// SIZE_T multiplication
//
#ifdef _WIN64
#define SIZETMult ULongLongMult
#else
__inline
HRESULT
SIZETMult(
__inn SIZE_T Multiplicand,
__inn SIZE_T Multiplier,
__outt __deref_out_range(==,Multiplier * Multiplicand) SIZE_T* pResult)
{
ULONGLONG ull64Result = UInt32x32To64(Multiplicand, Multiplier);
return ULongLongToSIZET(ull64Result, (unsigned long *)pResult);
}
#endif // _WIN64
//
// ULONGLONG multiplication
//
__inline
HRESULT
ULongLongMult(
__inn ULONGLONG ullMultiplicand,
__inn ULONGLONG ullMultiplier,
__outt __deref_out_range(==,ullMultiplier * ullMultiplicand) ULONGLONG* pullResult)
{
HRESULT hr;
#ifdef _AMD64_
ULONGLONG u64ResultHigh;
ULONGLONG u64ResultLow;
u64ResultLow = UnsignedMultiply128(ullMultiplicand, ullMultiplier, &u64ResultHigh);
if (u64ResultHigh == 0)
{
*pullResult = u64ResultLow;
hr = S_OK;
}
else
{
*pullResult = ULONGLONG_ERROR;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
}
#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;
hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
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 & 0xffffffff00000000LL) == 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 & 0xffffffff00000000LL) == 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;
}
}
}
}
}
}
if (FAILED(hr))
{
*pullResult = ULONGLONG_ERROR;
}
#endif // _AMD64_
return hr;
}
//
// DWORDLONG multiplication
//
#define DWordLongMult ULongLongMult
//
// ULONG64 multiplication
//
#define ULong64Mult ULongLongMult
//
// DWORD64 multiplication
//
#define DWord64Mult ULongLongMult
//
// UINT64 multiplication
//
#define UInt64Mult ULongLongMult
//
// Macros that are no longer used in this header but which clients may
// depend on being defined here.
//
#define LOWORD(_dw) ((WORD)(((DWORD_PTR)(_dw)) & 0xffff))
#define HIWORD(_dw) ((WORD)((((DWORD_PTR)(_dw)) >> 16) & 0xffff))
#define LODWORD(_qw) ((DWORD)(_qw))
#define HIDWORD(_qw) ((DWORD)(((_qw) >> 32) & 0xffffffff))
#endif // XPLAT_INTSAFE_H

View file

@ -0,0 +1,878 @@
//---------------------------------------------------------------------------------------------------------------------------------
// File: Localization.hpp
//
// Contents: Contains portable classes for localization
//
// Microsoft Drivers 4.0 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the ""Software""),
// to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and / or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions :
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//---------------------------------------------------------------------------------------------------------------------------------
#ifndef __LOCALIZATION_HPP__
#define __LOCALIZATION_HPP__
#include <time.h>
#include <assert.h>
#include "typedefs_for_linux.h"
#ifdef MPLAT_UNIX
namespace std
{
// Forward reference
class locale;
}
#endif
#define CP_UTF8 65001
#define CP_UTF16 1200
#define CP_UTF32 12000
#define CP_ACP 0 // default to ANSI code page
// This class provides allocation policies for the SystemLocale and AutoArray classes.
// This is primarily needed for the self-allocating ToUtf16/FromUtf16 methods.
// SNI needs all its allocations to use its own allocator so it would create a separate
// class that obeys this interface and provide it as a template parameter.
template< typename ArrayT >
struct ArrayTAllocator
{
static ArrayT * Alloc( size_t cch )
{
return reinterpret_cast< ArrayT * >( malloc(cch*sizeof(ArrayT)) );
}
// Realloc will free the 'old' memory if new memory was successfully allocated
// and copied to.
static ArrayT * Realloc( ArrayT * old, size_t cchNewSize )
{
return reinterpret_cast< ArrayT * >( realloc(old, cchNewSize*sizeof(ArrayT)) );
}
static void Free( ArrayT * mem )
{
free( mem );
}
};
// This is an auto_ptr-like class that is used with the SystemLocale.
// It allows for automatic freeing of the memory using the allocator policy.
// Callers would not normally use this class directly but would use one of the
// two specializations: AutoCharArray AutoWCharArray.
template< typename ArrayT, typename AllocT = ArrayTAllocator< ArrayT > >
struct AutoArray
{
size_t m_cchSize;
ArrayT * m_ptr;
AutoArray( const AutoArray & );
AutoArray & operator=( const AutoArray & );
AutoArray()
: m_cchSize( 0 ), m_ptr( NULL )
{
}
explicit AutoArray( size_t cchSize )
: m_cchSize( cchSize ), m_ptr( AllocT::Alloc(cchSize) )
{
}
virtual ~AutoArray()
{
Free();
}
void Free()
{
if ( NULL != m_ptr )
{
AllocT::Free( m_ptr );
m_ptr = NULL;
m_cchSize = 0;
}
}
bool Realloc( size_t cchSize )
{
ArrayT * newPtr = AllocT::Realloc( m_ptr, cchSize );
if ( NULL != newPtr )
{
// Safe to overwrite since Realloc freed m_ptr.
m_ptr = newPtr;
m_cchSize = cchSize;
return true;
}
return false;
}
ArrayT * Detach()
{
ArrayT * oldPtr = m_ptr;
m_ptr = NULL;
m_cchSize = 0;
return oldPtr;
}
void UpdateSize()
{
if ( NULL == m_ptr )
{
m_cchSize = 0;
}
else
{
// XPLAT_ODBC_TODO VSTS 819733 MPlat: Reconcile std c++ usage between platforms
// Should use char_traits<ArrayT>::length
ArrayT * end = m_ptr;
while ( (ArrayT)0 != *end++ )
;
// Want the null terminator included
m_cchSize = end - m_ptr;
}
}
};
class SystemLocale
{
public:
// -----------------------------------------------------------------------
// Public Static Functions
#ifdef MPLAT_UNIX
static const SystemLocale & Singleton();
#else
// Windows returns by value since this is an empty class
static const SystemLocale Singleton();
#endif
#ifdef MPLAT_UNIX
int GetResourcePath( char * buffer, size_t cchBuffer ) const;
static const int MINS_PER_HOUR = 60;
static const int MINS_PER_DAY = 24 * MINS_PER_HOUR;
// Returns the bias between the supplied utc and local times.
// utc = local + bias
static int BiasInMinutes( const struct tm & utc, const struct tm & local )
{
int bias = 0;
if ( utc.tm_mon != local.tm_mon )
{
// Offset crosses month boundary so one of two must be first day of month
if ( 1 == utc.tm_mday )
bias += MINS_PER_DAY;
else
{
assert( 1 == local.tm_mday );
bias -= MINS_PER_DAY;
}
}
else
{
bias += MINS_PER_DAY * (utc.tm_mday - local.tm_mday);
}
bias += MINS_PER_HOUR * (utc.tm_hour - local.tm_hour);
bias += (utc.tm_min - local.tm_min);
// Round based on diff in secs, in case utc/local straddle a day with leap seconds
int secs_diff = (utc.tm_sec - local.tm_sec);
if ( 29 < secs_diff )
++bias;
else if ( secs_diff < -29 )
--bias;
return bias;
}
// Returns both standard and daylight savings biases for the current year
// utc = local + bias
// Both might be equal if DST is not honored
// If platform doesn't know if bias is DST or standard (ie. unknown)
// then standard time is assumed.
// Note that applying current year's biases to dates from other years may result
// in incorrect time adjustments since regions change their rules over time.
// The current SNAC driver code uses this approach as well so we are doing this
// to preserve consistent behavior. If SNAC changes to lookup the offsets that
// were effective for a given date then we should update our logic here as well.
static DWORD TimeZoneBiases( int * stdInMinutes, int * dstInMinutes )
{
struct tm local, utc;
// Find current year
time_t now = time( NULL );
if ( (time_t)(-1) == now || NULL == localtime_r(&now, &local) )
return ERROR_INVALID_DATA;
// Find bias for first of each month until both STD and DST are found
// Possible perf improvements (can wait until perf tests indicate a need):
// Just use Dec 21 and Jun 21 (near the two soltices)
// Or calc once and cache (must be thread safe)
bool foundUNK = false;
bool foundSTD = false;
bool foundDST = false;
int std_bias = 0;
int dst_bias = 0;
local.tm_mday = 1;
for ( int mon = 0; mon < 12; ++mon )
{
local.tm_mon = mon;
if ( (time_t)(-1) == (now = mktime(&local)) || NULL == gmtime_r(&now, &utc) )
return ERROR_INVALID_DATA;
if ( 0 < local.tm_isdst )
{
if ( !foundDST )
{
dst_bias = BiasInMinutes( utc, local );
foundDST = true;
if ( foundSTD )
break; // Done checking when both STD & DST are found
}
}
else
{
// Time is STD or unknown, put in STD
if ( !foundSTD )
{
std_bias = BiasInMinutes( utc, local );
if ( local.tm_isdst < 0 )
foundUNK = true;
else
{
foundSTD = true;
if ( foundDST )
break; // Done checking when both STD and DST are found
}
}
}
}
// At least one of STD, DST, or unknown must have been set
assert( foundSTD || foundDST || foundUNK );
// For zones that don't observe DST (somewhat common),
// report DST bias as the same as STD
if ( !foundDST )
dst_bias = std_bias;
// For zones that ONLY observe DST (extremely rare if at all),
// report STD bias as the same as DST
if ( !foundSTD && !foundUNK )
std_bias = dst_bias;
*stdInMinutes = std_bias;
*dstInMinutes = dst_bias;
return ERROR_SUCCESS;
}
#endif
static DWORD CurrentLocalTime( LPSYSTEMTIME pTime );
// Multi-byte UTF8 code points start with '11xx xxxx'
static bool IsUtf8LeadByte( BYTE utf8 )
{
return (0xC0 == (utf8 & 0xC0));
}
// Maximum number of storage units (char or WCHAR)
// for a code page (e.g. UTF16 == 2 for surrogates)
static UINT MaxCharCchSize( UINT codepage );
// Inspects the byte at start, and returns the start
// of the next code point (possibly multiple bytes later).
// If NULL or start points at null terminator, than start is returned.
// If start points at a dangling UTF8 trail byte, then (start+1) is
// returned since we can't know how large this code point is.
static char * NextChar( UINT codepage, const char * start );
#ifdef MPLAT_UNIX
// This version is for non-null terminated strings.
// Last ptr will be one past end of buffer.
static char * NextChar( UINT codepage, const char * start, size_t cchBytesLeft );
#endif
// Given the start byte, how many total bytes are expected for
// this code point. If start is a UTF8 trail byte, then 1 is returned.
static UINT CchExpectedNextChar( UINT codepage, BYTE start )
{
if ( 0 == (start & (char)0x80) )
return 1; // ASCII
else if ( CP_UTF8 == codepage )
return IsUtf8LeadByte(start) ? CchUtf8CodePt(start) : 1;
else if ( IsDBCSLeadByteEx(codepage, start) )
return 2;
else
return 1;
}
// Returns the number of bytes that need to be trimmed to avoid splitting
// a multi-byte code point sequence at the end of the buffer.
// Returns zero if a trailing UTF8 code value is found but no
// matching lead byte was found for it (ie. invalid, dangling trail byte).
_Ret_range_(0, cchBuffer) static UINT TrimPartialCodePt( UINT codepage, _In_count_(cchBuffer) const BYTE * buffer, size_t cchBuffer )
{
if ( 0 == cchBuffer )
return 0;
if ( CP_UTF8 == codepage )
{
return TrimPartialUtf8CodePt( buffer, cchBuffer );
}
else
{
size_t i = cchBuffer;
for ( ; 0 < i; --i )
{
if ( !IsDBCSLeadByteEx( codepage, buffer[i-1] ) )
break;
}
// If odd, then last byte is truly a lead byte so return 1 byte to trim
return ((cchBuffer-i) & 1) ? 1 : 0;
}
}
// For all transcoding functions
// Returns zero on error. Do not call GetLastError() since that is not portable (pErrorCode has result of GetLastError()).
// pHasDataLoss will be true if an unrecognized code point was encountered in the source and a default output instead.
// Replaces calls to MultiByteToWideChar and WideCharToMultiByte
// Transcode between a code page and UTF16
static size_t ToUtf16( UINT srcCodePage, const char * src, SSIZE_T cchSrc,
__out_ecount_opt(cchDest) WCHAR * dest, size_t cchDest,
DWORD * pErrorCode = NULL );
static size_t ToUtf16Strict( UINT srcCodePage, const char * src, SSIZE_T cchSrc,
__out_ecount_opt(cchDest) WCHAR * dest, size_t cchDest,
DWORD * pErrorCode = NULL );
static size_t FromUtf16( UINT destCodePage, const WCHAR * src, SSIZE_T cchSrc,
__out_ecount_opt(cchDest) char * dest, size_t cchDest,
bool * pHasDataLoss = NULL, DWORD * pErrorCode = NULL );
static size_t FromUtf16Strict(UINT destCodePage, const WCHAR * src, SSIZE_T cchSrc,
__out_ecount_opt(cchDest) char * dest, size_t cchDest,
bool * pHasDataLoss = NULL, DWORD * pErrorCode = NULL);
// Allocates destination buffer to match required size
// Template is used so call can provide allocation policy
// Used instead of the Windows API pattern of calling with zero dest buffer size to find
// required buffer size, followed by second call with newly allocated buffer.
template< typename AllocT >
static size_t ToUtf16( UINT srcCodePage, const char * src, SSIZE_T cchSrc, __deref_out_ecount(1) WCHAR ** dest, DWORD * pErrorCode = NULL );
template< typename AllocT >
static size_t ToUtf16Strict( UINT srcCodePage, const char * src, SSIZE_T cchSrc, __deref_out_ecount(1) WCHAR ** dest, DWORD * pErrorCode = NULL );
template< typename AllocT >
static size_t FromUtf16( UINT destCodePage, const WCHAR * src, SSIZE_T cchSrc, __deref_out_ecount(1) char ** dest, bool * pHasDataLoss = NULL, DWORD * pErrorCode = NULL );
template< typename AllocT >
static size_t FromUtf16Strict(UINT destCodePage, const WCHAR * src, SSIZE_T cchSrc, __deref_out_ecount(1) char ** dest, bool * pHasDataLoss = NULL, DWORD * pErrorCode = NULL);
// -----------------------------------------------------------------------
// Public Member Functions
#ifndef TIME_ZONE_ID_UNKNOWN
#define TIME_ZONE_ID_UNKNOWN 0
#define TIME_ZONE_ID_STANDARD 1
#define TIME_ZONE_ID_DAYLIGHT 2
#endif
// pTZInfo, if supplied, holds one of the above defined values
DWORD CurrentTimeZoneBias( LONG * offsetInMinutes, DWORD * pTZInfo = NULL ) const;
// The Ansi code page, always UTF8 for Linux
UINT AnsiCP() const;
// Used for files (e.g. returns 437 on US Windows, UTF8 for Linux)
UINT OemCP() const;
// Returns UTF-16LE for all platforms (LE == Little Endian)
UINT WideCP() const
{
return CP_UTF16;
}
// Performs case folding to lower case using the current system locale
// Replaces calls to LCMapStringA
size_t ToLower( const char * src, SSIZE_T cchSrc, __out_ecount_opt(cchDest) char * dest, size_t cchDest, DWORD * pErrorCode = NULL ) const;
#ifndef CSTR_ERROR
#define CSTR_ERROR 0 // compare failed
#define CSTR_LESS_THAN 1 // string 1 less than string 2
#define CSTR_EQUAL 2 // string 1 equal to string 2
#define CSTR_GREATER_THAN 3 // string 1 greater than string 2
#endif
// String comparison using the rules of the current system locale.
// Replaces calls to CompareString
// Ignoring width (Bing for "Full Width Characters") has no affect on Linux
// Return value is one of the above defined values.
// On error, pErrorCode has result of GetLastError() (do not call GetLastError directly since it isn't portable).
int Compare( const char * left, SSIZE_T cchLeft, const char * right, SSIZE_T cchRight, DWORD * pErrorCode = NULL ) const;
int CompareIgnoreCase( const char * left, SSIZE_T cchLeft, const char * right, SSIZE_T cchRight, DWORD * pErrorCode = NULL ) const;
int CompareIgnoreWidth( const char * left, SSIZE_T cchLeft, const char * right, SSIZE_T cchRight, DWORD * pErrorCode = NULL ) const;
int CompareIgnoreCaseAndWidth( const char * left, SSIZE_T cchLeft, const char * right, SSIZE_T cchRight, DWORD * pErrorCode = NULL ) const;
private:
// Prevent copying.
// Also prevents misuse of return from Singleton() method.
// Since return types are different on Windows vs Linux,
// callers should not cache the result of Singleton().
SystemLocale( const SystemLocale & );
SystemLocale & operator=( const SystemLocale & );
#ifdef MPLAT_UNIX
// MPLAT_UNIX ----------------------------------------------------------------
std::locale * m_pLocale;
explicit SystemLocale( const char * localeName );
~SystemLocale();
static UINT ExpandSpecialCP( UINT codepage )
{
// Convert CP_ACP, CP_OEM to CP_UTF8
return (codepage < 2 ? CP_UTF8 : codepage);
}
// MPLAT_UNIX ----------------------------------------------------------------
#else
// !MPLAT_UNIX ---------------------------------------------------------------
SystemLocale() {}
static size_t ReturnCchResult( SSIZE_T cch, DWORD * pErrorCode )
{
if ( cch < 0 )
{
cch = 0;
}
if ( NULL != pErrorCode )
{
*pErrorCode = (0 == cch ? GetLastError() : ERROR_SUCCESS);
}
return static_cast<size_t>(cch);
}
static int CompareWithFlags( DWORD flags, const char * left, SSIZE_T cchLeft, const char * right, SSIZE_T cchRight, DWORD * pErrorCode = NULL );
static size_t FastAsciiMultiByteToWideChar
(
UINT CodePage,
__in_ecount(cch) const char *pch, // IN | source string
SSIZE_T cch, // IN | count of characters or -1
__out_ecount_opt(cwch) PWCHAR pwch, // IN | Result string
size_t cwch, // IN | count of wchars of result buffer or 0
DWORD* pErrorCode, // OUT | optional pointer to return error code
bool bStrict = false // IN | Return error if invalid chars in src
);
static size_t FastAsciiWideCharToMultiByte
(
UINT CodePage,
const WCHAR *pwch, // IN | source string
SSIZE_T cwch, // IN | count of characters or -1
__out_bcount(cch) char *pch, // IN | Result string
size_t cch, // IN | Length of result buffer or 0
BOOL *pfDataLoss, // OUT | True if there was data loss during CP conversion
DWORD *pErrorCode // OUT | optional pointer to return error code
);
// !MPLAT_UNIX ---------------------------------------------------------------
#endif
// Returns the number of bytes this UTF8 code point expects
static UINT CchUtf8CodePt( BYTE codept )
{
assert( IsUtf8LeadByte(codept) );
// Initial byte of utf8 sequence indicates its length
// 110x xxxx = 2 bytes
// 1110 xxxx = 3 bytes
// 1111 0xxx = 4 bytes
// 1111 10xx = 5 bytes, future Unicode extension not covered by this logic
// 1111 110x = 6 bytes, future Unicode extension not covered by this logic
UINT expected_size = (0xC0 == (codept & 0xE0)) ? 2 : (0xE0 == (codept & 0xF0)) ? 3 : 4;
// Verify constraints
assert( 4 == MaxCharCchSize(CP_UTF8) );
return expected_size;
}
// Returns the number of bytes that need to be trimmed to avoid splitting
// a UTF8 code point sequence at the end of the buffer.
// Returns zero for ASCII.
// Also returns zero if a trailing UTF8 code value is found but no
// matching lead byte was found for it (ie. invalid, dangling trail byte).
static UINT TrimPartialUtf8CodePt( const BYTE * buffer, size_t cchBuffer )
{
if ( 0 == cchBuffer )
return 0;
if ( 0 == (buffer[cchBuffer-1] & 0x80) )
{
// Last char is ASCII so no trim needed
return 0;
}
// Last char is non-initial byte of multibyte utf8 sequence
// Need to determine if it is the last (ie. no trim need)
UINT cchMax = MaxCharCchSize( CP_UTF8 );
for ( UINT i = 1; 0 < cchBuffer && i <= cchMax; --cchBuffer, ++i )
{
if ( IsUtf8LeadByte(buffer[cchBuffer-1]) )
{
// Found initial byte, verify size of sequence
UINT cchExpected = CchUtf8CodePt( buffer[cchBuffer-1] );
if ( i == cchExpected )
return 0; // utf8 sequence is complete so no trim needed
else
{
assert( i <= cchBuffer );
return i; // trim the incomplete sequence
}
}
}
// Did not find initial utf8 byte so trim nothing
return 0;
}
};
// Convenience wrapper for converting from UTF16 into a newly
// allocated char[]. Class behaves like auto_ptr (will free in dtor,
// but has Release method so caller can take ownership of memory).
template< typename AllocT = ArrayTAllocator< char > >
struct AutoCharArray : public AutoArray< char, AllocT >
{
size_t AllocConvertFromUtf16( UINT destCodePage, const WCHAR * src, SSIZE_T cchSrc, bool * pHasDataLoss = NULL, DWORD * pErrorCode = NULL )
{
char * converted = NULL;
size_t cchCvt = SystemLocale::FromUtf16< AllocT >( destCodePage, src, cchSrc, &converted, pHasDataLoss, pErrorCode );
if ( 0 < cchCvt )
{
this->Free();
this->m_ptr = converted;
this->m_cchSize = cchCvt;
}
return cchCvt;
}
};
// Convenience wrapper for converting to UTF16 into a newly
// allocated WCHAR[]. Class behaves like auto_ptr (will free in dtor,
// but has Release method so caller can take ownership of memory).
template< typename AllocT = ArrayTAllocator< WCHAR > >
struct AutoWCharArray : public AutoArray< WCHAR, AllocT >
{
size_t AllocConvertToUtf16( UINT destCodePage, const char * src, SSIZE_T cchSrc, bool * pHasDataLoss = NULL, DWORD * pErrorCode = NULL )
{
WCHAR * converted = NULL;
size_t cchCvt = SystemLocale::ToUtf16< AllocT >( destCodePage, src, cchSrc, &converted, pErrorCode );
if ( 0 < cchCvt )
{
this->Free();
this->m_ptr = converted;
this->m_cchSize = cchCvt;
}
return cchCvt;
}
};
// ---------------------------------------------------------------------------
// Inlines that vary by platform
#if defined(MPLAT_UNIX)
// MPLAT_UNIX ----------------------------------------------------------------
#include "globalization.h"
inline UINT SystemLocale::AnsiCP() const
{
return CP_UTF8;
}
inline UINT SystemLocale::OemCP() const
{
return CP_UTF8;
}
inline UINT SystemLocale::MaxCharCchSize( UINT codepage )
{
codepage = ExpandSpecialCP( codepage );
switch ( codepage )
{
case CP_UTF8:
return 4;
case 932:
case 936:
case 949:
case 950:
case CP_UTF16:
return 2;
default:
return 1;
}
}
inline int SystemLocale::CompareIgnoreWidth( const char * left, SSIZE_T cchLeft, const char * right, SSIZE_T cchRight, DWORD * pErrorCode ) const
{
// XPLAT_ODBC_TODO: VSTS 806013 MPLAT: Support IgnoreWidth for SNI string comparisons
return Compare( left, cchLeft, right, cchRight, pErrorCode );
}
inline int SystemLocale::CompareIgnoreCaseAndWidth( const char * left, SSIZE_T cchLeft, const char * right, SSIZE_T cchRight, DWORD * pErrorCode ) const
{
// XPLAT_ODBC_TODO: VSTS 806013 MPLAT: Support IgnoreWidth for SNI string comparisons
return CompareIgnoreCase( left, cchLeft, right, cchRight, pErrorCode );
}
template< typename AllocT >
inline size_t SystemLocale::ToUtf16( UINT srcCodePage, const char * src, SSIZE_T cchSrc, WCHAR ** dest, DWORD * pErrorCode )
{
srcCodePage = ExpandSpecialCP( srcCodePage );
EncodingConverter cvt( CP_UTF16, srcCodePage );
if ( !cvt.Initialize() )
{
if ( NULL != pErrorCode )
*pErrorCode = ERROR_INVALID_PARAMETER;
return 0;
}
size_t cchSrcActual = (cchSrc < 0 ? (1+strlen(src)) : cchSrc);
bool hasLoss;
return cvt.Convert< WCHAR, char, AllocT >( dest, src, cchSrcActual, false, &hasLoss, pErrorCode );
}
template< typename AllocT >
inline size_t SystemLocale::ToUtf16Strict( UINT srcCodePage, const char * src, SSIZE_T cchSrc, WCHAR ** dest, DWORD * pErrorCode )
{
srcCodePage = ExpandSpecialCP( srcCodePage );
EncodingConverter cvt( CP_UTF16, srcCodePage );
if ( !cvt.Initialize() )
{
if ( NULL != pErrorCode )
*pErrorCode = ERROR_INVALID_PARAMETER;
return 0;
}
size_t cchSrcActual = (cchSrc < 0 ? (1+strlen(src)) : cchSrc);
bool hasLoss;
return cvt.Convert< WCHAR, char, AllocT >( dest, src, cchSrcActual, true, &hasLoss, pErrorCode );
}
template< typename AllocT >
inline size_t SystemLocale::FromUtf16( UINT destCodePage, const WCHAR * src, SSIZE_T cchSrc, char ** dest, bool * pHasDataLoss, DWORD * pErrorCode )
{
destCodePage = ExpandSpecialCP( destCodePage );
EncodingConverter cvt( destCodePage, CP_UTF16 );
if ( !cvt.Initialize() )
{
if ( NULL != pErrorCode )
*pErrorCode = ERROR_INVALID_PARAMETER;
return 0;
}
size_t cchSrcActual = (cchSrc < 0 ? (1+mplat_wcslen(src)) : cchSrc);
bool hasLoss;
return cvt.Convert< char, WCHAR, AllocT >( dest, src, cchSrcActual, false, &hasLoss, pErrorCode );
}
// MPLAT_UNIX ----------------------------------------------------------------
#else
// ! MPLAT_UNIX ----------------------------------------------------------------
inline const SystemLocale SystemLocale::Singleton()
{
// On Windows, Localization is an empty class so creation of this
// should be optimized away. Empty classes have a sizeof 1 so there's
// something to take the address of.
C_ASSERT( 1 == sizeof(SystemLocale) );
return SystemLocale();
}
inline DWORD SystemLocale::CurrentTimeZoneBias( LONG * offsetInMinutes, DWORD * pTZInfo ) const
{
TIME_ZONE_INFORMATION tzi;
DWORD tzInfo;
if ( NULL == offsetInMinutes )
return ERROR_INVALID_PARAMETER;
else if ( TIME_ZONE_ID_INVALID == (tzInfo = GetTimeZoneInformation(&tzi)) )
return GetLastError();
else
{
*offsetInMinutes = tzi.Bias;
if ( NULL != pTZInfo )
*pTZInfo = tzInfo;
return ERROR_SUCCESS;
}
}
inline DWORD SystemLocale::CurrentLocalTime( LPSYSTEMTIME pTime )
{
GetLocalTime( pTime );
return ERROR_SUCCESS;
}
inline UINT SystemLocale::AnsiCP() const
{
return GetACP();
}
inline UINT SystemLocale::OemCP() const
{
return GetOEMCP();
}
inline UINT SystemLocale::MaxCharCchSize( UINT codepage )
{
CPINFO cpinfo;
BOOL rc = GetCPInfo( codepage, &cpinfo );
return (rc ? cpinfo.MaxCharSize : 0);
}
inline size_t SystemLocale::ToLower( const char * src, SSIZE_T cchSrc, char * dest, size_t cchDest, DWORD * pErrorCode ) const
{
// Windows API takes 'int' sized parameters
if ( cchSrc < -1 || 0x7FFFFFF < cchSrc || 0x7FFFFFF < cchDest )
{
if ( NULL != pErrorCode )
*pErrorCode = ERROR_INVALID_PARAMETER;
return 0;
}
OACR_WARNING_PUSH
OACR_WARNING_DISABLE(SYSTEM_LOCALE_MISUSE , " INTERNATIONALIZATION BASELINE AT KATMAI RTM. FUTURE ANALYSIS INTENDED. ")
OACR_WARNING_DISABLE(ANSI_APICALL, " Keeping the ANSI API for now. ")
int cch = LCMapStringA(
LOCALE_SYSTEM_DEFAULT,
LCMAP_LOWERCASE,
src,
(int)cchSrc,
dest,
(int)cchDest );
OACR_WARNING_POP
return ReturnCchResult( cch, pErrorCode );
}
inline int SystemLocale::CompareWithFlags( DWORD flags, const char * left, SSIZE_T cchLeft, const char * right, SSIZE_T cchRight, DWORD * pErrorCode )
{
// Windows API takes 'int' sized parameters
if ( cchLeft < -1 || 0x7FFFFFF < cchLeft || cchRight < -1 || 0x7FFFFFF < cchRight )
{
if ( NULL != pErrorCode )
*pErrorCode = ERROR_INVALID_PARAMETER;
return 0;
}
OACR_WARNING_PUSH
OACR_WARNING_DISABLE(SYSTEM_LOCALE_MISUSE , " INTERNATIONALIZATION BASELINE AT KATMAI RTM. FUTURE ANALYSIS INTENDED. ")
int cmp = CompareStringA( LOCALE_SYSTEM_DEFAULT, flags, left, (int)cchLeft, right, (int)cchRight );
OACR_WARNING_POP
if ( NULL != pErrorCode )
{
*pErrorCode = (CSTR_ERROR == cmp ? GetLastError() : ERROR_SUCCESS);
}
return cmp;
}
inline int SystemLocale::Compare( const char * left, SSIZE_T cchLeft, const char * right, SSIZE_T cchRight, DWORD * pErrorCode ) const
{
return CompareWithFlags( 0, left, cchLeft, right, cchRight, pErrorCode );
}
inline int SystemLocale::CompareIgnoreCase( const char * left, SSIZE_T cchLeft, const char * right, SSIZE_T cchRight, DWORD * pErrorCode ) const
{
return CompareWithFlags( NORM_IGNORECASE, left, cchLeft, right, cchRight, pErrorCode );
}
inline int SystemLocale::CompareIgnoreCaseAndWidth( const char * left, SSIZE_T cchLeft, const char * right, SSIZE_T cchRight, DWORD * pErrorCode ) const
{
return CompareWithFlags( NORM_IGNORECASE|NORM_IGNOREWIDTH, left, cchLeft, right, cchRight, pErrorCode );
}
inline int SystemLocale::CompareIgnoreWidth( const char * left, SSIZE_T cchLeft, const char * right, SSIZE_T cchRight, DWORD * pErrorCode ) const
{
return CompareWithFlags( NORM_IGNOREWIDTH, left, cchLeft, right, cchRight, pErrorCode );
}
inline char * SystemLocale::NextChar( UINT codepage, const char * start )
{
return CharNextExA( (WORD)codepage, start, 0 );
}
inline size_t SystemLocale::ToUtf16( UINT srcCodePage, const char * src, SSIZE_T cchSrc, WCHAR * dest, size_t cchDest, DWORD * pErrorCode )
{
return FastAsciiMultiByteToWideChar( srcCodePage, src, cchSrc, dest, cchDest, pErrorCode );
}
inline size_t SystemLocale::ToUtf16Strict( UINT srcCodePage, const char * src, SSIZE_T cchSrc, WCHAR * dest, size_t cchDest, DWORD * pErrorCode )
{
return FastAsciiMultiByteToWideChar( srcCodePage, src, cchSrc, dest, cchDest, pErrorCode, true );
}
inline size_t SystemLocale::FromUtf16( UINT destCodePage, const WCHAR * src, SSIZE_T cchSrc, char * dest, size_t cchDest, bool * pHasDataLoss, DWORD * pErrorCode )
{
BOOL dataloss = FALSE;
size_t cchCvt = FastAsciiWideCharToMultiByte( destCodePage, src, cchSrc, dest, cchDest, &dataloss, pErrorCode );
if ( NULL != pHasDataLoss )
{
*pHasDataLoss = (FALSE != dataloss);
}
return cchCvt;
}
template< typename AllocT >
inline size_t SystemLocale::ToUtf16( UINT srcCodePage, const char * src, SSIZE_T cchSrc, WCHAR ** dest, DWORD * pErrorCode )
{
size_t cchCvt = FastAsciiMultiByteToWideChar( srcCodePage, src, cchSrc, NULL, 0, pErrorCode );
if ( 0 < cchCvt )
{
AutoArray< WCHAR, AllocT > newDestBuffer( cchCvt );
cchCvt = FastAsciiMultiByteToWideChar( srcCodePage, src, cchSrc, newDestBuffer.m_ptr, cchCvt, pErrorCode );
if ( 0 < cchCvt )
*dest = newDestBuffer.Detach();
}
return cchCvt;
}
template< typename AllocT >
inline size_t SystemLocale::ToUtf16Strict( UINT srcCodePage, const char * src, SSIZE_T cchSrc, WCHAR ** dest, DWORD * pErrorCode )
{
size_t cchCvt = FastAsciiMultiByteToWideChar( srcCodePage, src, cchSrc, NULL, 0, pErrorCode, true );
if ( 0 < cchCvt )
{
AutoArray< WCHAR, AllocT > newDestBuffer( cchCvt );
cchCvt = FastAsciiMultiByteToWideChar( srcCodePage, src, cchSrc, newDestBuffer.m_ptr, cchCvt, pErrorCode, true );
if ( 0 < cchCvt )
*dest = newDestBuffer.Detach();
}
return cchCvt;
}
template< typename AllocT >
inline size_t SystemLocale::FromUtf16( UINT destCodePage, const WCHAR * src, SSIZE_T cchSrc, char ** dest, bool * pHasDataLoss, DWORD * pErrorCode )
{
BOOL dataloss = FALSE;
size_t cchCvt = FastAsciiWideCharToMultiByte( destCodePage, src, cchSrc, NULL, 0, &dataloss, pErrorCode );
if ( 0 < cchCvt )
{
AutoArray< char, AllocT > newDestBuffer( cchCvt );
cchCvt = FastAsciiWideCharToMultiByte( destCodePage, src, cchSrc, newDestBuffer.m_ptr, cchCvt, &dataloss, pErrorCode );
if ( 0 < cchCvt )
*dest = newDestBuffer.Detach();
}
if ( NULL != pHasDataLoss )
{
*pHasDataLoss = (FALSE != dataloss);
}
return cchCvt;
}
// ! MPLAT_UNIX ----------------------------------------------------------------
#endif
#endif // __LOCALIZATION_HPP__

View file

@ -0,0 +1,1039 @@
//---------------------------------------------------------------------------------------------------------------------------------
// File: LocalizationImpl.hpp
//
// Contents: Contains non-inline code for the SystemLocale class
// Must be included in one c/cpp file per binary
// A build error will occur if this inclusion policy is not followed
//
// Microsoft Drivers 4.0 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the ""Software""),
// to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and / or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions :
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//---------------------------------------------------------------------------------------------------------------------------------
#include "localization.hpp"
#include "globalization.h"
#include "StringFunctions.h"
struct cp_iconv
{
UINT CodePage;
const char * IConvEncoding;
static const cp_iconv g_cp_iconv[];
static const size_t g_cp_iconv_count;
static int GetIndex( UINT codepage )
{
for ( size_t idx = 0; idx < g_cp_iconv_count; ++idx )
{
if ( g_cp_iconv[idx].CodePage == codepage )
return (int)idx;
}
// Should never be an unknown code page
assert( false );
return -1;
}
};
// Array of CodePage-to-IConvEncoding mappings
// First few elements are most commonly used
const cp_iconv cp_iconv::g_cp_iconv[] = {
{ 65001, "UTF-8" },
{ 1200, "UTF-16LE" },
{ 3, "UTF-8" },
{ 1252, "CP1252//TRANSLIT" },
{ 850, "CP850//TRANSLIT" },
{ 437, "CP437//TRANSLIT" },
{ 874, "CP874//TRANSLIT" },
{ 932, "CP932//TRANSLIT" },
{ 936, "CP936//TRANSLIT" },
{ 949, "CP949//TRANSLIT" },
{ 950, "CP950//TRANSLIT" },
{ 1250, "CP1250//TRANSLIT" },
{ 1251, "CP1251//TRANSLIT" },
{ 1253, "CP1253//TRANSLIT" },
{ 1254, "CP1254//TRANSLIT" },
{ 1255, "CP1255//TRANSLIT" },
{ 1256, "CP1256//TRANSLIT" },
{ 1257, "CP1257//TRANSLIT" },
{ 1258, "CP1258//TRANSLIT" },
{ 12000, "UTF-32LE" }
};
const size_t cp_iconv::g_cp_iconv_count = ARRAYSIZE(cp_iconv::g_cp_iconv);
#ifdef MPLAT_UNIX
class IConvCachePool
{
SLIST_HEADER m_Pool[cp_iconv::g_cp_iconv_count][cp_iconv::g_cp_iconv_count];
IConvCachePool( const IConvCachePool & );
IConvCachePool & operator=( const IConvCachePool & );
// This bool indicates that the iconv pool is no longer available.
// For the driver,lis flag indicates the pool can no longer be used.
// Global destructors will be called by a single thread so this flag does not
// need thread synch protection.
static bool s_PoolDestroyed;
IConvCachePool()
{
for ( int dstIdx = 0; dstIdx < cp_iconv::g_cp_iconv_count; ++dstIdx )
{
for ( int srcIdx = 0; srcIdx < cp_iconv::g_cp_iconv_count; ++srcIdx )
{
InitializeSListHead( &m_Pool[dstIdx][srcIdx] );
}
}
}
~IConvCachePool()
{
IConvCachePool::s_PoolDestroyed = true;
// Clean up remaining nodes
for ( int dstIdx = 0; dstIdx < cp_iconv::g_cp_iconv_count; ++dstIdx )
{
for ( int srcIdx = 0; srcIdx < cp_iconv::g_cp_iconv_count; ++srcIdx )
{
IConvCache * pNode = static_cast<IConvCache*>( InterlockedFlushSList(&m_Pool[dstIdx][srcIdx]) );
while ( NULL != pNode )
{
IConvCache * pNext = static_cast<IConvCache*>( pNode->Next );
delete pNode;
pNode = pNext;
}
}
}
}
USHORT Depth( int dstIdx, int srcIdx )
{
assert( 0 <= dstIdx && dstIdx < cp_iconv::g_cp_iconv_count );
assert( 0 <= srcIdx && srcIdx < cp_iconv::g_cp_iconv_count );
return QueryDepthSList( &m_Pool[dstIdx][srcIdx] );
}
// If this returns NULL, then caller must allocate their own iconv_t.
// It will return NULL if allocation for a new instance failed (out of memory).
const IConvCache * Borrow( int dstIdx, int srcIdx )
{
assert( 0 <= dstIdx && dstIdx < cp_iconv::g_cp_iconv_count );
assert( 0 <= srcIdx && srcIdx < cp_iconv::g_cp_iconv_count );
const IConvCache * pCache = static_cast<const IConvCache*>( InterlockedPopEntrySList(&m_Pool[dstIdx][srcIdx]) );
if ( NULL == pCache )
{
const IConvCache * pNewCache = new IConvCache( dstIdx, srcIdx );
if ( NULL != pNewCache )
{
if ( INVALID_ICONV != pNewCache->GetIConv() )
pCache = pNewCache;
else
delete pNewCache;
}
}
return pCache;
}
void Return( const IConvCache * pCache, int dstIdx, int srcIdx )
{
assert( pCache );
assert( 0 <= dstIdx && dstIdx < cp_iconv::g_cp_iconv_count );
assert( 0 <= srcIdx && srcIdx < cp_iconv::g_cp_iconv_count );
// Setting an arbitrary limit to prevent unbounded memory use by the pool.
// Want this to be large enough for a substantial number of concurrent threads.
const USHORT MAX_POOL_SIZE = 1024;
if ( INVALID_ICONV != pCache->GetIConv() && Depth(dstIdx, srcIdx) < MAX_POOL_SIZE )
{
SLIST_ENTRY * pNode = const_cast<IConvCache*>( pCache );
InterlockedPushEntrySList( &m_Pool[dstIdx][srcIdx], pNode );
}
else
{
delete pCache;
}
}
static IConvCachePool & Singleton()
{
// GCC ensures that function scoped static initializers are threadsafe
// We must not use the -fno-threadsafe-statics compiler option
#if !defined(__GNUC__) || defined(NO_THREADSAFE_STATICS)
#error "Relying on GCC's threadsafe initialization of local statics."
#endif
static IConvCachePool s_Pool;
return s_Pool;
}
public:
static const IConvCache * BorrowCache( UINT dstCP, UINT srcCP )
{
int dstIdx = cp_iconv::GetIndex(dstCP);
int srcIdx = cp_iconv::GetIndex(srcCP);
if ( -1 == dstIdx || -1 == srcIdx )
return NULL;
else if ( !s_PoolDestroyed )
return Singleton().Borrow( dstIdx, srcIdx );
else
return new IConvCache( dstIdx, srcIdx );
}
static void ReturnCache( const IConvCache * pCache, UINT dstCP, UINT srcCP )
{
int dstIdx = cp_iconv::GetIndex(dstCP);
int srcIdx = cp_iconv::GetIndex(srcCP);
if ( -1 != dstIdx && -1 != srcIdx && !s_PoolDestroyed )
Singleton().Return( pCache, dstIdx, srcIdx );
else
delete pCache;
}
static USHORT Depth( UINT dstCP, UINT srcCP )
{
if ( IConvCachePool::s_PoolDestroyed )
return 0;
else
{
int dstIdx = cp_iconv::GetIndex(dstCP);
int srcIdx = cp_iconv::GetIndex(srcCP);
if ( -1 == dstIdx || -1 == srcIdx )
return 0;
else
return Singleton().Depth( dstIdx, srcIdx );
}
}
};
bool IConvCachePool::s_PoolDestroyed = false;
#ifdef DEBUG
// This is only used by unit tests.
// Product code should directly use IConvCachePool::Depth from
// within this translation unit.
USHORT GetIConvCachePoolDepth( UINT dstCP, UINT srcCP )
{
return IConvCachePool::Depth( dstCP, srcCP );
}
#endif // DEBUG
IConvCache::IConvCache( int dstIdx, int srcIdx )
: m_iconv( iconv_open(
cp_iconv::g_cp_iconv[dstIdx].IConvEncoding,
cp_iconv::g_cp_iconv[srcIdx].IConvEncoding) )
{
}
IConvCache::~IConvCache()
{
if ( INVALID_ICONV != m_iconv )
iconv_close( m_iconv );
}
#endif // MPLAT_UNIX
EncodingConverter::EncodingConverter( UINT dstCodePage, UINT srcCodePage )
: m_dstCodePage( dstCodePage ),
m_srcCodePage( srcCodePage )
#ifdef MPLAT_UNIX
, m_pCvtCache( NULL )
#endif
{
}
EncodingConverter::~EncodingConverter()
{
#ifdef MPLAT_UNIX
if ( NULL != m_pCvtCache )
{
IConvCachePool::ReturnCache( m_pCvtCache, m_dstCodePage, m_srcCodePage );
}
#endif
}
bool EncodingConverter::Initialize()
{
#if defined(MPLAT_UNIX)
if ( !IsValidIConv() )
{
m_pCvtCache = IConvCachePool::BorrowCache( m_dstCodePage, m_srcCodePage );
}
return IsValidIConv();
#elif defined(MPLAT_WWOWH)
return true;
#endif
}
//#endif
#ifdef MPLAT_UNIX
// MPLAT_UNIX ----------------------------------------------------------------
#include <locale>
using namespace std;
SystemLocale::SystemLocale( const char * localeName )
: m_pLocale( new std::locale(localeName) )
{
}
SystemLocale::~SystemLocale()
{
delete m_pLocale;
}
const SystemLocale & SystemLocale::Singleton()
{
// GCC ensures that function scoped static initializers are threadsafe
// We must not use the -fno-threadsafe-statics compiler option
#if !defined(__GNUC__) || defined(NO_THREADSAFE_STATICS)
#error "Relying on GCC's threadsafe initialization of local statics."
#endif
static const SystemLocale s_Default( "en_US.utf8" );
return s_Default;
}
int SystemLocale::GetResourcePath( char * buffer, size_t cchBuffer ) const
{
// XPLAT_ODBC_TODO: VSTS 718708 Localization
// Also need to use AdjustLCID logic when handling more locales
return snprintf( buffer, cchBuffer, "/opt/microsoft/msodbcsql/share/resources/en_US/");
}
DWORD SystemLocale::CurrentTimeZoneBias( LONG * offsetInMinutes, DWORD * tzinfo ) const
{
if ( NULL == offsetInMinutes )
return ERROR_INVALID_PARAMETER;
time_t now = time( NULL );
if ( (time_t)(-1) == now )
return ERROR_NOT_SUPPORTED;
struct tm utc, local;
if ( NULL == gmtime_r(&now, &utc) || NULL == localtime_r(&now, &local) )
return ERROR_INVALID_DATA;
*offsetInMinutes = BiasInMinutes( utc, local );
if ( NULL != tzinfo )
{
*tzinfo = (0 == local.tm_isdst ? TIME_ZONE_ID_STANDARD : (0 < local.tm_isdst ? TIME_ZONE_ID_DAYLIGHT : TIME_ZONE_ID_UNKNOWN));
}
return ERROR_SUCCESS;
}
DWORD SystemLocale::CurrentLocalTime( LPSYSTEMTIME pTime )
{
if ( NULL == pTime )
return ERROR_INVALID_PARAMETER;
memset( pTime, 0, sizeof(SYSTEMTIME) );
time_t now = time( NULL );
if ( (time_t)(-1) == now )
return ERROR_NOT_SUPPORTED;
struct tm local;
if ( NULL == localtime_r(&now, &local) )
return ERROR_INVALID_DATA;
pTime->wYear = local.tm_year + 1900;
pTime->wMonth = local.tm_mon + 1;
pTime->wDay = local.tm_mday;
pTime->wHour = local.tm_hour;
pTime->wMinute = local.tm_min;
pTime->wSecond = local.tm_sec;
pTime->wMilliseconds = 0;
pTime->wDayOfWeek = local.tm_wday;
return ERROR_SUCCESS;
}
size_t SystemLocale::ToUtf16( UINT srcCodePage, const char * src, SSIZE_T cchSrc, WCHAR * dest, size_t cchDest, DWORD * pErrorCode )
{
srcCodePage = ExpandSpecialCP( srcCodePage );
EncodingConverter cvt( CP_UTF16, srcCodePage );
if ( !cvt.Initialize() )
{
if ( NULL != pErrorCode )
*pErrorCode = ERROR_INVALID_PARAMETER;
return 0;
}
size_t cchSrcActual = (cchSrc < 0 ? (1+strlen(src)) : cchSrc);
bool hasLoss;
return cvt.Convert( dest, cchDest, src, cchSrcActual, false, &hasLoss, pErrorCode );
}
size_t SystemLocale::ToUtf16Strict( UINT srcCodePage, const char * src, SSIZE_T cchSrc, WCHAR * dest, size_t cchDest, DWORD * pErrorCode )
{
srcCodePage = ExpandSpecialCP( srcCodePage );
EncodingConverter cvt( CP_UTF16, srcCodePage );
if ( !cvt.Initialize() )
{
if ( NULL != pErrorCode )
*pErrorCode = ERROR_INVALID_PARAMETER;
return 0;
}
size_t cchSrcActual = (cchSrc < 0 ? (1+strlen(src)) : cchSrc);
bool hasLoss;
return cvt.Convert( dest, cchDest, src, cchSrcActual, true, &hasLoss, pErrorCode );
}
size_t SystemLocale::FromUtf16( UINT destCodePage, const WCHAR * src, SSIZE_T cchSrc, char * dest, size_t cchDest, bool * pHasDataLoss, DWORD * pErrorCode )
{
destCodePage = ExpandSpecialCP( destCodePage );
EncodingConverter cvt( destCodePage, CP_UTF16 );
if ( !cvt.Initialize() )
{
if ( NULL != pErrorCode )
*pErrorCode = ERROR_INVALID_PARAMETER;
return 0;
}
size_t cchSrcActual = (cchSrc < 0 ? (1+mplat_wcslen(src)) : cchSrc);
bool hasLoss;
return cvt.Convert( dest, cchDest, src, cchSrcActual, false, &hasLoss, pErrorCode );
}
size_t SystemLocale::FromUtf16Strict(UINT destCodePage, const WCHAR * src, SSIZE_T cchSrc, char * dest, size_t cchDest, bool * pHasDataLoss, DWORD * pErrorCode)
{
destCodePage = ExpandSpecialCP(destCodePage);
EncodingConverter cvt(destCodePage, CP_UTF16);
if (!cvt.Initialize())
{
if (NULL != pErrorCode)
*pErrorCode = ERROR_INVALID_PARAMETER;
return 0;
}
size_t cchSrcActual = (cchSrc < 0 ? (1 + mplat_wcslen(src)) : cchSrc);
bool hasLoss;
return cvt.Convert(dest, cchDest, src, cchSrcActual, true, &hasLoss, pErrorCode);
}
size_t SystemLocale::ToLower( const char * src, SSIZE_T cchSrc, char * dest, size_t cchDest, DWORD * pErrorCode ) const
{
size_t cchSrcActual = (cchSrc < 0 ? (1+strlen(src)) : cchSrc);
if ( 0 == cchSrcActual )
{
if ( NULL != pErrorCode )
*pErrorCode = ERROR_INVALID_PARAMETER;
return 0;
}
if ( 0 == cchDest )
{
if ( NULL != pErrorCode )
*pErrorCode = ERROR_SUCCESS;
return cchSrcActual;
}
else if ( cchDest < cchSrcActual )
{
if ( NULL != pErrorCode )
*pErrorCode = ERROR_INSUFFICIENT_BUFFER;
return 0;
}
memcpy_s( dest, cchSrcActual, src, cchSrcActual );
use_facet< ctype< char > >(*m_pLocale).tolower( dest, dest+cchSrcActual );
if ( NULL != pErrorCode )
*pErrorCode = ERROR_SUCCESS;
return cchSrcActual;
}
int SystemLocale::Compare( const char * left, SSIZE_T cchLeft, const char * right, SSIZE_T cchRight, DWORD * pErrorCode ) const
{
if ( NULL == left || NULL == right || 0 == cchLeft || 0 == cchRight )
{
if ( NULL != pErrorCode )
*pErrorCode = ERROR_INVALID_PARAMETER;
return CSTR_ERROR;
}
size_t cchLeftActual = (cchLeft < 0 ? strlen(left) : cchLeft);
size_t cchRightActual = (cchRight < 0 ? strlen(right) : cchRight);
int cmp = strncmp( left, right, min(cchLeftActual, cchRightActual) );
if ( 0 == cmp )
{
if ( cchLeftActual < cchRightActual )
cmp = -1;
else if ( cchLeftActual > cchRightActual )
cmp = 1;
}
else if ( cmp < 0 )
cmp = 1; // CompareString is inverse of strcmp
else
cmp = -1; // CompareString is inverse of strcmp
if ( NULL != pErrorCode )
*pErrorCode = ERROR_SUCCESS;
return cmp+2;
}
int SystemLocale::CompareIgnoreCase( const char * left, SSIZE_T cchLeft, const char * right, SSIZE_T cchRight, DWORD * pErrorCode ) const
{
if ( NULL == left || NULL == right || 0 == cchLeft || 0 == cchRight )
{
if ( NULL != pErrorCode )
*pErrorCode = ERROR_INVALID_PARAMETER;
return CSTR_ERROR;
}
size_t cchLeftActual = (cchLeft < 0 ? strlen(left) : cchLeft);
size_t cchRightActual = (cchRight < 0 ? strlen(right) : cchRight);
int cmp = strncasecmp( left, right, min(cchLeftActual, cchRightActual) );
if ( 0 == cmp )
{
if ( cchLeftActual < cchRightActual )
cmp = -1;
else if ( cchLeftActual > cchRightActual )
cmp = 1;
}
else if ( cmp < 0 )
cmp = 1; // CompareString is inverse of strcmp
else
cmp = -1; // CompareString is inverse of strcmp
if ( NULL != pErrorCode )
*pErrorCode = ERROR_SUCCESS;
return cmp+2;
}
char * SystemLocale::NextChar( UINT codepage, const char * start, size_t cchBytesLeft )
{
if ( NULL == start || '\0' == *start || 0 == cchBytesLeft )
return const_cast<char *>( start );
char first = *start;
codepage = ExpandSpecialCP( codepage );
if ( CP_UTF8 != codepage )
{
if ( !IsDBCSLeadByteEx(codepage, first) || '\0' == *(start+1) )
return const_cast<char *>( start+1 ); // single byte char or truncated double byte char
else
return const_cast<char *>( start+2 ); // double byte char
}
// CP_UTF8
// MB utf8 sequences have this format
// Lead byte starts with 2 set bits, '11'
// Rest of bytes start with one set and one not, '10'
// ASCII or not first of utf8 sequence
// If this isn't the first byte of a utf8 sequence, just move one byte at a time
// since we don't know where the correct boundary is located.
if ( (char)0 == (first & (char)0x80) || !SystemLocale::IsUtf8LeadByte((BYTE)first) )
return const_cast<char *>( start+1 );
else
{
// Initial char tells us how many bytes are supposed to be in this sequence
UINT cchExpectedSize = SystemLocale::CchUtf8CodePt( (BYTE)first );
// Skip lead bye
++start;
--cchExpectedSize;
--cchBytesLeft;
// Proceed to end of utf8 sequence, null term, or end of expected size
while ( 0 < cchExpectedSize && 0 < cchBytesLeft && (char)0x80 == (*start & (char)0xC0) )
{
++start;
--cchExpectedSize;
--cchBytesLeft;
}
return const_cast<char *>( start );
}
}
char * SystemLocale::NextChar( UINT codepage, const char * start )
{
// Just assume some large max buffer size since caller is saying
// start is null terminated.
return NextChar( codepage, start, DWORD_MAX );
}
// MPLAT_UNIX ----------------------------------------------------------------
#else
// !MPLAT_UNIX ----------------------------------------------------------------
//-----------------------------------------------------------------------------------
// IsW2CZeroFlagCodePage
//
// @func Does this code page need special handling for WideCharToMultiByte or
// MultiByteToWideChar to avoid error code as ERROR_INVALID_PARAMETER to be returned
//
// @rdesc bool
// @flag TRUE | needs special handling
// @flag FALSE | doesn't need special handling
//-----------------------------------------------------------------------------------
#define IsW2CZeroFlagCodePage(codePage) (((codePage) < 50220) ? FALSE : _IsW2CZeroFlagCodePage(codePage))
inline BOOL _IsW2CZeroFlagCodePage
(
UINT CodePage
)
{
assert(CodePage >= 50220);
// According to MSDN, these code pages need special handling
// during WideCharToMultiByte call w/r its parameter flags
if (CodePage == 50220 ||
CodePage == 50221 ||
CodePage == 50222 ||
CodePage == 50225 ||
CodePage == 50227 ||
CodePage == 50229 ||
CodePage == 52936 ||
CodePage == 54936 ||
CodePage == 65000 ||
CodePage == 65001 ||
CodePage >= 57002 && CodePage <= 57011)
{
return TRUE;
}
return FALSE;
}
//-------------------------------------------------------------------
// Custom version of MultiByteToWideChar (faster for all ASCII strings)
// Convert ASCII data (0x00-0x7f) until first non-ASCII data,
// calling OS MultiByteToWideChar in that case.
//
size_t SystemLocale::FastAsciiMultiByteToWideChar(
UINT CodePage,
__in_ecount(cch) const char *pch, // IN | source string
SSIZE_T cch, // IN | count of characters or -1
__out_ecount_opt(cwch) PWCHAR pwch, // IN | Result string
size_t cwch, // IN | counter of wcharacters of result buffer or 0
DWORD* pErrorCode, // OUT | optional pointer to return error code
bool bStrict // IN | Return error if invalid chars in src
)
{
if ( 0 == cch || cch < -1 || NULL == pch )
{
if ( NULL != pErrorCode )
*pErrorCode = ERROR_INVALID_PARAMETER;
return 0;
}
const char *pchStart = pch;
// Divide into
// Case 1a: cch, do convert
// Case 1b: cch, just count
// Case 2a: null-term, do convert
// Case 2b: null-term, just count
if (-1 != cch)
{
// 0 <= cch
//
// Case 1: We have counter of characters
if (0 != cch)
{
if (0 != cwch)
{
// Case 1a: Have to convert, not just calculate necessary space
// Optimization: When converting first cwch characters, it's not
// necessary to check for buffer overflow. Also, loop is unrolled.
size_t cquads = min((size_t)cch, cwch) >> 2;
while (0 != cquads)
{
unsigned quad = *(unsigned UNALIGNED *)pch;
if (quad & 0x80808080)
goto general;
OACR_WARNING_SUPPRESS ( INCORRECT_VALIDATION, "Due to performance, we suppress this PREFast warning" );
*(unsigned UNALIGNED *)pwch = (quad & 0x7F) | ((quad & 0x7F00) << 8);
quad >>= 16;
OACR_WARNING_SUPPRESS ( POTENTIAL_BUFFER_OVERFLOW_HIGH_PRIORITY, "PREFast incorrectly warns of buffer overrun for cwch < 4, which won't enter this loop." );
*(unsigned UNALIGNED *)(pwch+2) = (quad & 0x7F) | ((quad & 0x7F00) << 8);
pch += 4;
pwch += 4;
cch -= 4;
cquads --;
}
// Convert end of string - slower, but the loop will be executed 3 times max
if (0 != cch)
{
const char *pchEnd = pchStart + cwch;
do
{
unsigned ch = (unsigned)*pch;
if (pch == pchEnd)
{
if ( NULL != pErrorCode )
*pErrorCode = ERROR_INSUFFICIENT_BUFFER;
return 0; // Not enough space
}
if (ch > 0x7F)
goto general;
*(pwch++) = (WCHAR)ch;
pch++;
cch--;
} while (0 != cch);
}
}
else
{
// Case 1b: Have to calculate necessary space only
if (SystemLocale::MaxCharCchSize(CodePage) == 1) // SBCS code pages 1char = 1 unc char
{
if ( NULL != pErrorCode )
*pErrorCode = ERROR_SUCCESS;
return static_cast<size_t>(cch);
}
do
{
if ((unsigned)*pch > 0x7F)
goto general;
pch++;
} while (0 != --cch);
}
}
if ( NULL != pErrorCode )
*pErrorCode = ERROR_SUCCESS;
return static_cast<size_t>(pch - pchStart);
}
else
{
// Case 2: zero-terminated string
if (0 != cwch)
{
// Case 2a: Have to convert, not just calculate necessary space
const char *pchEnd = pch + cwch;
do
{
unsigned ch = (unsigned)*pch;
if (ch > 0x7F)
goto general;
else
{
*pwch = (WCHAR)ch;
pch ++;
if (0 == ch)
{
if ( NULL != pErrorCode )
*pErrorCode = ERROR_SUCCESS;
return static_cast<size_t>(pch - pchStart);
}
pwch ++;
}
} while (pch != pchEnd);
if ( NULL != pErrorCode )
*pErrorCode = ERROR_INSUFFICIENT_BUFFER;
return 0; // Not enough space
}
else
{
// Case 2b: Have to calculate necessary space
unsigned ch;
do
{
ch = (unsigned)*pch;
if (ch > 0x7F)
goto general;
pch ++;
} while (0 != ch);
if ( NULL != pErrorCode )
*pErrorCode = ERROR_SUCCESS;
return static_cast<size_t>(pch - pchStart);
}
}
// Have to call Win32 API
general:
{
size_t cwchConverted;
size_t cwchUnicode;
cwchConverted = (pch - pchStart);
if ( cwch > cwchConverted )
cwch -= cwchConverted;
else
cwch = 0;
// Windows MBtoWC takes int inputs
if ( INT32_MAX < cch || INT32_MAX < cwch )
{
if ( NULL != pErrorCode )
*pErrorCode = ERROR_INVALID_PARAMETER;
return 0;
}
cwchUnicode = (UINT)MultiByteToWideChar(
CodePage,
(IsW2CZeroFlagCodePage(CodePage) ? 0 : MB_PRECOMPOSED)
| (bStrict ? MB_ERR_INVALID_CHARS : 0),
pch,
(int)cch,
pwch,
(int)cwch);
if ( 0 == cwchUnicode )
{
if ( NULL != pErrorCode )
*pErrorCode = GetLastError();
return 0;
}
else
{
if ( NULL != pErrorCode )
*pErrorCode = ERROR_SUCCESS;
return (cwchConverted + cwchUnicode);
}
}
}
//-------------------------------------------------------------------
// Custom version of WideCharToMultiByte (faster for all ASCII strings)
// Convert ASCII data (0x00-0x7f) until first non-ASCII data,
// calling OS WideCharToMultiByte in that case.
size_t SystemLocale::FastAsciiWideCharToMultiByte
(
UINT CodePage,
const WCHAR *pwch, // IN | source string
SSIZE_T cwch, // IN | count of characters or -1
__out_ecount(cch) char *pch, // IN | Result string
size_t cch, // IN | Length of result buffer or 0
BOOL *pfDataLoss, // IN | True if there was data loss during CP conversion
DWORD *pErrorCode
)
{
if ( 0 == cwch || NULL == pwch || cwch < -1 )
{
if ( NULL != pErrorCode )
*pErrorCode = ERROR_INVALID_PARAMETER;
return 0;
}
const WCHAR *pwchStart = pwch;
const char *pchStart = pch;
// Divide into
// Case 1a: cwch, do convert
// Case 1b: cwch, just count
// Case 2a: null-term, do convert
// Case 2b: null-term, just count
if (-1 != cwch)
{
// Case 1: We have counter of characters
if (0 != cwch)
{
if (0 != cch)
{
// Case 1a: Have to convert, not just calculate necessary space
// Optimization: When converting first cch characters, it's not
// necessary to check for buffer overflow. Also, loop is unrolled.
size_t cquads = cch >> 2;
while (0 != cquads && 4 <= cwch)
{
unsigned pairLo = *(unsigned UNALIGNED *)pwch;
unsigned pairHi = *(unsigned UNALIGNED *)(pwch+2);
if ((pairLo | pairHi) & 0xFF80FF80)
goto general;
*(unsigned UNALIGNED *)pch = (pairLo & 0x7F) |
((pairLo >> 8) & 0x7F00) |
((pairHi & 0x7F) << 16) |
((pairHi & 0x7F0000) << 8);
pch += 4;
pwch += 4;
cwch -= 4;
cquads --;
}
// Convert end of string - slower, but the loop will be executed 3 times max
if (0 != cwch)
{
const char *pchEnd = pchStart + cch;
do
{
unsigned wch = (unsigned)*pwch;
if (pch == pchEnd)
{
if ( NULL != pErrorCode )
*pErrorCode = ERROR_INSUFFICIENT_BUFFER;
return 0; // Not enough space
}
if ((unsigned)*pwch > 0x7F)
goto general;
*(pch ++) = (char) wch;
pwch ++;
cwch --;
} while (0 != cwch);
}
}
else
{
// Case 1b: Have to calculate necessary space
do
{
if ((unsigned)*pwch > 0x7F)
goto general;
pwch ++;
cwch --;
} while (0 != cwch);
}
}
if ( NULL != pErrorCode )
*pErrorCode = ERROR_SUCCESS;
return static_cast<size_t>(pwch - pwchStart);
}
else
{
// Case 2: zero-terminated string
if (0 != cch)
{
// Case 2a: Have to convert, not just calculate necessary space
const char *pchEnd = pch + cch;
do
{
unsigned wch = (unsigned)*pwch;
if (wch > 0x7F)
goto general;
else
{
*pch = (char) wch;
pwch ++;
if (0 == wch)
{
if ( NULL != pErrorCode )
*pErrorCode = ERROR_SUCCESS;
return static_cast<size_t>(pwch - pwchStart);
}
pch ++;
}
} while (pch != pchEnd);
if ( NULL != pErrorCode )
*pErrorCode = ERROR_INSUFFICIENT_BUFFER;
return 0; // Not enough space
}
else
{
// Case 2b: Have to calculate necessary space
unsigned wch;
do
{
wch = (unsigned)*pwch;
if (wch > 0x7F)
goto general;
pwch ++;
} while (0 != wch);
if ( NULL != pErrorCode )
*pErrorCode = ERROR_SUCCESS;
return static_cast<size_t>(pwch - pwchStart);
}
}
// Have to call Win32 API
general:
{
size_t cchConverted;
size_t cchUnicode;
// initialize output param if any
if (pfDataLoss)
*pfDataLoss = FALSE;
cchConverted = (pwch - pwchStart);
if ( cch > cchConverted )
cch -= cchConverted;
else
cch = 0;
// Windows MBtoWC takes int inputs
if ( INT32_MAX < cch || INT32_MAX < cwch )
{
if ( NULL != pErrorCode )
*pErrorCode = ERROR_INVALID_PARAMETER;
return 0;
}
cchUnicode = (UINT)WideCharToMultiByte (
CodePage,
0,
pwch,
(int)cwch,
pch,
(int)cch,
NULL,
IsW2CZeroFlagCodePage(CodePage) ? NULL : pfDataLoss);
if ( 0 == cchUnicode )
{
if ( NULL != pErrorCode )
*pErrorCode = GetLastError();
return 0;
}
else
{
if ( NULL != pErrorCode )
*pErrorCode = ERROR_SUCCESS;
return (cchConverted + cchUnicode);
}
}
}
// !MPLAT_UNIX ----------------------------------------------------------------
#endif

796
source/shared/sal.h Normal file
View file

@ -0,0 +1,796 @@
//---------------------------------------------------------------------------------------------------------------------------------
// File: sal_def.h
//
// Contents: Contains the minimal definitions to build on non-Windows platforms
//
// Microsoft Drivers 4.0 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the ""Software""),
// to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and / or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions :
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//---------------------------------------------------------------------------------------------------------------------------------
#ifndef XPLAT_SAL_DEFINED
#define XPLAT_SAL_DEFINED
#define __allocator
#define __analysis_assert(e)
#define __analysis_assume(e)
#define __bcount(size)
#define __bcount_opt(size)
#define __blocksOn(resource)
#define __bound
#define __callback
#define __checkReturn
#define __control_entrypoint(category)
#define __data_entrypoint(category)
#define __deref
#define __deref_bcount(size)
#define __deref_bcount_opt(size)
#define __deref_ecount(size)
#define __deref_ecount_opt(size)
#define __deref_in
#define __deref_in
#define __deref_in_bcount(size)
#define __deref_in_bcount_opt(size)
#define __deref_in_ecount(size)
#define __deref_in_ecount_opt(size)
#define __deref_in_opt
#define __deref_in_range(lb,ub)
#define __deref_in_xcount(size)
#define __deref_in_xcount_opt(size)
#define __deref_inout
#define __deref_inout_bcount(size)
#define __deref_inout_bcount_full(size)
#define __deref_inout_bcount_full_opt(size)
#define __deref_inout_bcount_nz(size)
#define __deref_inout_bcount_nz_opt(size)
#define __deref_inout_bcount_opt(size)
#define __deref_inout_bcount_part(size,length)
#define __deref_inout_bcount_part_opt(size,length)
#define __deref_inout_bcount_z(size)
#define __deref_inout_bcount_z_opt(size)
#define __deref_inout_ecount(size)
#define __deref_inout_ecount_full(size)
#define __deref_inout_ecount_full_opt(size)
#define __deref_inout_ecount_nz(size)
#define __deref_inout_ecount_nz_opt(size)
#define __deref_inout_ecount_opt(size)
#define __deref_inout_ecount_part(size,length)
#define __deref_inout_ecount_part_opt(size,length)
#define __deref_inout_ecount_z(size)
#define __deref_inout_ecount_z_opt(size)
#define __deref_inout_nz
#define __deref_inout_nz_opt
#define __deref_inout_opt
#define __deref_inout_xcount(size)
#define __deref_inout_xcount_full(size)
#define __deref_inout_xcount_full_opt(size)
#define __deref_inout_xcount_opt(size)
#define __deref_inout_xcount_part(size,length)
#define __deref_inout_xcount_part_opt(size,length)
#define __deref_inout_z
#define __deref_inout_z_opt
#define __deref_opt_bcount(size)
#define __deref_opt_bcount_opt(size)
#define __deref_opt_ecount(size)
#define __deref_opt_ecount_opt(size)
#define __deref_opt_in
#define __deref_opt_in_bcount(size)
#define __deref_opt_in_bcount_opt(size)
#define __deref_opt_in_ecount(size)
#define __deref_opt_in_ecount_opt(size)
#define __deref_opt_in_opt
#define __deref_opt_in_xcount(size)
#define __deref_opt_in_xcount_opt(size)
#define __deref_opt_inout
#define __deref_opt_inout_bcount(size)
#define __deref_opt_inout_bcount_full(size)
#define __deref_opt_inout_bcount_full_opt(size)
#define __deref_opt_inout_bcount_nz(size)
#define __deref_opt_inout_bcount_nz_opt(size)
#define __deref_opt_inout_bcount_opt(size)
#define __deref_opt_inout_bcount_part(size,length)
#define __deref_opt_inout_bcount_part_opt(size,length)
#define __deref_opt_inout_bcount_z(size)
#define __deref_opt_inout_bcount_z_opt(size)
#define __deref_opt_inout_ecount(size)
#define __deref_opt_inout_ecount_full(size)
#define __deref_opt_inout_ecount_full_opt(size)
#define __deref_opt_inout_ecount_nz(size)
#define __deref_opt_inout_ecount_nz_opt(size)
#define __deref_opt_inout_ecount_opt(size)
#define __deref_opt_inout_ecount_part(size,length)
#define __deref_opt_inout_ecount_part_opt(size,length)
#define __deref_opt_inout_ecount_z(size)
#define __deref_opt_inout_ecount_z_opt(size)
#define __deref_opt_inout_nz
#define __deref_opt_inout_nz_opt
#define __deref_opt_inout_opt
#define __deref_opt_inout_xcount(size)
#define __deref_opt_inout_xcount_full(size)
#define __deref_opt_inout_xcount_full_opt(size)
#define __deref_opt_inout_xcount_opt(size)
#define __deref_opt_inout_xcount_part(size,length)
#define __deref_opt_inout_xcount_part_opt(size,length)
#define __deref_opt_inout_z
#define __deref_opt_inout_z_opt
#define __deref_opt_out
#define __deref_opt_out_bcount(size)
#define __deref_opt_out_bcount_full(size)
#define __deref_opt_out_bcount_full_opt(size)
#define __deref_opt_out_bcount_nz_opt(size)
#define __deref_opt_out_bcount_opt(size)
#define __deref_opt_out_bcount_part(size,length)
#define __deref_opt_out_bcount_part_opt(size,length)
#define __deref_opt_out_bcount_z_opt(size)
#define __deref_opt_out_ecount(size)
#define __deref_opt_out_ecount_full(size)
#define __deref_opt_out_ecount_full_opt(size)
#define __deref_opt_out_ecount_nz_opt(size)
#define __deref_opt_out_ecount_opt(size)
#define __deref_opt_out_ecount_part(size,length)
#define __deref_opt_out_ecount_part_opt(size,length)
#define __deref_opt_out_ecount_z_opt(size)
#define __deref_opt_out_nz_opt
#define __deref_opt_out_opt
#define __deref_opt_out_xcount(size)
#define __deref_opt_out_xcount_full(size)
#define __deref_opt_out_xcount_full_opt(size)
#define __deref_opt_out_xcount_opt(size)
#define __deref_opt_out_xcount_part(size,length)
#define __deref_opt_out_xcount_part_opt(size,length)
#define __deref_opt_out_z
#define __deref_opt_out_z_opt
#define __deref_opt_xcount(size)
#define __deref_opt_xcount_opt(size)
#define __deref_out
#define __deref_out_bcount(size)
#define __deref_out_bcount_full(size)
#define __deref_out_bcount_full_opt(size)
#define __deref_out_bcount_nz(size)
#define __deref_out_bcount_nz_opt(size)
#define __deref_out_bcount_opt(size)
#define __deref_out_bcount_part(size,length)
#define __deref_out_bcount_part_opt(size,length)
#define __deref_out_bcount_z(size)
#define __deref_out_bcount_z_opt(size)
#define __deref_out_bound
#define __deref_out_ecount(size)
#define __deref_out_ecount_full(size)
#define __deref_out_ecount_full_opt(size)
#define __deref_out_ecount_nz(size)
#define __deref_out_ecount_nz_opt(size)
#define __deref_out_ecount_opt(size)
#define __deref_out_ecount_part(size,length)
#define __deref_out_ecount_part_opt(size,length)
#define __deref_out_ecount_z(size)
#define __deref_out_ecount_z_opt(size)
#define __deref_out_nz
#define __deref_out_nz_opt
#define __deref_out_opt
#define __deref_out_range(lb,ub)
#define __deref_out_xcount(size)
#define __deref_out_xcount_full(size)
#define __deref_out_xcount_full_opt(size)
#define __deref_out_xcount_opt(size)
#define __deref_out_xcount_part(size,length)
#define __deref_out_xcount_part_opt(size,length)
#define __deref_out_z
#define __deref_out_z_opt
#define __deref_xcount(size)
#define __deref_xcount_opt(size)
#define __ecount(size)
#define __ecount_opt(size)
#define __fallthrough
#define __field_bcount(size)
#define __field_bcount_full(size)
#define __field_bcount_full_opt(size)
#define __field_bcount_opt(size)
#define __field_bcount_part(size,init)
#define __field_bcount_part_opt(size,init)
#define __field_data_source(src_sym)
#define __field_ecount(size)
#define __field_ecount_full(size)
#define __field_ecount_full_opt(size)
#define __field_ecount_opt(size)
#define __field_ecount_part(size,init)
#define __field_ecount_part_opt(size,init)
#define __field_range(lb,ub)
#define __field_xcount(size)
#define __field_xcount_full(size)
#define __field_xcount_full_opt(size)
#define __field_xcount_opt(size)
#define __field_xcount_part(size,init)
#define __field_xcount_part_opt(size,init)
#define __format_string
#define __inn
#define __in_bcount(size)
#define __in_bcount_nz(size)
#define __in_bcount_nz_opt(size)
#define __in_bcount_opt(size)
#define __in_bcount_z(size)
#define __in_bcount_z_opt(size)
#define __in_bound
#define __in_ecount(size)
#define __in_ecount_nz(size)
#define __in_ecount_nz_opt(size)
#define __in_ecount_opt(size)
#define __in_ecount_z(size)
#define __in_ecount_z_opt(size)
#define __in_nz
#define __in_nz_opt
#define __in_opt
#define __in_range(lb,ub)
#define __in_xcount(size)
#define __in_xcount_opt(size)
#define __in_z
#define __in_z_opt
#define __inexpressible_readableTo(size)
#define __inexpressible_writableTo(size)
#define __inner_allocator
#define __inner_assume_bound(i)
#define __inner_assume_bound_dec
#define __inner_bound
#define __inner_range(lb,ub)
#define __inout
#define __inout_bcount(size)
#define __inout_bcount_full(size)
#define __inout_bcount_full_opt(size)
#define __inout_bcount_nz(size)
#define __inout_bcount_nz_opt(size)
#define __inout_bcount_opt(size)
#define __inout_bcount_part(size,length)
#define __inout_bcount_part_opt(size,length)
#define __inout_bcount_z(size)
#define __inout_bcount_z_opt(size)
#define __inout_ecount(size)
#define __inout_ecount_full(size)
#define __inout_ecount_full_opt(size)
#define __inout_ecount_nz(size)
#define __inout_ecount_nz_opt(size)
#define __inout_ecount_opt(size)
#define __inout_ecount_part(size,length)
#define __inout_ecount_part_opt(size,length)
#define __inout_ecount_z(size)
#define __inout_ecount_z_opt(size)
#define __inout_nz
#define __inout_nz_opt
#define __inout_opt
#define __inout_xcount(size)
#define __inout_xcount_full(size)
#define __inout_xcount_full_opt(size)
#define __inout_xcount_opt(size)
#define __inout_xcount_opt(size)
#define __inout_xcount_part(size,length)
#define __inout_xcount_part_opt(size,length)
#define __inout_z
#define __inout_z_opt
#define __nullnullterminated
#define __nullterminated
#define __outt
#define __out_bcount(size)
#define __out_bcount_full(size)
#define __out_bcount_full_opt(size)
#define __out_bcount_full_z(size)
#define __out_bcount_full_z_opt(size)
#define __out_bcount_nz(size)
#define __out_bcount_nz_opt(size)
#define __out_bcount_opt(size)
#define __out_bcount_part(size,length)
#define __out_bcount_part_opt(size,length)
#define __out_bcount_part_z(size,length)
#define __out_bcount_part_z_opt(size,length)
#define __out_bcount_z(size)
#define __out_bcount_z_opt(size)
#define __out_bound
#define __out_ecount(size)
#define __out_ecount_full(size)
#define __out_ecount_full_opt(size)
#define __out_ecount_full_z(size)
#define __out_ecount_full_z_opt(size)
#define __out_ecount_nz(size)
#define __out_ecount_nz_opt(size)
#define __out_ecount_opt(size)
#define __out_ecount_part(size,length)
#define __out_ecount_part_opt(size,length)
#define __out_ecount_part_z(size,length)
#define __out_ecount_part_z_opt(size,length)
#define __out_ecount_z(size)
#define __out_ecount_z_opt(size)
#define __out_nz
#define __out_nz_opt
#define __out_opt
#define __out_range(lb,ub)
#define __out_xcount(size)
#define __out_xcount_full(size)
#define __out_xcount_full_opt(size)
#define __out_xcount_opt(size)
#define __out_xcount_part(size,length)
#define __out_xcount_part_opt(size,length)
#define __out_z
#define __out_z_opt
#define __override
#define __range(lb,ub)
#define __reserved
#define __sql_escaped_and_delimited_right_bracket
#define __struct_bcount(size)
#define __struct_xcount(size)
#define __success(expr)
#define __transfer(formal)
#define __typefix(ctype)
#define __xcount(size)
#define __xcount_opt(size)
#define _Analysis_assume_
#define _Check_return_
#define _Check_return_
#define _Deref
#define _Deref_in_bound_
#define _Deref_in_range_(lb,ub)
#define _Deref_inout_bound_
#define _Deref_inout_z_
#define _Deref_inout_z_bytecap_c_(size)
#define _Deref_inout_z_cap_c_(size)
#define _Deref_opt_out_
#define _Deref_opt_out_opt_
#define _Deref_opt_out_opt_z_
#define _Deref_opt_out_z_
#define _Deref_out_
#define _Deref_out_bound_
#define _Deref_out_opt_
#define _Deref_out_opt_z_
#define _Deref_out_range_(lb,ub)
#define _Deref_out_z_
#define _Deref_out_z_bytecap_c_(size)
#define _Deref_out_z_cap_c_(size)
#define _Deref_post_bytecap_(size)
#define _Deref_post_bytecap_c_(size)
#define _Deref_post_bytecap_x_(size)
#define _Deref_post_bytecount_(size)
#define _Deref_post_bytecount_c_(size)
#define _Deref_post_bytecount_x_(size)
#define _Deref_post_cap_(size)
#define _Deref_post_cap_c_(size)
#define _Deref_post_cap_x_(size)
#define _Deref_post_count_(size)
#define _Deref_post_count_c_(size)
#define _Deref_post_count_x_(size)
#define _Deref_post_maybenull_
#define _Deref_post_notnull_
#define _Deref_post_null_
#define _Deref_post_opt_bytecap_(size)
#define _Deref_post_opt_bytecap_c_(size)
#define _Deref_post_opt_bytecap_x_(size)
#define _Deref_post_opt_bytecount_(size)
#define _Deref_post_opt_bytecount_c_(size)
#define _Deref_post_opt_bytecount_x_(size)
#define _Deref_post_opt_cap_(size)
#define _Deref_post_opt_cap_c_(size)
#define _Deref_post_opt_cap_x_(size)
#define _Deref_post_opt_count_(size)
#define _Deref_post_opt_count_c_(size)
#define _Deref_post_opt_count_x_(size)
#define _Deref_post_opt_valid_
#define _Deref_post_opt_valid_bytecap_(size)
#define _Deref_post_opt_valid_bytecap_c_(size)
#define _Deref_post_opt_valid_bytecap_x_(size)
#define _Deref_post_opt_valid_cap_(size)
#define _Deref_post_opt_valid_cap_c_(size)
#define _Deref_post_opt_valid_cap_x_(size)
#define _Deref_post_opt_z_
#define _Deref_post_opt_z_bytecap_(size)
#define _Deref_post_opt_z_bytecap_c_(size)
#define _Deref_post_opt_z_bytecap_x_(size)
#define _Deref_post_opt_z_cap_(size)
#define _Deref_post_opt_z_cap_c_(size)
#define _Deref_post_opt_z_cap_x_(size)
#define _Deref_post_valid_
#define _Deref_post_valid_bytecap_(size)
#define _Deref_post_valid_bytecap_c_(size)
#define _Deref_post_valid_bytecap_x_(size)
#define _Deref_post_valid_cap_(size)
#define _Deref_post_valid_cap_c_(size)
#define _Deref_post_valid_cap_x_(size)
#define _Deref_post_z_
#define _Deref_post_z_
#define _Deref_post_z_bytecap_(size)
#define _Deref_post_z_bytecap_c_(size)
#define _Deref_post_z_bytecap_x_(size)
#define _Deref_post_z_cap_(size)
#define _Deref_post_z_cap_c_(size)
#define _Deref_post_z_cap_x_(size)
#define _Deref_pre_bytecap_(size)
#define _Deref_pre_bytecap_c_(size)
#define _Deref_pre_bytecap_x_(size)
#define _Deref_pre_bytecount_(size)
#define _Deref_pre_bytecount_c_(size)
#define _Deref_pre_bytecount_x_(size)
#define _Deref_pre_cap_(size)
#define _Deref_pre_cap_c_(size)
#define _Deref_pre_cap_x_(size)
#define _Deref_pre_count_(size)
#define _Deref_pre_count_c_(size)
#define _Deref_pre_count_x_(size)
#define _Deref_pre_invalid_
#define _Deref_pre_maybenull_
#define _Deref_pre_notnull_
#define _Deref_pre_null_
#define _Deref_pre_opt_bytecap_(size)
#define _Deref_pre_opt_bytecap_c_(size)
#define _Deref_pre_opt_bytecap_x_(size)
#define _Deref_pre_opt_bytecount_(size)
#define _Deref_pre_opt_bytecount_c_(size)
#define _Deref_pre_opt_bytecount_x_(size)
#define _Deref_pre_opt_cap_(size)
#define _Deref_pre_opt_cap_c_(size)
#define _Deref_pre_opt_cap_x_(size)
#define _Deref_pre_opt_count_(size)
#define _Deref_pre_opt_count_c_(size)
#define _Deref_pre_opt_count_x_(size)
#define _Deref_pre_opt_valid_
#define _Deref_pre_opt_valid_bytecap_(size)
#define _Deref_pre_opt_valid_bytecap_c_(size)
#define _Deref_pre_opt_valid_bytecap_x_(size)
#define _Deref_pre_opt_valid_cap_(size)
#define _Deref_pre_opt_valid_cap_c_(size)
#define _Deref_pre_opt_valid_cap_x_(size)
#define _Deref_pre_opt_z_
#define _Deref_pre_opt_z_bytecap_(size)
#define _Deref_pre_opt_z_bytecap_c_(size)
#define _Deref_pre_opt_z_bytecap_x_(size)
#define _Deref_pre_opt_z_cap_(size)
#define _Deref_pre_opt_z_cap_c_(size)
#define _Deref_pre_opt_z_cap_x_(size)
#define _Deref_pre_readonly_
#define _Deref_pre_valid_
#define _Deref_pre_valid_bytecap_(size)
#define _Deref_pre_valid_bytecap_c_(size)
#define _Deref_pre_valid_bytecap_x_(size)
#define _Deref_pre_valid_cap_(size)
#define _Deref_pre_valid_cap_c_(size)
#define _Deref_pre_valid_cap_x_(size)
#define _Deref_pre_writeonly_
#define _Deref_pre_z_
#define _Deref_pre_z_bytecap_(size)
#define _Deref_pre_z_bytecap_c_(size)
#define _Deref_pre_z_bytecap_x_(size)
#define _Deref_pre_z_cap_(size)
#define _Deref_pre_z_cap_c_(size)
#define _Deref_pre_z_cap_x_(size)
#define _Deref_prepost_bytecap_(size)
#define _Deref_prepost_bytecap_x_(size)
#define _Deref_prepost_bytecount_(size)
#define _Deref_prepost_bytecount_x_(size)
#define _Deref_prepost_cap_(size)
#define _Deref_prepost_cap_x_(size)
#define _Deref_prepost_count_(size)
#define _Deref_prepost_count_x_(size)
#define _Deref_prepost_opt_bytecap_(size)
#define _Deref_prepost_opt_bytecap_x_(size)
#define _Deref_prepost_opt_bytecount_(size)
#define _Deref_prepost_opt_bytecount_x_(size)
#define _Deref_prepost_opt_cap_(size)
#define _Deref_prepost_opt_cap_x_(size)
#define _Deref_prepost_opt_count_(size)
#define _Deref_prepost_opt_count_x_(size)
#define _Deref_prepost_opt_valid_
#define _Deref_prepost_opt_valid_bytecap_(size)
#define _Deref_prepost_opt_valid_bytecap_x_(size)
#define _Deref_prepost_opt_valid_cap_(size)
#define _Deref_prepost_opt_valid_cap_x_(size)
#define _Deref_prepost_opt_z_
#define _Deref_prepost_opt_z_bytecap_(size)
#define _Deref_prepost_opt_z_cap_(size)
#define _Deref_prepost_valid_
#define _Deref_prepost_valid_bytecap_(size)
#define _Deref_prepost_valid_bytecap_x_(size)
#define _Deref_prepost_valid_cap_(size)
#define _Deref_prepost_valid_cap_x_(size)
#define _Deref_prepost_z_
#define _Deref_prepost_z_bytecap_(size)
#define _Deref_prepost_z_cap_(size)
#define _Deref_ret_bound_
#define _Deref_ret_opt_z_
#define _Deref_ret_range_(lb,ub)
#define _Deref_ret_z_
#define _FormatMessage_format_string_
#define _In_
#define _In_bound_
#define _In_bytecount_(size)
#define _In_bytecount_c_(size)
#define _In_bytecount_x_(size)
#define _In_count_(size)
#define _In_count_c_(size)
#define _In_count_x_(size)
#define _In_opt_
#define _In_opt_
#define _In_opt_bytecount_(size)
#define _In_opt_bytecount_c_(size)
#define _In_opt_bytecount_x_(size)
#define _In_opt_count_(size)
#define _In_opt_count_c_(size)
#define _In_opt_count_x_(size)
#define _In_opt_ptrdiff_count_(size)
#define _In_opt_z_
#define _In_opt_z_bytecount_(size)
#define _In_opt_z_bytecount_c_(size)
#define _In_opt_z_count_(size)
#define _In_opt_z_count_c_(size)
#define _In_ptrdiff_count_(size)
#define _In_range_(lb,ub)
#define _In_reads_bytes_(size)
#define _In_z_
#define _In_z_bytecount_(size)
#define _In_z_bytecount_c_(size)
#define _In_z_count_(size)
#define _In_z_count_c_(size)
#define _Inout_
#define _Inout_bytecap_(size)
#define _Inout_bytecap_c_(size)
#define _Inout_bytecap_x_(size)
#define _Inout_bytecount_(size)
#define _Inout_bytecount_c_(size)
#define _Inout_bytecount_x_(size)
#define _Inout_cap_(size)
#define _Inout_cap_c_(size)
#define _Inout_cap_x_(size)
#define _Inout_count_(size)
#define _Inout_count_c_(size)
#define _Inout_count_x_(size)
#define _Inout_opt_
#define _Inout_opt_bytecap_(size)
#define _Inout_opt_bytecap_c_(size)
#define _Inout_opt_bytecap_x_(size)
#define _Inout_opt_bytecount_(size)
#define _Inout_opt_bytecount_c_(size)
#define _Inout_opt_bytecount_x_(size)
#define _Inout_opt_cap_(size)
#define _Inout_opt_cap_c_(size)
#define _Inout_opt_cap_x_(size)
#define _Inout_opt_count_(size)
#define _Inout_opt_count_c_(size)
#define _Inout_opt_count_x_(size)
#define _Inout_opt_ptrdiff_count_(size)
#define _Inout_opt_z_
#define _Inout_opt_z_bytecap_(size)
#define _Inout_opt_z_bytecap_c_(size)
#define _Inout_opt_z_bytecap_x_(size)
#define _Inout_opt_z_bytecount_(size)
#define _Inout_opt_z_bytecount_c_(size)
#define _Inout_opt_z_cap_(size)
#define _Inout_opt_z_cap_c_(size)
#define _Inout_opt_z_cap_x_(size)
#define _Inout_opt_z_count_(size)
#define _Inout_opt_z_count_c_(size)
#define _Inout_ptrdiff_count_(size)
#define _Inout_z_
#define _Inout_z_bytecap_(size)
#define _Inout_z_bytecap_c_(size)
#define _Inout_z_bytecap_x_(size)
#define _Inout_z_bytecount_(size)
#define _Inout_z_bytecount_c_(size)
#define _Inout_z_cap_(size)
#define _Inout_z_cap_c_(size)
#define _Inout_z_cap_x_(size)
#define _Inout_z_count_(size)
#define _Inout_z_count_c_(size)
#define _Out_
#define _Out_bound_
#define _Out_bytecap_(size)
#define _Out_bytecap_c_(size)
#define _Out_bytecap_post_bytecount_(cap,count)
#define _Out_bytecap_x_(size)
#define _Out_bytecapcount_(capcount)
#define _Out_bytecapcount_x_(capcount)
#define _Out_cap_(size)
#define _Out_cap_c_(size)
#define _Out_cap_m_(mult,size)
#define _Out_cap_post_count_(cap,count)
#define _Out_cap_x_(size)
#define _Out_capcount_(capcount)
#define _Out_capcount_x_(capcount)
#define _Out_opt_
#define _Out_opt_bytecap_(size)
#define _Out_opt_bytecap_c_(size)
#define _Out_opt_bytecap_post_bytecount_(cap,count)
#define _Out_opt_bytecap_x_(size)
#define _Out_opt_bytecapcount_(capcount)
#define _Out_opt_bytecapcount_x_(capcount)
#define _Out_opt_cap_(size)
#define _Out_opt_cap_c_(size)
#define _Out_opt_cap_m_(mult,size)
#define _Out_opt_cap_post_count_(cap,count)
#define _Out_opt_cap_x_(size)
#define _Out_opt_capcount_(capcount)
#define _Out_opt_capcount_x_(capcount)
#define _Out_opt_ptrdiff_cap_(size)
#define _Out_opt_z_bytecap_(size)
#define _Out_opt_z_bytecap_c_(size)
#define _Out_opt_z_bytecap_post_bytecount_(cap,count)
#define _Out_opt_z_bytecap_x_(size)
#define _Out_opt_z_bytecapcount_(capcount)
#define _Out_opt_z_cap_(size)
#define _Out_opt_z_cap_c_(size)
#define _Out_opt_z_cap_m_(mult,size)
#define _Out_opt_z_cap_post_count_(cap,count)
#define _Out_opt_z_cap_x_(size)
#define _Out_opt_z_capcount_(capcount)
#define _Out_ptrdiff_cap_(size)
#define _Out_range_(lb,ub)
#define _Out_writes_(size)
#define _Out_writes_bytes_(count)
#define _Out_z_bytecap_(size)
#define _Out_z_bytecap_c_(size)
#define _Out_z_bytecap_post_bytecount_(cap,count)
#define _Out_z_bytecap_x_(size)
#define _Out_z_bytecapcount_(capcount)
#define _Out_z_cap_(size)
#define _Out_z_cap_c_(size)
#define _Out_z_cap_m_(mult,size)
#define _Out_z_cap_post_count_(cap,count)
#define _Out_z_cap_x_(size)
#define _Out_z_capcount_(capcount)
#define _Post_bytecap_(size)
#define _Post_bytecount_(size)
#define _Post_bytecount_c_(size)
#define _Post_bytecount_x_(size)
#define _Post_cap_(size)
#define _Post_count_(size)
#define _Post_count_c_(size)
#define _Post_count_x_(size)
#define _Post_invalid_
#define _Post_maybez_
#define _Post_notnull_
#define _Post_ptr_invalid_
#define _Post_valid_
#define _Post_z_
#define _Post_z_bytecount_(size)
#define _Post_z_bytecount_c_(size)
#define _Post_z_bytecount_x_(size)
#define _Post_z_count_(size)
#define _Post_z_count_c_(size)
#define _Post_z_count_x_(size)
#define _Pre_bytecap_(size)
#define _Pre_bytecap_c_(size)
#define _Pre_bytecap_x_(size)
#define _Pre_bytecount_(size)
#define _Pre_bytecount_c_(size)
#define _Pre_bytecount_x_(size)
#define _Pre_cap_(size)
#define _Pre_cap_c_(size)
#define _Pre_cap_for_(param)
#define _Pre_cap_m_(mult,size)
#define _Pre_cap_x_(size)
#define _Pre_count_(size)
#define _Pre_count_c_(size)
#define _Pre_count_x_(size)
#define _Pre_invalid_
#define _Pre_maybenull_
#define _Pre_notnull_
#define _Pre_null_
#define _Pre_opt_bytecap_(size)
#define _Pre_opt_bytecap_c_(size)
#define _Pre_opt_bytecap_x_(size)
#define _Pre_opt_bytecount_(size)
#define _Pre_opt_bytecount_c_(size)
#define _Pre_opt_bytecount_x_(size)
#define _Pre_opt_cap_(size)
#define _Pre_opt_cap_c_(size)
#define _Pre_opt_cap_for_(param)
#define _Pre_opt_cap_m_(mult,size)
#define _Pre_opt_cap_x_(size)
#define _Pre_opt_count_(size)
#define _Pre_opt_count_c_(size)
#define _Pre_opt_count_x_(size)
#define _Pre_opt_ptrdiff_cap_(ptr)
#define _Pre_opt_ptrdiff_count_(ptr)
#define _Pre_opt_valid_
#define _Pre_opt_valid_bytecap_(size)
#define _Pre_opt_valid_bytecap_c_(size)
#define _Pre_opt_valid_bytecap_x_(size)
#define _Pre_opt_valid_cap_(size)
#define _Pre_opt_valid_cap_c_(size)
#define _Pre_opt_valid_cap_x_(size)
#define _Pre_opt_z_
#define _Pre_opt_z_bytecap_(size)
#define _Pre_opt_z_bytecap_c_(size)
#define _Pre_opt_z_bytecap_x_(size)
#define _Pre_opt_z_cap_(size)
#define _Pre_opt_z_cap_c_(size)
#define _Pre_opt_z_cap_x_(size)
#define _Pre_ptrdiff_cap_(ptr)
#define _Pre_ptrdiff_count_(ptr)
#define _Pre_readonly_
#define _Pre_valid_
#define _Pre_valid_bytecap_(size)
#define _Pre_valid_bytecap_c_(size)
#define _Pre_valid_bytecap_x_(size)
#define _Pre_valid_cap_(size)
#define _Pre_valid_cap_c_(size)
#define _Pre_valid_cap_x_(size)
#define _Pre_writeonly_
#define _Pre_z_
#define _Pre_z_bytecap_(size)
#define _Pre_z_bytecap_c_(size)
#define _Pre_z_bytecap_x_(size)
#define _Pre_z_cap_(size)
#define _Pre_z_cap_c_(size)
#define _Pre_z_cap_x_(size)
#define _Prepost_bytecount_(size)
#define _Prepost_bytecount_c_(size)
#define _Prepost_bytecount_x_(size)
#define _Prepost_count_(size)
#define _Prepost_count_c_(size)
#define _Prepost_count_x_(size)
#define _Prepost_opt_bytecount_(size)
#define _Prepost_opt_bytecount_c_(size)
#define _Prepost_opt_bytecount_x_(size)
#define _Prepost_opt_count_(size)
#define _Prepost_opt_count_c_(size)
#define _Prepost_opt_count_x_(size)
#define _Prepost_opt_valid_
#define _Prepost_opt_z_
#define _Prepost_valid_
#define _Prepost_z_
#define _Printf_format_string_
#define _Ret_
#define _Ret_bound_
#define _Ret_bytecap_(size)
#define _Ret_bytecap_c_(size)
#define _Ret_bytecap_x_(size)
#define _Ret_bytecount_(size)
#define _Ret_bytecount_c_(size)
#define _Ret_bytecount_x_(size)
#define _Ret_cap_(size)
#define _Ret_cap_c_(size)
#define _Ret_cap_x_(size)
#define _Ret_count_(size)
#define _Ret_count_c_(size)
#define _Ret_count_x_(size)
#define _Ret_maybenull_
#define _Ret_notnull_
#define _Ret_null_
#define _Ret_opt_
#define _Ret_opt_
#define _Ret_opt_bytecap_(size)
#define _Ret_opt_bytecap_c_(size)
#define _Ret_opt_bytecap_x_(size)
#define _Ret_opt_bytecount_(size)
#define _Ret_opt_bytecount_c_(size)
#define _Ret_opt_bytecount_x_(size)
#define _Ret_opt_cap_(size)
#define _Ret_opt_cap_c_(size)
#define _Ret_opt_cap_x_(size)
#define _Ret_opt_count_(size)
#define _Ret_opt_count_c_(size)
#define _Ret_opt_count_x_(size)
#define _Ret_opt_valid_
#define _Ret_opt_z_
#define _Ret_opt_z_
#define _Ret_opt_z_bytecap_(size)
#define _Ret_opt_z_bytecount_(size)
#define _Ret_opt_z_cap_(size)
#define _Ret_opt_z_count_(size)
#define _Ret_range_(lb,ub)
#define _Ret_valid_
#define _Ret_z_
#define _Ret_z_
#define _Ret_z_bytecap_(size)
#define _Ret_z_bytecount_(size)
#define _Ret_z_cap_(size)
#define _Ret_z_count_(size)
#define _Scanf_format_string_
#define _Scanf_s_format_string_
#define _Success_(expr)
#define _Outptr_
#define _Notnull_
#endif // XPLAT_SAL_DEFINED

View file

@ -0,0 +1,109 @@
//---------------------------------------------------------------------------------------------------------------------------------
// File: typedefs_for_linux.h
//
// Microsoft Drivers 4.0 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the ""Software""),
// to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and / or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions :
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//---------------------------------------------------------------------------------------------------------------------------------
#ifndef __linux_typedefs__
#define __linux_typedefs__
#define MPLAT_UNIX
#include "xplat.h"
#include "interlockedslist.h"
#define CP_OEMCP 1 // default to OEM code page
#define CP_MACCP 2 // default to MAC code page
#define CP_THREAD_ACP 3 // current thread's ANSI code page
#define CP_SYMBOL 42 // SYMBOL translations
#define CP_UTF7 65000 // UTF-7 translation
#define MAKELANGID(p, s) ((((WORD )(s)) << 10) | (WORD )(p))
#define LANG_NEUTRAL 0x00
#define SUBLANG_DEFAULT 0x01 // user default
// #ifndef _GETLASTERROR
// #define _GETLASTERROR
// void SSetLastError(DWORD err);
// unsigned int GGetLastError();
// #endif
DWORD FormatMessageA(
DWORD dwFlags,
LPCVOID lpSource,
DWORD dwMessageId,
DWORD dwLanguageId,
LPTSTR lpBuffer,
DWORD nSize,
va_list *Arguments
);
DWORD FormatMessageW(
DWORD dwFlags,
LPCVOID lpSource,
DWORD dwMessageId,
DWORD dwLanguageId,
LPWSTR lpBuffer,
DWORD nSize,
va_list *Arguments
);
#ifdef __linux__
#define FormatMessage FormatMessageA
#else
#define FormatMessage FormatMessageW
#endif
#define FORMAT_MESSAGE_ALLOCATE_BUFFER 0x00000100
#define FORMAT_MESSAGE_IGNORE_INSERTS 0x00000200
#define FORMAT_MESSAGE_FROM_STRING 0x00000400
#define FORMAT_MESSAGE_FROM_HMODULE 0x00000800
#define FORMAT_MESSAGE_FROM_SYSTEM 0x00001000
#define FORMAT_MESSAGE_ARGUMENT_ARRAY 0x00002000
#define FORMAT_MESSAGE_MAX_WIDTH_MASK 0x000000FF
#define ERROR_NO_UNICODE_TRANSLATION 1113L
#define ERROR_SUCCESS 0L
#define ERROR_INVALID_DATA 13L
typedef int errno_t;
int mplat_snwprintf_s(WCHAR *str, size_t sizeOfBuffer, size_t count, const WCHAR *format, ...);
int mplat_vsnwprintf( WCHAR * buffer, size_t count, const WCHAR * format, va_list args );
int mplat_snprintf_s(char *str, size_t sizeOfBuffer, size_t count, const char *format, ...);
int mplat_vsnprintf( char * buffer, size_t count, const char * format, va_list args );
errno_t mplat_wctomb_s(int *pRetValue, char *mbchar, size_t sizeInBytes, WCHAR wchar);
WCHAR * mplat_wcscpy(WCHAR * _Dst, const WCHAR * _Src);
char * mplat_cscpy(char * _Dst, const char * _Src);
BOOL IsDBCSLeadByteEx(__inn UINT CodePage, __inn BYTE TestChar);
typedef struct _SYSTEMTIME {
WORD wYear;
WORD wMonth;
WORD wDayOfWeek;
WORD wDay;
WORD wHour;
WORD wMinute;
WORD wSecond;
WORD wMilliseconds;
} SYSTEMTIME, *PSYSTEMTIME, *LPSYSTEMTIME;
typedef HINSTANCE HMODULE; /* HMODULEs can be used in place of HINSTANCEs */
//From sqlext.h
#define SQL_GUID (-11)
size_t mplat_wcslen( const WCHAR * );
#endif // __linux_typedefs__

132
source/shared/winerror.h Normal file
View file

@ -0,0 +1,132 @@
//---------------------------------------------------------------------------------------------------------------------------------
// File: winerror.h
//
// Contents: Contains the minimal definitions to build on non-Windows platforms
//
// Microsoft Drivers 4.0 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the ""Software""),
// to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and / or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions :
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//---------------------------------------------------------------------------------------------------------------------------------
#ifndef XPLAT_WINERROR_H
#define XPLAT_WINERROR_H
#define NOERROR 0
#define WAIT_TIMEOUT 258L // dderror
#define S_OK ((HRESULT)0L)
#define S_FALSE ((HRESULT)1L)
#define E_NOTIMPL ((HRESULT) 0x80004001L)
#define E_FAIL ((HRESULT) 0x80004005L)
#define E_ABORT _HRESULT_TYPEDEF_(0x80004004L)
#define ERROR_HANDLE_EOF 38L
#define E_UNEXPECTED ((HRESULT) 0x8000FFFFL)
#define SUCCEEDED(hr) (((HRESULT)(hr)) >= 0)
#define FAILED(hr) (((HRESULT)(hr)) < 0)
#define ERROR_SUCCESS 0L
#define ERROR_ACCESS_DENIED 5L
#define ERROR_TIMEOUT 1460L
#define E_POINTER _HRESULT_TYPEDEF_(0x80004003L)
#define _HRESULT_TYPEDEF_(_sc) ((HRESULT)_sc)
#define E_OUTOFMEMORY _HRESULT_TYPEDEF_(0x8007000EL)
#define NO_ERROR 0L
#define ERROR_CANCELLED 1223L
#define E_INVALIDARG _HRESULT_TYPEDEF_(0x80070057L)
#define DISP_E_TYPEMISMATCH _HRESULT_TYPEDEF_(0x80020005L)
#define DISP_E_OVERFLOW _HRESULT_TYPEDEF_(0x8002000AL)
#define ERROR_INSUFFICIENT_BUFFER 122L // dderror
#define FACILITY_WIN32 7
#define __HRESULT_FROM_WIN32(x) ((HRESULT)(x) <= 0 ? ((HRESULT)(x)) : ((HRESULT) (((x) & 0x0000FFFF) | (FACILITY_WIN32 << 16) | 0x80000000)))
#define HRESULT_FROM_WIN32(x) __HRESULT_FROM_WIN32(x)
#define SEVERITY_ERROR 1
#define FACILITY_ITF 4
#define MAKE_HRESULT(sev,fac,code) \
((HRESULT) (((windowsULong_t)(sev)<<31) | ((windowsULong_t)(fac)<<16) | ((windowsULong_t)(code))) )
#define ERROR_INVALID_DATA 13L
#define ERROR_INVALID_PARAMETER 87L // dderror
#define ERROR_POSSIBLE_DEADLOCK 1131L
#define ERROR_INVALID_FLAGS 1004L
#define ERROR_NO_UNICODE_TRANSLATION 1113L
#define ERROR_FILE_NOT_FOUND 2L
#define ERROR_PATH_NOT_FOUND 3L
#define ERROR_TOO_MANY_OPEN_FILES 4L
#define E_NOINTERFACE _HRESULT_TYPEDEF_(0x80004002L)
#define ERROR_MOD_NOT_FOUND 126L
#define ERROR_NO_MORE_FILES 18L
#define ERROR_FILE_EXISTS 80L
#define ERROR_ALREADY_EXISTS 183L
#define ERROR_SHARING_VIOLATION 32L
#define SCODE_CODE(sc) ((sc) & 0xFFFF)
#define ERROR_READ_FAULT 30L
#define ERROR_INTERNAL_ERROR 1359L
//----------------------------------------------------------------------------
// Error codes used by SNI
//
#define ERROR_NOT_ENOUGH_MEMORY 8L // dderror
#define ERROR_IO_PENDING 997L
#define WSA_IO_PENDING (ERROR_IO_PENDING)
#define WSAHOST_NOT_FOUND 11001L
#define WSATRY_AGAIN 11002L
#define WSANO_RECOVERY 11003L
#define WSANO_DATA 11004L
#define WSATYPE_NOT_FOUND 10109L
#define WSA_NOT_ENOUGH_MEMORY 8L
#define WSAEINTR 10004L
#define WSAEACCES 10013L
#define WSAEFAULT 10014L
#define WSAEINVAL 10022L
#define WSAEMFILE 10024L
#define WSAEWOULDBLOCK 10035L
#define WSAEALREADY 10037L
#define WSAENOTSOCK 10038L
#define WSAEMSGSIZE 10040L
#define WSAENOPROTOOPT 10042L
#define WSAEPROTONOSUPPORT 10043L
#define WSAESOCKTNOSUPPORT 10044L
#define WSAEOPNOTSUPP 10045L
#define WSAEAFNOSUPPORT 10047L
#define WSAEADDRINUSE 10048L
#define WSAEADDRNOTAVAIL 10049L
#define WSAENETUNREACH 10051L
#define WSAECONNRESET 10054L
#define WSAENOBUFS 10055L
#define WSAEISCONN 10056L
#define WSAENOTCONN 10057L
#define WSAETIMEDOUT 10060L
#define WSAECONNREFUSED 10061L
#define WSANOTINITIALISED 10093L
#define ERROR_OUTOFMEMORY 14L
#define ERROR_NOT_SUPPORTED 50L
#define ERROR_BUFFER_OVERFLOW 111L
#define ERROR_MAX_THRDS_REACHED 164L
#define ERROR_INVALID_OPERATION 4317L
#define ERROR_INVALID_STATE 5023L
#define SEC_E_BAD_BINDINGS _HRESULT_TYPEDEF_(0x80090346L)
#define ERROR_MORE_DATA 234L // dderror
#define ERROR_ARITHMETIC_OVERFLOW 534L
#define SEC_E_INCOMPLETE_MESSAGE _HRESULT_TYPEDEF_(0x80090318L)
#define ERROR_OPERATION_ABORTED 995L
#define ERROR_CONNECTION_REFUSED 1225L
#define SEC_E_OK ((HRESULT)0x00000000L)
#define SEC_E_UNSUPPORTED_FUNCTION _HRESULT_TYPEDEF_(0x80090302L)
#define SEC_E_TARGET_UNKNOWN _HRESULT_TYPEDEF_(0x80090303L)
#define SEC_E_OUT_OF_SEQUENCE _HRESULT_TYPEDEF_(0x80090310L)
#define SEC_E_INVALID_TOKEN _HRESULT_TYPEDEF_(0x80090308L)
#define SEC_I_CONTINUE_NEEDED _HRESULT_TYPEDEF_(0x00090312L)
#define ERROR_INVALID_FUNCTION 1L // dderror
#define TRUST_E_TIME_STAMP _HRESULT_TYPEDEF_(0x80096005L)
#define CRYPT_E_NOT_FOUND _HRESULT_TYPEDEF_(0x80092004L)
#define WAIT_TIMEOUT 258L // dderror
#endif // XPLAT_WINERROR_H

144
source/shared/winnls.h Normal file
View file

@ -0,0 +1,144 @@
//---------------------------------------------------------------------------------------------------------------------------------
// File: winnls.h
//
// Contents: Contains the minimal definitions to build on non-Windows platforms
//
// Microsoft Drivers 4.0 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the ""Software""),
// to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and / or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions :
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//---------------------------------------------------------------------------------------------------------------------------------
#ifndef XPLAT_WINNLS_H
#define XPLAT_WINNLS_H
#include <stdlib.h>
#include "typedefs_for_linux.h"
struct threadlocaleinfostruct;
struct threadmbcinfostruct;
typedef struct threadlocaleinfostruct * pthreadlocinfo;
typedef struct threadmbcinfostruct * pthreadmbcinfo;
typedef struct localeinfo_struct
{
pthreadlocinfo locinfo;
pthreadmbcinfo mbcinfo;
} _locale_tstruct, *_locale_t;
#define LOCALE_SDECIMAL 0x0000000E // decimal separator
#define LOCALE_SCURRENCY 0x00000014 // local monetary symbol
#define LOCALE_SMONDECIMALSEP 0x00000016 // monetary decimal separator
#define LOCALE_SMONTHOUSANDSEP 0x00000017 // monetary thousand separator
#define LOCALE_SMONGROUPING 0x00000018 // monetary grouping
#define LOCALE_ILDATE 0x00000022 // long date format ordering (derived from LOCALE_SLONGDATE, use that instead)
#define LOCALE_ITIME 0x00000023 // time format specifier (derived from LOCALE_STIMEFORMAT, use that instead)
#define LOCALE_SABBREVMONTHNAME1 0x00000044 // abbreviated name for January
#define LOCALE_IDEFAULTLANGUAGE 0x00000009 // default language id
#define LOCALE_IDEFAULTCOUNTRY 0x0000000A // default country/region code, deprecated
#define LOCALE_IDEFAULTCODEPAGE 0x0000000B // default oem code page
#define LOCALE_IDEFAULTANSICODEPAGE 0x00001004 // default ansi code page
#define LOCALE_IDEFAULTMACCODEPAGE 0x00001011 // default mac code page
#define LOCALE_STIMEFORMAT 0x00001003 // time format string, eg "HH:mm:ss"
typedef DWORD LCTYPE;
#define NORM_IGNORECASE 0x00000001 // ignore case
#define NORM_IGNORENONSPACE 0x00000002 // ignore nonspacing chars
#define NORM_IGNORESYMBOLS 0x00000004 // ignore symbols
#define LINGUISTIC_IGNORECASE 0x00000010 // linguistically appropriate 'ignore case'
#define LINGUISTIC_IGNOREDIACRITIC 0x00000020 // linguistically appropriate 'ignore nonspace'
#define NORM_IGNOREKANATYPE 0x00010000 // ignore kanatype
#define NORM_IGNOREWIDTH 0x00020000 // ignore width
#define NORM_LINGUISTIC_CASING 0x08000000 // use linguistic rules for casing
#define NORM_IGNORECASE 0x00000001 // ignore case
#define MB_PRECOMPOSED 0x00000001 // use precomposed chars
#define MB_COMPOSITE 0x00000002 // use composite chars
#define MB_USEGLYPHCHARS 0x00000004 // use glyph chars, not ctrl chars
#define MB_ERR_INVALID_CHARS 0x00000008 // error for invalid chars
#define WC_COMPOSITECHECK 0x00000200 // convert composite to precomposed
#define WC_DISCARDNS 0x00000010 // discard non-spacing chars
#define WC_SEPCHARS 0x00000020 // generate separate chars
#define WC_DEFAULTCHAR 0x00000040 // replace w/ default char
typedef WORD LANGID;
#define NLS_VALID_LOCALE_MASK 0x000fffff
#define MAKELANGID(p, s) ((((WORD )(s)) << 10) | (WORD )(p))
#define MAKELCID(lgid, srtid) ((DWORD)((((DWORD)((WORD )(srtid))) << 16) | \
((DWORD)((WORD )(lgid)))))
#define LANG_NEUTRAL 0x00
#define SUBLANG_DEFAULT 0x01 // user default
#define SUBLANG_SYS_DEFAULT 0x02 // system default
#define SORT_DEFAULT 0x0 // sorting default
#define LANG_USER_DEFAULT (MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT))
#define LOCALE_USER_DEFAULT (MAKELCID(LANG_USER_DEFAULT, SORT_DEFAULT))
#define SUBLANG_ENGLISH_US 0x01 // English (USA)
#define LANG_ENGLISH 0x09
#define LOCALE_ENGLISH_US MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT)
#define LANG_SYSTEM_DEFAULT (MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT))
#define LOCALE_SYSTEM_DEFAULT (MAKELCID(LANG_SYSTEM_DEFAULT, SORT_DEFAULT))
BOOL
WINAPI
IsDBCSLeadByte(
__inn BYTE TestChar);
#ifdef MPLAT_UNIX
// XPLAT_ODBC_TODO: VSTS 718708 Localization
// Find way to remove this
LCID GetUserDefaultLCID();
#endif
BOOL IsValidCodePage(UINT CodePage);
#define HIGH_SURROGATE_START 0xd800
#define HIGH_SURROGATE_END 0xdbff
#define LOW_SURROGATE_START 0xdc00
#define LOW_SURROGATE_END 0xdfff
#define IS_HIGH_SURROGATE(wch) (((wch) >= HIGH_SURROGATE_START) && ((wch) <= HIGH_SURROGATE_END))
#define IS_LOW_SURROGATE(wch) (((wch) >= LOW_SURROGATE_START) && ((wch) <= LOW_SURROGATE_END))
int
GetLocaleInfoA(
__inn LCID Locale,
__inn LCTYPE LCType,
__out_ecount_opt(cchData) LPSTR lpLCData,
__inn int cchData);
int
GetLocaleInfoW(
__inn LCID Locale,
__inn LCTYPE LCType,
__out_ecount_opt(cchData) LPWSTR lpLCData,
__inn int cchData);
#ifdef UNICODE
#define GetLocaleInfo GetLocaleInfoW
#else
#define GetLocaleInfo GetLocaleInfoA
#endif // !UNICODE
#endif // XPLAT_WINNLS_H

509
source/shared/xplat.h Normal file
View file

@ -0,0 +1,509 @@
//---------------------------------------------------------------------------------------------------------------------------------
// File: xplat.h
//
// Contents: include for definition of Windows types for non-Windows platforms
//
// Microsoft Drivers 4.0 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the ""Software""),
// to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and / or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions :
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//---------------------------------------------------------------------------------------------------------------------------------
#ifndef __XPLAT_H__
#define __XPLAT_H__
#ifndef _WCHART_DEFINED
#define _WCHART_DEFINED
#endif
#include <iostream>
#include <deque>
#include <map>
#include <algorithm>
#include <limits>
#include <cassert>
#include <memory>
#include <string>
#include <errno.h>
#include <sql.h>
#include <sqlext.h>
#include <stdarg.h>
#include <cstdlib>
#include <limits.h>
#include <cstdio>
#include <assert.h>
#include <string.h>
#include "msodbcsql.h"
#if defined(_MSC_VER)
// Turned on all warnings in WwoWH projects
// These warnings need to be disabled to be build warning free
// Note that some of these should be enabled and the code fixed
#pragma warning( disable : 4668 ) // preprocessor macro not defined
#pragma warning( disable : 4820 ) // padding after data member
#pragma warning( disable : 4201 ) // nonstandard: nameless union
#pragma warning( disable : 4100 ) // unreferenced formal parameter
#pragma warning( disable : 4514 ) // unreferenced inline function
#pragma warning( disable : 4505 ) // unreferenced inline function
#pragma warning( disable : 4710 ) // function not inlined
#pragma warning( disable : 4191 ) // unsafe conversion
#pragma warning( disable : 4365 ) // signed/unsigned argument conversion
#pragma warning( disable : 4245 ) // signed/unsigned assignment conversion
#pragma warning( disable : 4389 ) // signed/unsigned ==
#pragma warning( disable : 4987 ) // nonstandard: throw(...)
#pragma warning( disable : 4510 ) // default ctor could not be generated
#pragma warning( disable : 4512 ) // operator= could not be generated
#pragma warning( disable : 4626 ) // operator= could not be generated
#pragma warning( disable : 4625 ) // copy ctor could not be generated or accessed
#pragma warning( disable : 4189 ) // unused initialized local variable
#pragma warning( disable : 4127 ) // constant conditional test
#pragma warning( disable : 4061 ) // Unused enum values in switch
#pragma warning( disable : 4062 ) // Unused enum values in switch
#pragma warning( disable : 4706 ) // assignment within conditional
#pragma warning( disable : 4610 ) // can never be instantiated
#pragma warning( disable : 4244 ) // possible loss of data in conversion
#pragma warning( disable : 4701 ) // possible use of uninitialized variable
#pragma warning( disable : 4918 ) // invalid pragma optimization parameter
#pragma warning( disable : 4702 ) // unreachable code
#pragma warning( disable : 4265 ) // class with virtual fxns has non-virtual dtor
#pragma warning( disable : 4238 ) // nonstandard: class rvalue used as lvalue
#pragma warning( disable : 4310 ) // cast truncates constant value
#pragma warning( disable : 4946 ) // reinterpret_cast between related classes
#pragma warning( disable : 4264 ) // no matching override, hides base fxn
#pragma warning( disable : 4242 ) // conversion: possible loss of data
#pragma warning( disable : 4820 ) // added padding bytes
#endif
// Compiler specific items
#define _cdecl
#define __cdecl
#define __fastcall
#define _inline inline
#define __inline inline
#define __forceinline inline
#define __stdcall
#if !defined(_MSC_VER)
#define __declspec__noinline __attribute__((noinline))
#define __declspec__selectany
#define __declspec(a) __declspec__##a
#define __FUNCTION__ __func__
#define __int8 char
#define __int32 int
// __int64
// This type must be defined in a way that allows "unsigned __int64" as a valid type declaration.
// That precludes using the obvious "int64_t" from stdint.h, because "unsigned int64_t" is not allowed
// (one should use "uint64_t" for unsigned 64-bit integers). As a result, we must use compiler-specific
// types such as GCC's "long long" instead
#if defined(_LP64)
#define __int64 long
#elif defined(__GNUC__)
#define __int64 long long
#else
#error "Compiler-specific definition required for __int64 in 32-bit builds"
#endif
#endif
// GCC-specific definitions
#if defined(__GNUC__)
#define MPLAT_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
#endif // defined(__GNUC__)
// For compilers that don't support cross-module inlining (part of whole-program/link-time
// optimization), such as the current MPLAT compilers (GCC 4.1.2 for RHEL5 and GCC 4.4 for RHEL6),
// we must force the generation of out-of-line definitions for functions that otherwise
// are only defined inline when those functions are called from other translation units.
// There are a handful of instances of these in SNI code as well as ODBC code.
//
// To force the compiler to emit an out-of-line definition for a function, just add an otherwise
// unused global (external linkage) non-const pointer pointing to the function:
//
// #if defined(MPLAT_NO_LTO)
// void (* g_pfnMyFunctionUnused)(MyFunctionArguments *) = MyFunction;
// #endif // defined(MPLAT_NO_LTO)
//
// This works because, absent whole-program optimization, the compiler cannot determine that the
// pointers are never called through, and the out-of-line definition cannot be optimized out,
// giving calling translation units something to link to.
//
// GCC adds LTO as of version 4.5
//JL - TODO: this version check doesn't work in Ubuntu
//#if defined(__GNUC__) && MPLAT_GCC_VERSION < 40500
#define MPLAT_NO_LTO
//#endif
#ifdef MPLAT_UNIX
// Needed to use the standard library min and max
#include <algorithm>
using std::min;
using std::max;
#elif MPLAT_WWOWH
#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef min
#define min(a,b) (((a) < (b)) ? (a) : (b))
#endif
#endif // MPLAT_WWOWH
// Deal with differences between Windows and *nix interpretations of the C/C++ 'long' data type.
//
// On 64-bit Windows, 'long' is 32 bits. On 64-bit Linux, 'long' is 64 bits. Assuming the Windows code
// depends on it being 32 bits, use a definition that provides a guaranteed 32-bit type definition.
//
// Similarly, because 'long long' (and its cousin 'unsigned long long') are not portable across
// Linux/UNIX platforms and compilers, provide common definitions for 64-bit types as well.
//
// These types are used in this file primarily to define common Windows types (DWORD, LONG, etc.)
// Cross-platform code should use either the Windows types or appropriate types from <stdint.h>.
#if defined(_MSC_VER) // WwoWH
typedef long windowsLong_t;
typedef unsigned long windowsULong_t;
typedef __int64 windowsLongLong_t;
typedef unsigned __int64 windowsULongLong_t;
#else // *nix (!WwoWH)
#include <stdint.h> // Use standard bit-specific types (signed/unsigned integrated)
typedef int32_t windowsLong_t;
typedef uint32_t windowsULong_t;
typedef int64_t windowsLongLong_t;
typedef uint64_t windowsULongLong_t;
#endif
typedef windowsLong_t LONG, *PLONG, *LPLONG;
typedef windowsLongLong_t LONGLONG;
typedef windowsULongLong_t ULONGLONG;
#include <assert.h>
#include <stdlib.h>
#include <intsafe.h>
// Exclude these headers in Windows machines (just for building on Windows w/o Windows headers)
#define SPECSTRINGS_H // specstrings.h
#define ASOSHOST_DEFINED // asoshost.h
#define _WINDOWS_ // windows.h
#define _INC_WINDOWSX // windowsx.h
#define _WINBASE_ // winbase.h
#define _WINNLS_ // winnls.h
#define _WINERROR_ // winerror.h
#define NETCONS_INCLUDED // lmcons.h
#define __WINCRYPT_H__ // wincrypt.h
#define _INC_TCHAR // tchar.h
#define _INC_FCNTL // fcntl.h
#define _INC_SHARE // share.h
#define _INC_IO // io.h
#define _INC_TYPES // sys/types.h
#define _INC_STAT // sys/stat.h
#define _INC_TIMEB // sys/timeb.h
#define __unknwn_h__ // unknwn.h
#define __objidl_h__ // objidl.h
#define _OBJBASE_H_ // objbase.h
#define __RPC_H__ // rpc.h
#define __RPCNDR_H__ // rpcndr.h
#define _NP_HPP_ // np.hpp (no named pipes)
#define _SM_HPP_ // sm.hpp (no shared memory)
#define VIA_HEADER // via.hpp (no via)
#define _WINUSER_ // winuser.h
#define interface struct
// What we need from dlgattr.h
#define OPTIONON L"Yes"
#define OPTIONOFF L"No"
//-----------------------------------------------------------------------------
// Definitions for UnixODBC Driver Manager
// Define this to enable driver code to conditionalize around UnixODBC Driver
// Manager "quirks"...
#ifndef MPLAT_WWOWH
#define UNIXODBC
#endif
/* can be defined in php sources */
#ifdef ODBCVER
#undef ODBCVER
#endif
// Build the mplat driver as an ODBC 3.8 driver, so that all of the
// source code shared with Windows SNAC (which is ODBC 3.8) compiles.
#define ODBCVER 0x0380
// Define this to indicate that we provide our own definitions for Windows types
#define ALLREADY_HAVE_WINDOWS_TYPE
// Definitions not otherwise provided in sqltypes.h, given that we define our own Windows types
#define SQL_API
typedef signed char SCHAR;
typedef SCHAR SQLSCHAR;
typedef int SDWORD;
typedef unsigned int UDWORD;
typedef signed short int SWORD;
typedef signed short SSHORT;
typedef double SDOUBLE;
typedef double LDOUBLE;
typedef float SFLOAT;
typedef void* PTR;
typedef signed short RETCODE;
typedef void* SQLHWND;
// Definitions missing from sql.h
#define SQL_PARAM_DATA_AVAILABLE 101
#define SQL_APD_TYPE (-100)
// Bid control bit, only for xplat
// It traces everything we current enabled for bid.
// The correlated tracing feature is not enabled.
#define DEFAULT_BID_CORT_BIT 0xFFFFBFFFF
// End definitions for UnixODBC SQL headers
// ----------------------------------------------------------------------------
#define UNREFERENCED_PARAMETER(arg)
// From share.h
#define _SH_DENYNO 0x40 /* deny none mode */
// WinNT.h
#define CONST const
#define VOID void
#define DLL_PROCESS_ATTACH 1
#define DLL_THREAD_ATTACH 2
#define DLL_THREAD_DETACH 3
#define DLL_PROCESS_DETACH 0
#define VER_GREATER_EQUAL 3
#define VER_MINORVERSION 0x0000001
#define VER_MAJORVERSION 0x0000002
#define VER_SERVICEPACKMINOR 0x0000010
#define VER_SERVICEPACKMAJOR 0x0000020
#define VER_SET_CONDITION(_m_,_t_,_c_) \
((_m_)=VerSetConditionMask((_m_),(_t_),(_c_)))
// Predeclared types from windef needed for remaining WinNT types
// to break circular dependency between WinNT.h and windef.h types.
//typedef ULONG DWORD;
typedef unsigned char BYTE;
typedef unsigned char UCHAR;
typedef UCHAR *PUCHAR;
typedef DWORD LCID;
typedef LONG HRESULT;
typedef char CHAR;
typedef CHAR *LPSTR, *PSTR;
typedef CHAR *PCHAR, *LPCH, *PCH;
typedef CONST CHAR *LPCCH, *PCCH;
#ifdef SQL_WCHART_CONVERT
typedef wchar_t WCHAR;
#else
typedef unsigned short WCHAR;
#endif
typedef WCHAR *LPWSTR;
typedef WCHAR *PWSTR;
typedef CONST WCHAR *LPCWSTR;
typedef CONST WCHAR *PCWSTR;
typedef CONST CHAR *LPCSTR, *PCSTR;
typedef void *PVOID;
typedef PVOID HANDLE;
typedef BYTE BOOLEAN;
typedef BOOLEAN *PBOOLEAN;
typedef HANDLE *PHANDLE;
typedef WCHAR *PWCHAR, *LPWCH, *PWCH;
typedef CONST WCHAR *LPCWCH, *PCWCH;
typedef int HFILE;
typedef short SHORT;
typedef CONST CHAR *LPCCH, *PCCH;
typedef unsigned short WORD;
#define RTL_NUMBER_OF_V1(A) (sizeof(A)/sizeof((A)[0]))
#define ARRAYSIZE(A) RTL_NUMBER_OF_V1(A)
#define STATUS_STACK_OVERFLOW ((DWORD )0xC00000FDL)
typedef union _LARGE_INTEGER {
struct {
DWORD LowPart;
LONG HighPart;
};
struct {
DWORD LowPart;
LONG HighPart;
} u;
LONGLONG QuadPart;
} LARGE_INTEGER;
typedef LARGE_INTEGER *PLARGE_INTEGER;
typedef void * RPC_IF_HANDLE;
typedef WORD LANGID;
typedef enum _HEAP_INFORMATION_CLASS {
HeapCompatibilityInformation,
HeapEnableTerminationOnCorruption
} HEAP_INFORMATION_CLASS;
#define REG_SZ ( 1 ) // Unicode nul terminated string
#define REG_DWORD ( 4 ) // 32-bit number
#define RTL_NUMBER_OF_V1(A) (sizeof(A)/sizeof((A)[0]))
#define RTL_NUMBER_OF(A) RTL_NUMBER_OF_V1(A)
// windef.h
typedef VOID *LPVOID;
typedef CONST void *LPCVOID;
typedef int INT;
typedef int *LPINT;
typedef unsigned int UINT;
typedef ULONGLONG UINT64;
typedef unsigned int *PUINT;
typedef unsigned char BYTE;
typedef BYTE *PBYTE;
typedef BYTE *LPBYTE;
typedef const BYTE *LPCBYTE;
#define _LPCBYTE_DEFINED
//typedef int BOOL;
typedef BOOL * LPBOOL;
typedef unsigned short WORD;
typedef WORD * LPWORD;
typedef WORD UWORD;
typedef DWORD * LPDWORD;
typedef DWORD * PDWORD;
typedef unsigned short USHORT;
#define CDECL // TODO _cdecl and cdecl not portable?
#define WINAPI // TODO __stdcall not portable?
#define MAX_PATH 260
typedef HANDLE HINSTANCE;
typedef HANDLE HGLOBAL;
typedef ULONGLONG DWORDLONG;
typedef DWORDLONG *PDWORDLONG;
typedef float FLOAT;
typedef struct _FILETIME {
DWORD dwLowDateTime;
DWORD dwHighDateTime;
} FILETIME, *PFILETIME, *LPFILETIME;
typedef double DOUBLE;
#define MAKELONG(a, b) ((LONG)(((WORD)(((DWORD_PTR)(a)) & 0xffff)) | ((DWORD)((WORD)(((DWORD_PTR)(b)) & 0xffff))) << 16))
// INT_PTR - http://msdn.microsoft.com/en-us/library/aa384154(VS.85).aspx
#ifdef _WIN64
typedef __int64 INT_PTR;
#else
typedef int INT_PTR;
#endif
typedef INT_PTR (*FARPROC)();
typedef INT_PTR (*NEARPROC)();
typedef INT_PTR (*PROC)();
DWORD GetFileSize(
__inn HANDLE hFile,
__out_opt LPDWORD lpFileSizeHigh
);
typedef union _ULARGE_INTEGER {
struct {
DWORD LowPart;
DWORD HighPart;
};
struct {
DWORD LowPart;
DWORD HighPart;
} u;
ULONGLONG QuadPart;
} ULARGE_INTEGER;
typedef ULARGE_INTEGER *PULARGE_INTEGER;
#ifndef IN
#define IN
#endif
#ifndef OUT
#define OUT
#endif
#ifndef OPTIONAL
#define OPTIONAL
#endif
ULONGLONG
VerSetConditionMask(
IN ULONGLONG ConditionMask,
IN DWORD TypeMask,
IN BYTE Condition
);
//#include <basetsd.h>
//// ntdef.h
#define __unaligned
#ifndef UNALIGNED
#define UNALIGNED
#endif
//typedef __nullterminated WCHAR UNALIGNED *LPUWSTR;
//// crtdefs.h
//#if !defined(_TRUNCATE)
//#define _TRUNCATE ((size_t)-1)
//#endif
//// ??
//typedef ULONG_PTR DWORD_PTR;
#define FALSE ((BOOL)0)
#define TRUE ((BOOL)1)
//// asoshost.h (excluded above)
//struct ISOSHost_MemObj;
//struct ISOSHost;
//extern ISOSHost_MemObj *g_pMO;
//extern ISOSHost *g_pISOSHost;
//inline HRESULT CreateSQLSOSHostInterface() { return 0; }
//inline HRESULT CreateGlobalSOSHostInterface() { return 0; }
//// These are temporary solution versions of the real files that contain the minimal declarations
//// needed to compile for non-Windows platforms. See the special include path for the
//// location of these files.
//#include <guiddef.h>
//#include <objbase.h>
//#include <winbase.h>
//#include <winnls.h>
#include <winerror.h>
//#include <wtypes.h>
//#include <wctype.h>
//#include <winuser.h>
//#include <stdio.h>
//#include <tchar.h>
//#include <winuser.h>
//#include <wincon.h>
//#define LMEM_FIXED 0
typedef void * HLOCAL;
HLOCAL LocalAlloc(UINT uFlags, SIZE_T uBytes);
//HLOCAL LocalReAlloc(HLOCAL hMem, SIZE_T uBytes, UINT uFlags);
HLOCAL LocalFree(HLOCAL hMem);
// End of xplat.h
#endif //__XPLAT_H__