Merge remote-tracking branch 'upstream/dev' into PerformanceTests

This commit is contained in:
ulvii 2017-06-02 16:16:19 -07:00
commit b4b3669d5b
473 changed files with 37477 additions and 12595 deletions

View file

@ -3,6 +3,46 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
## Windows/Linux/MAC 4.2.0-preview - 2017-05-19
Here is the list of updates:
### Added
- Added support for sql_variant data type with limitation ([issue #51](https://github.com/Microsoft/msphpsql/issues/51) and [issue #127](https://github.com/Microsoft/msphpsql/issues/127))
- Support drivers on Debian Jessie (tested on Debian 8.7)
### Fixed
- Increased Test Coverage to 75%
- Bug fixes after running static analysis
### Limitation
- No support for inout / output params when using sql_variant type
### Known Issues
- User defined data types
- When pooling is enabled in Linux or MAC
- unixODBC <= 2.3.4 (Linux and MAC) might not return proper diagnostics information, such as error messages, warnings and informative messages
- due to this unixODBC bug, fetch large data (such as xml, binary) as streams as a workaround. See the examples [here](https://github.com/Microsoft/msphpsql/wiki/Connection-Pooling-on-Linux-and-Mac)
## Windows/Linux/MAC 4.1.9-preview - 2017-05-08
- Updated documentation for Readme regarding instructions for Linux and MAC
- Updated PECL release packages. Here is the list of updates:
### Added
- Azure Active Directory Authentication with ActiveDirectoryPassword and SqlPassword
### Fixed
- Fixed output parameter returning garbage when the parameter is initialized to a type that is different from the output type ([issue #378](https://github.com/Microsoft/msphpsql/issues/378)).
#### PDO_SQLSRV only
- Fixed incorrectly binding of unicode parameter when emulate prepare is on and the encoding is set at the statement level ([issue #92](https://github.com/Microsoft/msphpsql/issues/92)).
- Fixed binary column binding when emulate prepare is on ([issue #140](https://github.com/Microsoft/msphpsql/issues/140)).
### Known Issues
- User defined data types and SQL_VARIANT ([issue #127](https://github.com/Microsoft/msphpsql/issues/127)).
- When pooling is enabled in Linux or MAC
- unixODBC 2.3.1 (Linux) and unixODBC 2.3.4 (MAC) might not return proper diagnostics information, such as error messages, warnings and informative messages
- due to this unixODBC bug, fetch large data (such as xml, binary) as streams as a workaround. See the examples [here](https://github.com/Microsoft/msphpsql/wiki/Connection-Pooling-on-Linux-and-Mac)
## Windows/Linux/MAC 4.1.8-preview - 2017-04-10
Updated documentation for Readme regarding instructions for Linux and MAC
Updated PECL release packages. Here is the list of updates:

View file

@ -68,12 +68,16 @@ RUN phpize && ./configure LDFLAGS="-lgcov" CXXFLAGS="-O0 --coverage" && make &&
# set name of sql server host to use
WORKDIR $PHPSQLDIR/test/pdo_sqlsrv
RUN sed -i -e 's/localhost/sql/g' autonomous_setup.php
RUN sed -i -e 's/<YourStrong!Passw0rd>/'"$TEST_PHP_SQL_PWD"'/g' autonomous_setup.php
RUN sed -i -e 's/TARGET_SERVER/sql/g' MsSetup.inc
RUN sed -i -e 's/TARGET_DATABASE/msphpsql_pdosqlsrv/g' MsSetup.inc
RUN sed -i -e 's/TARGET_USERNAME/'"$TEST_PHP_SQL_UID"'/g' MsSetup.inc
RUN sed -i -e 's/TARGET_PASSWORD/'"$TEST_PHP_SQL_PWD"'/g' MsSetup.inc
WORKDIR $PHPSQLDIR/test/sqlsrv
RUN sed -i -e 's/localhost/sql/g' autonomous_setup.php
RUN sed -i -e 's/<YourStrong!Passw0rd>/'"$TEST_PHP_SQL_PWD"'/g' autonomous_setup.php
RUN sed -i -e 's/TARGET_SERVER/sql/g' MsSetup.inc
RUN sed -i -e 's/TARGET_DATABASE/msphpsql_sqlsrv/g' MsSetup.inc
RUN sed -i -e 's/TARGET_USERNAME/'"$TEST_PHP_SQL_UID"'/g' MsSetup.inc
RUN sed -i -e 's/TARGET_PASSWORD/'"$TEST_PHP_SQL_PWD"'/g' MsSetup.inc
ENV REPORT_EXIT_STATUS 1
ENV TEST_PHP_EXECUTABLE /usr/bin/php

View file

@ -2,7 +2,7 @@
**Welcome to the Microsoft Drivers for PHP for SQL Server PHP 7**
The Microsoft Drivers for PHP for SQL Server are PHP extensions that allow for the reading and writing of SQL Server data from within PHP scripts. The SQLSRV extension provides a procedural interface while the PDO_SQLSRV extension implements PDO for accessing data in all editions of SQL Server 2005 and later (including Azure SQL DB). These drivers rely on the Microsoft ODBC Driver for SQL Server to handle the low-level communication with SQL Server.
The Microsoft Drivers for PHP for SQL Server are PHP extensions that allow for the reading and writing of SQL Server data from within PHP scripts. The SQLSRV extension provides a procedural interface while the PDO_SQLSRV extension implements PDO for accessing data in all editions of SQL Server 2008 R2 and later (including Azure SQL DB). These drivers rely on the Microsoft ODBC Driver for SQL Server to handle the low-level communication with SQL Server.
This release contains the SQLSRV and PDO_SQLSRV drivers for PHP 7 with improvements on both drivers and some limitations (see Limitations below for details). Upcoming release(s) will contain more functionality, bug fixes, and more (see Plans below for more details).
@ -29,9 +29,9 @@ Thank you for taking time to take our February survey. Let us know how we are do
## Get Started
* [**Ubuntu + SQL Server + PHP 7**](https://www.microsoft.com/en-us/sql-server/developer-get-started/php-ubuntu)
* [**RedHat + SQL Server + PHP 7**](https://www.microsoft.com/en-us/sql-server/developer-get-started/php-rhel)
* [**Windows + SQL Server + PHP 7**](https://www.microsoft.com/en-us/sql-server/developer-get-started/php-windows)
* [**Ubuntu + SQL Server + PHP 7**](https://www.microsoft.com/en-us/sql-server/developer-get-started/php/ubuntu)
* [**RedHat + SQL Server + PHP 7**](https://www.microsoft.com/en-us/sql-server/developer-get-started/php/rhel)
* [**Windows + SQL Server + PHP 7**](https://www.microsoft.com/en-us/sql-server/developer-get-started/php/windows)
* [**Docker**](https://hub.docker.com/r/lbosqmsft/mssql-php-msphpsql/)
@ -205,7 +205,7 @@ The following instructions assume a clean environment and show how to install PH
**Mac OS X**
brew tap microsoft/mssql-preview https://github.com/Microsoft/homebrew-mssql-preview
brew tap microsoft/msodbcsql https://github.com/Microsoft/homebrew-mssql-release
brew update
brew install msodbcsql
brew install mssql-tools

View file

@ -56,7 +56,6 @@ environment:
PHP_INSTALL_DIR: c:\projects\php\x86\bin
PHP_ZTS: --disable-zts
platform: x86
# PHP_MAJOR_VER is PHP major version to build (7.0, 7.1)
# PHP_MINOR_VER is PHP point release number (or latest for latest release)
@ -112,20 +111,22 @@ install:
- move php-sdk-binary-tools-20110915.zip ..
- echo Downloading PHP source code [%PHP_VERSION%]
- ps: (new-object net.webclient).DownloadFile('http://windows.php.net/downloads/releases/php-' + ${env:PHP_VERSION} + '-src.zip', ${env:APPVEYOR_BUILD_FOLDER} + '\..\php.zip')
#- echo Downloading PHP deps [%PHP_DEPSVER%]
#- ps: (new-object net.webclient).DownloadFile('http://windows.php.net/downloads/php-sdk/deps-' + ${env:PHP_DEPSVER} + '-vc' + ${env:PHP_VC} + '-' + ${env:BUILD_PLATFORM} + '.7z', ${env:APPVEYOR_BUILD_FOLDER} + '\..\deps.7z')
- echo Downloading MSODBCSQL 13
- ps: (new-object net.webclient).DownloadFile('https://download.microsoft.com/download/1/E/7/1E7B1181-3974-4B29-9A47-CC857B271AA2/English/' + ${env:BUILD_PLATFORM} + '/msodbcsql.msi', 'msodbcsql.msi')
- ps: msiexec /i msodbcsql.msi /quiet /qn /norestart
- echo Downloading MSODBCSQL 13.1
# AppVeyor build works are x64 VMs and 32-bit ODBC driver cannot be installed on it
- ps: (new-object net.webclient).DownloadFile('https://download.microsoft.com/download/D/5/E/D5EEF288-A277-45C8-855B-8E2CB7E25B96/x64/msodbcsql.msi', 'c:\projects\msodbcsql.msi')
- cmd /c start /wait msiexec /i "c:\projects\msodbcsql.msi" /q
- echo Checking the version of MSODBCSQL
- reg query "HKLM\SOFTWARE\ODBC\odbcinst.ini\ODBC Driver 13 for SQL Server"
- dir C:\Windows\System32\msodbcsql13.dll
- cd ..
- cd
- 7z x -y php-sdk-binary-tools-20110915.zip -o%PHP_SDK%
- 7z x -y php.zip -o%PHP_SDK_DIR%
- echo update SQL connection string
- ps: (Get-Content ${env:APPVEYOR_BUILD_FOLDER}\test\pdo_sqlsrv\autonomous_setup.php) | ForEach-Object { $_ -replace "localhost", ${env:TEST_PHP_SQL_SERVER} -replace "<YourStrong!Passw0rd>", ${env:TEST_PHP_SQL_PWD} } | Set-Content ${env:APPVEYOR_BUILD_FOLDER}\test\pdo_sqlsrv\autonomous_setup.php
- ps: Get-Content ${env:APPVEYOR_BUILD_FOLDER}\test\pdo_sqlsrv\autonomous_setup.php
- ps: (Get-Content ${env:APPVEYOR_BUILD_FOLDER}\test\sqlsrv\autonomous_setup.php) | ForEach-Object { $_ -replace "localhost", ${env:TEST_PHP_SQL_SERVER} -replace "<YourStrong!Passw0rd>", ${env:TEST_PHP_SQL_PWD} } | Set-Content ${env:APPVEYOR_BUILD_FOLDER}\test\sqlsrv\autonomous_setup.php
- ps: Get-Content ${env:APPVEYOR_BUILD_FOLDER}\test\sqlsrv\autonomous_setup.php
- ps: (Get-Content ${env:APPVEYOR_BUILD_FOLDER}\test\pdo_sqlsrv\MsSetup.inc) | ForEach-Object { $_ -replace "TARGET_SERVER", ${env:TEST_PHP_SQL_SERVER} -replace "TARGET_DATABASE", ${env:PDOSQLSRV_DBNAME} -replace "TARGET_USERNAME", ${env:TEST_PHP_SQL_UID} -replace "TARGET_PASSWORD", ${env:TEST_PHP_SQL_PWD} } | Set-Content ${env:APPVEYOR_BUILD_FOLDER}\test\pdo_sqlsrv\MsSetup.inc
- ps: Get-Content ${env:APPVEYOR_BUILD_FOLDER}\test\pdo_sqlsrv\MsSetup.inc
- ps: (Get-Content ${env:APPVEYOR_BUILD_FOLDER}\test\sqlsrv\MsSetup.inc) | ForEach-Object { $_ -replace "TARGET_SERVER", ${env:TEST_PHP_SQL_SERVER} -replace "TARGET_DATABASE", ${env:SQLSRV_DBNAME} -replace "TARGET_USERNAME", ${env:TEST_PHP_SQL_UID} -replace "TARGET_PASSWORD", ${env:TEST_PHP_SQL_PWD} } | Set-Content ${env:APPVEYOR_BUILD_FOLDER}\test\sqlsrv\MsSetup.inc
- ps: Get-Content ${env:APPVEYOR_BUILD_FOLDER}\test\sqlsrv\MsSetup.inc
build_script:
- '"C:\\Program Files (x86)\\Microsoft Visual Studio %PHP_VC%.0\\VC\\vcvarsall.bat" %BUILD_PLATFORM%'

View file

@ -3,7 +3,7 @@
//
// Contents: JScript build configuration used by buildconf.bat
//
// Microsoft Drivers 4.1 for PHP for SQL Server
// Microsoft Drivers 4.2 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License

View file

@ -3,7 +3,7 @@
//
// Contents: Implements the PDO object for PDO_SQLSRV
//
// Microsoft Drivers 4.1 for PHP for SQL Server
// Microsoft Drivers 4.2 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -41,6 +41,7 @@ const char APP[] = "APP";
const char ApplicationIntent[] = "ApplicationIntent";
const char AttachDBFileName[] = "AttachDbFileName";
const char ConnectionPooling[] = "ConnectionPooling";
const char Authentication[] = "Authentication";
#ifdef _WIN32
const char ConnectRetryCount[] = "ConnectRetryCount";
const char ConnectRetryInterval[] = "ConnectRetryInterval";
@ -200,6 +201,15 @@ const connection_option PDO_CONN_OPTS[] = {
CONN_ATTR_STRING,
conn_str_append_func::func
},
{
PDOConnOptionNames::Authentication,
sizeof( PDOConnOptionNames::Authentication ),
SQLSRV_CONN_OPTION_AUTHENTICATION,
ODBCConnOptions::Authentication,
sizeof( ODBCConnOptions::Authentication ),
CONN_ATTR_STRING,
conn_str_append_func::func
},
{
PDOConnOptionNames::ConnectionPooling,
sizeof( PDOConnOptionNames::ConnectionPooling ),

View file

@ -3,7 +3,7 @@
//
// Contents: initialization routines for PDO_SQLSRV
//
// Microsoft Drivers 4.1 for PHP for SQL Server
// Microsoft Drivers 4.2 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License

View file

@ -5,7 +5,7 @@
//
// Copyright Microsoft Corporation
//
// Microsoft Drivers 4.1 for PHP for SQL Server
// Microsoft Drivers 4.2 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -139,7 +139,7 @@ void string_parser::add_key_value_pair( const char* value, int len TSRMLS_DC )
void sql_string_parser::add_key_int_value_pair( unsigned int value TSRMLS_DC ) {
zval value_z;
ZVAL_LONG( &value_z, value );
core::sqlsrv_zend_hash_index_update( *ctx, this->element_ht, this->current_key, &value_z TSRMLS_CC );
}
@ -169,6 +169,31 @@ void conn_string_parser::validate_key(const char *key, int key_len TSRMLS_DC )
THROW_PDO_ERROR( this->ctx, PDO_SQLSRV_ERROR_INVALID_DSN_KEY, static_cast<char*>( key_name ) );
}
void conn_string_parser::add_key_value_pair( const char* value, int len TSRMLS_DC )
{
// if the keyword is 'Authentication', check whether the user specified option is supported
bool valid = true;
if ( stricmp( this->current_key_name, ODBCConnOptions::Authentication ) == 0 ) {
if (len <= 0)
valid = false;
else {
// extract option from the value by len
sqlsrv_malloc_auto_ptr<char> option;
option = static_cast<char*>( sqlsrv_malloc( len + 1 ) );
memcpy_s( option, len + 1, value, len );
option[len] = '\0';
valid = core_is_authentication_option_valid( option, len );
}
}
if( !valid ) {
THROW_PDO_ERROR( this->ctx, PDO_SQLSRV_ERROR_INVALID_AUTHENTICATION_OPTION, this->current_key_name );
}
string_parser::add_key_value_pair( value, len );
}
inline bool sql_string_parser::is_placeholder_char( char c )
{
// placeholder only accepts numbers, upper and lower case alphabets and underscore
@ -390,9 +415,12 @@ void conn_string_parser:: parse_conn_string( TSRMLS_D )
// Primary function which parses out the named placeholders from a sql string.
void sql_string_parser::parse_sql_string( TSRMLS_D ) {
try {
int start_pos = -1;
while ( !this->is_eos() ) {
int start_pos = -1;
// if pos is -1, then reading from a string is an initialized read
if ( pos == -1 ) {
next();
}
// skip until a '"', '\'', ':' or '?'
char sym;
while ( this->orig_str[pos] != '"' && this->orig_str[pos] != '\'' && this->orig_str[pos] != ':' && this->orig_str[pos] != '?' && !this->is_eos() ) {
@ -411,7 +439,7 @@ void sql_string_parser::parse_sql_string( TSRMLS_D ) {
start_pos = this->pos;
next();
// keep going until the next space or line break
// while (!is_white_space(this->orig_str[pos]) && !this->is_eos()) {
// while (!is_white_space(this->orig_str[pos]) && !this->is_eos()) {
while ( is_placeholder_char( this->orig_str[pos] )) {
next();
}

View file

@ -3,7 +3,7 @@
//
// Contents: Implements the PDOStatement object for the PDO_SQLSRV
//
// Microsoft Drivers 4.1 for PHP for SQL Server
// Microsoft Drivers 4.2 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -1355,6 +1355,7 @@ sqlsrv_phptype pdo_sqlsrv_stmt::sql_type_to_php_type( SQLINTEGER sql_type, SQLUI
case SQL_LONGVARCHAR:
case SQL_WLONGVARCHAR:
case SQL_SS_XML:
case SQL_SS_VARIANT:
sqlsrv_phptype.typeinfo.type = SQLSRV_PHPTYPE_STRING;
break;
case SQL_BINARY:

View file

@ -3,7 +3,7 @@
//
// Contents: Utility functions used by both connection or statement functions
//
// Microsoft Drivers 4.1 for PHP for SQL Server
// Microsoft Drivers 4.2 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -377,6 +377,10 @@ pdo_error PDO_ERRORS[] = {
PDO_SQLSRV_ERROR_EMULATE_INOUT_UNSUPPORTED,
{ IMSSP, (SQLCHAR*) "Statement with emulate prepare on does not support output or input_output parameters.", -72, false }
},
{
PDO_SQLSRV_ERROR_INVALID_AUTHENTICATION_OPTION,
{ IMSSP, (SQLCHAR*) "Invalid option for the Authentication keyword. Only SqlPassword or ActiveDirectoryPassword is supported.", -73, false }
},
{ UINT_MAX, {} }
};
@ -558,15 +562,15 @@ namespace {
// Place get_error_message into the anonymous namespace in pdo_util.cpp
sqlsrv_error_const* get_error_message(unsigned int sqlsrv_error_code) {
sqlsrv_error_const *error_message = NULL;
int zr = (error_message = reinterpret_cast<sqlsrv_error_const*>(zend_hash_index_find_ptr(g_pdo_errors_ht, sqlsrv_error_code))) != NULL ? SUCCESS : FAILURE;
if (zr == FAILURE) {
DIE("get_error_message: zend_hash_index_find returned failure for sqlsrv_error_code = %1!d!", sqlsrv_error_code);
}
sqlsrv_error_const *error_message = NULL;
int zr = (error_message = reinterpret_cast<sqlsrv_error_const*>(zend_hash_index_find_ptr(g_pdo_errors_ht, sqlsrv_error_code))) != NULL ? SUCCESS : FAILURE;
if (zr == FAILURE) {
DIE("get_error_message: zend_hash_index_find returned failure for sqlsrv_error_code = %1!d!", sqlsrv_error_code);
}
SQLSRV_ASSERT(error_message != NULL, "get_error_message: error_message was null");
SQLSRV_ASSERT(error_message != NULL, "get_error_message: error_message was null");
return error_message;
return error_message;
}
void pdo_sqlsrv_throw_exception( sqlsrv_error_const* error TSRMLS_DC )

View file

@ -6,7 +6,7 @@
//
// Contents: Declarations for the extension
//
// Microsoft Drivers 4.1 for PHP for SQL Server
// Microsoft Drivers 4.2 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -165,6 +165,9 @@ class conn_string_parser : private string_parser
int discard_trailing_white_spaces(const char* str, int len);
void validate_key(const char *key, int key_len TSRMLS_DC);
protected:
void add_key_value_pair(const char* value, int len TSRMLS_DC);
public:
conn_string_parser( sqlsrv_context& ctx, const char* dsn, int len, _Inout_ HashTable* conn_options_ht );
void parse_conn_string( TSRMLS_D );
@ -390,6 +393,7 @@ enum PDO_ERROR_CODES {
PDO_SQLSRV_ERROR_INVALID_OUTPUT_PARAM_TYPE,
PDO_SQLSRV_ERROR_INVALID_CURSOR_WITH_SCROLL_TYPE,
PDO_SQLSRV_ERROR_EMULATE_INOUT_UNSUPPORTED,
PDO_SQLSRV_ERROR_INVALID_AUTHENTICATION_OPTION
};
extern pdo_error PDO_ERRORS[];

View file

@ -3,7 +3,7 @@
//
// Contents: Version resource
//
// Microsoft Drivers 4.1 for PHP for SQL Server
// Microsoft Drivers 4.2 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License

View file

@ -6,7 +6,7 @@
// Contents: Contains functions for handling Windows format strings
// and UTF-16 on non-Windows platforms
//
// Microsoft Drivers 4.1 for PHP for SQL Server
// Microsoft Drivers 4.2 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -23,39 +23,20 @@
#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_def.h"
#endif
#include "sal_def.h"
#ifndef _WIN32
#define PTR_IS_INT64 1
#else
#define PTR_IS_INT64 0
#endif // !_WIN32
#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
@ -233,10 +214,6 @@ static const unsigned char __lookuptable_s[] = {
/* '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));
@ -251,10 +228,6 @@ 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
@ -277,22 +250,6 @@ errno_t mplat_wctomb_s(
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 )
{
@ -312,16 +269,8 @@ void _CFLTCVT( double * dbl, char * buf, int bufSize, char fmt, int precision, i
// 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
}
@ -406,85 +355,6 @@ static enum STATE ProcessSizeA( char sizeCh, char fmt_ch, char next_fmt_ch, int
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;
@ -1075,607 +945,6 @@ int FormattedPrintA( IFormattedPrintOutput<char> * output, const char *format, v
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
@ -1944,205 +1213,6 @@ static bool GetFormatMessageArgsA( const char * format, std::vector< vararg_t >
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 )
@ -2314,177 +1384,24 @@ static DWORD FormatMessageToBufferA( const char * format, char * buffer, DWORD b
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;
}
// 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 FormatMessageA(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, DWORD dwLanguageId, LPTSTR lpBuffer, DWORD nSize, va_list *Arguments)
{
@ -2578,115 +1495,6 @@ DWORD FormatMessageA(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, DWORD d
}
// 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)
@ -2730,21 +1538,6 @@ BOOL IsDBCSLeadByteEx(
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 );
@ -2760,17 +1553,6 @@ int mplat_snprintf_s( char *buffer, size_t bufsize, size_t count, const char *fo
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;

View file

@ -4,7 +4,7 @@
// Contents: Contains functions for handling Windows format strings
// and UTF-16 on non-Windows platforms
//
// Microsoft Drivers 4.1 for PHP for SQL Server
// Microsoft Drivers 4.2 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -24,12 +24,6 @@
#include "xplat_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
@ -73,7 +67,6 @@ protected:
};
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>

View file

@ -3,7 +3,7 @@
//
// Contents: Contains functions for handling UTF-16 on non-Windows platforms
//
// Microsoft Drivers 4.1 for PHP for SQL Server
// Microsoft Drivers 4.2 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -136,7 +136,6 @@ int mplat_strcat_s( char * dest, size_t destSize, const char * src )
errno = ERANGE;
return ERANGE;
}
*p = 0;
return 0;
}
//

View file

@ -3,7 +3,7 @@
//
// Contents: Contains functions for handling UTF-16 on non-Windows platforms
//
// Microsoft Drivers 4.1 for PHP for SQL Server
// Microsoft Drivers 4.2 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License

View file

@ -92,7 +92,7 @@ void common_conn_str_append_func( const char* odbc_name, const char* val, size_t
sqlsrv_conn* core_sqlsrv_connect( sqlsrv_context& henv_cp, sqlsrv_context& henv_ncp, driver_conn_factory conn_factory,
const char* server, const char* uid, const char* pwd,
HashTable* options_ht, error_callback err, const connection_option valid_conn_opts[],
void* driver, const char* driver_func TSRMLS_DC )
void* driver, const char* driver_func TSRMLS_DC )
{
SQLRETURN r;
@ -112,7 +112,7 @@ sqlsrv_conn* core_sqlsrv_connect( sqlsrv_context& henv_cp, sqlsrv_context& henv_
// Due to the limitations on connection pooling in unixODBC 2.3.1 driver manager, we do not consider
// the connection string attributes to set (enable/disable) connection pooling.
// Instead, MSPHPSQL connection pooling is set according to the ODBCINST.INI file in [ODBC] section.
#ifndef _WIN32
char pooling_string[ 128 ] = {0};
SQLGetPrivateProfileString( "ODBC", "Pooling", "0", pooling_string, sizeof( pooling_string ), "ODBCINST.INI" );
@ -128,7 +128,7 @@ sqlsrv_conn* core_sqlsrv_connect( sqlsrv_context& henv_cp, sqlsrv_context& henv_
// it in build_connection_string_and_set_conn_attr.
if( options_ht && zend_hash_num_elements( options_ht ) > 0 ) {
zval* option_z = NULL;
option_z = zend_hash_index_find(options_ht, SQLSRV_CONN_OPTION_CONN_POOLING);
if ( option_z ) {
@ -163,18 +163,18 @@ sqlsrv_conn* core_sqlsrv_connect( sqlsrv_context& henv_cp, sqlsrv_context& henv_
SQLSMALLINT output_conn_size;
#ifndef _WIN32
// unixODBC 2.3.1 requires a non-wide SQLDriverConnect call while pooling enabled.
// connection handle has been allocated using henv_cp, means pooling enabled in a PHP script
if ( henv == &henv_cp )
{
r = SQLDriverConnect( conn->handle(), NULL, (SQLCHAR*)conn_str.c_str(), SQL_NTS, NULL, 0, &output_conn_size, SQL_DRIVER_NOPROMPT );
}
else
{
r = SQLDriverConnectW( conn->handle(), NULL, reinterpret_cast<SQLWCHAR*>( wconn_string.get() ), static_cast<SQLSMALLINT>( wconn_len ), NULL, 0, &output_conn_size, SQL_DRIVER_NOPROMPT );
// unixODBC 2.3.1 requires a non-wide SQLDriverConnect call while pooling enabled.
// connection handle has been allocated using henv_cp, means pooling enabled in a PHP script
if ( henv == &henv_cp )
{
r = SQLDriverConnect( conn->handle(), NULL, (SQLCHAR*)conn_str.c_str(), SQL_NTS, NULL, 0, &output_conn_size, SQL_DRIVER_NOPROMPT );
}
else
{
r = SQLDriverConnectW( conn->handle(), NULL, reinterpret_cast<SQLWCHAR*>( wconn_string.get() ), static_cast<SQLSMALLINT>( wconn_len ), NULL, 0, &output_conn_size, SQL_DRIVER_NOPROMPT );
}
#else
r = SQLDriverConnectW( conn->handle(), NULL, reinterpret_cast<SQLWCHAR*>( wconn_string.get() ), static_cast<SQLSMALLINT>( wconn_len ), NULL, 0, &output_conn_size, SQL_DRIVER_NOPROMPT );
r = SQLDriverConnectW( conn->handle(), NULL, reinterpret_cast<SQLWCHAR*>( wconn_string.get() ), static_cast<SQLSMALLINT>( wconn_len ), NULL, 0, &output_conn_size, SQL_DRIVER_NOPROMPT );
#endif // !_WIN32
// clear the connection string from memory to remove sensitive data (such as a password).
@ -215,11 +215,11 @@ sqlsrv_conn* core_sqlsrv_connect( sqlsrv_context& henv_cp, sqlsrv_context& henv_
// but fails if the connection is using a pool, i.e. r= SQL_SUCCESS.
// Thus, in Linux, we don't call determine_server_version() for a connection that uses pool.
#ifndef _WIN32
if ( r == SQL_SUCCESS_WITH_INFO ) {
if ( r == SQL_SUCCESS_WITH_INFO ) {
#endif // !_WIN32
determine_server_version( conn TSRMLS_CC );
#ifndef _WIN32
}
}
#endif // !_WIN32
}
catch( std::bad_alloc& ) {
@ -550,6 +550,20 @@ bool core_is_conn_opt_value_escaped( const char* value, size_t value_len )
return true;
}
// core_is_authentication_option_valid
// if the option for the authentication is valid, returns true. This returns false otherwise.
bool core_is_authentication_option_valid(const char* value, size_t value_len)
{
if (value_len <= 0)
return false;
if( ! stricmp( value, AzureADOptions::AZURE_AUTH_SQL_PASSWORD ) || ! stricmp( value, AzureADOptions::AZURE_AUTH_AD_PASSWORD ) ) {
return true;
}
return false;
}
// *** internal connection functions and classes ***
@ -625,33 +639,33 @@ void build_connection_string_and_set_conn_attr( sqlsrv_conn* conn, const char* s
if( zend_hash_index_exists( options, SQLSRV_CONN_OPTION_TRACE_FILE )) {
zval* trace_value = NULL;
trace_value = zend_hash_index_find(options, SQLSRV_CONN_OPTION_TRACE_ON);
trace_value = zend_hash_index_find(options, SQLSRV_CONN_OPTION_TRACE_ON);
if (trace_value == NULL || !zend_is_true(trace_value)) {
if (trace_value == NULL || !zend_is_true(trace_value)) {
zend_hash_index_del( options, SQLSRV_CONN_OPTION_TRACE_FILE );
}
}
zend_string *key = NULL;
zend_ulong index = -1;
zval* data = NULL;
zend_string *key = NULL;
zend_ulong index = -1;
zval* data = NULL;
ZEND_HASH_FOREACH_KEY_VAL( options, index, key, data ) {
int type = HASH_KEY_NON_EXISTENT;
type = key ? HASH_KEY_IS_STRING : HASH_KEY_IS_LONG;
ZEND_HASH_FOREACH_KEY_VAL( options, index, key, data ) {
int type = HASH_KEY_NON_EXISTENT;
type = key ? HASH_KEY_IS_STRING : HASH_KEY_IS_LONG;
// The driver layer should ensure a valid key.
DEBUG_SQLSRV_ASSERT(( type == HASH_KEY_IS_LONG ), "build_connection_string_and_set_conn_attr: invalid connection option key type." );
// The driver layer should ensure a valid key.
DEBUG_SQLSRV_ASSERT(( type == HASH_KEY_IS_LONG ), "build_connection_string_and_set_conn_attr: invalid connection option key type." );
conn_opt = get_connection_option( conn, index, valid_conn_opts TSRMLS_CC );
conn_opt = get_connection_option( conn, index, valid_conn_opts TSRMLS_CC );
if( index == SQLSRV_CONN_OPTION_MARS ) {
mars_mentioned = true;
}
if( index == SQLSRV_CONN_OPTION_MARS ) {
mars_mentioned = true;
}
conn_opt->func( conn_opt, data, conn, connection_string TSRMLS_CC );
} ZEND_HASH_FOREACH_END();
conn_opt->func( conn_opt, data, conn, connection_string TSRMLS_CC );
} ZEND_HASH_FOREACH_END();
// MARS on if not explicitly turned off
if( !mars_mentioned ) {
@ -707,7 +721,7 @@ const char* get_processor_arch( void )
return PROCESSOR_ARCH[2];
} else {
DIE( "Unknown processor architecture." );
}
}
return NULL;
#else
SYSTEM_INFO sys_info;
@ -727,7 +741,7 @@ const char* get_processor_arch( void )
DIE( "Unknown Windows processor architecture." );
return NULL;
}
return NULL;
return NULL;
#endif // !_WIN32
}
@ -747,7 +761,7 @@ void determine_server_version( sqlsrv_conn* conn TSRMLS_DC )
errno = 0;
char version_major_str[ 3 ];
SERVER_VERSION version_major;
memcpy_s( version_major_str, sizeof( version_major_str ), p, 2 );
memcpy_s( version_major_str, sizeof( version_major_str ), p, 2 );
version_major_str[ 2 ] = '\0';
version_major = static_cast<SERVER_VERSION>( atoi( version_major_str ));
@ -817,7 +831,7 @@ size_t core_str_zval_is_true( zval* value_z )
}
// save adjustments to the value made by stripping whitespace at the end
Z_STRLEN_P( value_z ) = val_len;
Z_STRLEN_P( value_z ) = val_len;
const char VALID_TRUE_VALUE_1[] = "true";
const char VALID_TRUE_VALUE_2[] = "1";

View file

@ -180,6 +180,11 @@ const int SQL_SERVER_2005_DEFAULT_DATETIME_SCALE = 3;
const int SQL_SERVER_2008_DEFAULT_DATETIME_PRECISION = 34;
const int SQL_SERVER_2008_DEFAULT_DATETIME_SCALE = 7;
namespace AzureADOptions {
const char AZURE_AUTH_SQL_PASSWORD[] = "SqlPassword";
const char AZURE_AUTH_AD_PASSWORD[] = "ActiveDirectoryPassword";
}
// types for conversions on output parameters (though they can be used for input parameters, they are ignored)
enum SQLSRV_PHPTYPE {
MIN_SQLSRV_PHPTYPE = 1, // lowest value for a php type
@ -1077,6 +1082,7 @@ namespace ODBCConnOptions {
const char APP[] = "APP";
const char ApplicationIntent[] = "ApplicationIntent";
const char AttachDBFileName[] = "AttachDbFileName";
const char Authentication[] = "Authentication";
const char CharacterSet[] = "CharacterSet";
const char ConnectionPooling[] = "ConnectionPooling";
#ifdef _WIN32
@ -1121,6 +1127,7 @@ enum SQLSRV_CONN_OPTIONS {
SQLSRV_CONN_OPTION_ATTACHDBFILENAME,
SQLSRV_CONN_OPTION_APPLICATION_INTENT,
SQLSRV_CONN_OPTION_MULTI_SUBNET_FAILOVER,
SQLSRV_CONN_OPTION_AUTHENTICATION,
#ifdef _WIN32
SQLSRV_CONN_OPTION_CONN_RETRY_COUNT,
SQLSRV_CONN_OPTION_CONN_RETRY_INTERVAL,
@ -1190,6 +1197,7 @@ void core_sqlsrv_get_server_version( sqlsrv_conn* conn, _Out_ zval *server_versi
void core_sqlsrv_get_client_info( sqlsrv_conn* conn, _Out_ zval *client_info TSRMLS_DC );
bool core_is_conn_opt_value_escaped( const char* value, size_t value_len );
size_t core_str_zval_is_true( zval* str_zval );
bool core_is_authentication_option_valid( const char* value, size_t value_len );
//*********************************************************************************************************************************
// Statement

View file

@ -1441,6 +1441,7 @@ void calc_string_size( sqlsrv_stmt* stmt, SQLUSMALLINT field_index, SQLLEN sql_t
case SQL_TYPE_DATE:
case SQL_SS_TIME2:
case SQL_SS_TIMESTAMPOFFSET:
case SQL_SS_VARIANT:
{
// unixODBC 2.3.1 requires wide calls to support pooling
core::SQLColAttributeW( stmt, field_index + 1, SQL_DESC_DISPLAY_SIZE, NULL, 0, NULL, &size TSRMLS_CC );

View file

@ -4,7 +4,7 @@
// Contents: Contains functions for handling Windows format strings
// and UTF-16 on non-Windows platforms
//
// Microsoft Drivers 4.1 for PHP for SQL Server
// Microsoft Drivers 4.2 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -25,7 +25,6 @@
#include "typedefs_for_linux.h"
#include <errno.h>
#if defined(MPLAT_UNIX)
#include <iconv.h>
const iconv_t INVALID_ICONV = (iconv_t)(-1);
@ -48,14 +47,12 @@ public:
}
};
#endif
class EncodingConverter
{
UINT m_dstCodePage;
UINT m_srcCodePage;
#if defined(MPLAT_UNIX)
const IConvCache * m_pCvtCache;
bool IsValidIConv() const
@ -269,21 +266,6 @@ class EncodingConverter
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 );
@ -300,7 +282,6 @@ public:
const SrcType * srcBuffer, size_t cchSource,
bool failIfLossy = false, bool * pHasLoss = NULL, DWORD * pErrorCode = NULL ) const
{
#if defined(MPLAT_UNIX)
if ( !IsValidIConv() )
return 0;
@ -353,68 +334,6 @@ public:
}
}
#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.
@ -425,7 +344,6 @@ public:
const SrcType * srcBuffer, size_t cchSource,
bool failIfLossy = false, bool * pHasLoss = NULL, DWORD * pErrorCode = NULL ) const
{
#if defined(MPLAT_UNIX)
if ( !IsValidIConv() )
return 0;
@ -471,46 +389,6 @@ public:
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)
}
};

View file

@ -4,7 +4,7 @@
// Contents: Contains a portable abstraction for interlocked, atomic
// operations on int32_t and pointer types.
//
// Microsoft Drivers 4.1 for PHP for SQL Server
// Microsoft Drivers 4.2 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -24,30 +24,10 @@
// 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
//

View file

@ -4,7 +4,7 @@
// Contents: Contains a portable abstraction for interlocked, atomic
// operations on int32_t and pointer types.
//
// Microsoft Drivers 4.1 for PHP for SQL Server
// Microsoft Drivers 4.2 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -25,39 +25,9 @@
#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

@ -4,7 +4,7 @@
// Contents: Contains a portable abstraction for interlocked, singly
// linked list.
//
// Microsoft Drivers 4.1 for PHP for SQL Server
// Microsoft Drivers 4.2 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License

View file

@ -3,7 +3,7 @@
//
// Contents: Contains portable classes for localization
//
// Microsoft Drivers 4.1 for PHP for SQL Server
// Microsoft Drivers 4.2 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -24,14 +24,10 @@
#include <assert.h>
#include "typedefs_for_linux.h"
#ifdef MPLAT_UNIX
#include <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.
@ -110,23 +106,6 @@ struct AutoArray
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;
}
}
};
@ -135,138 +114,11 @@ 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 )
{
@ -283,51 +135,10 @@ public:
// 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()).
@ -336,74 +147,26 @@ public:
// 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 );
__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 );
__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);
__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);
// -----------------------------------------------------------------------
// 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:
@ -414,9 +177,6 @@ private:
SystemLocale( const SystemLocale & );
SystemLocale & operator=( const SystemLocale & );
#ifdef MPLAT_UNIX
// MPLAT_UNIX ----------------------------------------------------------------
std::locale * m_pLocale;
explicit SystemLocale( const char * localeName );
@ -428,51 +188,6 @@ private:
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 )
{
@ -492,95 +207,11 @@ private:
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 ----------------------------------------------------------------
// Inlines
#include "globalization.h"
@ -589,11 +220,6 @@ 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 );
@ -612,264 +238,4 @@ inline UINT SystemLocale::MaxCharCchSize( UINT codepage )
}
}
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

@ -2,10 +2,10 @@
// 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
// 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.1 for PHP for SQL Server
// Microsoft Drivers 4.2 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -75,8 +75,6 @@ const cp_iconv cp_iconv::g_cp_iconv[] = {
};
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];
@ -110,7 +108,7 @@ class IConvCachePool
{
for ( int srcIdx = 0; srcIdx < cp_iconv::g_cp_iconv_count; ++srcIdx )
{
IConvCache * pNode = static_cast<IConvCache*>( InterlockedFlushSList(&m_Pool[dstIdx][srcIdx]) );
IConvCache * pNode = static_cast<IConvCache*>( InterlockedFlushSList(&m_Pool[dstIdx][srcIdx]) );
while ( NULL != pNode )
{
IConvCache * pNext = static_cast<IConvCache*>( pNode->Next );
@ -227,16 +225,6 @@ public:
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,
@ -250,50 +238,36 @@ IConvCache::~IConvCache()
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
m_srcCodePage( srcCodePage ),
m_pCvtCache( NULL )
{
}
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) )
{
@ -315,63 +289,6 @@ const SystemLocale & SystemLocale::Singleton()
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 );
@ -419,106 +336,17 @@ size_t SystemLocale::FromUtf16( UINT destCodePage, const WCHAR * src, SSIZE_T cc
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 )
destCodePage = ExpandSpecialCP(destCodePage);
EncodingConverter cvt(destCodePage, CP_UTF16);
if (!cvt.Initialize())
{
if ( NULL != pErrorCode )
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;
size_t cchSrcActual = (cchSrc < 0 ? (1 + mplat_wcslen(src)) : cchSrc);
bool hasLoss;
return cvt.Convert(dest, cchDest, src, cchSrcActual, true, &hasLoss, pErrorCode);
}
char * SystemLocale::NextChar( UINT codepage, const char * start, size_t cchBytesLeft )
@ -573,471 +401,3 @@ char * SystemLocale::NextChar( UINT codepage, const char * start )
// 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

View file

@ -20,7 +20,7 @@
// pecuniary loss) arising out of the use of or inability to use
// this SDK, even if Microsoft has been advised of the possibility
// of such damages.
// Microsoft Drivers 4.1 for PHP for SQL Server
// Microsoft Drivers 4.2 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -90,7 +90,8 @@
#define SQL_COPT_SS_AEKEYSTOREPROVIDER (SQL_COPT_SS_BASE_EX+11) /* Load a keystore provider or read the list of loaded keystore providers */
#define SQL_COPT_SS_AEKEYSTOREDATA (SQL_COPT_SS_BASE_EX+12) /* Communicate with a loaded keystore provider */
#define SQL_COPT_SS_AETRUSTEDCMKPATHS (SQL_COPT_SS_BASE_EX+13) /* List of trusted CMK paths */
#define SQL_COPT_SS_AECEKCACHETTL (SQL_COPT_SS_BASE_EX+14)// Symmetric Key Cache TTL
#define SQL_COPT_SS_AECEKCACHETTL (SQL_COPT_SS_BASE_EX+14) /* Symmetric Key Cache TTL */
#define SQL_COPT_SS_AUTHENTICATION (SQL_COPT_SS_BASE_EX+15) /* The authentication method used for the connection */
/*
* SQLColAttributes driver specific defines.
@ -410,8 +411,8 @@ typedef struct AEKeystoreData
/* The following constants are for the Azure Key Vault configuration interface */
#define AKV_CONFIG_FLAGS 0
#define AKVCFG_USECLIENTID 0x00000001
#define AKVCFG_AUTORENEW 0x00000002
#define AKVCFG_USECLIENTID 0x00000001
#define AKVCFG_AUTORENEW 0x00000002
#define AKV_CONFIG_CLIENTID 1
#define AKV_CONFIG_CLIENTKEY 2

View file

@ -3,7 +3,7 @@
//
// Contents: Contains the minimal definitions to build on non-Windows platforms
//
// Microsoft Drivers 4.1 for PHP for SQL Server
// Microsoft Drivers 4.2 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License

View file

@ -1,7 +1,7 @@
//---------------------------------------------------------------------------------------------------------------------------------
// File: typedefs_for_linux.h
//
// Microsoft Drivers 4.1 for PHP for SQL Server
// Microsoft Drivers 4.2 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -23,13 +23,6 @@
#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
@ -44,55 +37,24 @@ DWORD FormatMessageA(
va_list *Arguments
);
DWORD FormatMessageW(
DWORD dwFlags,
LPCVOID lpSource,
DWORD dwMessageId,
DWORD dwLanguageId,
LPWSTR lpBuffer,
DWORD nSize,
va_list *Arguments
);
#ifndef _WIN32
#define FormatMessage FormatMessageA
#else
#define FormatMessage FormatMessageW
#endif // !_WIN32
#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 */
size_t mplat_wcslen( const WCHAR * );

View file

@ -4,7 +4,7 @@
// File: version.h
// Contents: Version number constants
//
// Microsoft Drivers 4.1 for PHP for SQL Server
// Microsoft Drivers 4.2 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -23,8 +23,8 @@
#define TOSTRING(a) #a
#define SQLVERSION_MAJOR 4
#define SQLVERSION_MINOR 1
#define SQLVERSION_PATCH 8
#define SQLVERSION_MINOR 2
#define SQLVERSION_PATCH 0
#define SQLVERSION_BUILD 0
// Semantic versioning pre-release, for stable releases should be empty
@ -45,7 +45,7 @@
#define _FILEVERSION SQLVERSION_MAJOR,SQLVERSION_MINOR,SQLVERSION_PATCH,SQLVERSION_BUILD
// PECL package version macros (can't have '-' or '+')
#define PHP_SQLSRV_VERSION VER_APIVERSION_STR SEMVER_PRERELEASE
#define PHP_SQLSRV_VERSION VER_APIVERSION_STR SEMVER_PRERELEASE
#define PHP_PDO_SQLSRV_VERSION PHP_SQLSRV_VERSION
#endif // VERSION_H

View file

@ -3,7 +3,7 @@
//
// Contents: include for definition of Windows types for non-Windows platforms
//
// Microsoft Drivers 4.0 for PHP for SQL Server
// Microsoft Drivers 4.2 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -35,45 +35,6 @@
#include <assert.h>
#include <string.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
@ -83,7 +44,6 @@
#define __forceinline inline
#define __stdcall
#if !defined(_MSC_VER)
#define __declspec__noinline __attribute__((noinline))
#define __declspec__selectany
#define __declspec(a) __declspec__##a
@ -104,54 +64,17 @@
#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
@ -162,19 +85,12 @@ using std::max;
//
// 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 windowsLong_t LONG;
typedef windowsLongLong_t LONGLONG;
typedef windowsULongLong_t ULONGLONG;
@ -182,39 +98,6 @@ typedef windowsULongLong_t ULONGLONG;
#include <stdlib.h>
#include "xplat_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
@ -225,176 +108,48 @@ typedef windowsULongLong_t ULONGLONG;
#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;
typedef CHAR *LPSTR;
#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 CONST CHAR *LPCSTR;
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
@ -403,30 +158,6 @@ typedef __int64 INT_PTR;
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
@ -440,50 +171,21 @@ typedef ULARGE_INTEGER *PULARGE_INTEGER;
#endif
ULONGLONG
VerSetConditionMask(
IN ULONGLONG ConditionMask,
IN DWORD TypeMask,
IN BYTE Condition
);
//// 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 "xplat_winerror.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

View file

@ -4,7 +4,7 @@
// Contents: This module defines helper functions to prevent
// integer overflow bugs.
//
// Microsoft Drivers 4.1 for PHP for SQL Server
// Microsoft Drivers 4.2 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -41,7595 +41,22 @@
// 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

@ -3,7 +3,7 @@
//
// Contents: Contains the minimal definitions to build on non-Windows platforms
//
// Microsoft Drivers 4.1 for PHP for SQL Server
// Microsoft Drivers 4.2 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -126,7 +126,6 @@
#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

View file

@ -3,7 +3,7 @@
//
// Contents: Contains the minimal definitions to build on non-Windows platforms
//
// Microsoft Drivers 4.1 for PHP for SQL Server
// Microsoft Drivers 4.2 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -34,71 +34,15 @@ typedef struct localeinfo_struct
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
@ -106,39 +50,4 @@ 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

View file

@ -3,7 +3,7 @@
//
// Contents: JScript build configuration used by buildconf.bat
//
// Microsoft Drivers 4.1 for PHP for SQL Server
// Microsoft Drivers 4.2 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License

View file

@ -3,7 +3,7 @@
//
// Contents: Routines that use connection handles
//
// Microsoft Drivers 4.1 for PHP for SQL Server
// Microsoft Drivers 4.2 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -54,23 +54,23 @@ struct conn_char_set_func {
const char* encoding = Z_STRVAL_P( value );
size_t encoding_len = Z_STRLEN_P( value );
zend_ulong index = -1;
zend_string* key = NULL;
void* ss_encoding_temp = NULL;
zend_ulong index = -1;
zend_string* key = NULL;
void* ss_encoding_temp = NULL;
ZEND_HASH_FOREACH_KEY_PTR( g_ss_encodings_ht, index, key, ss_encoding_temp ) {
sqlsrv_encoding* ss_encoding = reinterpret_cast<sqlsrv_encoding*>( ss_encoding_temp );
ss_encoding_temp = NULL;
if (!strnicmp( encoding, ss_encoding->iana, encoding_len )) {
ZEND_HASH_FOREACH_KEY_PTR( g_ss_encodings_ht, index, key, ss_encoding_temp ) {
sqlsrv_encoding* ss_encoding = reinterpret_cast<sqlsrv_encoding*>( ss_encoding_temp );
ss_encoding_temp = NULL;
if (!strnicmp( encoding, ss_encoding->iana, encoding_len )) {
if ( ss_encoding->not_for_connection ) {
THROW_SS_ERROR( conn, SS_SQLSRV_ERROR_CONNECT_ILLEGAL_ENCODING, encoding );
}
if ( ss_encoding->not_for_connection ) {
THROW_SS_ERROR( conn, SS_SQLSRV_ERROR_CONNECT_ILLEGAL_ENCODING, encoding );
}
conn->set_encoding( static_cast<SQLSRV_ENCODING>(ss_encoding->code_page ));
return;
}
} ZEND_HASH_FOREACH_END();
conn->set_encoding( static_cast<SQLSRV_ENCODING>(ss_encoding->code_page ));
return;
}
} ZEND_HASH_FOREACH_END();
THROW_SS_ERROR( conn, SS_SQLSRV_ERROR_CONNECT_ILLEGAL_ENCODING, encoding );
}
@ -134,8 +134,8 @@ struct bool_conn_attr_func {
static void func( connection_option const* /*option*/, zval* value, sqlsrv_conn* conn, std::string& /*conn_str*/ TSRMLS_DC )
{
try {
core::SQLSetConnectAttr(conn, Attr, reinterpret_cast<SQLPOINTER>((zend_long)zend_is_true(value)),
SQL_IS_UINTEGER TSRMLS_CC);
core::SQLSetConnectAttr(conn, Attr, reinterpret_cast<SQLPOINTER>((zend_long)zend_is_true(value)),
SQL_IS_UINTEGER TSRMLS_CC);
}
catch( core::CoreException& ) {
@ -186,6 +186,7 @@ const char APP[] = "APP";
const char ApplicationIntent[] = "ApplicationIntent";
const char AttachDBFileName[] = "AttachDbFileName";
const char CharacterSet[] = "CharacterSet";
const char Authentication[] = "Authentication";
const char ConnectionPooling[] = "ConnectionPooling";
#ifdef _WIN32
const char ConnectRetryCount[] = "ConnectRetryCount";
@ -220,25 +221,25 @@ const stmt_option SS_STMT_OPTS[] = {
SSStmtOptionNames::QUERY_TIMEOUT,
sizeof( SSStmtOptionNames::QUERY_TIMEOUT ),
SQLSRV_STMT_OPTION_QUERY_TIMEOUT,
std::unique_ptr<stmt_option_query_timeout>( new stmt_option_query_timeout )
std::unique_ptr<stmt_option_query_timeout>( new stmt_option_query_timeout )
},
{
SSStmtOptionNames::SEND_STREAMS_AT_EXEC,
sizeof( SSStmtOptionNames::SEND_STREAMS_AT_EXEC ),
SQLSRV_STMT_OPTION_SEND_STREAMS_AT_EXEC,
std::unique_ptr<stmt_option_send_at_exec>( new stmt_option_send_at_exec )
std::unique_ptr<stmt_option_send_at_exec>( new stmt_option_send_at_exec )
},
{
SSStmtOptionNames::SCROLLABLE,
sizeof( SSStmtOptionNames::SCROLLABLE ),
SQLSRV_STMT_OPTION_SCROLLABLE,
std::unique_ptr<stmt_option_ss_scrollable>( new stmt_option_ss_scrollable )
std::unique_ptr<stmt_option_ss_scrollable>( new stmt_option_ss_scrollable )
},
{
SSStmtOptionNames::CLIENT_BUFFER_MAX_SIZE,
sizeof( SSStmtOptionNames::CLIENT_BUFFER_MAX_SIZE ),
SQLSRV_STMT_OPTION_CLIENT_BUFFER_MAX_SIZE,
std::unique_ptr<stmt_option_buffered_query_limit>( new stmt_option_buffered_query_limit )
std::unique_ptr<stmt_option_buffered_query_limit>( new stmt_option_buffered_query_limit )
},
{ NULL, 0, SQLSRV_STMT_OPTION_INVALID, std::unique_ptr<stmt_option_functor>{} },
};
@ -282,6 +283,15 @@ const connection_option SS_CONN_OPTS[] = {
CONN_ATTR_STRING,
conn_char_set_func::func
},
{
SSConnOptionNames::Authentication,
sizeof( SSConnOptionNames::Authentication ),
SQLSRV_CONN_OPTION_AUTHENTICATION,
ODBCConnOptions::Authentication,
sizeof( ODBCConnOptions::Authentication ),
CONN_ATTR_STRING,
conn_str_append_func::func
},
{
SSConnOptionNames::ConnectionPooling,
sizeof( SSConnOptionNames::ConnectionPooling ),
@ -503,11 +513,11 @@ PHP_FUNCTION ( sqlsrv_connect )
// register the connection with the PHP runtime
ss::zend_register_resource(conn_z, conn, ss_sqlsrv_conn::descriptor, ss_sqlsrv_conn::resource_name TSRMLS_CC);
ss::zend_register_resource(conn_z, conn, ss_sqlsrv_conn::descriptor, ss_sqlsrv_conn::resource_name TSRMLS_CC);
conn->stmts = stmts;
stmts.transferred();
RETURN_RES( Z_RES(conn_z) );
RETURN_RES( Z_RES(conn_z) );
}
catch( core::CoreException& ) {
@ -607,7 +617,7 @@ PHP_FUNCTION( sqlsrv_close )
try {
// dummy context to pass to the error handler
// dummy context to pass to the error handler
error_ctx = new (sqlsrv_malloc( sizeof( sqlsrv_context ))) sqlsrv_context( 0, ss_error_handler, NULL );
SET_FUNCTION_NAME( *error_ctx );
@ -618,7 +628,7 @@ PHP_FUNCTION( sqlsrv_close )
CHECK_CUSTOM_ERROR(( zr == FAILURE ), error_ctx, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_ ) {
throw ss::SSException();
}
// if sqlsrv_close was called on a non-existent connection then we just return success.
if( Z_TYPE_P( conn_r ) == IS_NULL ) {
RETURN_TRUE;
@ -630,31 +640,31 @@ PHP_FUNCTION( sqlsrv_close )
conn = static_cast<ss_sqlsrv_conn*>( zend_fetch_resource( Z_RES_P( conn_r ) TSRMLS_CC, ss_sqlsrv_conn::resource_name, ss_sqlsrv_conn::descriptor ));
// if sqlsrv_close was called on an already closed connection then we just return success.
if ( Z_RES_TYPE_P( conn_r ) == RSRC_INVALID_TYPE) {
RETURN_TRUE;
}
CHECK_CUSTOM_ERROR(( conn == NULL ), error_ctx, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_ ) {
// if sqlsrv_close was called on an already closed connection then we just return success.
if ( Z_RES_TYPE_P( conn_r ) == RSRC_INVALID_TYPE) {
RETURN_TRUE;
}
CHECK_CUSTOM_ERROR(( conn == NULL ), error_ctx, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_ ) {
throw ss::SSException();
}
SET_FUNCTION_NAME( *conn );
// cause any variables still holding a reference to this to be invalid so they cause
// an error when passed to a sqlsrv function. There's nothing we can do if the
// removal fails, so we just log it and move on.
if( zend_list_close( Z_RES_P( conn_r ) ) == FAILURE ) {
LOG( SEV_ERROR, "Failed to remove connection resource %1!d!", Z_RES_HANDLE_P( conn_r ));
}
ZVAL_NULL( conn_r );
ZVAL_NULL( conn_r );
RETURN_TRUE;
}
catch( core::CoreException& ) {
RETURN_FALSE;
}
catch( ... ) {
@ -937,10 +947,10 @@ PHP_FUNCTION( sqlsrv_prepare )
core_sqlsrv_prepare( stmt, sql, sql_len TSRMLS_CC );
if (params_z) {
stmt->params_z = (zval *)sqlsrv_malloc(sizeof(zval));
ZVAL_COPY(stmt->params_z, params_z);
}
if (params_z) {
stmt->params_z = (zval *)sqlsrv_malloc(sizeof(zval));
ZVAL_COPY(stmt->params_z, params_z);
}
stmt->prepared = true;
@ -1021,7 +1031,7 @@ PHP_FUNCTION( sqlsrv_query )
hash_auto_ptr ss_stmt_options_ht;
size_t sql_len = 0;
zval* options_z = NULL;
zval* params_z = NULL;
zval* params_z = NULL;
zval stmt_z;
ZVAL_UNDEF(&stmt_z);
@ -1058,8 +1068,8 @@ PHP_FUNCTION( sqlsrv_query )
ss_error_handler, NULL TSRMLS_CC ) );
if( params_z ) {
stmt->params_z = (zval *)sqlsrv_malloc(sizeof(zval));
ZVAL_COPY(stmt->params_z, params_z);
stmt->params_z = (zval *)sqlsrv_malloc(sizeof(zval));
ZVAL_COPY(stmt->params_z, params_z);
}
stmt->set_func( "sqlsrv_query" );
@ -1073,7 +1083,7 @@ PHP_FUNCTION( sqlsrv_query )
ss::zend_register_resource(stmt_z, stmt, ss_sqlsrv_stmt::descriptor, ss_sqlsrv_stmt::resource_name TSRMLS_CC);
// store the resource id with the connection so the connection
// can release this statement when it closes.
zend_ulong next_index = zend_hash_next_free_element( conn->stmts );
zend_ulong next_index = zend_hash_next_free_element( conn->stmts );
core::sqlsrv_zend_hash_index_update(*conn, conn->stmts, next_index, &stmt_z TSRMLS_CC);
stmt->conn_index = next_index;
@ -1103,7 +1113,7 @@ PHP_FUNCTION( sqlsrv_query )
void free_stmt_resource( zval* stmt_z TSRMLS_DC )
{
if( FAILURE == zend_list_close( Z_RES_P( stmt_z ))) {
if( FAILURE == zend_list_close( Z_RES_P( stmt_z ))) {
LOG(SEV_ERROR, "Failed to remove stmt resource %1!d!", Z_RES_HANDLE_P(stmt_z));
}
ZVAL_NULL( stmt_z );
@ -1127,31 +1137,31 @@ void sqlsrv_conn_close_stmts( ss_sqlsrv_conn* conn TSRMLS_DC )
// loop through the stmts hash table and destroy each stmt resource so we can close the
// ODBC connection
zval* rsrc_ptr = NULL;
ZEND_HASH_FOREACH_VAL( conn->stmts, rsrc_ptr ) {
try {
int zr = ( rsrc_ptr ) != NULL ? SUCCESS : FAILURE;
CHECK_ZEND_ERROR( zr, *conn, SQLSRV_ERROR_ZEND_HASH ) {
throw core::CoreException();
}
}
catch( core::CoreException& ) {
DIE( "sqlsrv_conn_close_stmts: Failed to retrieve a statement resource from the connection" );
}
// see if the statement is still valid, and if not skip to the next one
// presumably this should never happen because if it's in the list, it should still be valid
// by virtue that a statement resource should remove itself from its connection when it is
// destroyed in sqlsrv_stmt_dtor. However, rather than die (assert), we simply skip this resource
// and move to the next one.
ss_sqlsrv_stmt* stmt = NULL;
stmt = static_cast<ss_sqlsrv_stmt*>( Z_RES_VAL_P( rsrc_ptr ));
if( stmt == NULL || Z_RES_TYPE_P( rsrc_ptr ) != ss_sqlsrv_stmt::descriptor ) {
LOG( SEV_ERROR, "Non existent statement found in connection. Statements should remove themselves"
" from the connection so this shouldn't be out of sync." );
continue;
}
// delete the statement by deleting it from Zend's resource list, which will force its destruction
stmt->conn = NULL;
zval* rsrc_ptr = NULL;
ZEND_HASH_FOREACH_VAL( conn->stmts, rsrc_ptr ) {
try {
int zr = ( rsrc_ptr ) != NULL ? SUCCESS : FAILURE;
CHECK_ZEND_ERROR( zr, *conn, SQLSRV_ERROR_ZEND_HASH ) {
throw core::CoreException();
}
}
catch( core::CoreException& ) {
DIE( "sqlsrv_conn_close_stmts: Failed to retrieve a statement resource from the connection" );
}
// see if the statement is still valid, and if not skip to the next one
// presumably this should never happen because if it's in the list, it should still be valid
// by virtue that a statement resource should remove itself from its connection when it is
// destroyed in sqlsrv_stmt_dtor. However, rather than die (assert), we simply skip this resource
// and move to the next one.
ss_sqlsrv_stmt* stmt = NULL;
stmt = static_cast<ss_sqlsrv_stmt*>( Z_RES_VAL_P( rsrc_ptr ));
if( stmt == NULL || Z_RES_TYPE_P( rsrc_ptr ) != ss_sqlsrv_stmt::descriptor ) {
LOG( SEV_ERROR, "Non existent statement found in connection. Statements should remove themselves"
" from the connection so this shouldn't be out of sync." );
continue;
}
// delete the statement by deleting it from Zend's resource list, which will force its destruction
stmt->conn = NULL;
// this would call the destructor on the statement.
// There's nothing we can do if the removal fails, so we just log it and move on.
@ -1205,6 +1215,17 @@ int get_conn_option_key( sqlsrv_context& ctx, zend_string* key, size_t key_len,
throw ss::SSException();
}
bool valid = true;
if( stricmp( SS_CONN_OPTS[i].sqlsrv_name, SSConnOptionNames::Authentication ) == 0 ) {
valid = core_is_authentication_option_valid( value, value_len );
}
CHECK_CUSTOM_ERROR( !valid, ctx, SS_SQLSRV_ERROR_INVALID_AUTHENTICATION_OPTION, SS_CONN_OPTS[ i ].sqlsrv_name ) {
throw ss::SSException();
}
break;
}
}
@ -1263,23 +1284,23 @@ void validate_stmt_options( sqlsrv_context& ctx, zval* stmt_options, _Inout_ Has
if( stmt_options ) {
HashTable* options_ht = Z_ARRVAL_P( stmt_options );
zend_ulong int_key = -1;
zend_string *key = NULL;
zval* data = NULL;
ZEND_HASH_FOREACH_KEY_VAL( options_ht, int_key, key, data ) {
int type = HASH_KEY_NON_EXISTENT;
size_t key_len = 0;
zend_ulong int_key = -1;
zend_string *key = NULL;
zval* data = NULL;
ZEND_HASH_FOREACH_KEY_VAL( options_ht, int_key, key, data ) {
int type = HASH_KEY_NON_EXISTENT;
size_t key_len = 0;
type = key ? HASH_KEY_IS_STRING : HASH_KEY_IS_LONG;
type = key ? HASH_KEY_IS_STRING : HASH_KEY_IS_LONG;
if (type != HASH_KEY_IS_STRING) {
CHECK_CUSTOM_ERROR(true, ctx, SQLSRV_ERROR_INVALID_OPTION_KEY, std::to_string( int_key ).c_str() ) {
throw core::CoreException();
}
}
key_len = ZSTR_LEN(key) + 1;
add_stmt_option_key( ctx, key, key_len, ss_stmt_options_ht, data TSRMLS_CC );
} ZEND_HASH_FOREACH_END();
if (type != HASH_KEY_IS_STRING) {
CHECK_CUSTOM_ERROR(true, ctx, SQLSRV_ERROR_INVALID_OPTION_KEY, std::to_string( int_key ).c_str() ) {
throw core::CoreException();
}
}
key_len = ZSTR_LEN(key) + 1;
add_stmt_option_key( ctx, key, key_len, ss_stmt_options_ht, data TSRMLS_CC );
} ZEND_HASH_FOREACH_END();
}
}
catch( core::CoreException& ) {
@ -1299,37 +1320,37 @@ void validate_conn_options( sqlsrv_context& ctx, zval* user_options_z, _Out_ cha
if( user_options_z ) {
HashTable* options_ht = Z_ARRVAL_P( user_options_z );
zend_ulong int_key = -1;
zend_string *key = NULL;
zval* data = NULL;
ZEND_HASH_FOREACH_KEY_VAL( options_ht, int_key, key, data ) {
int type = HASH_KEY_NON_EXISTENT;
type = key ? HASH_KEY_IS_STRING : HASH_KEY_IS_LONG;
zend_ulong int_key = -1;
zend_string *key = NULL;
zval* data = NULL;
ZEND_HASH_FOREACH_KEY_VAL( options_ht, int_key, key, data ) {
int type = HASH_KEY_NON_EXISTENT;
type = key ? HASH_KEY_IS_STRING : HASH_KEY_IS_LONG;
CHECK_CUSTOM_ERROR(( Z_TYPE_P( data ) == IS_NULL || Z_TYPE_P( data ) == IS_UNDEF ), ctx, SS_SQLSRV_ERROR_INVALID_OPTION, key) {
throw ss::SSException();
}
CHECK_CUSTOM_ERROR(( Z_TYPE_P( data ) == IS_NULL || Z_TYPE_P( data ) == IS_UNDEF ), ctx, SS_SQLSRV_ERROR_INVALID_OPTION, key) {
throw ss::SSException();
}
CHECK_CUSTOM_ERROR(( type != HASH_KEY_IS_STRING ), ctx, SS_SQLSRV_ERROR_INVALID_CONNECTION_KEY ) {
throw ss::SSException();
}
CHECK_CUSTOM_ERROR(( type != HASH_KEY_IS_STRING ), ctx, SS_SQLSRV_ERROR_INVALID_CONNECTION_KEY ) {
throw ss::SSException();
}
// Length of the key string does not include the null terminator in PHP7, +1 has to be added
size_t key_len = ZSTR_LEN(key) + 1;
if( key_len == sizeof(SSConnOptionNames::UID) && !stricmp(ZSTR_VAL(key), SSConnOptionNames::UID )) {
// Length of the key string does not include the null terminator in PHP7, +1 has to be added
size_t key_len = ZSTR_LEN(key) + 1;
if( key_len == sizeof(SSConnOptionNames::UID) && !stricmp(ZSTR_VAL(key), SSConnOptionNames::UID )) {
*uid = Z_STRVAL_P( data );
}
*uid = Z_STRVAL_P( data );
}
else if( key_len == sizeof( SSConnOptionNames::PWD ) && !stricmp( ZSTR_VAL( key ), SSConnOptionNames::PWD )) {
else if( key_len == sizeof( SSConnOptionNames::PWD ) && !stricmp( ZSTR_VAL( key ), SSConnOptionNames::PWD )) {
*pwd = Z_STRVAL_P( data );
}
else {
*pwd = Z_STRVAL_P( data );
}
else {
::add_conn_option_key( ctx, key, key_len, ss_conn_options_ht, data TSRMLS_CC );
}
} ZEND_HASH_FOREACH_END();
::add_conn_option_key( ctx, key, key_len, ss_conn_options_ht, data TSRMLS_CC );
}
} ZEND_HASH_FOREACH_END();
}
}
catch( core::CoreException& ) {

View file

@ -2,7 +2,7 @@
// File: init.cpp
// Contents: initialization routines for the extension
//
// Microsoft Drivers 4.1 for PHP for SQL Server
// Microsoft Drivers 4.2 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -388,16 +388,16 @@ PHP_MINIT_FUNCTION(sqlsrv)
constant_type.typeinfo.scale = 7;
REGISTER_LONG_CONSTANT( "SQLSRV_SQLTYPE_DATETIME2", constant_type.value, CONST_PERSISTENT | CONST_CS );
// These constant are defined to provide type checking (type ==SQLSRV_SQLTYPE_DECIMAL).
// There are functions with the same name which accept parameters and is used in binding paramters.
REGISTER_LONG_CONSTANT("SQLSRV_SQLTYPE_DECIMAL", SQL_DECIMAL, CONST_PERSISTENT | CONST_CS);
REGISTER_LONG_CONSTANT("SQLSRV_SQLTYPE_NUMERIC", SQL_NUMERIC, CONST_PERSISTENT | CONST_CS);
REGISTER_LONG_CONSTANT("SQLSRV_SQLTYPE_CHAR", SQL_CHAR, CONST_PERSISTENT | CONST_CS);
REGISTER_LONG_CONSTANT("SQLSRV_SQLTYPE_NCHAR", SQL_WCHAR, CONST_PERSISTENT | CONST_CS);
REGISTER_LONG_CONSTANT("SQLSRV_SQLTYPE_VARCHAR", SQL_VARCHAR, CONST_PERSISTENT | CONST_CS);
REGISTER_LONG_CONSTANT("SQLSRV_SQLTYPE_NVARCHAR", SQL_WVARCHAR, CONST_PERSISTENT | CONST_CS);
REGISTER_LONG_CONSTANT("SQLSRV_SQLTYPE_BINARY", SQL_BINARY, CONST_PERSISTENT | CONST_CS);
REGISTER_LONG_CONSTANT("SQLSRV_SQLTYPE_VARBINARY", SQL_VARBINARY, CONST_PERSISTENT | CONST_CS);
// These constant are defined to provide type checking (type ==SQLSRV_SQLTYPE_DECIMAL).
// There are functions with the same name which accept parameters and is used in binding paramters.
REGISTER_LONG_CONSTANT("SQLSRV_SQLTYPE_DECIMAL", SQL_DECIMAL, CONST_PERSISTENT | CONST_CS);
REGISTER_LONG_CONSTANT("SQLSRV_SQLTYPE_NUMERIC", SQL_NUMERIC, CONST_PERSISTENT | CONST_CS);
REGISTER_LONG_CONSTANT("SQLSRV_SQLTYPE_CHAR", SQL_CHAR, CONST_PERSISTENT | CONST_CS);
REGISTER_LONG_CONSTANT("SQLSRV_SQLTYPE_NCHAR", SQL_WCHAR, CONST_PERSISTENT | CONST_CS);
REGISTER_LONG_CONSTANT("SQLSRV_SQLTYPE_VARCHAR", SQL_VARCHAR, CONST_PERSISTENT | CONST_CS);
REGISTER_LONG_CONSTANT("SQLSRV_SQLTYPE_NVARCHAR", SQL_WVARCHAR, CONST_PERSISTENT | CONST_CS);
REGISTER_LONG_CONSTANT("SQLSRV_SQLTYPE_BINARY", SQL_BINARY, CONST_PERSISTENT | CONST_CS);
REGISTER_LONG_CONSTANT("SQLSRV_SQLTYPE_VARBINARY", SQL_VARBINARY, CONST_PERSISTENT | CONST_CS);
REGISTER_LONG_CONSTANT( "SQLSRV_PARAM_IN", SQL_PARAM_INPUT, CONST_PERSISTENT | CONST_CS );
REGISTER_LONG_CONSTANT( "SQLSRV_PARAM_OUT", SQL_PARAM_OUTPUT, CONST_PERSISTENT | CONST_CS );

View file

@ -8,7 +8,7 @@
//
// Comments: Also contains "internal" declarations shared across source files.
//
// Microsoft Drivers 4.1 for PHP for SQL Server
// Microsoft Drivers 4.2 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -352,7 +352,8 @@ enum SS_ERROR_CODES {
SS_SQLSRV_ERROR_CONNECT_ILLEGAL_ENCODING,
SS_SQLSRV_ERROR_CONNECT_BRACES_NOT_ESCAPED,
SS_SQLSRV_ERROR_INVALID_OUTPUT_PARAM_TYPE,
SS_SQLSRV_ERROR_PARAM_VAR_NOT_REF
SS_SQLSRV_ERROR_PARAM_VAR_NOT_REF,
SS_SQLSRV_ERROR_INVALID_AUTHENTICATION_OPTION
};
extern ss_error SS_ERRORS[];

View file

@ -3,7 +3,7 @@
//
// Contents: Routines that use statement handles
//
// Microsoft Drivers 4.1 for PHP for SQL Server
// Microsoft Drivers 4.2 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -1538,6 +1538,7 @@ bool determine_column_size_or_precision( sqlsrv_stmt const* stmt, sqlsrv_sqltype
case SQL_CHAR:
case SQL_VARBINARY:
case SQL_VARCHAR:
case SQL_SS_VARIANT:
*column_size = sqlsrv_type.typeinfo.size;
if( *column_size == SQLSRV_SIZE_MAX_TYPE ) {
*column_size = SQL_SS_LENGTH_UNLIMITED;
@ -1616,6 +1617,7 @@ sqlsrv_phptype determine_sqlsrv_php_type( ss_sqlsrv_stmt const* stmt, SQLINTEGER
break;
case SQL_VARCHAR:
case SQL_WVARCHAR:
case SQL_SS_VARIANT:
if( prefer_string || size != SQL_SS_LENGTH_UNLIMITED ) {
sqlsrv_phptype.typeinfo.type = SQLSRV_PHPTYPE_STRING;
sqlsrv_phptype.typeinfo.encoding = stmt->encoding();

View file

@ -3,7 +3,7 @@
//
// Contents: Version resource
//
// Microsoft Drivers 4.1 for PHP for SQL Server
// Microsoft Drivers 4.2 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License

View file

@ -5,7 +5,7 @@
//
// Comments: Mostly error handling and some type handling
//
// Microsoft Drivers 4.1 for PHP for SQL Server
// Microsoft Drivers 4.2 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -366,6 +366,10 @@ ss_error SS_ERRORS[] = {
"Output or bidirectional variable parameters (SQLSRV_PARAM_OUT and SQLSRV_PARAM_INOUT) passed to sqlsrv_prepare or sqlsrv_query should be passed by reference, not by value."
, -61, true }
},
{
SS_SQLSRV_ERROR_INVALID_AUTHENTICATION_OPTION,
{ IMSSP, (SQLCHAR*)"Invalid option for the Authentication keyword. Only SqlPassword or ActiveDirectoryPassword is supported.", -62, false }
},
// internal warning definitions
{

View file

@ -49,11 +49,15 @@ def readAndPrint(inputStr, file, path):
def TestFilename(line):
terminateChar = os.sep
currentPos = 0
firstpos = len(line) * -1
while True:
currentPos = currentPos - 1
# if passed the first pos, stop
if currentPos < firstpos:
break
line[currentPos]
if line[currentPos] == terminateChar:
break
break
file = line[currentPos+1:-1]
return file

1628
test/pdo_sqlsrv/MsCommon.inc Normal file

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,65 @@
<?php
/*
Microsoft SQL Server Driver for PHP - Unit Test Framework
Copyright (c) Microsoft Corporation. All rights reserved.
Description:
Random data generator for INSERT statements.
*/
// globals
$table1 = "PDO_Types_1";
$table2= "PDO_AllTypes";
$large_string = "This is a really large string used to test certain large data types like xml data type. The length of this string is greater than 256 to correctly test a large data type. This is currently used by atleast varchar type and by xml type. The fetch tests are the primary consumer of this string to validate that fetch on large types work fine. The length of this string as counted in terms of number of characters is 417.";
$string_col = array("'STRINGCOL1'", "'STRINGCOL2'");
$date_col = array("'2000-11-11 11:11:11.111'", "'2000-11-11 11:11:11.222'");
$large_string_col = array("' 1 " . $large_string . "'", "' 2 " . $large_string . "'");
$xml_col = array("'<xml> 1 " . $large_string . "</xml>'", "'<xml> 2 " . $large_string . "</xml>'");
$binary_col = array('0x0', '0x0');
$int_col = array ( 1, 2);
$decimal_col = array (111.111, 222.222);
$guid_col = array("'AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA'", "'BBBBBBBB-BBBB-BBBB-BBBB-BBBBBBBBBBBB'");
$null_col = 'null';
$comma = ",";
$closing_brace = "),";
class PDO_Types_1_Class{
var $IntCol;
var $CharCol;
var $NCharCol;
var $DateTimeCol;
var $VarcharCol;
var $NVarCharCol;
var $FloatCol;
var $XmlCol;
function dumpAll()
{
var_dump($this->IntCol);
var_dump($this->CharCol);
var_dump($this->NCharCol);
var_dump($this->DateTimeCol);
var_dump($this->VarcharCol);
var_dump($this->NVarCharCol);
var_dump($this->FloatCol);
var_dump($this->XmlCol);
}
}
$table1_class = 'PDO_Types_1_Class';
?>

View file

@ -0,0 +1,38 @@
<?php
/*
Microsoft SQL Server Driver for PHP/PDO - Unit Test Framework
Copyright (c) Microsoft Corporation. All rights reserved
Description:
Global variables defining the execution context
*/
if (isset($_ENV['MSSQL_SERVER']) || isset($_ENV['MSSQL_USER']) || isset($_ENV['MSSQL_PASSWORD'])) {
$server = $_ENV['MSSQL_SERVER'];
$uid = $_ENV['MSSQL_USER'];
$pwd = $_ENV['MSSQL_PASSWORD'];
$databaseName = $_ENV['MSSQL_DATABASE_NAME'];
$DriverName = $_ENV['MSSQL_DRIVER_NAME'];
} else {
$server = 'TARGET_SERVER';
$uid = 'TARGET_USERNAME';
$pwd = 'TARGET_PASSWORD';
$databaseName = 'TARGET_DATABASE';
$DriverName = "ODBC Driver 11 for SQL Server";
}
$driverType = true;
$PhpDriver = "ODBC Driver 11 for SQL Server";
$tableName = 'pdo_test_table';
$tableIndex = 'php_test_table_idx';
$procName = 'php_test_proc';
$fileName = 'php_test_file.dat';
$dsn = "odbc:Driver={$DriverName};Server=$server";
$connectionOptions = array();
$daasMode = false;
$marsMode = true;
$dsnMode = true;
$traceEnabled = false;
?>

View file

@ -0,0 +1,113 @@
--TEST--
PDO - Insert Nulls
--DESCRIPTION--
Test inserting nulls into nullable columns
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function InsertNullsTest($bindType)
{
include 'MsSetup.inc';
$outvar = null;
$failed = false;
Setup();
$conn = Connect();
DropTable($conn, $tableName);
CreateTable($conn, $tableName);
$stmt = $conn->query(<<<SQL
SELECT [TABLE_NAME],[COLUMN_NAME],[IS_NULLABLE] FROM [INFORMATION_SCHEMA].[COLUMNS] WHERE [TABLE_NAME] = '$tableName'
SQL
);
if ($stmt === false)
{
FatalError("Could not query for column information on table $tableName");
}
while ($row = $stmt->fetch(PDO::FETCH_ASSOC))
{
Trace($row['COLUMN_NAME'] . ": " . $row['IS_NULLABLE'] . "\n");
$stmt2 = $conn->prepare("INSERT INTO [$tableName] ([" . $row['COLUMN_NAME'] . "]) VALUES (:p1)");
if (strpos($row['COLUMN_NAME'], "timestamp") !== false) continue;
if (($row['IS_NULLABLE'] == 'YES') && (strpos($row['COLUMN_NAME'], "binary") !== false))
{
if ($bindType == PDO::PARAM_LOB)
{
$stmt2->setAttribute(PDO::SQLSRV_ATTR_ENCODING, PDO::SQLSRV_ENCODING_BINARY);
$stmt2->bindValue(":p1", null, $bindType);
}
else if ($bindType == PDO::PARAM_STR)
{
$stmt2->bindParam(":p1", $outvar, $bindType, null, PDO::SQLSRV_ENCODING_BINARY);
}
}
else
{
$stmt2->bindParam(":p1", $outvar);
}
$stmt2->execute();
if ($stmt2->errorCode() !== '00000')
{
print_r($stmt2->errorInfo());
$failed = true;
}
}
DropTable($conn, $tableName);
return($failed);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
$failed = null;
$testName = "PDO - Insert Nulls";
StartTest($testName);
try
{
$failed |= InsertNullsTest(PDO::PARAM_LOB);
$failed |= InsertNullsTest(PDO::PARAM_STR);
}
catch (Exception $e)
{
echo $e->getMessage();
}
if ($failed)
FatalError("Possible Regression: Could not insert NULL");
EndTest($testName);
}
Repro();
?>
--EXPECT--
Test "PDO - Insert Nulls" completed successfully.

View file

@ -0,0 +1,76 @@
--TEST--
PDO - Large Column Name Test
--DESCRIPTION--
Verifies that long column names are supported (up to 128 chars).
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function LargeColumnNameTest($columnName, $expectfail)
{
include 'MsSetup.inc';
Setup();
$conn = Connect();
$tableName = "LargeColumnNameTest";
DropTable($conn, $tableName);
$conn->query("CREATE TABLE [$tableName] ([$columnName] int)");
$conn->query("INSERT INTO [$tableName] ([$columnName]) VALUES (5)");
$stmt = $conn->query("SELECT * from [$tableName]");
if ( null == $stmt )
{
if (!$expectfail)
FatalError("Possible regression: Unable to retrieve inserted value.");
}
DropTable($conn, $tableName);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
$testName = "PDO - Large Column Name Test";
StartTest($testName);
$columnName = "a";
try
{
for ($a = 1; $a <= 128; $a++)
{
LargeColumnNameTest($columnName, $a > 128);
$columnName .= "A";
}
}
catch (Exception $e)
{
echo $e->getMessage();
}
EndTest($testName);
}
Repro();
?>
--EXPECT--
Test "PDO - Large Column Name Test" completed successfully.

View file

@ -0,0 +1,76 @@
--TEST--
PDO - Large Unicode Column Name Test
--DESCRIPTION--
Verifies that long column names in Unicode are supported (up to 128 chars).
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function LargeColumnNameTest($columnName, $expectfail)
{
include 'MsSetup.inc';
Setup();
$conn = Connect();
$tableName = "LargeColumnNameTest";
DropTable($conn, $tableName);
$conn->query("CREATE TABLE [$tableName] ([$columnName] int)");
$conn->query("INSERT INTO [$tableName] ([$columnName]) VALUES (5)");
$stmt = $conn->query("SELECT * from [$tableName]");
if ( null == $stmt )
{
if (!$expectfail)
FatalError("Possible regression: Unable to retrieve inserted value.");
}
DropTable($conn, $tableName);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
$testName = "PDO - Large Column Name Test";
StartTest($testName);
$columnName = "是";
try
{
for ($a = 1; $a <= 128; $a++)
{
LargeColumnNameTest($columnName, $a > 128);
$columnName .= "是";
}
}
catch (Exception $e)
{
echo $e->getMessage();
}
EndTest($testName);
}
Repro();
?>
--EXPECT--
Test "PDO - Large Column Name Test" completed successfully.

View file

@ -0,0 +1,82 @@
--TEST--
PDO - Max Output Params Test
--DESCRIPTION--
Fetch data as VARCHAR(MAX)
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function MaxOutputParamsTest($expected, $length)
{
include 'MsSetup.inc';
$outstr = null;
$conn = Connect();
CreateProc(
$conn,
"EXEC_TEST",
"@OUT varchar(80) output",
"SET NOCOUNT ON; select @OUT = '$expected'; return (0)
");
$sql = "execute EXEC_TEST ?";
$stmt = $conn->prepare($sql);
if ($length)
{
$stmt->bindParam(1, $outstr, PDO::PARAM_STR, 10);
}
else
{
$stmt->bindParam(1, $outstr, PDO::PARAM_STR, 3);
}
$stmt->execute();
echo "Expected: $expected Received: $outstr\n";
if ($outstr !== $expected)
{
print_r($stmt->errorInfo());
return(-1);
}
return(0);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
$failed = null;
$testName = "PDO - Max Output Params Test";
StartTest($testName);
$failed |= MaxOutputParamsTest("abc", null);
$failed |= MaxOutputParamsTest("abc", -1);
if ($failed)
FatalError("Possible Regression: Value returned as VARCHAR(MAX) truncated");
EndTest($testName);
}
Repro();
?>
--EXPECT--
Expected: abc Received: abc
Expected: abc Received: abc
Test "PDO - Max Output Params Test" completed successfully.

View file

@ -0,0 +1,60 @@
--TEST--
PDO Drivers Info Test
--DESCRIPTION--
Verifies the functionality of "PDO:getAvailableDrivers()”.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function DriversInfo()
{
include 'MsSetup.inc';
$testName = "PDO - Drivers";
StartTest($testName);
$drivers = PDO::getAvailableDrivers();
if (in_array("sqlsrv", $drivers))
{
$count = count($drivers);
for ($i = 0; $i < $count; $i++)
{
Trace("Driver #".($i + 1).": ".$drivers[$i]."\n");
}
}
else
{
printf("$PhpDriver is missing.\n");
}
EndTest($testName);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
DriversInfo();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
Test "PDO - Drivers" completed successfully.

View file

@ -0,0 +1,61 @@
--TEST--
PDO PHP Info Test
--DESCRIPTION--
Verifies the functionality of PDO with phpinfo().
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function DriversInfo()
{
include 'MsSetup.inc';
$testName = "PDO - phpinfo";
StartTest($testName);
ob_start();
phpinfo();
$info = ob_get_contents();
ob_end_clean();
// Check phpinfo() data
if (stristr($info, "PDO support => enabled") === false)
{
printf("PDO is not enabled\n");
}
else if (stristr($info, "pdo_sqlsrv support => enabled") === false)
{
printf("Cannot find PDO driver line in phpinfo() output\n");
}
EndTest($testName);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
DriversInfo();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
Test "PDO - phpinfo" completed successfully.

View file

@ -0,0 +1,62 @@
--TEST--
PDO Connection Test
--DESCRIPTION--
Checks whether the driver can successfully establish a database connection.
Verifies as well that invalid connection attempts fail as expected.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function ConnectionTest()
{
include 'MsSetup.inc';
$testName = "PDO Connection";
StartTest($testName);
// Invalid connection attempt => errors are expected
Trace("Invalid connection attempt (to a non-existing server) ....\n");
$conn1 = PDOConnect('PDO', "InvalidServerName", $uid, $pwd, false);
if ($conn1)
{
printf("Invalid connection attempt should have failed.\n");
}
$conn1 = null;
// Valid connection attempt => no errors are expected
Trace("\nValid connection attempt (to $server) ....\n");
$conn2 = Connect();
$conn2 = null;
EndTest($testName);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
ConnectionTest();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
Test "PDO Connection" completed successfully.

View file

@ -0,0 +1,149 @@
--TEST--
PDO Connection Pooling Test
--DESCRIPTION--
Checks whether the driver can successfully establish a database connection
when an URI-based construct is used.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif_unix.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function ConnectionTest()
{
include 'MsSetup.inc';
$testName = "PDO Connection Pooling";
StartTest($testName);
$optionsDefault = null;
$optionsPool = null;
$optionsNotPool = null;
if ($dsnMode)
{
$optionsDefault = "APP=Microsoft PHP;";
$optionsPool = "APP=Microsoft PHP;ConnectionPooling=1;";
$optionsNotPool = "APP=Microsoft PHP;ConnectionPooling=0;";
}
else
{
$optionsDefault = array('APP'=>'Microsoft PHP');
$optionsPool = array('APP'=>'Microsoft PHP', 'ConnectionPooling'=>1);
$optionsNotPool = array('APP'=>'Microsoft PHP', 'ConnectionPooling'=>0);
}
// Create pool
$conn1 = DoConnect($optionsPool);
$conn2 = DoConnect($optionsPool);
$conn3 = DoConnect($optionsPool);
$connId1 = ConnectionID($conn1);
$connId2 = ConnectionID($conn2);
$connId3 = ConnectionID($conn3);
$conn1 = null;
$conn2 = null;
$conn3 = null;
$conn4 = DoConnect($optionsDefault);
if (!IsPoolConnection($conn4, $connId1, $connId2, $connId3))
{
echo "Default connection was expected to be a pool connection..\n";
}
$conn4 = null;
$conn5 = DoConnect($optionsPool);
if (!IsPoolConnection($conn5, $connId1, $connId2, $connId3))
{
echo "A pool connection was expected...\n";
}
$conn5 = null;
$conn6 = DoConnect($optionsNotPool);
if (IsPoolConnection($conn6, $connId1, $connId2, $connId3))
{
echo "A pool connection was not expected...\n";
}
$conn6 = null;
EndTest($testName);
}
function DoConnect($options)
{
include 'MsSetup.inc';
$conn = null;
try
{
if ($dsnMode)
{
$conn = new PDO("sqlsrv:Server=$server;$options", $uid, $pwd);
}
else
{
$conn = new PDO("sqlsrv:Server=$server", $uid, $pwd, $options);
}
$conn->setAttribute(PDO::SQLSRV_ATTR_ENCODING, PDO::SQLSRV_ENCODING_SYSTEM);
}
catch (PDOException $e)
{
$conn = null;
TraceEx("\nFailed to connect to $server: ".$e->getMessage(), true);
}
return ($conn);
}
function ConnectionID($conn)
{
$tsql = "SELECT @@SPID FROM master.dbo.sysprocesses WHERE (program_name='Microsoft PHP')";
$stmt = ExecuteQuery($conn, $tsql);
$connID = $stmt->fetchColumn(0);
$stmt->closeCursor();
$stmt = null;
return ($connID);
}
function IsPoolConnection($conn, $Id1, $Id2, $Id3)
{
$connID = ConnectionID($conn);
if (($connID == $Id1) || ($connID == $Id2) || ($connID == $Id3))
{
return (true);
}
return (false);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
ConnectionTest();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECTF--
Test "PDO Connection Pooling" completed successfully.

View file

@ -0,0 +1,142 @@
--TEST--
PDO Connection Pooling Test
--DESCRIPTION--
Checks whether the driver can successfully establish a database connection
when an URI-based construct is used.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif_unix.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function ConnectionTest($noPasses)
{
include 'MsSetup.inc';
$testName = "PDO Connection Pooling";
StartTest($testName);
$optionsPool = null;
$optionsNotPool = null;
if ($dsnMode)
{
$optionsPool = "APP=Microsoft PHP;ConnectionPooling=1;";
$optionsNotPool = "APP=Microsoft PHP;ConnectionPooling=0;";
}
else
{
$optionsPool = array('APP'=>'Microsoft PHP', 'ConnectionPooling'=>1);
$optionsNotPool = array('APP'=>'Microsoft PHP', 'ConnectionPooling'=>0);
}
// Establish a pool connection
$conn1 = DoConnect($optionsPool);
$conn1ID = ConnectionID($conn1);
$conn1 = null;
// Verifies that non-pool connections have a different id
for ($i = 0; $i < $noPasses; $i++)
{
$conn2 = DoConnect($optionsNotPool);
$conn2ID = ConnectionID($conn2);
$conn2 = null;
if ($conn1ID == $conn2ID)
{
echo "A different connection id was expected: $conn1ID => $conn2ID\n";
break;
}
$conn2 = null;
}
// Verifies that pool connections have the same id
for ($i = 0; $i < $noPasses; $i++)
{
$conn2 = DoConnect($optionsPool);
$conn2ID = ConnectionID($conn2);
$conn2 = null;
if ($conn1ID != $conn2ID)
{
echo "The same connection id was expected: $conn1ID => $conn2ID\n";
break;
}
$conn2 = null;
}
EndTest($testName);
}
function DoConnect($options)
{
include 'MsSetup.inc';
$conn = null;
try
{
if ($dsnMode)
{
$conn = new PDO("sqlsrv:Server=$server;$options", $uid, $pwd);
}
else
{
$conn = new PDO("sqlsrv:Server=$server", $uid, $pwd, $options);
}
$conn->setAttribute(PDO::SQLSRV_ATTR_ENCODING, PDO::SQLSRV_ENCODING_SYSTEM);
}
catch (PDOException $e)
{
$conn = null;
TraceEx("\nFailed to connect to $server: ".$e->getMessage(), true);
}
return ($conn);
}
function ConnectionID($conn)
{
$query = "SELECT @@SPID FROM master.dbo.sysprocesses WHERE (program_name='Microsoft PHP')";
$connID = null;
$stmt = $conn->query($query);
$row = $stmt->fetch();
if ($row)
{
$connID = $row[0];
}
else
{
echo "Failed to retrieve connection id\n";
}
$stmt = null;
return ($connID);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
ConnectionTest(5);
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
Test "PDO Connection Pooling" completed successfully.

View file

@ -0,0 +1,80 @@
--TEST--
PDO Test for PDO::errorCode()
--DESCRIPTION--
Verification of PDO::errorCode()
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function CheckErrorCode()
{
include 'MsSetup.inc';
$testName = "PDO Connection - Error Code";
StartTest($testName);
$conn1 = Connect();
CheckError(1, $conn1, '00000');
// Prepare test table
$table1 = $tableName."1";
$table2 = $tableName."2";
CreateTableEx($conn1, $table1, "id int NOT NULL PRIMARY KEY, label VARCHAR(10)", null);
// Check errors when executing SELECT queries
$stmt1 = $conn1->prepare("SELECT id, label FROM [$table1]");
CheckError(2, $conn1);
CheckError(3, $stmt1);
$stmt1->execute();
$stmt2 = &$stmt1;
CheckError(4, $stmt1);
$stmt1->closeCursor();
DropTable($conn1, $table1);
CheckError(5, $conn1);
// Cleanup
$stmt1 = null;
$conn1 = null;
EndTest($testName);
}
function CheckError($offset, &$obj, $expected = '00000')
{
$code = $obj->errorCode();
if (($code != $expected) && (($expected != '00000') || ($code !='')))
{
printf("[%03d] Expecting error code '%s' got code '%s'\n",
$offset, $expected, $code);
}
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
CheckErrorCode();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
Test "PDO Connection - Error Code" completed successfully.

View file

@ -0,0 +1,116 @@
--TEST--
PDO Test for PDO::errorInfo()
--DESCRIPTION--
Verification of PDO::errorInfo()
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function CheckErrorInfo()
{
include 'MsSetup.inc';
$testName = "PDO Connection - Error Info";
StartTest($testName);
$conn1 = Connect();
CheckError(1, $conn1, '00000');
// Prepare test table
$table1 = $tableName."1";
$table2 = $tableName."2";
CreateTableEx($conn1, $table1, "id int NOT NULL PRIMARY KEY, label VARCHAR(10)", null);
// Check errors when executing SELECT queries
$stmt1 = $conn1->prepare("SELECT id, label FROM [$table1]");
CheckError(2, $conn1);
CheckError(3, $stmt1);
$stmt1->execute();
$stmt2 = &$stmt1;
CheckError(4, $stmt1);
$stmt1->closeCursor();
//DropTable($conn1, $table1);
@$stmt1->execute();
CheckError(5, $conn1);
//CheckError(6, $stmt1, '42S02');
//CheckError(7, $stmt2, '42S02');
$stmt1->closeCursor();
DropTable($conn1, $table2);
$conn2 = &$conn1;
//@$conn1->query("SELECT id, label FROM [$table2]");
//CheckError(8, $conn1, '42S02');
//CheckError(9, $conn2, '42S02');
CreateTableEx($conn1, $table1, "id int NOT NULL PRIMARY KEY, label VARCHAR(10)", null);
$stmt1 = $conn1->query("SELECT id, label FROM [$table1]");
CheckError(10, $conn1);
CheckError(11, $stmt1);
$stmt1->closeCursor();
// @$conn1->query("SELECT id, label FROM [$table2]");
// CheckError(12, $conn1, '42S02');
// CheckError(13, $conn2, '42S02');
CheckError(14, $stmt1);
// Cleanup
DropTable($conn1, $table1);
$stmt1 = null;
$conn1 = null;
EndTest($testName);
}
function CheckError($offset, &$obj, $expected = '00000')
{
$info = $obj->errorInfo();
$code = $info[0];
if (($code != $expected) && (($expected != '00000') || ($code != '')))
{
printf("[%03d] Expecting error code '%s' got code '%s'\n",
$offset, $expected, $code);
}
if ($expected != '00000')
{
if (!isset($info[1]) || ($info[1] == ''))
{
printf("[%03d] Driver-specific error code not set\n", $offset);
}
if (!isset($info[2]) || ($info[2] == ''))
{
printf("[%03d] Driver-specific error message.not set\n", $offset);
}
}
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
CheckErrorInfo();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
Test "PDO Connection - Error Info" completed successfully.

View file

@ -0,0 +1,77 @@
--TEST--
PDO Info Test
--DESCRIPTION--
Verifies the functionality of "getAttribute”.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function AttrTest()
{
include 'MsSetup.inc';
$testName = "PDO Connection - Attribute Info";
StartTest($testName);
$conn1 = Connect();
ShowInfo($conn1);
$conn1 = null;
EndTest($testName);
}
function ShowInfo($conn)
{
$attributes = array("AUTOCOMMIT", // Not supported
"CASE", // 0
"CLIENT_VERSION", // array
"CONNECTION_STATUS", // Not supported
"DRIVER_NAME", // sqlsrv
"ERRMODE", // 0
"ORACLE_NULLS", // 0
"PERSISTENT", // false
"PREFETCH", // Not supported
"SERVER_INFO", // array
"SERVER_VERSION", // string
"STATEMENT_CLASS", // array
"STRINGIFY_FETCHES", // false
"TIMEOUT"); // Not supported
foreach ($attributes as $val)
{
$att = "PDO::ATTR_$val";
$attKey = constant($att);
$attVal = $conn->getAttribute($attKey);
Trace("$att ($attKey): [$attVal]\n");
}
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
AttrTest();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECTF--
SQLSTATE[IM001]: Driver does not support this function: driver does not support that attribute

View file

@ -0,0 +1,77 @@
--TEST--
PDO Test for read-only attributes
--DESCRIPTION--
Verification of read-only attributes
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function ReadOnly()
{
include 'MsSetup.inc';
$testName = "PDO Connection - Attribute";
StartTest($testName);
$conn1 = Connect();
$conn1->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
CheckAttribute($conn1, "PDO::ATTR_CLIENT_VERSION");
CheckAttribute($conn1, "PDO::ATTR_DRIVER_NAME");
CheckAttribute($conn1, "PDO::ATTR_SERVER_INFO");
CheckAttribute($conn1, "PDO::ATTR_SERVER_VERSION");
// Cleanup
$conn1 = null;
EndTest($testName);
}
function CheckAttribute($conn, $attName)
{
$att = constant($attName);
// Attribute value is a non-empty string
$value1 = $conn->getAttribute($att);
// Attribute is read-only
if ($conn->setAttribute($att, $value1) !== false)
{
printf("Attribute $attName must be read-only\n");
}
// Attribute value should not change
$value2 = $conn->getAttribute($att);
if ($value2 !== $value1)
{
printf("Value of attribute $attName should not change from '%s' to '%s'\n", $value1, $value2);
}
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
ReadOnly();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
Test "PDO Connection - Attribute" completed successfully.

View file

@ -0,0 +1,149 @@
--TEST--
PDO Test for PDO::ATTR_CASE
--DESCRIPTION--
Verification of fetch behavior when using PDO::ATTR_CASE.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function ExecStmt()
{
include 'MsSetup.inc';
$testName = "PDO Connection - Case Attribute";
StartTest($testName);
$conn1 = Connect();
// Prepare test table
$dataCols = "id, val";
CreateTableEx($conn1, $tableName, "ID int NOT NULL PRIMARY KEY, val VARCHAR(10)", null);
InsertRowEx($conn1, $tableName, $dataCols, "1, 'A'", null);
InsertRowEx($conn1, $tableName, $dataCols, "2, 'B'", null);
InsertRowEx($conn1, $tableName, $dataCols, "3, 'C'", null);
// Retrieve data as array with no change on columns case
$conn1->setAttribute(PDO::ATTR_CASE, PDO::CASE_NATURAL);
$stmt1 = PrepareQuery($conn1, "SELECT * FROM [$tableName]");
$stmt1->execute();
var_dump($stmt1->fetchAll(PDO::FETCH_ASSOC));
$stmt1->closeCursor();
// Retrieve data as array with lower case columns
$conn1->setAttribute(PDO::ATTR_CASE, PDO::CASE_LOWER);
$stmt1 = PrepareQuery($conn1, "SELECT * FROM [$tableName]");
$stmt1->execute();
var_dump($stmt1->fetchAll(PDO::FETCH_ASSOC));
$stmt1->closeCursor();
// Retrieve data as array with upper case columns
$conn1->setAttribute(PDO::ATTR_CASE, PDO::CASE_UPPER);
$stmt1 = PrepareQuery($conn1, "SELECT * FROM [$tableName]");
$stmt1->execute();
var_dump($stmt1->fetchAll(PDO::FETCH_ASSOC));
$stmt1->closeCursor();
// Cleanup
DropTable($conn1, $tableName);
$stmt1 = null;
$conn1 = null;
EndTest($testName);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
ExecStmt();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
array(3) {
[0]=>
array(2) {
["ID"]=>
string(1) "1"
["val"]=>
string(1) "A"
}
[1]=>
array(2) {
["ID"]=>
string(1) "2"
["val"]=>
string(1) "B"
}
[2]=>
array(2) {
["ID"]=>
string(1) "3"
["val"]=>
string(1) "C"
}
}
array(3) {
[0]=>
array(2) {
["id"]=>
string(1) "1"
["val"]=>
string(1) "A"
}
[1]=>
array(2) {
["id"]=>
string(1) "2"
["val"]=>
string(1) "B"
}
[2]=>
array(2) {
["id"]=>
string(1) "3"
["val"]=>
string(1) "C"
}
}
array(3) {
[0]=>
array(2) {
["ID"]=>
string(1) "1"
["VAL"]=>
string(1) "A"
}
[1]=>
array(2) {
["ID"]=>
string(1) "2"
["VAL"]=>
string(1) "B"
}
[2]=>
array(2) {
["ID"]=>
string(1) "3"
["VAL"]=>
string(1) "C"
}
}
Test "PDO Connection - Case Attribute" completed successfully.

View file

@ -0,0 +1,98 @@
--TEST--
PDO Interface Test
--DESCRIPTION--
Verifies the compliance of the PDO API Interface.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function ConnInfo()
{
include 'MsSetup.inc';
$testName = "PDO - Interface";
StartTest($testName);
$conn1 = Connect();
CheckInterface($conn1);
$conn1 = null;
EndTest($testName);
}
function CheckInterface($conn)
{
$expected = array(
'getAvailableDrivers' => true,
'__construct' => true,
'errorCode' => true,
'errorInfo' => true,
'getAttribute' => true,
'setAttribute' => true,
'beginTransaction' => true,
'commit' => true,
'rollBack' => true,
'exec' => true,
'query' => true,
'prepare' => true,
'lastInsertId' => true,
'quote' => true,
'__wakeup' => true,
'__sleep' => true,
'inTransaction' => true,
);
$classname = get_class($conn);
$methods = get_class_methods($classname);
foreach ($methods as $k => $method)
{
if (isset($expected[$method]))
{
unset($expected[$method]);
unset($methods[$k]);
}
if ($method == $classname)
{
unset($expected['__construct']);
unset($methods[$k]);
}
}
if (!empty($expected))
{
printf("Dumping missing class methods\n");
var_dump($expected);
}
if (!empty($methods))
{
printf("Found more methods than expected, dumping list\n");
var_dump($methods);
}
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
ConnInfo();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
Test "PDO - Interface" completed successfully.

View file

@ -0,0 +1,93 @@
--TEST--
PDO Exec Test
--DESCRIPTION--
Basic verification for PDO::exec().
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function ExecStmt()
{
include 'MsSetup.inc';
$testName = "PDO Connection - Exec";
StartTest($testName);
$conn1 = Connect();
$dbName1 = $databaseName."1";
$dbName2 = $databaseName."2";
CreateDB($conn1, $dbName1);
DoExec(1, $conn1, "ALTER DATABASE [$dbName1] MODIFY NAME = [$dbName2]", 0);
DoExec(2, $conn1, "DROP DATABASE [$dbName2]", 0);
CreateTableEx($conn1, $tableName, "id INT, val CHAR(10)", null);
DoExec(3, $conn1, "CREATE INDEX [$tableIndex] ON [$tableName](id)", 0);
DoExec(4, $conn1, "DROP INDEX [$tableIndex] ON [$tableName]", 0);
DoExec(5, $conn1, "ALTER TABLE [$tableName] DROP COLUMN id", 0);
DoExec(6, $conn1, "ALTER TABLE [$tableName] ADD id INT", 0);
DoExec(7, $conn1, "INSERT INTO [$tableName] (id, val) VALUES (1, 'ABC')", 1);
// Cleanup
DropTable($conn1, $tableName);
DropDB($conn1, $dbName1);
$stmt1 = null;
$conn1 = null;
EndTest($testName);
}
function DoExec($offset, &$conn, $tsql, $expected)
{
$ret = false;
try
{
$actual = @$conn->exec($tsql);
if ($actual === $expected)
{
$ret = true;
}
else
{
printf("[%03d] Expecting '%s' (%s) instead of '%s' (%s) when executing '%s', [%s] %s\n",
$offset, $expected, gettype($expected), $actual, gettype($actual),
$tsql, $conn->errorCode(), implode(' ', $conn->errorInfo()));
}
}
catch (PDOException $e)
{
printf("[%03d] Execution of '%s' has failed, [%s] %s\n",
$offset, $tsql, $conn->errorCode(), implode(' ', $conn->errorInfo()));
}
return ($ret);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
ExecStmt();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
Test "PDO Connection - Exec" completed successfully.

View file

@ -0,0 +1,132 @@
--TEST--
PDO Basic Statement Test
--DESCRIPTION--
Basic verification for PDOStatement.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function ExecStmt()
{
include 'MsSetup.inc';
$testName = "PDO Statement";
StartTest($testName);
$conn1 = Connect();
// Prepare test table
$dataCols = "id, val, grp";
CreateTableEx($conn1, $tableName, "id int NOT NULL PRIMARY KEY, val VARCHAR(10), grp VARCHAR(10)", null);
InsertRowEx($conn1, $tableName, $dataCols, "1, 'A', 'Group1'", null);
InsertRowEx($conn1, $tableName, $dataCols, "2, 'B', 'Group2'", null);
$tsql = "SELECT val, grp FROM [$tableName]";
// Testing prepared query
$stmt1 = ExecuteQueryEx($conn1, $tsql, false);
$stmt1->setFetchMode(PDO::FETCH_NUM);
foreach ($stmt1 as $data)
{
var_dump($data);
}
unset($stmt1);
// Testing direct query
$stmt1 = $conn1->query($tsql, PDO::FETCH_CLASS, 'Test');
foreach ($stmt1 as $data)
{
var_dump($data);
}
unset($stmt1);
$stmt1 = $conn1->query($tsql, PDO::FETCH_CLASS, 'Test', array('WOW'));
foreach ($stmt1 as $data)
{
var_dump($data);
}
// Cleanup
DropTable($conn1, $tableName);
$stmt1 = null;
$conn1 = null;
EndTest($testName);
}
class Test
{
function __construct($name = 'N/A')
{
echo __METHOD__ . "($name)\n";
}
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
ExecStmt();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECTF--
array(2) {
[0]=>
string(1) "A"
[1]=>
string(6) "Group1"
}
array(2) {
[0]=>
string(1) "B"
[1]=>
string(6) "Group2"
}
Test::__construct(N/A)
object(Test)#%d (2) {
["val"]=>
string(1) "A"
["grp"]=>
string(6) "Group1"
}
Test::__construct(N/A)
object(Test)#%d (2) {
["val"]=>
string(1) "B"
["grp"]=>
string(6) "Group2"
}
Test::__construct(WOW)
object(Test)#%d (2) {
["val"]=>
string(1) "A"
["grp"]=>
string(6) "Group1"
}
Test::__construct(WOW)
object(Test)#%d (2) {
["val"]=>
string(1) "B"
["grp"]=>
string(6) "Group2"
}
Test "PDO Statement" completed successfully.

View file

@ -0,0 +1,100 @@
--TEST--
PDOStatement Interface Test
--DESCRIPTION--
Verifies the compliance of the PDOStatement API Interface.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function StmtInfo()
{
include 'MsSetup.inc';
$testName = "PDOStatement - Interface";
StartTest($testName);
$conn1 = Connect();
CreateTableEx($conn1, $tableName, "id int NOT NULL PRIMARY KEY, val VARCHAR(10)", null);
$stmt1 = ExecuteQuery($conn1, "SELECT * FROM [$tableName]");
CheckInterface($stmt1);
$stmt1 = null;
$conn1 = null;
EndTest($testName);
}
function CheckInterface($stmt)
{
$expected = array(
'errorCode' => true,
'errorInfo' => true,
'getAttribute' => true,
'setAttribute' => true,
'debugDumpParams' => true,
'bindColumn' => true,
'bindParam' => true,
'bindValue' => true,
'closeCursor' => true,
'columnCount' => true,
'execute' => true,
'setFetchMode' => true,
'fetch' => true,
'fetchAll' => true,
'fetchColumn' => true,
'fetchObject' => true,
'getColumnMeta' => true,
'nextRowset' => true,
'rowCount' => true,
'__wakeup' => true,
'__sleep' => true,
);
$classname = get_class($stmt);
$methods = get_class_methods($classname);
foreach ($methods as $k => $method)
{
if (isset($expected[$method]))
{
unset($expected[$method]);
unset($methods[$k]);
}
}
if (!empty($expected))
{
printf("Dumping missing class methods\n");
var_dump($expected);
}
if (!empty($methods))
{
printf("Found more methods than expected, dumping list\n");
var_dump($methods);
}
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
StmtInfo();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
Test "PDOStatement - Interface" completed successfully.

View file

@ -0,0 +1,105 @@
--TEST--
PDO Statement Execution Test
--DESCRIPTION--
Basic verification for "PDOStatement::execute()".
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function ExecStmt()
{
include 'MsSetup.inc';
$testName = "PDO Statement - Execute";
StartTest($testName);
$conn1 = Connect();
// Prepare test table
CreateTableEx($conn1, $tableName, "id int NOT NULL PRIMARY KEY, val VARCHAR(10), val2 VARCHAR(16)", null);
$data = array( array('10', 'Abc', 'zxy'),
array('20', 'Def', 'wvu'),
array('30', 'Ghi', 'tsr'),
array('40', 'Jkl', 'qpo'),
array('50', 'Mno', 'nml'),
array('60', 'Pqr', 'kji'));
// Insert using question mark placeholders
$stmt1 = PrepareQuery($conn1, "INSERT INTO [$tableName] VALUES(?, ?, ?)");
foreach ($data as $row)
{
$stmt1->execute($row);
}
unset($stmt1);
// Count inserted rows
$stmt2 = PrepareQuery($conn1, "SELECT COUNT(id) FROM [$tableName]");
$stmt2->execute();
$num = $stmt2->fetchColumn();
echo 'There are ' . $num . " rows in the table.\n";
$stmt2->closeCursor();
// Insert using named parameters
$stmt1 = PrepareQuery($conn1, "INSERT INTO [$tableName] VALUES(:first, :second, :third)");
foreach ($data as $row)
{
$stmt1->execute(array(':first'=>($row[0] + 5), ':second'=>$row[1], ':third'=>$row[2]));
}
unset($stmt1);
$stmt2->execute();
$num = $stmt2->fetchColumn();
unset($stmt2);
echo 'There are ' . $num . " rows in the table.\n";
// Fetch
$stmt1 = PrepareQuery($conn1, "SELECT TOP(1) :param FROM [$tableName] ORDER BY id ASC");
$stmt1->execute(array(':param' => 'ID'));
var_dump($stmt1->fetchAll(PDO::FETCH_ASSOC));
$stmt1->closeCursor();
// Cleanup
DropTable($conn1, $tableName);
$stmt1 = null;
$stmt2 = null;
$conn1 = null;
EndTest($testName);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
ExecStmt();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
There are 6 rows in the table.
There are 12 rows in the table.
array(1) {
[0]=>
array(1) {
[""]=>
string(2) "ID"
}
}
Test "PDO Statement - Execute" completed successfully.

View file

@ -0,0 +1,75 @@
--TEST--
PDO Columns Count Test
--DESCRIPTION--
Basic verification for "PDOStatement::columnCount()".
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function ExecStmt()
{
include 'MsSetup.inc';
$testName = "PDO Statement - Column Count";
StartTest($testName);
$conn1 = Connect();
// Prepare test table
$dataCols = "id, val, val2";
CreateTableEx($conn1, $tableName, "id int NOT NULL PRIMARY KEY, val VARCHAR(10), val2 VARCHAR(16)", null);
InsertRowEx($conn1, $tableName, $dataCols, "1, 'A', 'A'", null);
InsertRowEx($conn1, $tableName, $dataCols, "2, 'B', 'B'", null);
InsertRowEx($conn1, $tableName, $dataCols, "3, 'C', 'C'", null);
$tsql1 = "SELECT id, val FROM [$tableName]";
$tsql2 = "SELECT id, val, val2 FROM [$tableName]";
$tsql3 = "SELECT COUNT(*) FROM [$tableName]";
// Testing with direct query
foreach (array($tsql1, $tsql2, $tsql3) as $tsql)
{
$stmt1 = ExecuteQuery($conn1, $tsql);
$res = $stmt1->columnCount();
echo "Counted $res columns.\n";
unset($stmt1);
}
// Cleanup
DropTable($conn1, $tableName);
$stmt1 = null;
$conn1 = null;
EndTest($testName);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
ExecStmt();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECTF--
Counted 2 columns.
Counted 3 columns.
Counted 1 columns.
Test "PDO Statement - Column Count" completed successfully.

View file

@ -0,0 +1,157 @@
--TEST--
PDO Column Metadata Test
--DESCRIPTION--
Verification for "PDOStatenent::getColumnMetadata".
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function Fetch()
{
include 'MsSetup.inc';
$testName = "PDO Statement - Column Metadata";
StartTest($testName);
$conn1 = Connect();
// Prepare test table
CreateTableEx($conn1, $tableName, "id int NOT NULL PRIMARY KEY, val VARCHAR(10), val2 VARCHAR(16)", null);
$data = array( array('10', 'Abc', 'zxy'),
array('20', 'Def', 'wvu'),
array('30', 'Ghi', 'tsr'),
array('40', 'Jkl', 'qpo'),
array('50', 'Mno', 'nml'),
array('60', 'Pqr', 'kji'));
// Insert using question mark placeholders
$stmt1 = PrepareQuery($conn1, "INSERT INTO [$tableName] VALUES(?, ?, ?)");
foreach ($data as $row)
{
$stmt1->execute($row);
}
unset($stmt1);
// Retrieve column metadata via a SELECT query
$stmt1 = ExecuteQuery($conn1, "SELECT id, val, val2 FROM [$tableName]");
$md = $stmt1->getColumnMeta(0);
var_dump($md);
$md = $stmt1->getColumnMeta(1);
var_dump($md);
$md = $stmt1->getColumnMeta(2);
var_dump($md);
unset($stmt1);
// Retrieve column metadata as returned by a COUNT query
$stmt1 = ExecuteQuery($conn1, "SELECT COUNT(*) FROM [$tableName]");
$md = $stmt1->getColumnMeta(0);
var_dump($md);
// Cleanup
DropTable($conn1, $tableName);
$stmt1 = null;
$conn1 = null;
EndTest($testName);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
Fetch();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
array(8) {
["flags"]=>
int(0)
["sqlsrv:decl_type"]=>
string(3) "int"
["native_type"]=>
string(6) "string"
["table"]=>
string(0) ""
["pdo_type"]=>
int(2)
["name"]=>
string(2) "id"
["len"]=>
int(10)
["precision"]=>
int(0)
}
array(8) {
["flags"]=>
int(0)
["sqlsrv:decl_type"]=>
string(7) "varchar"
["native_type"]=>
string(6) "string"
["table"]=>
string(0) ""
["pdo_type"]=>
int(2)
["name"]=>
string(3) "val"
["len"]=>
int(10)
["precision"]=>
int(0)
}
array(8) {
["flags"]=>
int(0)
["sqlsrv:decl_type"]=>
string(7) "varchar"
["native_type"]=>
string(6) "string"
["table"]=>
string(0) ""
["pdo_type"]=>
int(2)
["name"]=>
string(4) "val2"
["len"]=>
int(16)
["precision"]=>
int(0)
}
array(8) {
["flags"]=>
int(0)
["sqlsrv:decl_type"]=>
string(3) "int"
["native_type"]=>
string(6) "string"
["table"]=>
string(0) ""
["pdo_type"]=>
int(2)
["name"]=>
string(0) ""
["len"]=>
int(10)
["precision"]=>
int(0)
}
Test "PDO Statement - Column Metadata" completed successfully.

View file

@ -0,0 +1,85 @@
--TEST--
PDO Row Count Test
--DESCRIPTION--
Verification for "PDOStatement::rowCount()".
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function RowCountTest()
{
include 'MsSetup.inc';
$testName = "PDO Statement - Row Count";
StartTest($testName);
$conn1 = Connect();
// Prepare test table
$dataCols = "id, label";
CreateTableEx($conn1, $tableName, "id int NOT NULL PRIMARY KEY, label CHAR(1)", null);
InsertRowEx($conn1, $tableName, $dataCols, "1, 'a'", null);
InsertRowEx($conn1, $tableName, $dataCols, "2, 'b'", null);
InsertRowEx($conn1, $tableName, $dataCols, "3, 'c'", null);
InsertRowEx($conn1, $tableName, $dataCols, "4, 'd'", null);
InsertRowEx($conn1, $tableName, $dataCols, "5, 'e'", null);
InsertRowEx($conn1, $tableName, $dataCols, "6, 'f'", null);
// Check row count
$tsql1 = "SELECT id FROM [$tableName] WHERE 1 = 0";
//CheckRowCount($conn1, $tsql1, 0);
$tsql2 = "SELECT id FROM [$tableName] WHERE id = 1";
CheckRowCount($conn1, $tsql2, -1);
$tsql3 = "INSERT INTO [$tableName] ($dataCols) VALUES (7, 'g')";
CheckRowCount($conn1, $tsql3, 1);
$tsql3 = "DELETE FROM [$tableName]";
CheckRowCount($conn1, $tsql3, 7);
// Cleanup
DropTable($conn1, $tableName);
$conn1 = null;
EndTest($testName);
}
function CheckRowCount($conn, $tsql, $rows)
{
$stmt = ExecuteQuery($conn, $tsql);
$count = $stmt->rowCount();
if ($count !== $rows)
{
printf("Unexpected row count: $count instead of $rows\n");
}
unset($stmt);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
RowCountTest();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
Test "PDO Statement - Row Count" completed successfully.

View file

@ -0,0 +1,133 @@
--TEST--
PDO Fetch Mode Test
--DESCRIPTION--
Basic verification for "PDOStatement::setFetchMode()”.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function FetchMode()
{
include 'MsSetup.inc';
$testName = "PDO Statement - Set Fetch Mode";
StartTest($testName);
$conn1 = Connect();
// Prepare test table
$dataCols = "id, val, grp";
CreateTableEx($conn1, $tableName, "id int NOT NULL PRIMARY KEY, val VARCHAR(10), grp VARCHAR(10)", null);
InsertRowEx($conn1, $tableName, $dataCols, "1, 'A', 'Group1'", null);
InsertRowEx($conn1, $tableName, $dataCols, "2, 'B', 'Group2'", null);
// Execute test
$tsql = "SELECT val, grp FROM [$tableName]";
$stmt1 = $conn1->query($tsql, PDO::FETCH_NUM);
var_dump($stmt1->fetchAll());
unset($stmt1);
$stmt1 = $conn1->query($tsql, PDO::FETCH_CLASS, 'Test');
var_dump($stmt1->fetchAll());
unset($stmt1);
$stmt1 = $conn1->query($tsql, PDO::FETCH_NUM);
$stmt1->setFetchMode(PDO::FETCH_CLASS, 'Test', array('Changed'));
var_dump($stmt1->fetchAll());
// Cleanup
DropTable($conn1, $tableName);
$stmt1 = null;
$conn1 = null;
EndTest($testName);
}
class Test
{
function __construct($name = 'N/A')
{
echo __METHOD__ . "($name)\n";
}
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
FetchMode();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECTF--
array(2) {
[0]=>
array(2) {
[0]=>
string(1) "A"
[1]=>
string(6) "Group1"
}
[1]=>
array(2) {
[0]=>
string(1) "B"
[1]=>
string(6) "Group2"
}
}
Test::__construct(N/A)
Test::__construct(N/A)
array(2) {
[0]=>
object(Test)#%d (2) {
["val"]=>
string(1) "A"
["grp"]=>
string(6) "Group1"
}
[1]=>
object(Test)#%d (2) {
["val"]=>
string(1) "B"
["grp"]=>
string(6) "Group2"
}
}
Test::__construct(Changed)
Test::__construct(Changed)
array(2) {
[0]=>
object(Test)#%d (2) {
["val"]=>
string(1) "A"
["grp"]=>
string(6) "Group1"
}
[1]=>
object(Test)#%d (2) {
["val"]=>
string(1) "B"
["grp"]=>
string(6) "Group2"
}
}
Test "PDO Statement - Set Fetch Mode" completed successfully.

View file

@ -0,0 +1,273 @@
--TEST--
PDO Fetch Bound Test
--DESCRIPTION--
Verification for "PDOStatenent::fetch(PDO::FETCH_BOUND)".
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function Fetch()
{
include 'MsSetup.inc';
$testName = "PDO Statement - Fetch Bound";
StartTest($testName);
$conn1 = Connect();
// Prepare test table
CreateTableEx($conn1, $tableName, "id int NOT NULL PRIMARY KEY, val VARCHAR(10), val2 VARCHAR(16)", null);
$data = array( array('10', 'Abc', 'zxy'),
array('20', 'Def', 'wvu'),
array('30', 'Ghi', 'tsr'),
array('40', 'Jkl', 'qpo'),
array('50', 'Mno', 'nml'),
array('60', 'Pqr', 'kji'));
// Insert using question mark placeholders
$stmt1 = PrepareQuery($conn1, "INSERT INTO [$tableName] VALUES(?, ?, ?)");
foreach ($data as $row)
{
$stmt1->execute($row);
}
unset($stmt1);
// Count inserted rows
$stmt2 = PrepareQuery($conn1, "SELECT COUNT(id) FROM [$tableName]");
$stmt2->execute();
$num = $stmt2->fetchColumn();
echo 'There are ' . $num . " rows in the table.\n";
$stmt2->closeCursor();
// Insert using named parameters
$stmt1 = PrepareQuery($conn1, "INSERT INTO [$tableName] VALUES(:first, :second, :third)");
foreach ($data as $row)
{
$stmt1->execute(array(':first'=>($row[0] + 5), ':second'=>$row[1], ':third'=>$row[2]));
}
unset($stmt1);
$stmt2->execute();
$num = $stmt2->fetchColumn();
echo 'There are ' . $num . " rows in the table.\n";
$dataCols = "idx, txt";
CreateTableEx($conn1, $tableName, "idx int NOT NULL PRIMARY KEY, txt VARCHAR(20)", null);
InsertRowEx($conn1, $tableName, $dataCols, "0, 'String0'", null);
InsertRowEx($conn1, $tableName, $dataCols, "1, 'String1'", null);
InsertRowEx($conn1, $tableName, $dataCols, "2, 'String2'", null);
// Testing with prepared query
$stmt1 = PrepareQuery($conn1, "SELECT COUNT(idx) FROM [$tableName]");
$stmt1->execute();
var_dump($stmt1->fetchColumn());
unset($stmt1);
$stmt1 = PrepareQuery($conn1, "SELECT idx, txt FROM [$tableName] ORDER BY idx");
$stmt1->execute();
$data = $stmt1->fetchAll(PDO::FETCH_COLUMN|PDO::FETCH_UNIQUE);
var_dump($data);
echo "===WHILE===\n";
$stmt1->bindColumn('idx', $idx);
$stmt1->bindColumn('txt', $txt);
$stmt1->execute();
while ($stmt1->fetch(PDO::FETCH_BOUND))
{
var_dump(array($idx=>$txt));
}
echo "===ALONE===\n";
$stmt2 = PrepareQuery($conn1, "SELECT txt FROM [$tableName] WHERE idx=:inp");
$stmt2->bindParam(':inp', $idx); // by foreign name
$stmt3 = PrepareQuery($conn1, "SELECT idx FROM [$tableName] WHERE txt=:txt");
$stmt3->bindParam(':txt', $txt); // using same name
foreach($data as $idx => $txt)
{
var_dump(array($idx=>$txt));
var_dump($stmt2->execute());
if ($idx == 0)
{ // bindColumn()s after execute() has been called at least once
$stmt2->bindColumn('txt', $col1);
}
var_dump($stmt2->fetch(PDO::FETCH_BOUND));
$stmt2->closeCursor();
var_dump($stmt3->execute());
if ($idx == 0)
{ // bindColumn()s after execute() has been called at least once
$stmt3->bindColumn('idx', $col2);
}
var_dump($stmt3->fetch(PDO::FETCH_BOUND));
$stmt3->closeCursor();
var_dump(array($col2=>$col1));
}
echo "===REBIND/SAME===\n";
$stmt3->bindColumn('idx', $col1);
foreach($data as $idx => $txt)
{
var_dump(array($idx=>$txt));
var_dump($stmt2->execute());
var_dump($stmt2->fetch(PDO::FETCH_BOUND));
$stmt2->closeCursor();
var_dump($col1);
var_dump($stmt3->execute());
var_dump($stmt3->fetch(PDO::FETCH_BOUND));
$stmt3->closeCursor();
var_dump($col1);
}
echo "===REBIND/CONFLICT===\n";
$stmt1->bindColumn('idx', $col1);
$stmt1->bindColumn('txt', $col1);
$stmt1->execute();
while($stmt1->fetch(PDO::FETCH_BOUND))
{
var_dump($col1);
}
// Cleanup
DropTable($conn1, $tableName);
$stmt1 = null;
$stmt2 = null;
$stmt3 = null;
$conn1 = null;
EndTest($testName);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
Fetch();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
There are 6 rows in the table.
There are 12 rows in the table.
string(1) "3"
array(3) {
[0]=>
string(7) "String0"
[1]=>
string(7) "String1"
[2]=>
string(7) "String2"
}
===WHILE===
array(1) {
[0]=>
string(7) "String0"
}
array(1) {
[1]=>
string(7) "String1"
}
array(1) {
[2]=>
string(7) "String2"
}
===ALONE===
array(1) {
[0]=>
string(7) "String0"
}
bool(true)
bool(true)
bool(true)
bool(true)
array(1) {
[0]=>
string(7) "String0"
}
array(1) {
[1]=>
string(7) "String1"
}
bool(true)
bool(true)
bool(true)
bool(true)
array(1) {
[1]=>
string(7) "String1"
}
array(1) {
[2]=>
string(7) "String2"
}
bool(true)
bool(true)
bool(true)
bool(true)
array(1) {
[2]=>
string(7) "String2"
}
===REBIND/SAME===
array(1) {
[0]=>
string(7) "String0"
}
bool(true)
bool(true)
string(7) "String0"
bool(true)
bool(true)
string(1) "0"
array(1) {
[1]=>
string(7) "String1"
}
bool(true)
bool(true)
string(7) "String1"
bool(true)
bool(true)
string(1) "1"
array(1) {
[2]=>
string(7) "String2"
}
bool(true)
bool(true)
string(7) "String2"
bool(true)
bool(true)
string(1) "2"
===REBIND/CONFLICT===
string(7) "String0"
string(7) "String1"
string(7) "String2"
Test "PDO Statement - Fetch Bound" completed successfully.

View file

@ -0,0 +1,155 @@
--TEST--
PDO Fetch Test with FETCH_INTO mode
--DESCRIPTION--
Verification of fetch behavior with "PDO::FETCH_INTO" mode.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function Fetch()
{
include 'MsSetup.inc';
$testName = "PDO Statement - Fetch Into";
StartTest($testName);
$conn1 = Connect();
// Prepare test table
CreateTableEx($conn1, $tableName, "id int NOT NULL PRIMARY KEY, val VARCHAR(10), val2 VARCHAR(16)", null);
$data = array( array('10', 'Abc', 'zxy'),
array('20', 'Def', 'wvu'),
array('30', 'Ghi', 'tsr'),
array('40', 'Jkl', 'qpo'),
array('50', 'Mno', 'nml'),
array('60', 'Pqr', 'kji'));
// Insert data using question mark placeholders
$stmt1 = PrepareQuery($conn1, "INSERT INTO [$tableName] VALUES(?, ?, ?)");
foreach ($data as $row)
{
$stmt1->execute($row);
}
unset($stmt1);
// Retrive data
$stmt1 = PrepareQuery($conn1, "SELECT * FROM [$tableName]");
echo "===SUCCESS===\n";
$stmt1->setFetchMode(PDO::FETCH_INTO, new Test);
$stmt1->execute();
foreach($stmt1 as $obj)
{
var_dump($obj);
}
echo "===FAIL===\n";
$stmt1->setFetchMode(PDO::FETCH_INTO, new Fail);
$stmt1->execute();
foreach($stmt1 as $obj)
{
var_dump($obj);
}
// Cleanup
DropTable($conn1, $tableName);
$stmt1 = null;
$conn1 = null;
EndTest($testName);
}
class Test
{
public $id, $val, $val2;
}
class Fail
{
protected $id;
public $val, $val2;
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
Fetch();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECTF--
===SUCCESS===
object(Test)#%d (3) {
["id"]=>
string(2) "10"
["val"]=>
string(3) "Abc"
["val2"]=>
string(3) "zxy"
}
object(Test)#%d (3) {
["id"]=>
string(2) "20"
["val"]=>
string(3) "Def"
["val2"]=>
string(3) "wvu"
}
object(Test)#%d (3) {
["id"]=>
string(2) "30"
["val"]=>
string(3) "Ghi"
["val2"]=>
string(3) "tsr"
}
object(Test)#%d (3) {
["id"]=>
string(2) "40"
["val"]=>
string(3) "Jkl"
["val2"]=>
string(3) "qpo"
}
object(Test)#%d (3) {
["id"]=>
string(2) "50"
["val"]=>
string(3) "Mno"
["val2"]=>
string(3) "nml"
}
object(Test)#%d (3) {
["id"]=>
string(2) "60"
["val"]=>
string(3) "Pqr"
["val2"]=>
string(3) "kji"
}
===FAIL===
Fatal error: Uncaught Error: Cannot access protected property Fail::$id in %sPDO39_FetchInto.php:%x
Stack trace:
#0 %sPDO39_FetchInto.php(%x): Fetch()
#1 %sPDO39_FetchInto.php(%x): Repro()
#2 {main}
thrown in %sPDO39_FetchInto.php on line %x

View file

@ -0,0 +1,67 @@
--TEST--
PDO Query Test with PDO::FETCH_LAZY
--DESCRIPTION--
Verification for "PDO::query() with PDO::FETCH_LAZY mode".
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function Fetch()
{
include 'MsSetup.inc';
$testName = "PDO Statement - Fetch Lazy";
StartTest($testName);
$conn1 = Connect();
// Prepare test table
$dataCols = "id, name";
CreateTableEx($conn1, $tableName, "id int NOT NULL PRIMARY KEY, name VARCHAR(20)", null);
InsertRowEx($conn1, $tableName, $dataCols, "1, 'test1'", null);
InsertRowEx($conn1, $tableName, $dataCols, "2, 'test2'", null);
// Testing with direct query
$stmt1 = $conn1->query("SELECT * FROM [$tableName]", PDO::FETCH_LAZY);
foreach ($stmt1 as $v)
{
echo "lazy: " . $v->id.$v->name."\n";
}
// Cleanup
DropTable($conn1, $tableName);
$stmt1 = null;
$conn1 = null;
EndTest($testName);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
Fetch();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
lazy: 1test1
lazy: 2test2
Test "PDO Statement - Fetch Lazy" completed successfully.

View file

@ -0,0 +1,86 @@
--TEST--
PDO Fetch Test with PDO::FETCH_ASSOC
--DESCRIPTION--
Basic verification for "PDOStatement::fetchAll(PDO::FETCH_ASSOC)”.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function FetchAll($execMode, $fetchMode)
{
include 'MsSetup.inc';
$testName = "PDO Statement - Fetch All";
StartTest($testName);
$conn1 = Connect();
// Prepare test table
$dataCols = "id, val";
CreateTableEx($conn1, $tableName, "id int NOT NULL PRIMARY KEY, val VARCHAR(10)", null);
InsertRowEx($conn1, $tableName, $dataCols, "1, 'A'", null);
InsertRowEx($conn1, $tableName, $dataCols, "2, 'B'", null);
InsertRowEx($conn1, $tableName, $dataCols, "3, 'C'", null);
// Query table and retrieve data
$stmt1 = ExecuteQueryEx($conn1, "SELECT * FROM [$tableName]", $execMode);
var_dump($stmt1->fetchAll($fetchMode));
// Cleanup
DropTable($conn1, $tableName);
$stmt1 = null;
$conn1 = null;
EndTest($testName);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
FetchAll(false, PDO::FETCH_ASSOC);
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
array(3) {
[0]=>
array(2) {
["id"]=>
string(1) "1"
["val"]=>
string(1) "A"
}
[1]=>
array(2) {
["id"]=>
string(1) "2"
["val"]=>
string(1) "B"
}
[2]=>
array(2) {
["id"]=>
string(1) "3"
["val"]=>
string(1) "C"
}
}
Test "PDO Statement - Fetch All" completed successfully.

View file

@ -0,0 +1,86 @@
--TEST--
PDO Fetch Test with PDO::FETCH_NUM
--DESCRIPTION--
Basic verification for "PDOStatement::fetchAll(PDO::FETCH_NUM)”.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function FetchAll($execMode, $fetchMode)
{
include 'MsSetup.inc';
$testName = "PDO Statement - Fetch All";
StartTest($testName);
$conn1 = Connect();
// Prepare test table
$dataCols = "id, val";
CreateTableEx($conn1, $tableName, "id int NOT NULL PRIMARY KEY, val VARCHAR(10)", null);
InsertRowEx($conn1, $tableName, $dataCols, "1, 'A'", null);
InsertRowEx($conn1, $tableName, $dataCols, "2, 'B'", null);
InsertRowEx($conn1, $tableName, $dataCols, "3, 'C'", null);
// Query table and retrieve data
$stmt1 = ExecuteQueryEx($conn1, "SELECT * FROM [$tableName]", $execMode);
var_dump($stmt1->fetchAll($fetchMode));
// Cleanup
DropTable($conn1, $tableName);
$stmt1 = null;
$conn1 = null;
EndTest($testName);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
FetchAll(true, PDO::FETCH_NUM);
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
array(3) {
[0]=>
array(2) {
[0]=>
string(1) "1"
[1]=>
string(1) "A"
}
[1]=>
array(2) {
[0]=>
string(1) "2"
[1]=>
string(1) "B"
}
[2]=>
array(2) {
[0]=>
string(1) "3"
[1]=>
string(1) "C"
}
}
Test "PDO Statement - Fetch All" completed successfully.

View file

@ -0,0 +1,98 @@
--TEST--
PDO Fetch Test with PDO::FETCH_BOTH
--DESCRIPTION--
Basic verification for "PDOStatement::fetchAll(PDO::FETCH_BOTH)”.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function FetchAll($execMode, $fetchMode)
{
include 'MsSetup.inc';
$testName = "PDO Statement - Fetch All";
StartTest($testName);
$conn1 = Connect();
// Prepare test table
$dataCols = "id, val";
CreateTableEx($conn1, $tableName, "id int NOT NULL PRIMARY KEY, val VARCHAR(10)", null);
InsertRowEx($conn1, $tableName, $dataCols, "1, 'A'", null);
InsertRowEx($conn1, $tableName, $dataCols, "2, 'B'", null);
InsertRowEx($conn1, $tableName, $dataCols, "3, 'C'", null);
// Query table and retrieve data
$stmt1 = ExecuteQueryEx($conn1, "SELECT * FROM [$tableName]", $execMode);
var_dump($stmt1->fetchAll($fetchMode));
// Cleanup
DropTable($conn1, $tableName);
$stmt1 = null;
$conn1 = null;
EndTest($testName);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
FetchAll(false, PDO::FETCH_BOTH);
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
array(3) {
[0]=>
array(4) {
["id"]=>
string(1) "1"
[0]=>
string(1) "1"
["val"]=>
string(1) "A"
[1]=>
string(1) "A"
}
[1]=>
array(4) {
["id"]=>
string(1) "2"
[0]=>
string(1) "2"
["val"]=>
string(1) "B"
[1]=>
string(1) "B"
}
[2]=>
array(4) {
["id"]=>
string(1) "3"
[0]=>
string(1) "3"
["val"]=>
string(1) "C"
[1]=>
string(1) "C"
}
}
Test "PDO Statement - Fetch All" completed successfully.

View file

@ -0,0 +1,86 @@
--TEST--
PDO Fetch Test with PDO::FETCH_OBJ
--DESCRIPTION--
Basic verification for "PDOStatement::fetchAll(PDO::FETCH_OBJ)”.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function FetchAll($execMode, $fetchMode)
{
include 'MsSetup.inc';
$testName = "PDO Statement - Fetch All";
StartTest($testName);
$conn1 = Connect();
// Prepare test table
$dataCols = "id, val";
CreateTableEx($conn1, $tableName, "id int NOT NULL PRIMARY KEY, val VARCHAR(10)", null);
InsertRowEx($conn1, $tableName, $dataCols, "1, 'A'", null);
InsertRowEx($conn1, $tableName, $dataCols, "2, 'B'", null);
InsertRowEx($conn1, $tableName, $dataCols, "3, 'C'", null);
// Query table and retrieve data
$stmt1 = ExecuteQueryEx($conn1, "SELECT * FROM [$tableName]", $execMode);
var_dump($stmt1->fetchAll($fetchMode));
// Cleanup
DropTable($conn1, $tableName);
$stmt1 = null;
$conn1 = null;
EndTest($testName);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
FetchAll(false, PDO::FETCH_OBJ);
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECTF--
array(3) {
[0]=>
object(stdClass)#%d (2) {
["id"]=>
string(1) "1"
["val"]=>
string(1) "A"
}
[1]=>
object(stdClass)#%d (2) {
["id"]=>
string(1) "2"
["val"]=>
string(1) "B"
}
[2]=>
object(stdClass)#%d (2) {
["id"]=>
string(1) "3"
["val"]=>
string(1) "C"
}
}
Test "PDO Statement - Fetch All" completed successfully.

View file

@ -0,0 +1,114 @@
--TEST--
PDO Fetch Test with PDO::FETCH_GROUP
--DESCRIPTION--
Basic verification for "PDOStatement::fetchAll(PDO::FETCH_GROUP)”.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function FetchAll($fetchMode)
{
include 'MsSetup.inc';
$testName = "PDO Statement - Fetch All";
StartTest($testName);
$conn1 = Connect();
// Prepare test table
$dataCols = "id, val";
CreateTableEx($conn1, $tableName, "id int NOT NULL PRIMARY KEY, val VARCHAR(10)", null);
InsertRowEx($conn1, $tableName, $dataCols, "1, 'A'", null);
InsertRowEx($conn1, $tableName, $dataCols, "2, 'A'", null);
InsertRowEx($conn1, $tableName, $dataCols, "3, 'C'", null);
// Query table and retrieve data
$stmt1 = PrepareQuery($conn1, "SELECT val, id FROM [$tableName]");
$stmt1->execute();
var_dump($stmt1->fetchAll(PDO::FETCH_NUM|$fetchMode));
$stmt1->execute();
var_dump($stmt1->fetchAll(PDO::FETCH_ASSOC|$fetchMode));
// Cleanup
DropTable($conn1, $tableName);
$stmt1 = null;
$conn1 = null;
EndTest($testName);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
FetchAll(PDO::FETCH_GROUP);
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
array(2) {
["A"]=>
array(2) {
[0]=>
array(1) {
[0]=>
string(1) "1"
}
[1]=>
array(1) {
[0]=>
string(1) "2"
}
}
["C"]=>
array(1) {
[0]=>
array(1) {
[0]=>
string(1) "3"
}
}
}
array(2) {
["A"]=>
array(2) {
[0]=>
array(1) {
["id"]=>
string(1) "1"
}
[1]=>
array(1) {
["id"]=>
string(1) "2"
}
}
["C"]=>
array(1) {
[0]=>
array(1) {
["id"]=>
string(1) "3"
}
}
}
Test "PDO Statement - Fetch All" completed successfully.

View file

@ -0,0 +1,120 @@
--TEST--
PDO Fetch Test with PDO::FETCH_UNIQUE
--DESCRIPTION--
Basic verification for "PDOStatement::fetchAll(PDO::FETCH_UNIQUE)”.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function FetchAll()
{
include 'MsSetup.inc';
$testName = "PDO Statement - Fetch All";
StartTest($testName);
$conn1 = Connect();
// Prepare test table
$dataCols = "id, val";
CreateTableEx($conn1, $tableName, "id CHAR(1) NOT NULL PRIMARY KEY, val VARCHAR(10)", null);
InsertRowEx($conn1, $tableName, $dataCols, "'A', 'A'", null);
InsertRowEx($conn1, $tableName, $dataCols, "'B', 'A'", null);
InsertRowEx($conn1, $tableName, $dataCols, "'C', 'C'", null);
// Test FetchAll(PDO::FETCH_UNIQUE) without conflict
$stmt1 = PrepareQuery($conn1, "SELECT id, val FROM [$tableName]");
$stmt1->execute();
var_dump($stmt1->fetchAll(PDO::FETCH_NUM|PDO::FETCH_UNIQUE));
$stmt1->execute();
var_dump($stmt1->fetchAll(PDO::FETCH_ASSOC|PDO::FETCH_UNIQUE));
unset($stmt1);
// Test FetchAll(PDO::FETCH_UNIQUE) with conflict
$stmt1 = ExecuteQuery($conn1, "SELECT val, id FROM [$tableName]");
var_dump($stmt1->fetchAll(PDO::FETCH_NUM|PDO::FETCH_UNIQUE));
// Cleanup
DropTable($conn1, $tableName);
$stmt1 = null;
$conn1 = null;
EndTest($testName);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
FetchAll();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
array(3) {
["A"]=>
array(1) {
[0]=>
string(1) "A"
}
["B"]=>
array(1) {
[0]=>
string(1) "A"
}
["C"]=>
array(1) {
[0]=>
string(1) "C"
}
}
array(3) {
["A"]=>
array(1) {
["val"]=>
string(1) "A"
}
["B"]=>
array(1) {
["val"]=>
string(1) "A"
}
["C"]=>
array(1) {
["val"]=>
string(1) "C"
}
}
array(2) {
["A"]=>
array(1) {
[0]=>
string(1) "B"
}
["C"]=>
array(1) {
[0]=>
string(1) "C"
}
}
Test "PDO Statement - Fetch All" completed successfully.

View file

@ -0,0 +1,250 @@
--TEST--
PDO Fetch Test with PDO::FETCH_CLASSTYPE
--DESCRIPTION--
Basic verification for "PDOStatement::fetchAll(PDO::FETCH_CLASSTYPE)”.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function FetchAll()
{
include 'MsSetup.inc';
$testName = "PDO Statement - Fetch All";
StartTest($testName);
$conn1 = Connect();
// Prepare test tables
$dataCols1 = "id, name";
$table1 = $tableName."1";
CreateTableEx($conn1, $table1, "id int NOT NULL PRIMARY KEY, name VARCHAR(10) NOT NULL UNIQUE", null);
InsertRowEx($conn1, $table1, $dataCols1, "0, 'stdClass'", null);
InsertRowEx($conn1, $table1, $dataCols1, "1, 'Test1'", null);
InsertRowEx($conn1, $table1, $dataCols1, "2, 'Test2'", null);
$dataCols2 = "id, classtype, val";
$table2 = $tableName."2";
CreateTableEx($conn1, $table2, "id int NOT NULL PRIMARY KEY, classtype int, val VARCHAR(10)", null);
InsertRowEx($conn1, $table2, $dataCols2, "1, 0, 'A'", null);
InsertRowEx($conn1, $table2, $dataCols2, "2, 1, 'B'", null);
InsertRowEx($conn1, $table2, $dataCols2, "3, 2, 'C'", null);
InsertRowEx($conn1, $table2, $dataCols2, "4, 3, 'D'", null);
$dataCols3 = "id, classtype, val, grp";
$table3 = $tableName."3";
CreateTableEx($conn1, $table3, "id int NOT NULL PRIMARY KEY, classtype int, val VARCHAR(10), grp VARCHAR(10)", null);
InsertRowEx($conn1, $table3, $dataCols3, "1, 0, 'A', 'Group1'", null);
InsertRowEx($conn1, $table3, $dataCols3, "2, 1, 'B', 'Group1'", null);
InsertRowEx($conn1, $table3, $dataCols3, "3, 2, 'C', 'Group2'", null);
InsertRowEx($conn1, $table3, $dataCols3, "4, 3, 'D', 'Group2'", null);
// Test fetchAll(PDO::FETCH_CLASSTYPE)
$stmt1 = PrepareQuery($conn1, "SELECT $table1.name, $table2.id AS id, $table2.val AS val FROM $table2 LEFT JOIN $table1 ON $table2.classtype=$table1.id");
$stmt1->execute();
var_dump($stmt1->fetchAll(PDO::FETCH_NUM));
$stmt1->execute();
var_dump($stmt1->fetchAll(PDO::FETCH_CLASS|PDO::FETCH_CLASSTYPE, 'Test3'));
unset($stmt1);
// Test fetchAll(PDO::FETCH_CLASSTYPE) with GROUP/UNIQUE
$stmt1 = PrepareQuery($conn1, "SELECT $table1.name, $table3.grp AS grp, $table3.id AS id, $table3.val AS val FROM $table3 LEFT JOIN $table1 ON $table3.classtype=$table1.id");
$stmt1->execute();
var_dump($stmt1->fetchAll(PDO::FETCH_CLASS|PDO::FETCH_CLASSTYPE|PDO::FETCH_GROUP, 'Test3'));
$stmt1->execute();
var_dump($stmt1->fetchAll(PDO::FETCH_CLASS|PDO::FETCH_CLASSTYPE|PDO::FETCH_UNIQUE, 'Test3'));
// Cleanup
DropTable($conn1, $table1);
DropTable($conn1, $table2);
DropTable($conn1, $table3);
$stmt1 = null;
$conn1 = null;
EndTest($testName);
}
class Test1
{
public function __construct()
{
echo __METHOD__ . "()\n";
}
}
class Test2
{
public function __construct()
{
echo __METHOD__ . "()\n";
}
}
class Test3
{
public function __construct()
{
echo __METHOD__ . "()\n";
}
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
FetchAll();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECTF--
array(4) {
[0]=>
array(3) {
[0]=>
string(8) "stdClass"
[1]=>
string(1) "1"
[2]=>
string(1) "A"
}
[1]=>
array(3) {
[0]=>
string(5) "Test1"
[1]=>
string(1) "2"
[2]=>
string(1) "B"
}
[2]=>
array(3) {
[0]=>
string(5) "Test2"
[1]=>
string(1) "3"
[2]=>
string(1) "C"
}
[3]=>
array(3) {
[0]=>
NULL
[1]=>
string(1) "4"
[2]=>
string(1) "D"
}
}
Test1::__construct()
Test2::__construct()
Test3::__construct()
array(4) {
[0]=>
object(stdClass)#%d (2) {
["id"]=>
string(1) "1"
["val"]=>
string(1) "A"
}
[1]=>
object(Test1)#%d (2) {
["id"]=>
string(1) "2"
["val"]=>
string(1) "B"
}
[2]=>
object(Test2)#%d (2) {
["id"]=>
string(1) "3"
["val"]=>
string(1) "C"
}
[3]=>
object(Test3)#%d (2) {
["id"]=>
string(1) "4"
["val"]=>
string(1) "D"
}
}
Test1::__construct()
Test2::__construct()
Test3::__construct()
array(2) {
["Group1"]=>
array(2) {
[0]=>
object(stdClass)#%d (2) {
["id"]=>
string(1) "1"
["val"]=>
string(1) "A"
}
[1]=>
object(Test1)#%d (2) {
["id"]=>
string(1) "2"
["val"]=>
string(1) "B"
}
}
["Group2"]=>
array(2) {
[0]=>
object(Test2)#%d (2) {
["id"]=>
string(1) "3"
["val"]=>
string(1) "C"
}
[1]=>
object(Test3)#%d (2) {
["id"]=>
string(1) "4"
["val"]=>
string(1) "D"
}
}
}
Test1::__construct()
Test2::__construct()
Test3::__construct()
array(2) {
["Group1"]=>
object(Test1)#%d (2) {
["id"]=>
string(1) "2"
["val"]=>
string(1) "B"
}
["Group2"]=>
object(Test3)#%d (2) {
["id"]=>
string(1) "4"
["val"]=>
string(1) "D"
}
}
Test "PDO Statement - Fetch All" completed successfully.

View file

@ -0,0 +1,138 @@
--TEST--
PDO Fetch Test with PDO::FETCH_COLUMN
--DESCRIPTION--
Verification for "PDOStatement::fetchAll(PDO::FETCH_COLUMN)".
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function Fetch()
{
include 'MsSetup.inc';
$testName = "PDO Statement - Fetch All";
StartTest($testName);
$conn1 = Connect();
// Prepare test table
$dataCols = "id, val, val2";
CreateTableEx($conn1, $tableName, "id int NOT NULL PRIMARY KEY, val VARCHAR(10), val2 VARCHAR(10)", null);
InsertRowEx($conn1, $tableName, $dataCols, "1, 'A', 'A2'", null);
InsertRowEx($conn1, $tableName, $dataCols, "2, 'A', 'B2'", null);
// Testing with prepared query
$stmt1 = PrepareQuery($conn1, "SELECT id, val, val2 FROM [$tableName]");
$stmt1->execute();
var_dump($stmt1->fetchAll(PDO::FETCH_COLUMN));
$stmt1->execute();
var_dump($stmt1->fetchAll(PDO::FETCH_COLUMN, 2));
$stmt1->execute();
var_dump($stmt1->fetchAll(PDO::FETCH_COLUMN|PDO::FETCH_GROUP));
$stmt1->execute();
var_dump($stmt1->fetchAll(PDO::FETCH_COLUMN|PDO::FETCH_UNIQUE));
$stmt1->execute();
var_dump($stmt1->fetchAll(PDO::FETCH_COLUMN|PDO::FETCH_UNIQUE, 0));
$stmt1->execute();
var_dump($stmt1->fetchAll(PDO::FETCH_COLUMN|PDO::FETCH_UNIQUE, 1));
$stmt1->execute();
var_dump($stmt1->fetchAll(PDO::FETCH_COLUMN|PDO::FETCH_UNIQUE, 2));
unset($stmt1);
$stmt1 = PrepareQuery($conn1, "SELECT val, val2 FROM [$tableName]");
$stmt1->execute();
var_dump($stmt1->fetchAll(PDO::FETCH_COLUMN|PDO::FETCH_GROUP));
// Cleanup
DropTable($conn1, $tableName);
$stmt1 = null;
$conn1 = null;
EndTest($testName);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
Fetch();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
array(2) {
[0]=>
string(1) "1"
[1]=>
string(1) "2"
}
array(2) {
[0]=>
string(2) "A2"
[1]=>
string(2) "B2"
}
array(2) {
[1]=>
array(1) {
[0]=>
string(1) "A"
}
[2]=>
array(1) {
[0]=>
string(1) "A"
}
}
array(2) {
[1]=>
string(1) "A"
[2]=>
string(1) "A"
}
array(2) {
[1]=>
string(1) "1"
[2]=>
string(1) "2"
}
array(2) {
[1]=>
string(1) "A"
[2]=>
string(1) "A"
}
array(2) {
[1]=>
string(2) "A2"
[2]=>
string(2) "B2"
}
array(1) {
["A"]=>
array(2) {
[0]=>
string(2) "A2"
[1]=>
string(2) "B2"
}
}
Test "PDO Statement - Fetch All" completed successfully.

View file

@ -0,0 +1,141 @@
--TEST--
PDO Fetch Test with PDO::FETCH_COLUMN for unicode column names
--DESCRIPTION--
Verification for "PDOStatement::fetchAll(PDO::FETCH_COLUMN)".
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function Fetch()
{
include 'MsSetup.inc';
$testName = "PDO Statement - Fetch All";
StartTest($testName);
$conn1 = Connect();
// Prepare test table
$val = str_repeat("P银河系", 32);
$val2 = str_repeat("银河系мужирафиtest是", 8);
$dataCols = "id, $val, $val2";
CreateTableEx($conn1, $tableName, "id int NOT NULL PRIMARY KEY, $val VARCHAR(10), $val2 VARCHAR(10)", null);
InsertRowEx($conn1, $tableName, $dataCols, "1, 'A', 'A2'", null);
InsertRowEx($conn1, $tableName, $dataCols, "2, 'A', 'B2'", null);
// Testing with prepared query
$stmt1 = PrepareQuery($conn1, "SELECT id, $val, $val2 FROM [$tableName]");
$stmt1->execute();
var_dump($stmt1->fetchAll(PDO::FETCH_COLUMN));
$stmt1->execute();
var_dump($stmt1->fetchAll(PDO::FETCH_COLUMN, 2));
$stmt1->execute();
var_dump($stmt1->fetchAll(PDO::FETCH_COLUMN|PDO::FETCH_GROUP));
$stmt1->execute();
var_dump($stmt1->fetchAll(PDO::FETCH_COLUMN|PDO::FETCH_UNIQUE));
$stmt1->execute();
var_dump($stmt1->fetchAll(PDO::FETCH_COLUMN|PDO::FETCH_UNIQUE, 0));
$stmt1->execute();
var_dump($stmt1->fetchAll(PDO::FETCH_COLUMN|PDO::FETCH_UNIQUE, 1));
$stmt1->execute();
var_dump($stmt1->fetchAll(PDO::FETCH_COLUMN|PDO::FETCH_UNIQUE, 2));
unset($stmt1);
$stmt1 = PrepareQuery($conn1, "SELECT $val, $val2 FROM [$tableName]");
$stmt1->execute();
var_dump($stmt1->fetchAll(PDO::FETCH_COLUMN|PDO::FETCH_GROUP));
// Cleanup
DropTable($conn1, $tableName);
$stmt1 = null;
$conn1 = null;
EndTest($testName);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
Fetch();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
array(2) {
[0]=>
string(1) "1"
[1]=>
string(1) "2"
}
array(2) {
[0]=>
string(2) "A2"
[1]=>
string(2) "B2"
}
array(2) {
[1]=>
array(1) {
[0]=>
string(1) "A"
}
[2]=>
array(1) {
[0]=>
string(1) "A"
}
}
array(2) {
[1]=>
string(1) "A"
[2]=>
string(1) "A"
}
array(2) {
[1]=>
string(1) "1"
[2]=>
string(1) "2"
}
array(2) {
[1]=>
string(1) "A"
[2]=>
string(1) "A"
}
array(2) {
[1]=>
string(2) "A2"
[2]=>
string(2) "B2"
}
array(1) {
["A"]=>
array(2) {
[0]=>
string(2) "A2"
[1]=>
string(2) "B2"
}
}
Test "PDO Statement - Fetch All" completed successfully.

View file

@ -0,0 +1,340 @@
--TEST--
PDO Fetch Test with PDO::FETCH_FUNC
--DESCRIPTION--
Basic verification for "PDOStatement::fetchAll(PDO::FETCH_FUNC)”.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function FetchAll()
{
include 'MsSetup.inc';
$testName = "PDO Statement - Fetch All";
StartTest($testName);
$conn1 = Connect();
// Prepare test tables
$dataCols = "id, val, grp";
CreateTableEx($conn1, $tableName, "id int NOT NULL PRIMARY KEY, val VARCHAR(10), grp VARCHAR(10)", null);
InsertRowEx($conn1, $tableName, $dataCols, "1, 'A', 'Group1'", null);
InsertRowEx($conn1, $tableName, $dataCols, "2, 'B', 'Group1'", null);
InsertRowEx($conn1, $tableName, $dataCols, "3, 'C', 'Group2'", null);
InsertRowEx($conn1, $tableName, $dataCols, "4, 'D', 'Group2'", null);
$f = new Test1(0, 0);
// Query table and retrieve data
$stmt1 = PrepareQuery($conn1, "SELECT grp, id FROM [$tableName]");
$stmt1->execute();
var_dump($stmt1->fetchAll(PDO::FETCH_FUNC|PDO::FETCH_GROUP, 'test'));
unset($stmt1);
$stmt1 = PrepareQuery($conn1, "SELECT id, val FROM [$tableName]");
$stmt1->execute();
var_dump($stmt1->fetchAll(PDO::FETCH_FUNC, 'test'));
$stmt1->execute();
var_dump($stmt1->fetchAll(PDO::FETCH_FUNC, array('Test1','factory')));
$stmt1->execute();
var_dump($stmt1->fetchAll(PDO::FETCH_FUNC, array($f, 'factory')));
unset($stmt1);
$stmt1 = $conn1->prepare("SELECT id, val FROM [$tableName]",
array(PDO::ATTR_STATEMENT_CLASS=>array('DerivedStatement',
array('Overloaded', $conn1))));
var_dump(get_class($stmt1));
$stmt1->execute();
var_dump($stmt1->fetchAll(PDO::FETCH_FUNC, array($stmt1, 'retrieve')));
$stmt1->execute();
var_dump($stmt1->fetchAll(PDO::FETCH_FUNC, array($stmt1, 'reTrieve')));
$stmt1->execute();
var_dump($stmt1->fetchAll(PDO::FETCH_FUNC, array($stmt1, 'RETRIEVE')));
// Cleanup
DropTable($conn1, $tableName);
$stmt1 = null;
$conn1 = null;
EndTest($testName);
}
class DerivedStatement extends PDOStatement
{
private function __construct($name, $conn)
{
$this->name = $name;
echo __METHOD__ . "($name)\n";
}
function reTrieve($id, $val) {
echo __METHOD__ . "($id,$val)\n";
return array($id=>$val);
}
}
class Test1
{
public function __construct($id, $val)
{
echo __METHOD__ . "($id,$val)\n";
$this->id = $id;
$this->val = $val;
}
static public function factory($id, $val)
{
echo __METHOD__ . "($id,$val)\n";
return new self($id, $val);
}
}
function test($id,$val='N/A')
{
echo __METHOD__ . "($id,$val)\n";
return array($id=>$val);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
FetchAll();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECTF--
Test1::__construct(0,0)
test(1,N/A)
test(2,N/A)
test(3,N/A)
test(4,N/A)
array(2) {
["Group1"]=>
array(2) {
[0]=>
array(1) {
[1]=>
string(3) "N/A"
}
[1]=>
array(1) {
[2]=>
string(3) "N/A"
}
}
["Group2"]=>
array(2) {
[0]=>
array(1) {
[3]=>
string(3) "N/A"
}
[1]=>
array(1) {
[4]=>
string(3) "N/A"
}
}
}
test(1,A)
test(2,B)
test(3,C)
test(4,D)
array(4) {
[0]=>
array(1) {
[1]=>
string(1) "A"
}
[1]=>
array(1) {
[2]=>
string(1) "B"
}
[2]=>
array(1) {
[3]=>
string(1) "C"
}
[3]=>
array(1) {
[4]=>
string(1) "D"
}
}
Test1::factory(1,A)
Test1::__construct(1,A)
Test1::factory(2,B)
Test1::__construct(2,B)
Test1::factory(3,C)
Test1::__construct(3,C)
Test1::factory(4,D)
Test1::__construct(4,D)
array(4) {
[0]=>
object(Test1)#%d (2) {
["id"]=>
string(1) "1"
["val"]=>
string(1) "A"
}
[1]=>
object(Test1)#%d (2) {
["id"]=>
string(1) "2"
["val"]=>
string(1) "B"
}
[2]=>
object(Test1)#%d (2) {
["id"]=>
string(1) "3"
["val"]=>
string(1) "C"
}
[3]=>
object(Test1)#%d (2) {
["id"]=>
string(1) "4"
["val"]=>
string(1) "D"
}
}
Test1::factory(1,A)
Test1::__construct(1,A)
Test1::factory(2,B)
Test1::__construct(2,B)
Test1::factory(3,C)
Test1::__construct(3,C)
Test1::factory(4,D)
Test1::__construct(4,D)
array(4) {
[0]=>
object(Test1)#%d (2) {
["id"]=>
string(1) "1"
["val"]=>
string(1) "A"
}
[1]=>
object(Test1)#%d (2) {
["id"]=>
string(1) "2"
["val"]=>
string(1) "B"
}
[2]=>
object(Test1)#%d (2) {
["id"]=>
string(1) "3"
["val"]=>
string(1) "C"
}
[3]=>
object(Test1)#%d (2) {
["id"]=>
string(1) "4"
["val"]=>
string(1) "D"
}
}
DerivedStatement::__construct(Overloaded)
string(16) "DerivedStatement"
DerivedStatement::reTrieve(1,A)
DerivedStatement::reTrieve(2,B)
DerivedStatement::reTrieve(3,C)
DerivedStatement::reTrieve(4,D)
array(4) {
[0]=>
array(1) {
[1]=>
string(1) "A"
}
[1]=>
array(1) {
[2]=>
string(1) "B"
}
[2]=>
array(1) {
[3]=>
string(1) "C"
}
[3]=>
array(1) {
[4]=>
string(1) "D"
}
}
DerivedStatement::reTrieve(1,A)
DerivedStatement::reTrieve(2,B)
DerivedStatement::reTrieve(3,C)
DerivedStatement::reTrieve(4,D)
array(4) {
[0]=>
array(1) {
[1]=>
string(1) "A"
}
[1]=>
array(1) {
[2]=>
string(1) "B"
}
[2]=>
array(1) {
[3]=>
string(1) "C"
}
[3]=>
array(1) {
[4]=>
string(1) "D"
}
}
DerivedStatement::reTrieve(1,A)
DerivedStatement::reTrieve(2,B)
DerivedStatement::reTrieve(3,C)
DerivedStatement::reTrieve(4,D)
array(4) {
[0]=>
array(1) {
[1]=>
string(1) "A"
}
[1]=>
array(1) {
[2]=>
string(1) "B"
}
[2]=>
array(1) {
[3]=>
string(1) "C"
}
[3]=>
array(1) {
[4]=>
string(1) "D"
}
}
Test "PDO Statement - Fetch All" completed successfully.

View file

@ -0,0 +1,130 @@
--TEST--
PDO Fetch Object Test
--DESCRIPTION--
Basic verification for "PDOStatement::fetchObject”.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
class TestClass
{
private $set_calls = 0;
protected static $static_set_calls = 0;
// NOTE: PDO does not care about protected
protected $grp;
// NOTE: PDO does not care about private and calls __construct() after __set()
private function __construct($param1, $param2)
{
printf("TestClass::__construct(%s, %s): %d / %d\n", $param1, $param2,
self::$static_set_calls, $this->set_calls);
}
// NOTE: PDO will call __set() prior to calling __construct()
public function __set($prop, $value)
{
$this->inc();
printf("TestClass::__set(%s, -%s-) %d\n",
$prop, var_export($value, true), $this->set_calls, self::$static_set_calls);
$this->{$prop} = $value;
}
// NOTE: PDO can call regular methods prior to calling __construct()
public function inc()
{
$this->set_calls++;
self::$static_set_calls++;
}
}
function Fetch()
{
include 'MsSetup.inc';
$testName = "PDO Statement - Fetch Object";
StartTest($testName);
$conn1 = Connect();
// Prepare test table
// Prepare test table
$dataCols = "id, label";
CreateTableEx($conn1, $tableName, "id int NOT NULL PRIMARY KEY, label CHAR(1)", null);
InsertRowEx($conn1, $tableName, $dataCols, "1, 'a'", null);
InsertRowEx($conn1, $tableName, $dataCols, "2, 'b'", null);
InsertRowEx($conn1, $tableName, $dataCols, "3, 'c'", null);
InsertRowEx($conn1, $tableName, $dataCols, "4, 'd'", null);
InsertRowEx($conn1, $tableName, $dataCols, "5, 'e'", null);
InsertRowEx($conn1, $tableName, $dataCols, "6, 'f'", null);
// Query test table and retrieve data
$tsql = "SELECT TOP(3) * FROM [$tableName] ORDER BY id ASC";
$stmt1 = PrepareQuery($conn1, $tsql);
$stmt1->execute();
$rowno = 0;
$rows[] = array();
while (is_object($rows[] = $stmt1->fetchObject('TestClass', array($rowno++, $rowno))))
{
printf("PDOStatement::fetchObject() was called for row $rowno\n");
}
var_dump($rows[$rowno - 1]);
// Cleanup
DropTable($conn1, $tableName);
$stmt1 = null;
$conn1 = null;
EndTest($testName);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
Fetch();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECTF--
TestClass::__set(id, -'1'-) 1
TestClass::__set(label, -'a'-) 2
TestClass::__construct(0, 1): 2 / 2
PDOStatement::fetchObject() was called for row 1
TestClass::__set(id, -'2'-) 1
TestClass::__set(label, -'b'-) 2
TestClass::__construct(1, 2): 4 / 2
PDOStatement::fetchObject() was called for row 2
TestClass::__set(id, -'3'-) 1
TestClass::__set(label, -'c'-) 2
TestClass::__construct(2, 3): 6 / 2
PDOStatement::fetchObject() was called for row 3
object(TestClass)#%d (4) {
["set_calls":"TestClass":private]=>
int(2)
["grp":protected]=>
NULL
["id"]=>
string(1) "3"
["label"]=>
string(1) "c"
}
Test "PDO Statement - Fetch Object" completed successfully.

View file

@ -0,0 +1,123 @@
--TEST--
PDO Fetch LOB Test
--DESCRIPTION--
Verification for LOB handling.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function LobTest()
{
include 'MsSetup.inc';
$testName = "PDO Statement - Fetch LOB";
StartTest($testName);
$conn1 = Connect();
// Execute test
$data = str_repeat('A', 255);
FetchLob(1, $conn1, $tableName, "VARCHAR(512)", 1, $data);
FetchLob(2, $conn1, $tableName, "NVARCHAR(512)", 2, $data);
unset($data);
$data = str_repeat('B', 4000);
FetchLob(3, $conn1, $tableName, "VARCHAR(8000)", 3, $data);
FetchLob(4, $conn1, $tableName, "NVARCHAR(4000)", 4, $data);
unset($data);
$data = str_repeat('C', 100000);
FetchLob(5, $conn1, $tableName, "TEXT", 5, $data);
FetchLob(6, $conn1, $tableName, "NTEXT", 6, $data);
unset($data);
// Cleanup
DropTable($conn1, $tableName);
$conn1 = null;
EndTest($testName);
}
function FetchLob($offset, $conn, $table, $sqlType, $data1, $data2)
{
$id = NULL;
$label = NULL;
CreateTableEx($conn, $table, "id int NOT NULL PRIMARY KEY, label $sqlType", null);
InsertRowEx($conn, $table, "id, label", "$data1, '$data2'", null);
// Check data fetched with PDO::FETCH_BOUND
$stmt = ExecuteQuery($conn, "SELECT * FROM [$table]");
if (!$stmt->bindColumn(1, $id, PDO::PARAM_INT))
{
LogInfo($offset, "Cannot bind integer column");
}
if (!$stmt->bindColumn(2, $label, PDO::PARAM_LOB))
{
LogInfo($offset, "Cannot bind LOB column");
}
if (!$stmt->fetch(PDO::FETCH_BOUND))
{
LogInfo($offset, "Cannot fetch bound data");
}
if ($id != $data1)
{
LogInfo($offset, "ID data corruption: [$id] instead of [$data1]");
}
if ($label != $data2)
{
LogInfo($offset, "Label data corruption: [$label] instead of [$data2]");
}
unset($stmt);
unset($label);
// Check data fetched with PDO::FETCH_ASSOC
$stmt = ExecuteQuery($conn, "SELECT * FROM [$table]");
$refData = $stmt->fetch(PDO::FETCH_ASSOC);
if ($refData['id'] != $data1)
{
$id = $refData['id'];
LogInfo($offset, "ID data corruption: [$id] instead of [$data1]");
}
if ($refData['label'] != $data2)
{
$label = $refData['label'];
LogInfo($offset, "Label data corruption: [$label] instead of [$data2]");
}
unset($stmt);
unset($refData);
}
function LogInfo($offset, $msg)
{
printf("[%03d] %s\n", $offset, $msg);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
LobTest();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
Test "PDO Statement - Fetch LOB" completed successfully.

View file

@ -0,0 +1,163 @@
--TEST--
PDO Bind Column Test
--DESCRIPTION--
Verification for "PDOStatement::bindColumn".
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function Fetch()
{
include 'MsSetup.inc';
$testName = "PDO Statement - Bind Column";
StartTest($testName);
$conn1 = Connect();
// Prepare test table
$dataCols = "idx, txt";
CreateTableEx($conn1, $tableName, "idx int NOT NULL PRIMARY KEY, txt VARCHAR(20)", null);
InsertRowEx($conn1, $tableName, $dataCols, "0, 'String0'", null);
InsertRowEx($conn1, $tableName, $dataCols, "1, 'String1'", null);
InsertRowEx($conn1, $tableName, $dataCols, "2, 'String2'", null);
InsertRowEx($conn1, $tableName, $dataCols, "3, 'String3'", null);
// Testing with prepared query
LogInfo(1, "Testing fetchColumn() ...");
$stmt1 = ExecuteQuery($conn1, "SELECT COUNT(idx) FROM [$tableName]");
var_dump($stmt1->fetchColumn());
unset($stmt1);
LogInfo(2, "Testing fetchAll() ...");
$stmt1 = PrepareQuery($conn1, "SELECT idx, txt FROM [$tableName] ORDER BY idx");
$stmt1->execute();
$data = $stmt1->fetchAll(PDO::FETCH_COLUMN|PDO::FETCH_UNIQUE);
var_dump($data);
LogInfo(3, "Testing bindColumn() ...");
$stmt1->bindColumn('idx', $idx);
$stmt1->bindColumn('txt', $txt);
$stmt1->execute();
while ($stmt1->fetch(PDO::FETCH_BOUND))
{
var_dump(array($idx=>$txt));
}
LogInfo(4, "Testing bindColumn() with data check ...");
$id = null;
$val = null;
$data = array();
$index = 0;
if (!$stmt1->bindColumn(1, $id, PDO::PARAM_INT))
{
LogError(5, "Cannot bind integer column", $stmt1);
}
if (!$stmt1->bindColumn(2, $val, PDO::PARAM_STR))
{
LogError(5, "Cannot bind string column", $stmt1);
}
$stmt1->execute();
while ($stmt1->fetch(PDO::FETCH_BOUND))
{
$data[] = array('id' => $id, 'val' => $val);
printf("id = %s (%s) / val = %s (%s)\n",
var_export($id, true), gettype($id),
var_export($val, true), gettype($val));
}
unset($stmt1);
$stmt1 = ExecuteQuery($conn1, "SELECT idx, txt FROM [$tableName] ORDER BY idx");
while ($row = $stmt1->fetch(PDO::FETCH_ASSOC))
{
if ($row['idx'] != $data[$index]['id'])
{
LogInfo(6, "Data corruption for integer column in row $index");
}
if ($row['txt'] != $data[$index]['val'])
{
LogInfo(6, "Data corruption for string column in row $index");
}
$index++;
}
// Cleanup
DropTable($conn1, $tableName);
$stmt1 = null;
$conn1 = null;
EndTest($testName);
}
function LogInfo($offset, $msg)
{
printf("[%03d] %s\n", $offset, $msg);
}
function LogError($offset, $msg, &$obj)
{
printf("[%03d] %s: %s\n", $offset, $msg, $obj->errorCode);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
Fetch();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
[001] Testing fetchColumn() ...
string(1) "4"
[002] Testing fetchAll() ...
array(4) {
[0]=>
string(7) "String0"
[1]=>
string(7) "String1"
[2]=>
string(7) "String2"
[3]=>
string(7) "String3"
}
[003] Testing bindColumn() ...
array(1) {
[0]=>
string(7) "String0"
}
array(1) {
[1]=>
string(7) "String1"
}
array(1) {
[2]=>
string(7) "String2"
}
array(1) {
[3]=>
string(7) "String3"
}
[004] Testing bindColumn() with data check ...
id = 0 (integer) / val = 'String0' (string)
id = 1 (integer) / val = 'String1' (string)
id = 2 (integer) / val = 'String2' (string)
id = 3 (integer) / val = 'String3' (string)
Test "PDO Statement - Bind Column" completed successfully.

View file

@ -0,0 +1,133 @@
--TEST--
PDO Bind Column Test
--DESCRIPTION--
Verification for "PDOStatement::bindColumn()".
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function Bind()
{
include 'MsSetup.inc';
$testName = "PDO Statement - Bind Column";
StartTest($testName);
$conn1 = Connect();
// Prepare test table
$dataCols = "id, label";
CreateTableEx($conn1, $tableName, "id int NOT NULL PRIMARY KEY, label CHAR(1)", null);
InsertRowEx($conn1, $tableName, $dataCols, "1, 'a'", null);
InsertRowEx($conn1, $tableName, $dataCols, "2, 'b'", null);
InsertRowEx($conn1, $tableName, $dataCols, "3, 'c'", null);
InsertRowEx($conn1, $tableName, $dataCols, "4, 'd'", null);
InsertRowEx($conn1, $tableName, $dataCols, "5, 'e'", null);
InsertRowEx($conn1, $tableName, $dataCols, "6, 'f'", null);
$rowCount = 3;
$midRow = 4;
// Check bind column
$tsql1 = "SELECT TOP($rowCount) id, label FROM [$tableName] ORDER BY id ASC";
$data = BindColumn($conn1, $tsql1);
CheckBind($conn1, $tsql1, $data);
$tsql2 = "SELECT TOP($rowCount) id, label FROM (SELECT *, ROW_NUMBER() OVER(ORDER BY id ASC) as row FROM [$tableName]) [$tableName] WHERE row >= $midRow";
$data = BindColumn($conn1, $tsql2);
CheckBind($conn1, $tsql2, $data);
// Cleanup
DropTable($conn1, $tableName);
$conn1 = null;
EndTest($testName);
}
function BindColumn($conn, $tsql)
{
$id = null;
$label = null;
$data = array();
$stmt = PrepareQuery($conn, $tsql);
$stmt->execute();
if (!$stmt->bindColumn(1, $id, PDO::PARAM_INT))
{
LogInfo(1, "Cannot bind integer column");
}
if (!$stmt->bindColumn(2, $label, PDO::PARAM_STR))
{
LogInfo(1, "Cannot bind string column");
}
while ($stmt->fetch(PDO::FETCH_BOUND))
{
printf("id = %s (%s) / label = %s (%s)\n",
var_export($id, true), gettype($id),
var_export($label, true), gettype($label));
$data[] = array('id' => $id, 'label' => $label);
}
unset($stmt);
return ($data);
}
function CheckBind($conn, $tsql, $data)
{
$index = 0;
$stmt = ExecuteQuery($conn, $tsql);
while ($row = $stmt->fetch(PDO::FETCH_ASSOC))
{
if ($row['id'] != $data[$index]['id'])
{
LogInfo(2, "Fetch bound and fetch assoc differ - column 'id', row $index");
}
if ($row['label'] != $data[$index]['label'])
{
LogInfo(2, "Fetch bound and fetch assoc differ - column 'label', row $index");
}
$index++;
}
unset($stmt);
}
function LogInfo($offset, $msg)
{
printf("[%03d] %s\n", $offset, $msg);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
Bind();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
id = 1 (integer) / label = 'a' (string)
id = 2 (integer) / label = 'b' (string)
id = 3 (integer) / label = 'c' (string)
id = 4 (integer) / label = 'd' (string)
id = 5 (integer) / label = 'e' (string)
id = 6 (integer) / label = 'f' (string)
Test "PDO Statement - Bind Column" completed successfully.

View file

@ -0,0 +1,85 @@
--TEST--
PDO Bind Param Test
--DESCRIPTION--
Verification for "PDOStatement::bindParam()".
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function Bind()
{
include 'MsSetup.inc';
$testName = "PDO Statement - Bind Param";
StartTest($testName);
$conn1 = Connect();
// Prepare test table
$dataCols = "id, name";
CreateTableEx($conn1, $tableName, "id int, name VARCHAR(20)", null);
$conn1->exec( "CREATE CLUSTERED INDEX [idx_test_int] ON " . $tableName . "(id)" );
// Insert test data
$stmt1 = PrepareQuery($conn1, "INSERT INTO [$tableName] ($dataCols) VALUES(0, :name)");
$name = NULL;
$before_bind = $name;
$stmt1->bindParam(':name', $name);
// Check that bindParam does not modify parameter
if ($name !== $before_bind)
{
echo "bind: fail\n";
}
else
{
echo "bind: success\n";
}
var_dump($stmt1->execute());
unset($stmt1);
// Retrieve test data
$stmt1 = ExecuteQuery($conn1, "SELECT name FROM [$tableName] WHERE id = 0");
var_dump($stmt1->fetchColumn());
// Cleanup
DropTable($conn1, $tableName);
$stmt1 = null;
$conn1 = null;
EndTest($testName);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
Bind();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
bind: success
bool(true)
NULL
Test "PDO Statement - Bind Param" completed successfully.

View file

@ -0,0 +1,142 @@
--TEST--
PDO Bind Param Test
--DESCRIPTION--
Verification for "PDOStatement::bindParam()".
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function Bind()
{
include 'MsSetup.inc';
$testName = "PDO Statement - Bind Param";
StartTest($testName);
$conn1 = Connect();
// Prepare test table
$dataCols = "id, label";
CreateTableEx($conn1, $tableName, "id int NOT NULL PRIMARY KEY, label CHAR(1)", null);
InsertRowEx($conn1, $tableName, $dataCols, "1, 'a'", null);
InsertRowEx($conn1, $tableName, $dataCols, "2, 'b'", null);
InsertRowEx($conn1, $tableName, $dataCols, "3, 'c'", null);
InsertRowEx($conn1, $tableName, $dataCols, "4, 'd'", null);
InsertRowEx($conn1, $tableName, $dataCols, "5, 'e'", null);
InsertRowEx($conn1, $tableName, $dataCols, "6, 'f'", null);
$id = null;
$label = null;
// Bind param @ SELECT
$tsql1 = "SELECT TOP(2) id, label FROM [$tableName] WHERE id > ? ORDER BY id ASC";
$value1 = 0;
$stmt1 = PrepareQuery($conn1, $tsql1);
BindParam(1, $stmt1, $value1);
ExecStmt(1, $stmt1);
BindColumn(1, $stmt1, $id, $label);
FetchBound($stmt1, $id, $label);
ExecStmt(1, $stmt1);
FetchBound($stmt1, $id, $label);
unset($stmt1);
// Bind param @ INSERT
$tsql2 = "INSERT INTO [$tableName](id, label) VALUES (100, ?)";
$value2 = null;
$stmt1 = PrepareQuery($conn1, $tsql2);
BindParam(2, $stmt1, $value2);
ExecStmt(2, $stmt1);
unset($stmt1);
// Check binding
$tsql3 = "SELECT id, NULL AS _label FROM [$tableName] WHERE label IS NULL";
$stmt1 = ExecuteQuery($conn1, $tsql3);
BindColumn(3, $stmt1, $id, $label);
FetchBound($stmt1, $id, $label);
unset($stmt1);
// Cleanup
DropTable($conn1, $tableName);
$stmt1 = null;
$conn1 = null;
EndTest($testName);
}
function BindParam($offset, $stmt, &$value)
{
if (!$stmt->bindParam(1, $value))
{
LogInfo($offset,"Cannot bind parameter");
}
}
function BindColumn($offset, $stmt, &$param1, &$param2)
{
if (!$stmt->bindColumn(1, $param1, PDO::PARAM_INT))
{
LogInfo($offset, "Cannot bind integer column");
}
if (!$stmt->bindColumn(2, $param2, PDO::PARAM_STR))
{
LogInfo($offset, "Cannot bind string column");
}
}
function ExecStmt($offset, $stmt)
{
if (!$stmt->execute())
{
LogInfo($offset, "Cannot execute statement");
}
}
function FetchBound($stmt, &$param1, &$param2)
{
while ($stmt->fetch(PDO::FETCH_BOUND))
{
printf("id = %s (%s) / label = %s (%s)\n",
var_export($param1, true), gettype($param1),
var_export($param2, true), gettype($param2));
}
}
function LogInfo($offset, $msg)
{
printf("[%03d] %s\n", $offset, $msg);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
Bind();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
id = 1 (integer) / label = 'a' (string)
id = 2 (integer) / label = 'b' (string)
id = 1 (integer) / label = 'a' (string)
id = 2 (integer) / label = 'b' (string)
id = 100 (integer) / label = NULL (NULL)
Test "PDO Statement - Bind Param" completed successfully.

View file

@ -0,0 +1,84 @@
--TEST--
PDO Bind Value Test
--DESCRIPTION--
Verification for "PDOStatement::bindValue()".
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function Bind()
{
include 'MsSetup.inc';
$testName = "PDO Statement - Bind Value";
StartTest($testName);
$conn1 = Connect();
// Prepare test table
CreateTableEx($conn1, $tableName, "id int NOT NULL PRIMARY KEY, val1 VARCHAR(10), val2 VARCHAR(10), val3 VARCHAR(10)", null);
$data = array("one", "two", "three");
// Insert test data
$stmt1 = PrepareQuery($conn1, "INSERT INTO [$tableName] VALUES(1, ?, ?, ?)");
foreach ($data as $i => $v)
{
$stmt1->bindValue($i+1, $v);
}
$stmt1->execute();
unset($stmt1);
// Retrieve test data
$stmt1 = PrepareQuery($conn1, "SELECT * FROM [$tableName]");
$stmt1->execute();
var_dump($stmt1->fetchAll(PDO::FETCH_ASSOC));
// Cleanup
DropTable($conn1, $tableName);
$stmt1 = null;
$conn1 = null;
EndTest($testName);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
Bind();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
array(1) {
[0]=>
array(4) {
["id"]=>
string(1) "1"
["val1"]=>
string(3) "one"
["val2"]=>
string(3) "two"
["val3"]=>
string(5) "three"
}
}
Test "PDO Statement - Bind Value" completed successfully.

View file

@ -0,0 +1,203 @@
--TEST--
PDO Bind Value Test
--DESCRIPTION--
Verification for "PDOStatement::bindValue()".
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function Bind()
{
include 'MsSetup.inc';
$testName = "PDO Statement - Bind Value";
StartTest($testName);
$conn1 = Connect();
// Prepare test table
$dataCols = "id, label";
CreateTableEx($conn1, $tableName, "id int NOT NULL PRIMARY KEY, label CHAR(1)", null);
InsertRowEx($conn1, $tableName, $dataCols, "1, 'a'", null);
InsertRowEx($conn1, $tableName, $dataCols, "2, 'b'", null);
InsertRowEx($conn1, $tableName, $dataCols, "3, 'c'", null);
InsertRowEx($conn1, $tableName, $dataCols, "4, 'd'", null);
InsertRowEx($conn1, $tableName, $dataCols, "5, 'e'", null);
InsertRowEx($conn1, $tableName, $dataCols, "6, 'f'", null);
$id = null;
$label = null;
// Check different value bind modes
$tsql1 = "SELECT TOP(2) id, label FROM [$tableName] WHERE id > ? ORDER BY id ASC";
$stmt1 = PrepareQuery($conn1, $tsql1);
printf("Binding value and not variable...\n");
BindValue(1, $stmt1, 0);
ExecStmt(1, $stmt1);
BindColumn(1, $stmt1, $id, $label);
FetchBound($stmt1, $id, $label);
printf("Binding variable...\n");
$var1 = 0;
BindVar(2, $stmt1, $var1);
ExecStmt(2, $stmt1);
BindColumn(2, $stmt1, $id, $label);
FetchBound($stmt1, $id, $label);
printf("Binding variable which references another variable...\n");
$var2 = 0;
$var_ref = &$var2;
BindVar(3, $stmt1, $var_ref);
ExecStmt(3, $stmt1);
BindColumn(3, $stmt1, $id, $label);
FetchBound($stmt1, $id, $label);
unset($stmt1);
$tsql2 = "SELECT TOP(2) id, label FROM [$tableName] WHERE id > ? AND id <= ? ORDER BY id ASC";
$stmt1 = PrepareQuery($conn1, $tsql2);
printf("Binding a variable and a value...\n");
$var3 = 0;
BindMixed(4, $stmt1, $var3, 2);
ExecStmt(4, $stmt1);
BindColumn(4, $stmt1, $id, $label);
FetchBound($stmt1, $id, $label);
printf("Binding a variable to two placeholders and changing the variable value in between the binds...\n");
$var4 = 0;
$var5 = 2;
BindPlaceholder(5, $stmt1, $var4, $var5);
ExecStmt(5, $stmt1);
BindColumn(5, $stmt1, $id, $label);
FetchBound($stmt1, $id, $label);
unset($stmt1);
// Cleanup
DropTable($conn1, $tableName);
$stmt1 = null;
$conn1 = null;
EndTest($testName);
}
function BindValue($offset, $stmt, $value)
{
if (!$stmt->bindValue(1, $value))
{
LogInfo($offset, "Cannot bind value");
}
}
function BindVar($offset, $stmt, &$var)
{
if (!$stmt->bindValue(1, $var))
{
LogInfo($offset, "Cannot bind variable");
}
}
function BindMixed($offset, $stmt, &$var, $value)
{
if (!$stmt->bindValue(1, $var))
{
LogInfo($offset, "Cannot bind variable");
}
if (!$stmt->bindValue(2, $value))
{
LogInfo($offset, "Cannot bind value");
}
}
function BindPlaceholder($offset, $stmt, &$var1, &$var2)
{
if (!$stmt->bindValue(1, $var1))
{
LogInfo($offset, "Cannot bind variable 1");
}
if (!$stmt->bindValue(2, $var2))
{
LogInfo($offset, "Cannot bind variable 2");
}
}
function BindColumn($offset, $stmt, &$param1, &$param2)
{
if (!$stmt->bindColumn(1, $param1, PDO::PARAM_INT))
{
LogInfo($offset, "Cannot bind integer column");
}
if (!$stmt->bindColumn(2, $param2, PDO::PARAM_STR))
{
LogInfo($offset, "Cannot bind string column");
}
}
function ExecStmt($offset, $stmt)
{
if (!$stmt->execute())
{
LogInfo($offset, "Cannot execute statement");
}
}
function FetchBound($stmt, &$param1, &$param2)
{
while ($stmt->fetch(PDO::FETCH_BOUND))
{
printf("id = %s (%s) / label = %s (%s)\n",
var_export($param1, true), gettype($param1),
var_export($param2, true), gettype($param2));
}
}
function LogInfo($offset, $msg)
{
printf("[%03d] %s\n", $offset, $msg);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
Bind();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
Binding value and not variable...
id = 1 (integer) / label = 'a' (string)
id = 2 (integer) / label = 'b' (string)
Binding variable...
id = 1 (integer) / label = 'a' (string)
id = 2 (integer) / label = 'b' (string)
Binding variable which references another variable...
id = 1 (integer) / label = 'a' (string)
id = 2 (integer) / label = 'b' (string)
Binding a variable and a value...
id = 1 (integer) / label = 'a' (string)
id = 2 (integer) / label = 'b' (string)
Binding a variable to two placeholders and changing the variable value in between the binds...
id = 1 (integer) / label = 'a' (string)
id = 2 (integer) / label = 'b' (string)
Test "PDO Statement - Bind Value" completed successfully.

View file

@ -0,0 +1,141 @@
--TEST--
PDO Bind Param Truncation Test
--DESCRIPTION--
Verification for "PDOStatement::bindParam()".
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function Bind()
{
include 'MsSetup.inc';
$testName = "PDO Statement - Bind Param Truncation";
StartTest($testName);
$conn1 = Connect();
// Prepare test table
CreateTableEx($conn1, $tableName, "id INT IDENTITY NOT NULL, class INT, value CHAR(32)", null);
$conn1->exec( "CREATE CLUSTERED INDEX [idx_test_int] ON " . $tableName . "(id)" );
$tsql1 = "SET IDENTITY_INSERT [$tableName] ON";
$tsql2 = "INSERT INTO [$tableName] (id, class, value) VALUES(:id, :class, :value)";
$tsql3 = "SET IDENTITY_INSERT [$tableName] OFF";
$tsql4 = "SELECT id, value FROM [$tableName]";
$id = 0;
$class = 0;
$value = '';
// Prepare insert query
$stmt1 = PrepareQuery($conn1, "$tsql1; $tsql2; $tsql3;");
BindParam(1, $stmt1, ':id', $id);
BindParam(2, $stmt1, ':class', $class);
BindParam(3, $stmt1, ':value', $value);
// Insert test rows
$id = 1;
$class = 4;
$value = '2011';
ExecStmt(1, $stmt1);
$id = 2;
$class = 5;
$value = 'Sat, 20 Mar 10 21:29:13 -0600';
ExecStmt(2, $stmt1);
$id = 3;
$class = 6;
$value = 'Fri, 07 May 10 11:35:32 -0600';
ExecStmt(3, $stmt1);
unset($stmt1);
$stmt1 = null;
// Check data
$id = 0;
$value = '';
$stmt2 = ExecuteQuery($conn1, $tsql4);
BindColumn(1, $stmt2, $id, $value);
while ($stmt2->fetch(PDO::FETCH_BOUND))
{
printf("id = %s (%s) / value = %s (%s)\n",
var_export($id, true), gettype($id),
var_export($value, true), gettype($value));
}
unset($stmt2);
$stmt2 = null;
// Cleanup
DropTable($conn1, $tableName);
$stmt1 = null;
$conn1 = null;
EndTest($testName);
}
function BindParam($offset, $stmt, $param, &$value)
{
if (!$stmt->bindParam($param, $value))
{
LogInfo($offset,"Cannot bind parameter $param");
}
}
function BindColumn($offset, $stmt, &$param1, &$param2)
{
if (!$stmt->bindColumn(1, $param1, PDO::PARAM_INT))
{
LogInfo($offset, "Cannot bind integer column");
}
if (!$stmt->bindColumn(2, $param2, PDO::PARAM_STR))
{
LogInfo($offset, "Cannot bind string column");
}
}
function ExecStmt($offset, $stmt)
{
if (!$stmt->execute())
{
LogInfo($offset, "Cannot execute statement");
var_dump($stmt->errorInfo());
}
}
function LogInfo($offset, $msg)
{
printf("[%03d] %s\n", $offset, $msg);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
Bind();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
id = 1 (integer) / value = '2011 ' (string)
id = 2 (integer) / value = 'Sat, 20 Mar 10 21:29:13 -0600 ' (string)
id = 3 (integer) / value = 'Fri, 07 May 10 11:35:32 -0600 ' (string)
Test "PDO Statement - Bind Param Truncation" completed successfully.

View file

@ -0,0 +1,100 @@
--TEST--
PDO Transactions Test
--DESCRIPTION--
Basic verification for PDO Transactions.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function Transactions()
{
include 'MsSetup.inc';
$testName = "PDO - Transactions";
StartTest($testName);
$conn1 = Connect();
// Prepare test table
$dataCols = "id, val";
CreateTableEx($conn1, $tableName, "id int NOT NULL PRIMARY KEY, val VARCHAR(10)", null);
InsertRowEx($conn1, $tableName, $dataCols, "1, 'A'", null);
InsertRowEx($conn1, $tableName, $dataCols, "2, 'B'", null);
InsertRowEx($conn1, $tableName, $dataCols, "3, 'C'", null);
// After INSERT ...
$count = countRows($conn1, $tableName);
echo "Rows after INSERT: $count.\n";
// Prepare DELETE query
$stmt1 = PrepareQuery($conn1, "DELETE FROM [$tableName]");
// Transaction -> Rollback
$conn1->beginTransaction();
$stmt1->execute();
$count = countRows($conn1, $tableName);
echo "Rows after DELETE: $count.\n";
$conn1->rollBack();
$count = countRows($conn1, $tableName);
echo "Rows after ROLLBACK: $count.\n";
// Transaction -> Commit
$conn1->beginTransaction();
$stmt1->execute();
$count = countRows($conn1, $tableName);
echo "Rows after DELETE: $count.\n";
$conn1->commit();
$count = countRows($conn1, $tableName);
echo "Rows after COMMIT: $count.\n";
// Cleanup
DropTable($conn1, $tableName);
$stmt1 = null;
$conn1 = null;
EndTest($testName);
}
function countRows($conn, $table)
{
$stmt = ExecuteQuery($conn, "SELECT COUNT(*) FROM [$table]");
$res = $stmt->fetchColumn();
unset($stmt);
return ($res);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
Transactions();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECTF--
Rows after INSERT: 3.
Rows after DELETE: 0.
Rows after ROLLBACK: 3.
Rows after DELETE: 0.
Rows after COMMIT: 0.
Test "PDO - Transactions" completed successfully.

View file

@ -0,0 +1,95 @@
--TEST--
PDO Transactions Test
--DESCRIPTION--
Basic verification for PDO Transactions.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function Transactions()
{
include 'MsSetup.inc';
$testName = "PDO - Transactions";
StartTest($testName);
$conn1 = Connect();
// Prepare test table
$dataCols = "id, val";
CreateTableEx($conn1, $tableName, "id int NOT NULL PRIMARY KEY, val VARCHAR(10)", null);
InsertRowEx($conn1, $tableName, $dataCols, "1, 'A'", null);
InsertRowEx($conn1, $tableName, $dataCols, "2, 'B'", null);
InsertRowEx($conn1, $tableName, $dataCols, "3, 'C'", null);
// After initial INSERT ...
$count = countRows($conn1, $tableName);
echo "Rows after INSERT: $count.\n";
// Transaction -> Automatic rollback on disconnect
$conn1->beginTransaction();
InsertRowEx($conn1, $tableName, $dataCols, "4, 'X'", null);
InsertRowEx($conn1, $tableName, $dataCols, "5, 'Y'", null);
$conn1 = null; // disconnect without commit
$conn1 = Connect();
$count = countRows($conn1, $tableName);
echo "Rows after ROLLBACK: $count.\n";
// Transaction -> Commit
$conn1->beginTransaction();
InsertRowEx($conn1, $tableName, $dataCols, "4, 'D'", null);
InsertRowEx($conn1, $tableName, $dataCols, "5, 'E'", null);
InsertRowEx($conn1, $tableName, $dataCols, "6, 'F'", null);
$conn1->commit();
$count = countRows($conn1, $tableName);
echo "Rows after COMMIT: $count.\n";
// Cleanup
DropTable($conn1, $tableName);
$stmt1 = null;
$conn1 = null;
EndTest($testName);
}
function countRows($conn, $table)
{
$stmt = ExecuteQuery($conn, "SELECT COUNT(*) FROM [$table]");
$res = $stmt->fetchColumn();
unset($stmt);
return ($res);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
Transactions();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECTF--
Rows after INSERT: 3.
Rows after ROLLBACK: 3.
Rows after COMMIT: 6.
Test "PDO - Transactions" completed successfully.

View file

@ -0,0 +1,82 @@
--TEST--
Complex Insert Query Test
--DESCRIPTION--
Test the driver behavior with a complex insert query.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function ComplexInsert($count)
{
include 'MsSetup.inc';
$testName = "PDO - Complex Insert Query";
StartTest($testName);
Setup();
$conn1 = Connect();
DropTable($conn1, $tableName);
// $data = "a1='1234567890',a2='0987654321',a3='1234567890',a4='0987654321',a5='1234567890',a6='0987654321'";
$data = "a1='1', a2='2', a3='3', a4='4', a5='5', a6='6'";
$querySelect = "SELECT COUNT(*) FROM [$tableName]";
$queryInsert =
" SELECT $data INTO [$tableName]
DECLARE @i int
SET @i=1
WHILE (@i < $count)
BEGIN
INSERT [$tableName]
SELECT $data
SET @i = @i + 1
END
";
$stmt1 = ExecuteQuery($conn1, $queryInsert);
$stmt1->closeCursor();
$stmt1 = null;
$stmt2 = ExecuteQuery($conn1, $querySelect);
$row = $stmt2->fetch(PDO::FETCH_NUM);
printf("$count rows attempted; actual rows created = ".$row[0]."\n");
$stmt2 = null;
$conn1 = null;
EndTest($testName);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
ComplexInsert(1000);
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
1000 rows attempted; actual rows created = 1000
Test "PDO - Complex Insert Query" completed successfully.

View file

@ -0,0 +1,68 @@
--TEST--
PDO Get Parent Class Test
--DESCRIPTION--
Verification for "get_parent_class()" functionality.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function ExecTest()
{
include 'MsSetup.inc';
$testName = "PDO - Get Parent";
StartTest($testName);
$conn1 = Connect();
// Prepare test table
CreateTableEx($conn1, $tableName, "id int", null);
$conn1->exec( "CREATE CLUSTERED INDEX [idx_test_int] ON " . $tableName . "(id)" );
InsertRowEx($conn1, $tableName, "id", "23", null);
// Retrieve data
$stmt1 = PrepareQuery($conn1, "SELECT id FROM [$tableName]");
$stmt1->execute();
$result = $stmt1->fetch(PDO::FETCH_LAZY);
// Retrieve class and parent
echo get_class($result), "\n";
var_dump(get_parent_class($result));
// Cleanup
DropTable($conn1, $tableName);
$stmt1 = null;
$conn1 = null;
EndTest($testName);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
ExecTest();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
PDORow
bool(false)
Test "PDO - Get Parent" completed successfully.

View file

@ -0,0 +1,118 @@
--TEST--
PDO Statement Iterator Test
--DESCRIPTION--
Verification of PDOStatement with an iterator.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function ExecStmt()
{
include 'MsSetup.inc';
$testName = "PDO Statement - Iterator";
StartTest($testName);
$conn1 = Connect();
// Prepare test table
$dataCols = "id, val, grp";
CreateTableEx($conn1, $tableName, "id int NOT NULL PRIMARY KEY, val VARCHAR(10), grp VARCHAR(10)", null);
InsertRowEx($conn1, $tableName, $dataCols, "1, 'A', 'Group1'", null);
InsertRowEx($conn1, $tableName, $dataCols, "2, 'B', 'Group2'", null);
$tsql = "SELECT val, grp FROM [$tableName]";
// Testing with direct query
/*$stmt1 = $conn1->query($tsql, PDO::FETCH_CLASS, 'Test', array('WOW'));
$iter = new IteratorIterator($stmt1);
foreach ($iter as $data)
{
var_dump($data);
}
$iter->next(); // allowed
var_dump($iter->current()); // should return NULL
var_dump($iter->valid());*/ // should must return
unset($stmt1);
// Testing with prepared query
$stmt1 = $conn1->prepare($tsql, array(PDO::ATTR_STATEMENT_CLASS=>array('PDOStatementAggregate')));
foreach ($stmt1 as $data)
{
var_dump($data);
}
// Cleanup
DropTable($conn1, $tableName);
$stmt1 = null;
$conn1 = null;
EndTest($testName);
}
class Test
{
function __construct($name = 'N/A')
{
echo __METHOD__ . "($name)\n";
}
}
class PDOStatementAggregate extends PDOStatement implements IteratorAggregate
{
private function __construct()
{
echo __METHOD__ . "\n";
$this->setFetchMode(PDO::FETCH_NUM);
}
function getIterator()
{
echo __METHOD__ . "\n";
$this->execute();
return (new IteratorIterator($this, 'PDOStatement'));
}
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
ExecStmt();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECTF--
PDOStatementAggregate::__construct
PDOStatementAggregate::getIterator
array(2) {
[0]=>
string(1) "A"
[1]=>
string(6) "Group1"
}
array(2) {
[0]=>
string(1) "B"
[1]=>
string(6) "Group2"
}
Test "PDO Statement - Iterator" completed successfully.

View file

@ -0,0 +1,116 @@
--TEST--
PDO Recursive Iterator Test
--DESCRIPTION--
Verification of PDOStatement with a recursive iterator.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function ExecStmt()
{
include 'MsSetup.inc';
$testName = "PDO Statement - Recursive Iterator";
StartTest($testName);
$conn1 = Connect();
// Prepare test tables
$dataCols = "id, val, val2";
CreateTableEx($conn1, $tableName, "id int NOT NULL PRIMARY KEY, val VARCHAR(10), val2 VARCHAR(16)", null);
$data = array( array('10', 'Abc', 'zxy'),
array('20', 'Def', 'wvu'),
array('30', 'Ghi', 'tsr'));
// Insert using question mark placeholders
$stmt1 = PrepareQuery($conn1, "INSERT INTO [$tableName] VALUES(?, ?, ?)");
foreach ($data as $row)
{
$stmt1->execute($row);
}
unset($stmt1);
echo "===QUERY===\n";
$stmt1 = ExecuteQuery($conn1, "SELECT * FROM [$tableName]");
foreach(new RecursiveTreeIterator(new RecursiveArrayIterator($stmt1->fetchAll(PDO::FETCH_ASSOC)),
RecursiveTreeIterator::BYPASS_KEY) as $c=>$v)
{
echo "$v [$c]\n";
}
echo "===DONE===\n";
// Cleanup
DropTable($conn1, $tableName);
$stmt1 = null;
$conn1 = null;
EndTest($testName);
}
class Test
{
function __construct($name = 'N/A')
{
echo __METHOD__ . "($name)\n";
}
}
class PDOStatementAggregate extends PDOStatement implements IteratorAggregate
{
private function __construct()
{
echo __METHOD__ . "\n";
$this->setFetchMode(PDO::FETCH_NUM);
}
function getIterator()
{
echo __METHOD__ . "\n";
$this->execute();
return (new IteratorIterator($this, 'PDOStatement'));
}
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
ExecStmt();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
===QUERY===
|-Array [0]
| |-10 [id]
| |-Abc [val]
| \-zxy [val2]
|-Array [1]
| |-20 [id]
| |-Def [val]
| \-wvu [val2]
\-Array [2]
|-30 [id]
|-Ghi [val]
\-tsr [val2]
===DONE===
Test "PDO Statement - Recursive Iterator" completed successfully.

View file

@ -0,0 +1,133 @@
--TEST--
Extending PDO Test #1
--DESCRIPTION--
Verification of capabilities for extending PDO.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function Extend()
{
include 'MsSetup.inc';
$testName = "PDO - Extension";
StartTest($testName);
$conn1 = PDOConnect('ExPDO', $server, $uid, $pwd, true);
$conn1->test();
var_dump($conn1);
// Prepare test table
DropTable($conn1, $tableName);
$conn1->query("CREATE TABLE [$tableName] (id int NOT NULL PRIMARY KEY, val VARCHAR(10))");
$conn1->query("INSERT INTO [$tableName] VALUES(0, 'A')");
$conn1->query("INSERT INTO [$tableName] VALUES(1, 'B')");
// Retrieve test data via a direct query
$stmt1 = ExecuteQuery($conn1, "SELECT val, id FROM [$tableName]");
$result = $stmt1->fetchAll(PDO::FETCH_COLUMN|PDO::FETCH_UNIQUE);
var_dump($result);
// Cleanup
DropTable($conn1, $tableName);
$stmt1 = null;
$conn1 = null;
EndTest($testName);
}
class ExPDO extends PDO
{
public $test1 = 1;
function __destruct()
{
echo __METHOD__ . "()\n";
}
function test()
{
$this->test2 = 2;
var_dump($this->test1);
var_dump($this->test2);
$this->test2 = 22;
}
function query($sql)
{
echo __METHOD__ . "()\n";
$stmt = parent::prepare($sql, array(PDO::ATTR_STATEMENT_CLASS=>array('ExPDOStatement')));
$stmt->execute();
return ($stmt);
}
}
class ExPDOStatement extends PDOStatement
{
protected function __construct()
{
echo __METHOD__ . "()\n";
}
function __destruct()
{
echo __METHOD__ . "()\n";
}
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
Extend();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECTF--
int(1)
int(2)
object(ExPDO)#%d (2) {
["test1"]=>
int(1)
["test2"]=>
int(22)
}
ExPDO::query()
ExPDOStatement::__construct()
ExPDOStatement::__destruct()
ExPDO::query()
ExPDOStatement::__construct()
ExPDOStatement::__destruct()
ExPDO::query()
ExPDOStatement::__construct()
ExPDOStatement::__destruct()
ExPDO::query()
ExPDOStatement::__construct()
array(2) {
["A"]=>
string(1) "0"
["B"]=>
string(1) "1"
}
ExPDOStatement::__destruct()
ExPDO::__destruct()
Test "PDO - Extension" completed successfully.

View file

@ -0,0 +1,131 @@
--TEST--
Extending PDO Test #1
--DESCRIPTION--
Verification of capabilities for extending PDO.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function Extend()
{
include 'MsSetup.inc';
$testName = "PDO - Extension";
StartTest($testName);
// simply use $databaseName from MsSetup.inc to facilitate testing in Azure,
// which does not support switching databases
$conn2 = new ExPDO("sqlsrv:Server=$server;Database=$databaseName", $uid, $pwd);
DropTable($conn2, "tmp_table");
$conn2->exec("CREATE TABLE tmp_table (id INT)");
$conn2->exec("INSERT INTO tmp_table (id) VALUES (1), (2)");
$stmt1 = $conn2->query("SELECT * FROM tmp_table ORDER BY id ASC");
var_dump($stmt1->fetchAll(PDO::FETCH_ASSOC));
var_dump($stmt1->fetch());
$conn2->intercept_call();
// Cleanup
DropTable($conn2, "tmp_table");
$stmt1 = null;
$conn2 = null;
EndTest($testName);
}
class ExPDO extends PDO
{
public function __construct()
{
$this->protocol();
$args = func_get_args();
return (call_user_func_array(array($this, 'parent::__construct'), $args));
}
public function exec($args1)
{
$this->protocol();
$args = func_get_args();
return (call_user_func_array(array($this, 'parent::exec'), $args));
}
public function query()
{
$this->protocol();
$args = func_get_args();
return (call_user_func_array(array($this, 'parent::query'), $args));
}
public function __call($method, $args)
{
print "__call(".var_export($method, true).", ".var_export($args, true).")\n";
}
private function protocol()
{
$stack = debug_backtrace();
if (!isset($stack[1]))
{
return;
}
printf("%s(", $stack[1]['function']);
$args = '';
foreach ($stack[1]['args'] as $k => $v)
{
$args .= sprintf("%s, ", var_export($v, true));
}
if ($args != '')
{
printf("%s", substr($args, 0, -2));
}
printf(")\n");
}
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
Extend();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECTF--
__construct('%s', '%s', '%s')
exec('DROP TABLE %s')
exec('CREATE TABLE %s (id INT)')
exec('INSERT INTO %s (id) VALUES (1), (2)')
query('SELECT * FROM %s ORDER BY id ASC')
array(2) {
[0]=>
array(1) {
["id"]=>
string(1) "1"
}
[1]=>
array(1) {
["id"]=>
string(1) "2"
}
}
bool(false)
__call('intercept_call', array (
))
exec('DROP TABLE %s')
Test "PDO - Extension" completed successfully.

View file

@ -0,0 +1,145 @@
--TEST--
Extending PDO Test #2
--DESCRIPTION--
Verification of capabilities for extending PDO.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function Extend()
{
include 'MsSetup.inc';
$testName = "PDO - Extension";
StartTest($testName);
$data = array( array('10', 'Abc', 'zxy'),
array('20', 'Def', 'wvu'),
array('30', 'Ghi', 'tsr'));
$conn1 = PDOConnect('ExPDO', $server, $uid, $pwd, true);
var_dump(get_class($conn1));
// Prepare test table
DropTable($conn1, $tableName);
$conn1->exec("CREATE TABLE [$tableName] (id int NOT NULL PRIMARY KEY, val VARCHAR(10), val2 VARCHAR(16))");
$stmt1 = $conn1->prepare("INSERT INTO [$tableName] VALUES(?, ?, ?)");
var_dump(get_class($stmt1));
foreach ($data as $row)
{
$stmt1->execute($row);
}
unset($stmt1);
// Retrieve test data via a direct query
$stmt1 = $conn1->query("SELECT * FROM [$tableName]");
var_dump(get_class($stmt1));
var_dump(get_class($stmt1->dbh));
foreach($stmt1 as $obj)
{
var_dump($obj);
}
echo "===DONE===\n";
// Cleanup
DropTable($conn1, $tableName);
$stmt1 = null;
$conn1 = null;
EndTest($testName);
}
class ExPDO extends PDO
{
function __destruct()
{
echo __METHOD__ . "()\n";
}
function query($sql)
{
echo __METHOD__ . "()\n";
$stmt = $this->prepare($sql, array(PDO::ATTR_STATEMENT_CLASS=>array('ExPDOStatement', array($this))));
$stmt->setFetchMode(PDO::FETCH_ASSOC);
$stmt->execute();
return ($stmt);
}
}
class ExPDOStatement extends PDOStatement
{
public $dbh;
protected function __construct($dbh)
{
$this->dbh = $dbh;
echo __METHOD__ . "()\n";
}
function __destruct()
{
echo __METHOD__ . "()\n";
}
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
Extend();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
string(5) "ExPDO"
string(12) "PDOStatement"
ExPDO::query()
ExPDOStatement::__construct()
string(14) "ExPDOStatement"
string(5) "ExPDO"
array(3) {
["id"]=>
string(2) "10"
["val"]=>
string(3) "Abc"
["val2"]=>
string(3) "zxy"
}
array(3) {
["id"]=>
string(2) "20"
["val"]=>
string(3) "Def"
["val2"]=>
string(3) "wvu"
}
array(3) {
["id"]=>
string(2) "30"
["val"]=>
string(3) "Ghi"
["val2"]=>
string(3) "tsr"
}
===DONE===
ExPDOStatement::__destruct()
ExPDO::__destruct()
Test "PDO - Extension" completed successfully.

View file

@ -0,0 +1,159 @@
--TEST--
Extending PDO Test #3
--DESCRIPTION--
Verification of capabilities for extending PDO.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function Extend()
{
include 'MsSetup.inc';
$testName = "PDO - Extension";
StartTest($testName);
$data = array( array('10', 'Abc', 'zxy'),
array('20', 'Def', 'wvu'),
array('30', 'Ghi', 'tsr'));
$conn1 = PDOConnect('ExPDO', $server, $uid, $pwd, true);
var_dump(get_class($conn1));
// Prepare test table
DropTable($conn1, $tableName);
$conn1->exec("CREATE TABLE [$tableName] (id int NOT NULL PRIMARY KEY, val VARCHAR(10), val2 VARCHAR(16))");
$stmt1 = $conn1->prepare("INSERT INTO [$tableName] VALUES(?, ?, ?)");
var_dump(get_class($stmt1));
foreach ($data as $row)
{
$stmt1->execute($row);
}
unset($stmt1);
echo "===QUERY===\n";
// Retrieve test data via a direct query
$stmt1 = $conn1->query("SELECT * FROM [$tableName]");
var_dump(get_class($stmt1));
var_dump(get_class($stmt1->dbh));
echo "===FOREACH===\n";
foreach($stmt1 as $obj)
{
var_dump($obj);
}
echo "===DONE===\n";
// Cleanup
DropTable($conn1, $tableName);
$stmt1 = null;
$conn1 = null;
EndTest($testName);
}
class ExPDO extends PDO
{
function __destruct()
{
echo __METHOD__ . "()\n";
}
function query($sql)
{
echo __METHOD__ . "()\n";
$stmt = $this->prepare($sql, array(PDO::ATTR_STATEMENT_CLASS=>array('ExPDOStatement', array($this))));
$stmt->setFetchMode(PDO::FETCH_ASSOC);
$stmt->execute();
return ($stmt);
}
}
class ExPDOStatement extends PDOStatement
{
public $dbh;
protected function __construct($dbh)
{
$this->dbh = $dbh;
echo __METHOD__ . "()\n";
}
function __destruct()
{
echo __METHOD__ . "()\n";
}
function execute($params = array())
{
echo __METHOD__ . "()\n";
parent::execute();
}
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
Extend();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
string(5) "ExPDO"
string(12) "PDOStatement"
===QUERY===
ExPDO::query()
ExPDOStatement::__construct()
ExPDOStatement::execute()
string(14) "ExPDOStatement"
string(5) "ExPDO"
===FOREACH===
array(3) {
["id"]=>
string(2) "10"
["val"]=>
string(3) "Abc"
["val2"]=>
string(3) "zxy"
}
array(3) {
["id"]=>
string(2) "20"
["val"]=>
string(3) "Def"
["val2"]=>
string(3) "wvu"
}
array(3) {
["id"]=>
string(2) "30"
["val"]=>
string(3) "Ghi"
["val2"]=>
string(3) "tsr"
}
===DONE===
ExPDOStatement::__destruct()
ExPDO::__destruct()
Test "PDO - Extension" completed successfully.

View file

@ -0,0 +1,174 @@
--TEST--
Extending PDO Test #4
--DESCRIPTION--
Verification of capabilities for extending PDO.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function Extend()
{
include 'MsSetup.inc';
$testName = "PDO - Extension";
StartTest($testName);
$data = array( array('10', 'Abc', 'zxy'),
array('20', 'Def', 'wvu'),
array('30', 'Ghi', 'tsr'));
$conn1 = PDOConnect('ExPDO', $server, $uid, $pwd, true);
var_dump(get_class($conn1));
// Prepare test table
DropTable($conn1, $tableName);
$conn1->exec("CREATE TABLE [$tableName] (id int NOT NULL PRIMARY KEY, val VARCHAR(10), val2 VARCHAR(16))");
$stmt1 = $conn1->prepare("INSERT INTO [$tableName] VALUES(?, ?, ?)");
var_dump(get_class($stmt1));
foreach ($data as $row)
{
$stmt1->execute($row);
}
unset($stmt1);
echo "===QUERY===\n";
// Retrieve test data via a direct query
var_dump($conn1->getAttribute(PDO::ATTR_STATEMENT_CLASS));
$conn1->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('ExPDOStatement', array($conn1)));
var_dump($conn1->getAttribute(PDO::ATTR_STATEMENT_CLASS));
$stmt1 = $conn1->query("SELECT * FROM [$tableName]");
var_dump(get_class($stmt1));
var_dump(get_class($stmt1->dbh));
echo "===FOREACH===\n";
foreach($stmt1 as $obj)
{
var_dump($obj);
}
echo "===DONE===\n";
// Cleanup
DropTable($conn1, $tableName);
$stmt1 = null;
$conn1 = null;
EndTest($testName);
}
class ExPDO extends PDO
{
function __destruct()
{
echo __METHOD__ . "()\n";
}
function query($sql)
{
echo __METHOD__ . "()\n";
$stmt = parent::query($sql);
return ($stmt);
}
}
class ExPDOStatement extends PDOStatement
{
public $dbh;
protected function __construct($dbh)
{
$this->dbh = $dbh;
$this->setFetchMode(PDO::FETCH_ASSOC);
echo __METHOD__ . "()\n";
}
function __destruct()
{
echo __METHOD__ . "()\n";
}
function execute($params = array())
{
echo __METHOD__ . "()\n";
parent::execute();
}
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
Extend();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECTF--
string(5) "ExPDO"
string(12) "PDOStatement"
===QUERY===
array(1) {
[0]=>
string(12) "PDOStatement"
}
array(2) {
[0]=>
string(14) "ExPDOStatement"
[1]=>
array(1) {
[0]=>
object(ExPDO)#%d (0) {
}
}
}
ExPDO::query()
ExPDOStatement::__construct()
string(14) "ExPDOStatement"
string(5) "ExPDO"
===FOREACH===
array(3) {
["id"]=>
string(2) "10"
["val"]=>
string(3) "Abc"
["val2"]=>
string(3) "zxy"
}
array(3) {
["id"]=>
string(2) "20"
["val"]=>
string(3) "Def"
["val2"]=>
string(3) "wvu"
}
array(3) {
["id"]=>
string(2) "30"
["val"]=>
string(3) "Ghi"
["val2"]=>
string(3) "tsr"
}
===DONE===
ExPDOStatement::__destruct()
Test "PDO - Extension" completed successfully.
ExPDO::__destruct()

Some files were not shown because too many files have changed in this diff Show more