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

This commit is contained in:
ulvii 2017-07-04 17:34:42 -07:00
commit 7f2f89ec3b
529 changed files with 7792 additions and 5089 deletions

View file

@ -3,6 +3,8 @@ sudo: required
os: linux
dist: trusty
group: edge
services:
- docker
@ -25,16 +27,16 @@ install:
script:
- docker run -e TRAVIS_JOB_ID -t -d -w $PHPSQLDIR --link $TEST_PHP_SQL_SERVER --name=client msphpsql-dev
- docker ps -a
- docker exec client python ./test/setup/setup_dbs.py -dbname $SQLSRV_DBNAME
- docker exec client python ./test/setup/setup_dbs.py -dbname $PDOSQLSRV_DBNAME
- docker exec client php ./source/pdo_sqlsrv/run-tests.php ./test/pdo_sqlsrv/*.phpt
- docker exec client php ./source/sqlsrv/run-tests.php ./test/sqlsrv/*.phpt
- docker exec client bash -c 'for f in ./test/sqlsrv/*.diff; do ls $f 2>/dev/null; cat $f 2>/dev/null; done || true'
- docker exec client bash -c 'for f in ./test/sqlsrv/*.out; do ls $f 2>/dev/null; cat $f 2>/dev/null; done || true'
- docker exec client bash -c 'for f in ./test/pdo_sqlsrv/*.diff; do ls $f 2>/dev/null; cat $f 2>/dev/null; done || true'
- docker exec client bash -c 'for f in ./test/pdo_sqlsrv/*.out; do ls $f 2>/dev/null; cat $f 2>/dev/null; done || true'
- docker exec client python ./test/setup/cleanup_dbs.py -dbname $SQLSRV_DBNAME
- docker exec client python ./test/setup/cleanup_dbs.py -dbname $PDOSQLSRV_DBNAME
- docker exec client python ./test/functional/setup/setup_dbs.py -dbname $SQLSRV_DBNAME
- docker exec client python ./test/functional/setup/setup_dbs.py -dbname $PDOSQLSRV_DBNAME
- docker exec client php ./source/pdo_sqlsrv/run-tests.php ./test/functional/pdo_sqlsrv/*.phpt
- docker exec client php ./source/sqlsrv/run-tests.php ./test/functional/sqlsrv/*.phpt
- docker exec client bash -c 'for f in ./test/functional/sqlsrv/*.diff; do ls $f 2>/dev/null; cat $f 2>/dev/null; done || true'
- docker exec client bash -c 'for f in ./test/functional/sqlsrv/*.out; do ls $f 2>/dev/null; cat $f 2>/dev/null; done || true'
- docker exec client bash -c 'for f in ./test/functional/pdo_sqlsrv/*.diff; do ls $f 2>/dev/null; cat $f 2>/dev/null; done || true'
- docker exec client bash -c 'for f in ./test/functional/pdo_sqlsrv/*.out; do ls $f 2>/dev/null; cat $f 2>/dev/null; done || true'
- docker exec client python ./test/functional/setup/cleanup_dbs.py -dbname $SQLSRV_DBNAME
- docker exec client python ./test/functional/setup/cleanup_dbs.py -dbname $PDOSQLSRV_DBNAME
- docker exec client coveralls -e ./source/shared/ --gcov-options '\-lp'
- docker stop client
- docker ps -a
@ -42,3 +44,4 @@ script:
notifications:
email: false

View file

@ -3,6 +3,24 @@ 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.3.0-RC1 - 2017-06-21
Here is the list of updates:
### Added
- Transparent Network IP Resolution ([TNIR](https://github.com/Microsoft/msphpsql/wiki/Features#TNIR)) feature.
### Fixed
- Fixed a memory leak in closing connection resources.
- Fixed load ordering issue in MacOS ([issue #417](https://github.com/Microsoft/msphpsql/issues/417))
### Limitation
- No support for inout / output params when using sql_variant type
### Known Issues
- 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.2.0-preview - 2017-05-19
Here is the list of updates:

View file

@ -67,13 +67,13 @@ WORKDIR $PHPSQLDIR/source/pdo_sqlsrv
RUN phpize && ./configure LDFLAGS="-lgcov" CXXFLAGS="-O0 --coverage" && make && make install
# set name of sql server host to use
WORKDIR $PHPSQLDIR/test/pdo_sqlsrv
WORKDIR $PHPSQLDIR/test/functional/pdo_sqlsrv
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
WORKDIR $PHPSQLDIR/test/functional/sqlsrv
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

View file

@ -13,7 +13,7 @@ SQL Server Team
Thank you for taking time to take our February survey. Let us know how we are doing and how you use PHP by taking our March pulse survey:
<a href="https://www.surveybuilder.com/s/neQnb"><img style="float: right;" height="67" width="156" src="https://meetsstorenew.blob.core.windows.net/contianerhd/survey.png?st=2017-02-17T22%3A03%3A00Z&se=2100-02-18T22%3A03%3A00Z&sp=rl&sv=2015-12-11&sr=b&sig=DJSFoihBptSvO%2BjvWzwpHecf8o5yfAbJoD2qW5oB8tc%3D"></a>
<a href="https://www.surveymonkey.com/r/CZNSBYW"><img style="float: right;" height="67" width="156" src="https://meetsstorenew.blob.core.windows.net/contianerhd/survey.png?st=2017-02-17T22%3A03%3A00Z&se=2100-02-18T22%3A03%3A00Z&sp=rl&sv=2015-12-11&sr=b&sig=DJSFoihBptSvO%2BjvWzwpHecf8o5yfAbJoD2qW5oB8tc%3D"></a>
### Status of Most Recent Builds
| AppVeyor (Windows) |Travis CI (Linux) | Coverage Status

View file

@ -123,10 +123,10 @@ install:
- 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\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
- ps: (Get-Content ${env:APPVEYOR_BUILD_FOLDER}\test\functional\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\functional\pdo_sqlsrv\MsSetup.inc
- ps: Get-Content ${env:APPVEYOR_BUILD_FOLDER}\test\functional\pdo_sqlsrv\MsSetup.inc
- ps: (Get-Content ${env:APPVEYOR_BUILD_FOLDER}\test\functional\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\functional\sqlsrv\MsSetup.inc
- ps: Get-Content ${env:APPVEYOR_BUILD_FOLDER}\test\functional\sqlsrv\MsSetup.inc
build_script:
- '"C:\\Program Files (x86)\\Microsoft Visual Studio %PHP_VC%.0\\VC\\vcvarsall.bat" %BUILD_PLATFORM%'
@ -163,18 +163,18 @@ test_script:
- php -i
- python -V
- Echo setup test database for SQLSRV tests - %SQLSRV_DBNAME%
- python %APPVEYOR_BUILD_FOLDER%\test\setup\setup_dbs.py -dbname %SQLSRV_DBNAME%
- python %APPVEYOR_BUILD_FOLDER%\test\functional\setup\setup_dbs.py -dbname %SQLSRV_DBNAME%
- Echo setup test database for PDO_SQLSRV tests - %PDOSQLSRV_DBNAME%
- python %APPVEYOR_BUILD_FOLDER%\test\setup\setup_dbs.py -dbname %PDOSQLSRV_DBNAME%
- php run-tests.php -p php.exe %APPVEYOR_BUILD_FOLDER%\test\sqlsrv\*.phpt > %APPVEYOR_BUILD_FOLDER%\test\sqlsrv.log 2>&1
- type %APPVEYOR_BUILD_FOLDER%\test\sqlsrv.log
- php run-tests.php -p php.exe %APPVEYOR_BUILD_FOLDER%\test\pdo_sqlsrv\*.phpt > %APPVEYOR_BUILD_FOLDER%\test\pdo_sqlsrv.log 2>&1
- type %APPVEYOR_BUILD_FOLDER%\test\pdo_sqlsrv.log
- python %APPVEYOR_BUILD_FOLDER%\test\setup\cleanup_dbs.py -dbname %SQLSRV_DBNAME%
- python %APPVEYOR_BUILD_FOLDER%\test\setup\cleanup_dbs.py -dbname %PDOSQLSRV_DBNAME%
- python %APPVEYOR_BUILD_FOLDER%\test\functional\setup\setup_dbs.py -dbname %PDOSQLSRV_DBNAME%
- php run-tests.php -p php.exe %APPVEYOR_BUILD_FOLDER%\test\functional\sqlsrv\*.phpt > %APPVEYOR_BUILD_FOLDER%\test\functional\sqlsrv.log 2>&1
- type %APPVEYOR_BUILD_FOLDER%\test\functional\sqlsrv.log
- php run-tests.php -p php.exe %APPVEYOR_BUILD_FOLDER%\test\functional\pdo_sqlsrv\*.phpt > %APPVEYOR_BUILD_FOLDER%\test\functional\pdo_sqlsrv.log 2>&1
- type %APPVEYOR_BUILD_FOLDER%\test\functional\pdo_sqlsrv.log
- python %APPVEYOR_BUILD_FOLDER%\test\functional\setup\cleanup_dbs.py -dbname %SQLSRV_DBNAME%
- python %APPVEYOR_BUILD_FOLDER%\test\functional\setup\cleanup_dbs.py -dbname %PDOSQLSRV_DBNAME%
after_test:
- cd %APPVEYOR_BUILD_FOLDER%\test\
- cd %APPVEYOR_BUILD_FOLDER%\test\functional\
- python output.py
- ps: $difffiles = Get-ChildItem sqlsrv\*.diff
- ps: $outfiles = Get-ChildItem sqlsrv\*.out

View file

@ -52,8 +52,14 @@ if test "$PHP_PDO_SQLSRV" != "no"; then
fi
AC_MSG_RESULT($pdo_sqlsrv_inc_path)
HOST_OS_ARCH=`uname`
if test "${HOST_OS_ARCH}" = "Darwin"; then
MACOSX_DEPLOYMENT_TARGET=`sw_vers -productVersion`
fi
CXXFLAGS="$CXXFLAGS -std=c++11"
CXXFLAGS="$CXXFLAGS -D_FORTIFY_SOURCE=2 -O2"
CXXFLAGS="$CXXFLAGS -fstack-protector"
PHP_REQUIRE_CXX()
PHP_ADD_LIBRARY(stdc++, 1, PDO_SQLSRV_SHARED_LIBADD)
PHP_ADD_LIBRARY(odbc, 1, PDO_SQLSRV_SHARED_LIBADD)

View file

@ -3,7 +3,7 @@
//
// Contents: JScript build configuration used by buildconf.bat
//
// Microsoft Drivers 4.2 for PHP for SQL Server
// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -34,6 +34,7 @@ if( PHP_PDO_SQLSRV != "no" ) {
ADD_FLAG( "CFLAGS_PDO_SQLSRV", "/EHsc" );
ADD_FLAG( "CFLAGS_PDO_SQLSRV", "/GS" );
ADD_FLAG( "CFLAGS_PDO_SQLSRV", "/Zi" );
ADD_FLAG( "CFLAGS_PDO_SQLSRV", "/O2" );
ADD_FLAG( "CFLAGS_PDO_SQLSRV", "/D ZEND_WIN32_FORCE_INLINE" );
ADD_EXTENSION_DEP('pdo_sqlsrv', 'pdo');
EXTENSION("pdo_sqlsrv", pdo_sqlsrv_src_class, PHP_PDO_SQLSRV_SHARED, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1");

View file

@ -3,7 +3,7 @@
//
// Contents: Implements the PDO object for PDO_SQLSRV
//
// Microsoft Drivers 4.2 for PHP for SQL Server
// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -57,6 +57,7 @@ const char TraceFile[] = "TraceFile";
const char TraceOn[] = "TraceOn";
const char TrustServerCertificate[] = "TrustServerCertificate";
const char TransactionIsolation[] = "TransactionIsolation";
const char TransparentNetworkIPResolution[] = "TransparentNetworkIPResolution";
const char WSID[] = "WSID";
}
@ -95,18 +96,18 @@ const stmt_option PDO_STMT_OPTS[] = {
// boolean connection string
struct pdo_bool_conn_str_func
{
static void func( connection_option const* option, zval* value, sqlsrv_conn* /*conn*/, std::string& conn_str TSRMLS_DC );
static void func( _In_ connection_option const* option, _Inout_ zval* value, sqlsrv_conn* /*conn*/, _Out_ std::string& conn_str TSRMLS_DC );
};
struct pdo_txn_isolation_conn_attr_func
{
static void func( connection_option const* /*option*/, zval* value_z, sqlsrv_conn* conn, std::string& /*conn_str*/ TSRMLS_DC );
static void func( connection_option const* /*option*/, _In_ zval* value_z, _Inout_ sqlsrv_conn* conn, std::string& /*conn_str*/ TSRMLS_DC );
};
#ifdef _WIN32
struct pdo_int_conn_str_func {
static void func( connection_option const* option, zval* value, sqlsrv_conn* /*conn*/, std::string& conn_str TSRMLS_DC )
static void func( _In_ connection_option const* option, _In_ zval* value, sqlsrv_conn* /*conn*/, _Out_ std::string& conn_str TSRMLS_DC )
{
TSRMLS_C;
SQLSRV_ASSERT( Z_TYPE_P( value ) == IS_STRING, "Wrong zval type for this keyword" )
@ -124,7 +125,7 @@ struct pdo_int_conn_str_func {
template <unsigned int Attr>
struct pdo_int_conn_attr_func {
static void func( connection_option const* /*option*/, zval* value, sqlsrv_conn* conn, std::string& /*conn_str*/ TSRMLS_DC )
static void func( connection_option const* /*option*/, _In_ zval* value, _Inout_ sqlsrv_conn* conn, std::string& /*conn_str*/ TSRMLS_DC )
{
try {
@ -142,7 +143,7 @@ struct pdo_int_conn_attr_func {
template <unsigned int Attr>
struct pdo_bool_conn_attr_func {
static void func( connection_option const* /*option*/, zval* value, sqlsrv_conn* conn, std::string& /*conn_str*/ TSRMLS_DC )
static void func( connection_option const* /*option*/, _Inout_ zval* value, _Inout_ sqlsrv_conn* conn, std::string& /*conn_str*/ TSRMLS_DC )
{
try {
@ -156,9 +157,9 @@ struct pdo_bool_conn_attr_func {
};
// statement options related functions
void add_stmt_option_key( sqlsrv_context& ctx, size_t key, HashTable* options_ht,
zval** data TSRMLS_DC );
void validate_stmt_options( sqlsrv_context& ctx, zval* stmt_options, _Inout_ HashTable* pdo_stmt_options_ht TSRMLS_DC );
void add_stmt_option_key( _Inout_ sqlsrv_context& ctx, _In_ size_t key, _Inout_ HashTable* options_ht,
_Inout_ zval** data TSRMLS_DC );
void validate_stmt_options( _Inout_ sqlsrv_context& ctx, _Inout_ zval* stmt_options, _Inout_ HashTable* pdo_stmt_options_ht TSRMLS_DC );
} // namespace
@ -338,6 +339,15 @@ const connection_option PDO_CONN_OPTS[] = {
CONN_ATTR_BOOL,
pdo_bool_conn_str_func::func
},
{
PDOConnOptionNames::TransparentNetworkIPResolution,
sizeof(PDOConnOptionNames::TransparentNetworkIPResolution),
SQLSRV_CONN_OPTION_TRANSPARANT_NETWORK_IP_RESOLUTION,
ODBCConnOptions::TransparentNetworkIPResolution,
sizeof(ODBCConnOptions::TransparentNetworkIPResolution),
CONN_ATTR_STRING,
conn_str_append_func::func
},
{
PDOConnOptionNames::WSID,
sizeof( PDOConnOptionNames::WSID ),
@ -352,34 +362,34 @@ const connection_option PDO_CONN_OPTS[] = {
// close the connection
int pdo_sqlsrv_dbh_close( pdo_dbh_t *dbh TSRMLS_DC );
int pdo_sqlsrv_dbh_close( _Inout_ pdo_dbh_t *dbh TSRMLS_DC );
// execute queries
int pdo_sqlsrv_dbh_prepare( pdo_dbh_t *dbh, const char *sql,
size_t sql_len, pdo_stmt_t *stmt, zval *driver_options TSRMLS_DC );
zend_long pdo_sqlsrv_dbh_do( pdo_dbh_t *dbh, const char *sql, size_t sql_len TSRMLS_DC );
int pdo_sqlsrv_dbh_prepare( _Inout_ pdo_dbh_t *dbh, _In_reads_(sql_len) const char *sql,
_Inout_ size_t sql_len, _Inout_ pdo_stmt_t *stmt, _In_ zval *driver_options TSRMLS_DC );
zend_long pdo_sqlsrv_dbh_do( _Inout_ pdo_dbh_t *dbh, _In_reads_bytes_(sql_len) const char *sql, _In_ size_t sql_len TSRMLS_DC );
// transaction support functions
int pdo_sqlsrv_dbh_commit( pdo_dbh_t *dbh TSRMLS_DC );
int pdo_sqlsrv_dbh_begin( pdo_dbh_t *dbh TSRMLS_DC );
int pdo_sqlsrv_dbh_rollback( pdo_dbh_t *dbh TSRMLS_DC );
int pdo_sqlsrv_dbh_commit( _Inout_ pdo_dbh_t *dbh TSRMLS_DC );
int pdo_sqlsrv_dbh_begin( _Inout_ pdo_dbh_t *dbh TSRMLS_DC );
int pdo_sqlsrv_dbh_rollback( _Inout_ pdo_dbh_t *dbh TSRMLS_DC );
// attribute functions
int pdo_sqlsrv_dbh_set_attr( pdo_dbh_t *dbh, zend_long attr, zval *val TSRMLS_DC );
int pdo_sqlsrv_dbh_get_attr( pdo_dbh_t *dbh, zend_long attr, zval *return_value TSRMLS_DC );
int pdo_sqlsrv_dbh_set_attr( _Inout_ pdo_dbh_t *dbh, _In_ zend_long attr, _Inout_ zval *val TSRMLS_DC );
int pdo_sqlsrv_dbh_get_attr( _Inout_ pdo_dbh_t *dbh, _In_ zend_long attr, _Inout_ zval *return_value TSRMLS_DC );
// return more information
int pdo_sqlsrv_dbh_return_error( pdo_dbh_t *dbh, pdo_stmt_t *stmt,
zval *info TSRMLS_DC);
int pdo_sqlsrv_dbh_return_error( _In_ pdo_dbh_t *dbh, _In_opt_ pdo_stmt_t *stmt,
_Out_ zval *info TSRMLS_DC);
// return the last id generated by an executed SQL statement
char * pdo_sqlsrv_dbh_last_id( pdo_dbh_t *dbh, const char *name, size_t* len TSRMLS_DC );
char * pdo_sqlsrv_dbh_last_id( _Inout_ pdo_dbh_t *dbh, _In_z_ const char *name, _Out_ size_t* len TSRMLS_DC );
// additional methods are supported in this function
pdo_sqlsrv_function_entry *pdo_sqlsrv_get_driver_methods( pdo_dbh_t *dbh, int kind TSRMLS_DC );
pdo_sqlsrv_function_entry *pdo_sqlsrv_get_driver_methods( _Inout_ pdo_dbh_t *dbh, int kind TSRMLS_DC );
// quote a string, meaning put quotes around it and escape any quotes within it
int pdo_sqlsrv_dbh_quote( pdo_dbh_t* dbh, const char* unquoted, size_t unquotedlen, char **quoted, size_t* quotedlen,
int pdo_sqlsrv_dbh_quote( _Inout_ pdo_dbh_t* dbh, _In_reads_(unquotedlen) const char* unquoted, _In_ size_t unquotedlen, _Outptr_result_buffer_(*quotedlen) char **quoted, _Out_ size_t* quotedlen,
enum pdo_param_type paramtype TSRMLS_DC );
struct pdo_dbh_methods pdo_sqlsrv_dbh_methods = {
@ -424,7 +434,7 @@ struct pdo_dbh_methods pdo_sqlsrv_dbh_methods = {
#endif
// constructor for the internal object for connections
pdo_sqlsrv_dbh::pdo_sqlsrv_dbh( SQLHANDLE h, error_callback e, void* driver TSRMLS_DC ) :
pdo_sqlsrv_dbh::pdo_sqlsrv_dbh( _In_ SQLHANDLE h, _In_ error_callback e, _In_ void* driver TSRMLS_DC ) :
sqlsrv_conn( h, e, driver, SQLSRV_ENCODING_UTF8 TSRMLS_CC ),
stmts( NULL ),
direct_query( false ),
@ -454,7 +464,7 @@ pdo_sqlsrv_dbh::pdo_sqlsrv_dbh( SQLHANDLE h, error_callback e, void* driver TSRM
// driver_options - A HashTable (within the zval) of options to use when creating the connection.
// Return:
// 0 for failure, 1 for success.
int pdo_sqlsrv_db_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC)
int pdo_sqlsrv_db_handle_factory( _Inout_ pdo_dbh_t *dbh, _In_opt_ zval *driver_options TSRMLS_DC)
{
LOG( SEV_NOTICE, "pdo_sqlsrv_db_handle_factory: entering" );
@ -556,7 +566,7 @@ int pdo_sqlsrv_db_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC)
// dbh - The PDO managed connection object.
// Return:
// Always returns 1 for success.
int pdo_sqlsrv_dbh_close( pdo_dbh_t *dbh TSRMLS_DC )
int pdo_sqlsrv_dbh_close( _Inout_ pdo_dbh_t *dbh TSRMLS_DC )
{
LOG( SEV_NOTICE, "pdo_sqlsrv_dbh_close: entering" );
@ -587,8 +597,8 @@ int pdo_sqlsrv_dbh_close( pdo_dbh_t *dbh TSRMLS_DC )
// driver_options - User provided list of statement options.
// Return:
// 0 for failure, 1 for success.
int pdo_sqlsrv_dbh_prepare( pdo_dbh_t *dbh, const char *sql,
size_t sql_len, pdo_stmt_t *stmt, zval *driver_options TSRMLS_DC )
int pdo_sqlsrv_dbh_prepare( _Inout_ pdo_dbh_t *dbh, _In_reads_(sql_len) const char *sql,
_Inout_ size_t sql_len, _Inout_ pdo_stmt_t *stmt, _In_ zval *driver_options TSRMLS_DC )
{
PDO_RESET_DBH_ERROR;
PDO_VALIDATE_CONN;
@ -725,7 +735,7 @@ int pdo_sqlsrv_dbh_prepare( pdo_dbh_t *dbh, const char *sql,
// sql_len - length of sql query
// Return
// # of rows affected, -1 for an error.
zend_long pdo_sqlsrv_dbh_do( pdo_dbh_t *dbh, const char *sql, size_t sql_len TSRMLS_DC )
zend_long pdo_sqlsrv_dbh_do( _Inout_ pdo_dbh_t *dbh, _In_reads_bytes_(sql_len) const char *sql, _In_ size_t sql_len TSRMLS_DC )
{
PDO_RESET_DBH_ERROR;
PDO_VALIDATE_CONN;
@ -743,6 +753,7 @@ zend_long pdo_sqlsrv_dbh_do( pdo_dbh_t *dbh, const char *sql, size_t sql_len TSR
try {
SQLSRV_ASSERT( sql != NULL, "NULL or empty SQL string passed." );
SQLSRV_ASSERT( driver_dbh != NULL, "pdo_sqlsrv_dbh_do: driver_data object was NULL.");
// temp PDO statement used for error handling if something happens
pdo_stmt_t temp_stmt;
@ -813,7 +824,7 @@ zend_long pdo_sqlsrv_dbh_do( pdo_dbh_t *dbh, const char *sql, size_t sql_len TSR
// dbh - The PDO managed connection object.
// Return:
// 0 for failure and 1 for success.
int pdo_sqlsrv_dbh_begin( pdo_dbh_t *dbh TSRMLS_DC )
int pdo_sqlsrv_dbh_begin( _Inout_ pdo_dbh_t *dbh TSRMLS_DC )
{
PDO_RESET_DBH_ERROR;
PDO_VALIDATE_CONN;
@ -855,7 +866,7 @@ int pdo_sqlsrv_dbh_begin( pdo_dbh_t *dbh TSRMLS_DC )
// dbh - The PDO managed connection object.
// Return:
// 0 for failure and 1 for success.
int pdo_sqlsrv_dbh_commit( pdo_dbh_t *dbh TSRMLS_DC )
int pdo_sqlsrv_dbh_commit( _Inout_ pdo_dbh_t *dbh TSRMLS_DC )
{
PDO_RESET_DBH_ERROR;
PDO_VALIDATE_CONN;
@ -895,7 +906,7 @@ int pdo_sqlsrv_dbh_commit( pdo_dbh_t *dbh TSRMLS_DC )
// dbh - The PDO managed connection object.
// Return:
// 0 for failure and 1 for success.
int pdo_sqlsrv_dbh_rollback( pdo_dbh_t *dbh TSRMLS_DC )
int pdo_sqlsrv_dbh_rollback( _Inout_ pdo_dbh_t *dbh TSRMLS_DC )
{
PDO_RESET_DBH_ERROR;
PDO_VALIDATE_CONN;
@ -934,13 +945,14 @@ int pdo_sqlsrv_dbh_rollback( pdo_dbh_t *dbh TSRMLS_DC )
// val - The value of the attribute to be set.
// Return:
// 0 for failure, 1 for success.
int pdo_sqlsrv_dbh_set_attr( pdo_dbh_t *dbh, zend_long attr, zval *val TSRMLS_DC )
int pdo_sqlsrv_dbh_set_attr( _Inout_ pdo_dbh_t *dbh, _In_ zend_long attr, _Inout_ zval *val TSRMLS_DC )
{
PDO_RESET_DBH_ERROR;
PDO_VALIDATE_CONN;
PDO_LOG_DBH_ENTRY;
pdo_sqlsrv_dbh* driver_dbh = static_cast<pdo_sqlsrv_dbh*>( dbh->driver_data );
SQLSRV_ASSERT( driver_dbh != NULL, "pdo_sqlsrv_dbh_set_attr: driver_data object was NULL.");
try {
@ -1049,13 +1061,14 @@ int pdo_sqlsrv_dbh_set_attr( pdo_dbh_t *dbh, zend_long attr, zval *val TSRMLS_DC
// return_value - zval in which to return the attribute value.
// Return:
// 0 for failure, 1 for success.
int pdo_sqlsrv_dbh_get_attr( pdo_dbh_t *dbh, zend_long attr, zval *return_value TSRMLS_DC )
int pdo_sqlsrv_dbh_get_attr( _Inout_ pdo_dbh_t *dbh, _In_ zend_long attr, _Inout_ zval *return_value TSRMLS_DC )
{
PDO_RESET_DBH_ERROR;
PDO_VALIDATE_CONN;
PDO_LOG_DBH_ENTRY;
pdo_sqlsrv_dbh* driver_dbh = static_cast<pdo_sqlsrv_dbh*>( dbh->driver_data );
SQLSRV_ASSERT( driver_dbh != NULL, "pdo_sqlsrv_dbh_get_attr: driver_data object was NULL.");
try {
@ -1166,8 +1179,8 @@ int pdo_sqlsrv_dbh_get_attr( pdo_dbh_t *dbh, zend_long attr, zval *return_value
// info - zval in which to return the error info.
// Return:
// 0 for failure, 1 for success.
int pdo_sqlsrv_dbh_return_error( pdo_dbh_t *dbh, pdo_stmt_t *stmt,
zval *info TSRMLS_DC)
int pdo_sqlsrv_dbh_return_error( _In_ pdo_dbh_t *dbh, _In_opt_ pdo_stmt_t *stmt,
_Out_ zval *info TSRMLS_DC)
{
SQLSRV_ASSERT( dbh != NULL || stmt != NULL, "Either dbh or stmt must not be NULL to dereference the error." );
@ -1193,7 +1206,7 @@ int pdo_sqlsrv_dbh_return_error( pdo_dbh_t *dbh, pdo_stmt_t *stmt,
// len - Length of the name.
// Return:
// Returns the last insert id as a string.
char * pdo_sqlsrv_dbh_last_id( pdo_dbh_t *dbh, const char *name, _Out_ size_t* len TSRMLS_DC )
char * pdo_sqlsrv_dbh_last_id( _Inout_ pdo_dbh_t *dbh, _In_z_ const char *name, _Out_ size_t* len TSRMLS_DC )
{
PDO_RESET_DBH_ERROR;
PDO_VALIDATE_CONN;
@ -1206,6 +1219,7 @@ char * pdo_sqlsrv_dbh_last_id( pdo_dbh_t *dbh, const char *name, _Out_ size_t* l
sqlsrv_malloc_auto_ptr<sqlsrv_stmt> driver_stmt;
pdo_sqlsrv_dbh* driver_dbh = static_cast<pdo_sqlsrv_dbh*>( dbh->driver_data );
SQLSRV_ASSERT( driver_dbh != NULL, "pdo_sqlsrv_dbh_last_id: driver_data object was NULL." );
sqlsrv_malloc_auto_ptr<char> id_str;
id_str = reinterpret_cast<char*>( sqlsrv_malloc( LAST_INSERT_ID_BUFF_LEN ));
@ -1292,7 +1306,7 @@ char * pdo_sqlsrv_dbh_last_id( pdo_dbh_t *dbh, const char *name, _Out_ size_t* l
// quoted_len - Length of the output string.
// Return:
// 0 for failure, 1 for success.
int pdo_sqlsrv_dbh_quote( pdo_dbh_t* dbh, const char* unquoted, size_t unquoted_len, char **quoted, size_t* quoted_len,
int pdo_sqlsrv_dbh_quote( _Inout_ pdo_dbh_t* dbh, _In_reads_(unquoted_len) const char* unquoted, _In_ size_t unquoted_len, _Outptr_result_buffer_(*quoted_len) char **quoted, _Out_ size_t* quoted_len,
enum pdo_param_type /*paramtype*/ TSRMLS_DC )
{
PDO_RESET_DBH_ERROR;
@ -1309,15 +1323,16 @@ int pdo_sqlsrv_dbh_quote( pdo_dbh_t* dbh, const char* unquoted, size_t unquoted_
// iterate through parents to find "PDOStatement"
bool is_statement = false;
zend_class_entry* curr_class = ( Z_OBJ_P( object ))->ce;
while ( curr_class != NULL ) {
if ( strcmp( reinterpret_cast<const char*>( curr_class->name->val ), "PDOStatement" ) == 0 ) {
is_statement = true;
break;
if ( object ) {
zend_class_entry* curr_class = ( Z_OBJ_P( object ))->ce;
while ( curr_class != NULL ) {
if ( strcmp( reinterpret_cast<const char*>( curr_class->name->val ), "PDOStatement" ) == 0 ) {
is_statement = true;
break;
}
curr_class = curr_class->parent;
}
curr_class = curr_class->parent;
}
// only change the encoding if quote is called from the statement level (which should only be called when a statement
// is prepared with emulate prepared on)
if ( is_statement ) {
@ -1333,7 +1348,7 @@ int pdo_sqlsrv_dbh_quote( pdo_dbh_t* dbh, const char* unquoted, size_t unquoted_
}
// get the placeholder at the current position in driver_stmt->placeholders ht
zval* placeholder = NULL;
if (( placeholder = zend_hash_get_current_data( driver_stmt->placeholders )) != NULL && zend_hash_move_forward( driver_stmt->placeholders ) == SUCCESS ) {
if (( placeholder = zend_hash_get_current_data( driver_stmt->placeholders )) != NULL && zend_hash_move_forward( driver_stmt->placeholders ) == SUCCESS && stmt->bound_params != NULL ) {
pdo_bound_param_data* param = NULL;
if ( Z_TYPE_P( placeholder ) == IS_STRING ) {
param = reinterpret_cast<pdo_bound_param_data*>( zend_hash_find_ptr( stmt->bound_params, Z_STR_P( placeholder )));
@ -1425,13 +1440,14 @@ int pdo_sqlsrv_dbh_quote( pdo_dbh_t* dbh, const char* unquoted, size_t unquoted_
}
// This method is not implemented by this driver.
pdo_sqlsrv_function_entry *pdo_sqlsrv_get_driver_methods( pdo_dbh_t *dbh, int kind TSRMLS_DC )
pdo_sqlsrv_function_entry *pdo_sqlsrv_get_driver_methods( _Inout_ pdo_dbh_t *dbh, int kind TSRMLS_DC )
{
PDO_RESET_DBH_ERROR;
PDO_VALIDATE_CONN;
PDO_LOG_DBH_ENTRY;
sqlsrv_conn* driver_conn = reinterpret_cast<sqlsrv_conn*>( dbh->driver_data );
SQLSRV_ASSERT( driver_conn != NULL, "pdo_sqlsrv_get_driver_methods: driver_data object was NULL." );
CHECK_CUSTOM_ERROR( true, driver_conn, PDO_SQLSRV_ERROR_FUNCTION_NOT_IMPLEMENTED ) {
return NULL;
}
@ -1443,8 +1459,8 @@ namespace {
// Maps the PDO driver specific statement option/attribute constants to the core layer
// statement option/attribute constants.
void add_stmt_option_key( sqlsrv_context& ctx, size_t key, HashTable* options_ht,
zval* data TSRMLS_DC )
void add_stmt_option_key( _Inout_ sqlsrv_context& ctx, _In_ size_t key, _Inout_ HashTable* options_ht,
_Inout_ zval* data TSRMLS_DC )
{
zend_ulong option_key = -1;
switch( key ) {
@ -1507,7 +1523,7 @@ void add_stmt_option_key( sqlsrv_context& ctx, size_t key, HashTable* options_ht
// ctx - The current context.
// stmt_options - The user provided list of statement options.
// pdo_stmt_options_ht - Output hashtable of statement options.
void validate_stmt_options( sqlsrv_context& ctx, zval* stmt_options, _Inout_ HashTable* pdo_stmt_options_ht TSRMLS_DC )
void validate_stmt_options( _Inout_ sqlsrv_context& ctx, _Inout_ zval* stmt_options, _Inout_ HashTable* pdo_stmt_options_ht TSRMLS_DC )
{
try {
@ -1537,7 +1553,7 @@ void validate_stmt_options( sqlsrv_context& ctx, zval* stmt_options, _Inout_ Has
}
void pdo_bool_conn_str_func::func(connection_option const* option, zval* value, sqlsrv_conn* /*conn*/, std::string& conn_str TSRMLS_DC )
void pdo_bool_conn_str_func::func( _In_ connection_option const* option, _Inout_ zval* value, sqlsrv_conn* /*conn*/, _Out_ std::string& conn_str TSRMLS_DC )
{
TSRMLS_C;
char const* val_str = "no";
@ -1553,7 +1569,7 @@ void pdo_bool_conn_str_func::func(connection_option const* option, zval* value,
conn_str += "};";
}
void pdo_txn_isolation_conn_attr_func::func( connection_option const* /*option*/, zval* value_z, sqlsrv_conn* conn,
void pdo_txn_isolation_conn_attr_func::func( connection_option const* /*option*/, _In_ zval* value_z, _Inout_ sqlsrv_conn* conn,
std::string& /*conn_str*/ TSRMLS_DC )
{
try {

View file

@ -3,7 +3,7 @@
//
// Contents: initialization routines for PDO_SQLSRV
//
// Microsoft Drivers 4.2 for PHP for SQL Server
// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -47,8 +47,8 @@ pdo_driver_t pdo_sqlsrv_driver = {
// functions to register SQLSRV constants with the PDO class
// (It's in all CAPS so it looks like the Zend macros that do similar work)
void REGISTER_PDO_SQLSRV_CLASS_CONST_LONG( char const* name, long value TSRMLS_DC );
void REGISTER_PDO_SQLSRV_CLASS_CONST_STRING( char const* name, char const* value TSRMLS_DC );
void REGISTER_PDO_SQLSRV_CLASS_CONST_LONG( _In_z_ char const* name, _In_ long value TSRMLS_DC );
void REGISTER_PDO_SQLSRV_CLASS_CONST_STRING( _In_z_ char const* name, _In_z_ char const* value TSRMLS_DC );
struct sqlsrv_attr_pdo_constant {
const char *name;
@ -100,7 +100,7 @@ zend_module_entry g_pdo_sqlsrv_module_entry =
};
// called by Zend for each parameter in the g_pdo_errors_ht hash table when it is destroyed
void pdo_error_dtor( zval* elem ) {
void pdo_error_dtor( _Inout_ zval* elem ) {
pdo_error* error_to_ignore = reinterpret_cast<pdo_error*>( Z_PTR_P( elem ) );
pefree( error_to_ignore, 1 );
}
@ -252,7 +252,7 @@ namespace {
// mimic the functionality of the REGISTER_PDO_CLASS_CONST_LONG. We use this instead of the macro because
// we dynamically link the pdo_get_dbh_class function rather than use the static php_pdo_get_dbh_ce (see MINIT)
void REGISTER_PDO_SQLSRV_CLASS_CONST_LONG( char const* name, long value TSRMLS_DC )
void REGISTER_PDO_SQLSRV_CLASS_CONST_LONG( _In_z_ char const* name, _In_ long value TSRMLS_DC )
{
zend_class_entry* zend_class = php_pdo_get_dbh_ce();
@ -263,7 +263,7 @@ namespace {
}
}
void REGISTER_PDO_SQLSRV_CLASS_CONST_STRING( char const* name, char const* value TSRMLS_DC )
void REGISTER_PDO_SQLSRV_CLASS_CONST_STRING( _In_z_ char const* name, _In_z_ char const* value TSRMLS_DC )
{
zend_class_entry* zend_class = php_pdo_get_dbh_ce();

View file

@ -5,7 +5,7 @@
//
// Copyright Microsoft Corporation
//
// Microsoft Drivers 4.2 for PHP for SQL Server
// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -22,7 +22,7 @@
#include "php_pdo_sqlsrv.h"
// Constructor
conn_string_parser:: conn_string_parser( sqlsrv_context& ctx, const char* dsn, int len, _Inout_ HashTable* conn_options_ht )
conn_string_parser:: conn_string_parser( _In_ sqlsrv_context& ctx, _In_ const char* dsn, _In_ int len, _In_ HashTable* conn_options_ht )
{
this->orig_str = dsn;
this->len = len;
@ -33,7 +33,7 @@ conn_string_parser:: conn_string_parser( sqlsrv_context& ctx, const char* dsn, i
this->current_key_name = NULL;
}
sql_string_parser:: sql_string_parser( sqlsrv_context& ctx, const char* sql_str, int len, _Inout_ HashTable* placeholders_ht )
sql_string_parser:: sql_string_parser( _In_ sqlsrv_context& ctx, _In_ const char* sql_str, _In_ int len, _In_ HashTable* placeholders_ht )
{
this->orig_str = sql_str;
this->len = len;
@ -78,7 +78,7 @@ inline bool string_parser::is_eos( void )
}
// Check for white space.
inline bool string_parser::is_white_space( char c )
inline bool string_parser::is_white_space( _In_ char c )
{
if( c == ' ' || c == '\r' || c == '\n' || c == '\t' ) {
return true;
@ -87,7 +87,7 @@ inline bool string_parser::is_white_space( char c )
}
// Discard any trailing white spaces.
int conn_string_parser::discard_trailing_white_spaces( const char* str, int len )
int conn_string_parser::discard_trailing_white_spaces( _In_reads_(len) const char* str, _Inout_ int len )
{
const char* end = str + ( len - 1 );
@ -118,7 +118,7 @@ bool string_parser::discard_white_spaces()
}
// Add a key-value pair to the hashtable
void string_parser::add_key_value_pair( const char* value, int len TSRMLS_DC )
void string_parser::add_key_value_pair( _In_reads_(len) const char* value, _In_ int len TSRMLS_DC )
{
zval value_z;
ZVAL_UNDEF( &value_z );
@ -136,7 +136,7 @@ void string_parser::add_key_value_pair( const char* value, int len TSRMLS_DC )
}
// Add a key-value pair to the hashtable with int value
void sql_string_parser::add_key_int_value_pair( unsigned int value TSRMLS_DC ) {
void sql_string_parser::add_key_int_value_pair( _In_ unsigned int value TSRMLS_DC ) {
zval value_z;
ZVAL_LONG( &value_z, value );
@ -144,7 +144,7 @@ void sql_string_parser::add_key_int_value_pair( unsigned int value TSRMLS_DC ) {
}
// Validate a given DSN keyword.
void conn_string_parser::validate_key(const char *key, int key_len TSRMLS_DC )
void conn_string_parser::validate_key( _In_reads_(key_len) const char *key, _Inout_ int key_len TSRMLS_DC )
{
int new_len = discard_trailing_white_spaces( key, key_len );
@ -169,7 +169,7 @@ 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 )
void conn_string_parser::add_key_value_pair( _In_reads_(len) const char* value, _In_ int len TSRMLS_DC )
{
// if the keyword is 'Authentication', check whether the user specified option is supported
bool valid = true;

View file

@ -3,7 +3,7 @@
//
// Contents: Implements the PDOStatement object for the PDO_SQLSRV
//
// Microsoft Drivers 4.2 for PHP for SQL Server
// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -37,7 +37,7 @@ SQLSMALLINT odbc_fetch_orientation[] =
// max length of a field type
const int SQL_SERVER_IDENT_SIZE_MAX = 128;
inline SQLSMALLINT pdo_fetch_ori_to_odbc_fetch_ori (enum pdo_fetch_orientation ori)
inline SQLSMALLINT pdo_fetch_ori_to_odbc_fetch_ori ( _In_ enum pdo_fetch_orientation ori )
{
SQLSRV_ASSERT( ori >= PDO_FETCH_ORI_NEXT && ori <= PDO_FETCH_ORI_REL, "Fetch orientation out of range.");
#ifdef _WIN32
@ -49,7 +49,7 @@ inline SQLSMALLINT pdo_fetch_ori_to_odbc_fetch_ori (enum pdo_fetch_orientation o
// Returns SQLSRV data type for a given PDO type. See pdo_param_type
// for list of supported pdo types.
SQLSRV_PHPTYPE pdo_type_to_sqlsrv_php_type( sqlsrv_stmt* driver_stmt, enum pdo_param_type pdo_type TSRMLS_DC )
SQLSRV_PHPTYPE pdo_type_to_sqlsrv_php_type( _Inout_ sqlsrv_stmt* driver_stmt, _In_ enum pdo_param_type pdo_type TSRMLS_DC )
{
switch( pdo_type ) {
@ -80,7 +80,7 @@ SQLSRV_PHPTYPE pdo_type_to_sqlsrv_php_type( sqlsrv_stmt* driver_stmt, enum pdo_p
// Returns a pdo type for a given SQL type. See pdo_param_type
// for list of supported pdo types.
inline pdo_param_type sql_type_to_pdo_type( SQLSMALLINT sql_type )
inline pdo_param_type sql_type_to_pdo_type( _In_ SQLSMALLINT sql_type )
{
pdo_param_type return_type = PDO_PARAM_STR;
@ -127,7 +127,7 @@ inline pdo_param_type sql_type_to_pdo_type( SQLSMALLINT sql_type )
// Calls core_sqlsrv_set_scrollable function to set cursor.
// PDO supports two cursor types: PDO_CURSOR_FWDONLY, PDO_CURSOR_SCROLL.
void set_stmt_cursors( sqlsrv_stmt* stmt, zval* value_z TSRMLS_DC )
void set_stmt_cursors( _Inout_ sqlsrv_stmt* stmt, _In_ zval* value_z TSRMLS_DC )
{
if( Z_TYPE_P( value_z ) != IS_LONG ) {
@ -154,7 +154,7 @@ void set_stmt_cursors( sqlsrv_stmt* stmt, zval* value_z TSRMLS_DC )
core_sqlsrv_set_scrollable( stmt, odbc_cursor_type TSRMLS_CC );
}
void set_stmt_cursor_scroll_type( sqlsrv_stmt* stmt, zval* value_z TSRMLS_DC )
void set_stmt_cursor_scroll_type( _Inout_ sqlsrv_stmt* stmt, _In_ zval* value_z TSRMLS_DC )
{
if( Z_TYPE_P( value_z ) != IS_LONG ) {
@ -175,7 +175,7 @@ void set_stmt_cursor_scroll_type( sqlsrv_stmt* stmt, zval* value_z TSRMLS_DC )
// Sets the statement encoding. Default encoding on the statement
// implies use the connection's encoding.
void set_stmt_encoding( sqlsrv_stmt* stmt, zval* value_z TSRMLS_DC )
void set_stmt_encoding( _Inout_ sqlsrv_stmt* stmt, _In_ zval* value_z TSRMLS_DC )
{
// validate the value
if( Z_TYPE_P( value_z ) != IS_LONG ) {
@ -202,7 +202,7 @@ void set_stmt_encoding( sqlsrv_stmt* stmt, zval* value_z TSRMLS_DC )
}
// internal helper function to free meta data structures allocated
void meta_data_free( field_meta_data* meta )
void meta_data_free( _Inout_ field_meta_data* meta )
{
if( meta->field_name ) {
meta->field_name.reset();
@ -210,9 +210,10 @@ void meta_data_free( field_meta_data* meta )
sqlsrv_free( meta );
}
zval convert_to_zval( SQLSRV_PHPTYPE sqlsrv_php_type, void** in_val, SQLLEN field_len )
zval convert_to_zval( _In_ SQLSRV_PHPTYPE sqlsrv_php_type, _Inout_ void** in_val, _In_opt_ SQLLEN field_len )
{
zval out_zval;
ZVAL_UNDEF( &out_zval );
switch( sqlsrv_php_type ) {
@ -274,20 +275,20 @@ zval convert_to_zval( SQLSRV_PHPTYPE sqlsrv_php_type, void** in_val, SQLLEN fiel
} // namespace
int pdo_sqlsrv_stmt_dtor(pdo_stmt_t *stmt TSRMLS_DC);
int pdo_sqlsrv_stmt_execute(pdo_stmt_t *stmt TSRMLS_DC);
int pdo_sqlsrv_stmt_fetch(pdo_stmt_t *stmt, enum pdo_fetch_orientation ori,
zend_long offset TSRMLS_DC);
int pdo_sqlsrv_stmt_param_hook(pdo_stmt_t *stmt,
struct pdo_bound_param_data *param, enum pdo_param_event event_type TSRMLS_DC);
int pdo_sqlsrv_stmt_describe_col(pdo_stmt_t *stmt, int colno TSRMLS_DC);
int pdo_sqlsrv_stmt_get_col_data(pdo_stmt_t *stmt, int colno,
char **ptr, size_t *len, int *caller_frees TSRMLS_DC);
int pdo_sqlsrv_stmt_set_attr(pdo_stmt_t *stmt, zend_long attr, zval *val TSRMLS_DC);
int pdo_sqlsrv_stmt_get_attr(pdo_stmt_t *stmt, zend_long attr, zval *return_value TSRMLS_DC);
int pdo_sqlsrv_stmt_get_col_meta(pdo_stmt_t *stmt, zend_long colno, zval *return_value TSRMLS_DC);
int pdo_sqlsrv_stmt_next_rowset(pdo_stmt_t *stmt TSRMLS_DC);
int pdo_sqlsrv_stmt_close_cursor(pdo_stmt_t *stmt TSRMLS_DC);
int pdo_sqlsrv_stmt_dtor( _Inout_ pdo_stmt_t *stmt TSRMLS_DC );
int pdo_sqlsrv_stmt_execute( _Inout_ pdo_stmt_t *stmt TSRMLS_DC );
int pdo_sqlsrv_stmt_fetch( _Inout_ pdo_stmt_t *stmt, _In_ enum pdo_fetch_orientation ori,
_In_ zend_long offset TSRMLS_DC );
int pdo_sqlsrv_stmt_param_hook( _Inout_ pdo_stmt_t *stmt,
_Inout_ struct pdo_bound_param_data *param, _In_ enum pdo_param_event event_type TSRMLS_DC );
int pdo_sqlsrv_stmt_describe_col( _Inout_ pdo_stmt_t *stmt, _In_ int colno TSRMLS_DC );
int pdo_sqlsrv_stmt_get_col_data( _Inout_ pdo_stmt_t *stmt, _In_ int colno,
_Out_writes_bytes_opt_(*len) char **ptr, _Inout_ size_t *len, _Out_opt_ int *caller_frees TSRMLS_DC );
int pdo_sqlsrv_stmt_set_attr( _Inout_ pdo_stmt_t *stmt, _In_ zend_long attr, _Inout_ zval *val TSRMLS_DC );
int pdo_sqlsrv_stmt_get_attr( _Inout_ pdo_stmt_t *stmt, _In_ zend_long attr, _Inout_ zval *return_value TSRMLS_DC );
int pdo_sqlsrv_stmt_get_col_meta( _Inout_ pdo_stmt_t *stmt, _In_ zend_long colno, _Inout_ zval *return_value TSRMLS_DC );
int pdo_sqlsrv_stmt_next_rowset( _Inout_ pdo_stmt_t *stmt TSRMLS_DC );
int pdo_sqlsrv_stmt_close_cursor( _Inout_ pdo_stmt_t *stmt TSRMLS_DC );
struct pdo_stmt_methods pdo_sqlsrv_stmt_methods = {
@ -305,34 +306,34 @@ struct pdo_stmt_methods pdo_sqlsrv_stmt_methods = {
};
void stmt_option_pdo_scrollable:: operator()( sqlsrv_stmt* stmt, stmt_option const* /*opt*/, zval* value_z TSRMLS_DC )
void stmt_option_pdo_scrollable:: operator()( _Inout_ sqlsrv_stmt* stmt, stmt_option const* /*opt*/, _In_ zval* value_z TSRMLS_DC )
{
set_stmt_cursors( stmt, value_z TSRMLS_CC );
}
void stmt_option_encoding:: operator()( sqlsrv_stmt* stmt, stmt_option const* /*opt*/, zval* value_z TSRMLS_DC )
void stmt_option_encoding:: operator()( _Inout_ sqlsrv_stmt* stmt, stmt_option const* /*opt*/, _In_ zval* value_z TSRMLS_DC )
{
set_stmt_encoding( stmt, value_z TSRMLS_CC );
}
void stmt_option_direct_query:: operator()( sqlsrv_stmt* stmt, stmt_option const* /*opt*/, zval* value_z TSRMLS_DC )
void stmt_option_direct_query:: operator()( _Inout_ sqlsrv_stmt* stmt, stmt_option const* /*opt*/, _In_ zval* value_z TSRMLS_DC )
{
pdo_sqlsrv_stmt *pdo_stmt = static_cast<pdo_sqlsrv_stmt*>( stmt );
pdo_stmt->direct_query = ( zend_is_true( value_z )) ? true : false;
}
void stmt_option_cursor_scroll_type:: operator()( sqlsrv_stmt* stmt, stmt_option const* /*opt*/, zval* value_z TSRMLS_DC )
void stmt_option_cursor_scroll_type:: operator()( _Inout_ sqlsrv_stmt* stmt, stmt_option const* /*opt*/, _In_ zval* value_z TSRMLS_DC )
{
set_stmt_cursor_scroll_type( stmt, value_z TSRMLS_CC );
}
void stmt_option_emulate_prepares:: operator()( sqlsrv_stmt* stmt, stmt_option const* /*opt*/, zval* value_z TSRMLS_DC )
void stmt_option_emulate_prepares:: operator()( _Inout_ sqlsrv_stmt* stmt, stmt_option const* /*opt*/, _In_ zval* value_z TSRMLS_DC )
{
pdo_stmt_t *pdo_stmt = static_cast<pdo_stmt_t*>( stmt->driver() );
pdo_stmt->supports_placeholders = ( zend_is_true( value_z )) ? PDO_PLACEHOLDER_NONE : PDO_PLACEHOLDER_POSITIONAL;
}
void stmt_option_fetch_numeric:: operator()( sqlsrv_stmt* stmt, stmt_option const* /*opt*/, zval* value_z TSRMLS_DC )
void stmt_option_fetch_numeric:: operator()( _Inout_ sqlsrv_stmt* stmt, stmt_option const* /*opt*/, _In_ zval* value_z TSRMLS_DC )
{
pdo_sqlsrv_stmt *pdo_stmt = static_cast<pdo_sqlsrv_stmt*>( stmt );
pdo_stmt->fetch_numeric = ( zend_is_true( value_z )) ? true : false;
@ -385,7 +386,7 @@ pdo_sqlsrv_stmt::~pdo_sqlsrv_stmt( void )
// *stmt - Pointer to current statement
// Return:
// Returns 0 for failure, 1 for success.
int pdo_sqlsrv_stmt_close_cursor(pdo_stmt_t *stmt TSRMLS_DC)
int pdo_sqlsrv_stmt_close_cursor( _Inout_ pdo_stmt_t *stmt TSRMLS_DC )
{
PDO_RESET_STMT_ERROR;
PDO_VALIDATE_STMT;
@ -402,9 +403,9 @@ int pdo_sqlsrv_stmt_close_cursor(pdo_stmt_t *stmt TSRMLS_DC)
// to "close the cursor" means we make the statement ready for execution again. To do this, we
// skip all the result sets on the current statement.
// If the statement has not been executed there are no next results to iterate over.
if ( driver_stmt->executed == true )
if ( driver_stmt && driver_stmt->executed == true )
{
while( driver_stmt->past_next_result_end == false ) {
while( driver_stmt && driver_stmt->past_next_result_end == false ) {
core_sqlsrv_next_result( driver_stmt TSRMLS_CC );
}
}
@ -429,13 +430,14 @@ int pdo_sqlsrv_stmt_close_cursor(pdo_stmt_t *stmt TSRMLS_DC)
// colno - Index of the column which requires description.
// Return:
// 0 for failure, 1 for success.
int pdo_sqlsrv_stmt_describe_col(pdo_stmt_t *stmt, int colno TSRMLS_DC)
int pdo_sqlsrv_stmt_describe_col( _Inout_ pdo_stmt_t *stmt, _In_ int colno TSRMLS_DC)
{
PDO_RESET_STMT_ERROR;
PDO_VALIDATE_STMT;
PDO_LOG_STMT_ENTRY;
SQLSRV_ASSERT(( colno >= 0 ), "pdo_sqlsrv_stmt_describe_col: Column number should be >= 0." );
SQLSRV_ASSERT( stmt->driver_data != NULL, "pdo_sqlsrv_stmt_describe_col: driver_data object was NULL." );
sqlsrv_malloc_auto_ptr<field_meta_data> core_meta_data;
@ -486,7 +488,7 @@ int pdo_sqlsrv_stmt_describe_col(pdo_stmt_t *stmt, int colno TSRMLS_DC)
// *stmt - pointer to current statement
// Return:
// 1 for success.
int pdo_sqlsrv_stmt_dtor( pdo_stmt_t *stmt TSRMLS_DC )
int pdo_sqlsrv_stmt_dtor( _Inout_ pdo_stmt_t *stmt TSRMLS_DC )
{
pdo_sqlsrv_stmt* driver_stmt = reinterpret_cast<pdo_sqlsrv_stmt*>( stmt->driver_data );
@ -519,7 +521,7 @@ int pdo_sqlsrv_stmt_dtor( pdo_stmt_t *stmt TSRMLS_DC )
// *stmt - pointer to the current statement.
// Return:
// 0 for failure, 1 for success.
int pdo_sqlsrv_stmt_execute(pdo_stmt_t *stmt TSRMLS_DC)
int pdo_sqlsrv_stmt_execute( _Inout_ pdo_stmt_t *stmt TSRMLS_DC )
{
PDO_RESET_STMT_ERROR;
PDO_VALIDATE_STMT;
@ -532,7 +534,7 @@ int pdo_sqlsrv_stmt_execute(pdo_stmt_t *stmt TSRMLS_DC)
// prepare for execution by flushing anything remaining in the result set if it wasn't already
// done before binding parameters
if( driver_stmt->executed && !driver_stmt->past_next_result_end ) {
if( driver_stmt && driver_stmt->executed && !driver_stmt->past_next_result_end ) {
while( driver_stmt->past_next_result_end == false ) {
@ -615,8 +617,8 @@ int pdo_sqlsrv_stmt_execute(pdo_stmt_t *stmt TSRMLS_DC)
// offset - For orientations that use it, offset to move to.
// Return:
// 0 for failure, 1 for success.
int pdo_sqlsrv_stmt_fetch(pdo_stmt_t *stmt, enum pdo_fetch_orientation ori,
zend_long offset TSRMLS_DC)
int pdo_sqlsrv_stmt_fetch( _Inout_ pdo_stmt_t *stmt, _In_ enum pdo_fetch_orientation ori,
_In_ zend_long offset TSRMLS_DC)
{
PDO_RESET_STMT_ERROR;
PDO_VALIDATE_STMT;
@ -709,8 +711,8 @@ int pdo_sqlsrv_stmt_fetch(pdo_stmt_t *stmt, enum pdo_fetch_orientation ori,
// freeing the memory.
// Return:
// 0 for failure, 1 for success.
int pdo_sqlsrv_stmt_get_col_data(pdo_stmt_t *stmt, int colno,
char **ptr, size_t *len, int *caller_frees TSRMLS_DC)
int pdo_sqlsrv_stmt_get_col_data( _Inout_ pdo_stmt_t *stmt, _In_ int colno,
_Out_writes_bytes_opt_(*len) char **ptr, _Inout_ size_t *len, _Out_opt_ int *caller_frees TSRMLS_DC)
{
PDO_RESET_STMT_ERROR;
PDO_VALIDATE_STMT;
@ -787,11 +789,12 @@ int pdo_sqlsrv_stmt_get_col_data(pdo_stmt_t *stmt, int colno,
core_sqlsrv_get_field( driver_stmt, colno, sqlsrv_php_type, false, *(reinterpret_cast<void**>(ptr)),
reinterpret_cast<SQLLEN*>( len ), true, &sqlsrv_phptype_out TSRMLS_CC );
zval* zval_ptr = reinterpret_cast<zval*>( sqlsrv_malloc( sizeof( zval )));
*zval_ptr = convert_to_zval( sqlsrv_phptype_out, reinterpret_cast<void**>( ptr ), *len );
*ptr = reinterpret_cast<char*>( zval_ptr );
*len = sizeof( zval );
if ( ptr ) {
zval* zval_ptr = reinterpret_cast<zval*>( sqlsrv_malloc( sizeof( zval )));
*zval_ptr = convert_to_zval( sqlsrv_phptype_out, reinterpret_cast<void**>( ptr ), *len );
*ptr = reinterpret_cast<char*>( zval_ptr );
*len = sizeof( zval );
}
return 1;
}
@ -812,13 +815,14 @@ int pdo_sqlsrv_stmt_get_col_data(pdo_stmt_t *stmt, int colno,
// val - Attribute value.
// Return:
// 0 for failure, 1 for success.
int pdo_sqlsrv_stmt_set_attr(pdo_stmt_t *stmt, zend_long attr, zval *val TSRMLS_DC)
int pdo_sqlsrv_stmt_set_attr( _Inout_ pdo_stmt_t *stmt, _In_ zend_long attr, _Inout_ zval *val TSRMLS_DC)
{
PDO_RESET_STMT_ERROR;
PDO_VALIDATE_STMT;
PDO_LOG_STMT_ENTRY;
pdo_sqlsrv_stmt* driver_stmt = static_cast<pdo_sqlsrv_stmt*>( stmt->driver_data );
SQLSRV_ASSERT( driver_stmt != NULL, "pdo_sqlsrv_stmt_set_attr: driver_data object was null" );
try {
@ -877,7 +881,7 @@ int pdo_sqlsrv_stmt_set_attr(pdo_stmt_t *stmt, zend_long attr, zval *val TSRMLS_
// return_value - Attribute value.
// Return:
// 0 for failure, 1 for success.
int pdo_sqlsrv_stmt_get_attr( pdo_stmt_t *stmt, zend_long attr, zval *return_value TSRMLS_DC )
int pdo_sqlsrv_stmt_get_attr( _Inout_ pdo_stmt_t *stmt, _In_ zend_long attr, _Inout_ zval *return_value TSRMLS_DC )
{
PDO_RESET_STMT_ERROR;
PDO_VALIDATE_STMT;
@ -961,7 +965,7 @@ int pdo_sqlsrv_stmt_get_attr( pdo_stmt_t *stmt, zend_long attr, zval *return_val
// return_value - zval* consisting of the metadata.
// Return:
// 0 for failure, 1 for success.
int pdo_sqlsrv_stmt_get_col_meta(pdo_stmt_t *stmt, zend_long colno, zval *return_value TSRMLS_DC)
int pdo_sqlsrv_stmt_get_col_meta( _Inout_ pdo_stmt_t *stmt, _In_ zend_long colno, _Inout_ zval *return_value TSRMLS_DC)
{
PDO_RESET_STMT_ERROR;
PDO_VALIDATE_STMT;
@ -975,6 +979,7 @@ int pdo_sqlsrv_stmt_get_col_meta(pdo_stmt_t *stmt, zend_long colno, zval *return
sqlsrv_malloc_auto_ptr<field_meta_data> core_meta_data;
sqlsrv_stmt* driver_stmt = static_cast<sqlsrv_stmt*>( stmt->driver_data );
SQLSRV_ASSERT( driver_stmt != NULL, "pdo_sqlsrv_stmt_get_col_meta: stmt->driver_data was null");
SQLSRV_ASSERT( colno >= 0 && colno < stmt->column_count, "pdo_sqlsrv_stmt_get_col_meta: invalid column number." );
@ -1018,7 +1023,7 @@ int pdo_sqlsrv_stmt_get_col_meta(pdo_stmt_t *stmt, zend_long colno, zval *return
&out_buff_len, &field_type_num TSRMLS_CC );
add_assoc_string( return_value, "table", table_name );
if( stmt->columns[ colno ].param_type == PDO_PARAM_ZVAL ) {
if( stmt->columns && stmt->columns[ colno ].param_type == PDO_PARAM_ZVAL ) {
add_assoc_long( return_value, "pdo_type", pdo_type );
}
@ -1048,7 +1053,7 @@ int pdo_sqlsrv_stmt_get_col_meta(pdo_stmt_t *stmt, zend_long colno, zval *return
// stmt - PDOStatement object containing the result set.
// Return:
// 0 for failure, 1 for success.
int pdo_sqlsrv_stmt_next_rowset(pdo_stmt_t *stmt TSRMLS_DC)
int pdo_sqlsrv_stmt_next_rowset( _Inout_ pdo_stmt_t *stmt TSRMLS_DC )
{
PDO_RESET_STMT_ERROR;
PDO_VALIDATE_STMT;
@ -1103,8 +1108,8 @@ int pdo_sqlsrv_stmt_next_rowset(pdo_stmt_t *stmt TSRMLS_DC)
// event_type - Event to bind a parameter
// Return:
// Returns 0 for failure, 1 for success.
int pdo_sqlsrv_stmt_param_hook(pdo_stmt_t *stmt,
struct pdo_bound_param_data *param, enum pdo_param_event event_type TSRMLS_DC)
int pdo_sqlsrv_stmt_param_hook( _Inout_ pdo_stmt_t *stmt,
_Inout_ struct pdo_bound_param_data *param, _In_ enum pdo_param_event event_type TSRMLS_DC)
{
PDO_RESET_STMT_ERROR;
@ -1306,7 +1311,7 @@ int pdo_sqlsrv_stmt_param_hook(pdo_stmt_t *stmt,
// Returns a sqlsrv_phptype for a given SQL Server data type.
sqlsrv_phptype pdo_sqlsrv_stmt::sql_type_to_php_type( SQLINTEGER sql_type, SQLUINTEGER size, bool prefer_string_over_stream )
sqlsrv_phptype pdo_sqlsrv_stmt::sql_type_to_php_type( _In_ SQLINTEGER sql_type, _In_ SQLUINTEGER size, _In_ bool prefer_string_over_stream )
{
sqlsrv_phptype sqlsrv_phptype;
int local_encoding = this->encoding();

View file

@ -3,7 +3,7 @@
//
// Contents: Utility functions used by both connection or statement functions
//
// Microsoft Drivers 4.2 for PHP for SQL Server
// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -43,10 +43,10 @@ char log_msg[ LOG_MSG_SIZE ];
SQLCHAR INTERNAL_FORMAT_ERROR[] = "An internal error occurred. FormatMessage failed writing an error message.";
// Returns a sqlsrv_error for a given error code.
sqlsrv_error_const* get_error_message(unsigned int sqlsrv_error_code);
sqlsrv_error_const* get_error_message( _In_opt_ unsigned int sqlsrv_error_code);
// build the object and throw the PDO exception
void pdo_sqlsrv_throw_exception( sqlsrv_error_const* error TSRMLS_DC );
void pdo_sqlsrv_throw_exception( _In_ sqlsrv_error_const* error TSRMLS_DC );
}
@ -385,8 +385,8 @@ pdo_error PDO_ERRORS[] = {
};
// PDO error handler for the environment context.
bool pdo_sqlsrv_handle_env_error( sqlsrv_context& ctx, unsigned int sqlsrv_error_code, bool warning TSRMLS_DC,
va_list* print_args )
bool pdo_sqlsrv_handle_env_error( _Inout_ sqlsrv_context& ctx, _In_opt_ unsigned int sqlsrv_error_code, _In_opt_ bool warning TSRMLS_DC,
_In_opt_ va_list* print_args )
{
SQLSRV_ASSERT(( ctx != NULL ), "pdo_sqlsrv_handle_env_error: sqlsrv_context was null" );
pdo_dbh_t* dbh = reinterpret_cast<pdo_dbh_t*>( ctx.driver());
@ -428,8 +428,8 @@ bool pdo_sqlsrv_handle_env_error( sqlsrv_context& ctx, unsigned int sqlsrv_error
}
// pdo error handler for the dbh context.
bool pdo_sqlsrv_handle_dbh_error( sqlsrv_context& ctx, unsigned int sqlsrv_error_code, bool warning TSRMLS_DC,
va_list* print_args )
bool pdo_sqlsrv_handle_dbh_error( _Inout_ sqlsrv_context& ctx, _In_opt_ unsigned int sqlsrv_error_code, _In_opt_ bool warning TSRMLS_DC,
_In_opt_ va_list* print_args )
{
pdo_dbh_t* dbh = reinterpret_cast<pdo_dbh_t*>( ctx.driver());
SQLSRV_ASSERT( dbh != NULL, "pdo_sqlsrv_handle_dbh_error: Null dbh passed" );
@ -481,8 +481,8 @@ bool pdo_sqlsrv_handle_dbh_error( sqlsrv_context& ctx, unsigned int sqlsrv_error
}
// PDO error handler for the statement context.
bool pdo_sqlsrv_handle_stmt_error( sqlsrv_context& ctx, unsigned int sqlsrv_error_code, bool warning TSRMLS_DC,
va_list* print_args )
bool pdo_sqlsrv_handle_stmt_error( _Inout_ sqlsrv_context& ctx, _In_opt_ unsigned int sqlsrv_error_code, _In_opt_ bool warning TSRMLS_DC,
_In_opt_ va_list* print_args )
{
pdo_stmt_t* pdo_stmt = reinterpret_cast<pdo_stmt_t*>( ctx.driver());
SQLSRV_ASSERT( pdo_stmt != NULL && pdo_stmt->dbh != NULL, "pdo_sqlsrv_handle_stmt_error: Null statement or dbh passed" );
@ -529,7 +529,7 @@ bool pdo_sqlsrv_handle_stmt_error( sqlsrv_context& ctx, unsigned int sqlsrv_erro
// 1, native message
// 2, SQLSTATE of the error (driver specific error messages are 'IMSSP')
void pdo_sqlsrv_retrieve_context_error( sqlsrv_error const* last_error, zval* pdo_zval )
void pdo_sqlsrv_retrieve_context_error( _In_ sqlsrv_error const* last_error, _Out_ zval* pdo_zval )
{
if( last_error ) {
// SQLSTATE is already present in the zval.
@ -539,7 +539,7 @@ void pdo_sqlsrv_retrieve_context_error( sqlsrv_error const* last_error, zval* pd
}
// Formats the error message and writes to the php error log.
void pdo_sqlsrv_log( unsigned int severity TSRMLS_DC, const char* msg, va_list* print_args )
void pdo_sqlsrv_log( _In_opt_ unsigned int severity TSRMLS_DC, _In_opt_ const char* msg, _In_opt_ va_list* print_args )
{
if( (severity & PDO_SQLSRV_G( log_severity )) == 0 ) {
return;
@ -560,7 +560,7 @@ namespace {
// Workaround for name collision problem between the SQLSRV and PDO_SQLSRV drivers on Mac
// 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* get_error_message( _In_opt_ 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;
@ -573,7 +573,7 @@ sqlsrv_error_const* get_error_message(unsigned int sqlsrv_error_code) {
return error_message;
}
void pdo_sqlsrv_throw_exception( sqlsrv_error_const* error TSRMLS_DC )
void pdo_sqlsrv_throw_exception( _In_ sqlsrv_error_const* error TSRMLS_DC )
{
zval ex_obj;
ZVAL_UNDEF( &ex_obj );

View file

@ -6,7 +6,7 @@
//
// Contents: Declarations for the extension
//
// Microsoft Drivers 4.2 for PHP for SQL Server
// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -137,9 +137,9 @@ class string_parser
HashTable* element_ht;
inline bool next(void);
inline bool is_eos(void);
inline bool is_white_space(char c);
inline bool is_white_space( _In_ char c );
bool discard_white_spaces(void);
void add_key_value_pair(const char* value, int len TSRMLS_DC);
void add_key_value_pair( _In_reads_(len) const char* value, _In_ int len TSRMLS_DC );
};
//*********************************************************************************************************************************
@ -162,14 +162,14 @@ class conn_string_parser : private string_parser
private:
const char* current_key_name;
int discard_trailing_white_spaces(const char* str, int len);
void validate_key(const char *key, int key_len TSRMLS_DC);
int discard_trailing_white_spaces( _In_reads_(len) const char* str, _Inout_ int len );
void validate_key( _In_reads_(key_len) const char *key, _Inout_ int key_len TSRMLS_DC);
protected:
void add_key_value_pair(const char* value, int len TSRMLS_DC);
void add_key_value_pair( _In_reads_(len) const char* value, _In_ int len TSRMLS_DC);
public:
conn_string_parser( sqlsrv_context& ctx, const char* dsn, int len, _Inout_ HashTable* conn_options_ht );
conn_string_parser( _In_ sqlsrv_context& ctx, _In_ const char* dsn, _In_ int len, _In_ HashTable* conn_options_ht );
void parse_conn_string( TSRMLS_D );
};
@ -183,8 +183,8 @@ class sql_string_parser : private string_parser
private:
bool is_placeholder_char(char);
public:
void add_key_int_value_pair(unsigned int value TSRMLS_DC);
sql_string_parser(sqlsrv_context& ctx, const char* sql_str, int len, _Inout_ HashTable* placeholder_ht);
void add_key_int_value_pair( _In_ unsigned int value TSRMLS_DC );
sql_string_parser(_In_ sqlsrv_context& ctx, _In_ const char* sql_str, _In_ int len, _In_ HashTable* placeholder_ht);
void parse_sql_string(TSRMLS_D);
};
@ -193,7 +193,7 @@ class sql_string_parser : private string_parser
//*********************************************************************************************************************************
extern const connection_option PDO_CONN_OPTS[];
int pdo_sqlsrv_db_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC);
int pdo_sqlsrv_db_handle_factory( _Inout_ pdo_dbh_t *dbh, _In_opt_ zval *driver_options TSRMLS_DC);
// a core layer pdo dbh object. This object inherits and overrides the statement factory
struct pdo_sqlsrv_dbh : public sqlsrv_conn {
@ -204,7 +204,7 @@ struct pdo_sqlsrv_dbh : public sqlsrv_conn {
zend_long client_buffer_max_size;
bool fetch_numeric;
pdo_sqlsrv_dbh( SQLHANDLE h, error_callback e, void* driver TSRMLS_DC );
pdo_sqlsrv_dbh( _In_ SQLHANDLE h, _In_ error_callback e, _In_ void* driver TSRMLS_DC );
};
@ -214,31 +214,31 @@ struct pdo_sqlsrv_dbh : public sqlsrv_conn {
struct stmt_option_encoding : public stmt_option_functor {
virtual void operator()( sqlsrv_stmt* stmt, stmt_option const* /*opt*/, zval* value_z TSRMLS_DC );
virtual void operator()( _Inout_ sqlsrv_stmt* stmt, stmt_option const* /*opt*/, _In_ zval* value_z TSRMLS_DC );
};
struct stmt_option_pdo_scrollable : public stmt_option_functor {
virtual void operator()( sqlsrv_stmt* stmt, stmt_option const* /*opt*/, zval* value_z TSRMLS_DC );
virtual void operator()( _Inout_ sqlsrv_stmt* stmt, stmt_option const* /*opt*/, _In_ zval* value_z TSRMLS_DC );
};
struct stmt_option_direct_query : public stmt_option_functor {
virtual void operator()( sqlsrv_stmt* stmt, stmt_option const* /*opt*/, zval* value_z TSRMLS_DC );
virtual void operator()( _Inout_ sqlsrv_stmt* stmt, stmt_option const* /*opt*/, _In_ zval* value_z TSRMLS_DC );
};
struct stmt_option_cursor_scroll_type : public stmt_option_functor {
virtual void operator()( sqlsrv_stmt* stmt, stmt_option const* /*opt*/, zval* value_z TSRMLS_DC );
virtual void operator()( _Inout_ sqlsrv_stmt* stmt, stmt_option const* /*opt*/, _In_ zval* value_z TSRMLS_DC );
};
struct stmt_option_emulate_prepares : public stmt_option_functor {
virtual void operator()( sqlsrv_stmt* stmt, stmt_option const* /*opt*/, zval* value_z TSRMLS_DC );
virtual void operator()( _Inout_ sqlsrv_stmt* stmt, stmt_option const* /*opt*/, _In_ zval* value_z TSRMLS_DC );
};
struct stmt_option_fetch_numeric : public stmt_option_functor {
virtual void operator()( sqlsrv_stmt* stmt, stmt_option const* /*opt*/, zval* value_z TSRMLS_DC );
virtual void operator()( _Inout_ sqlsrv_stmt* stmt, stmt_option const* /*opt*/, _In_ zval* value_z TSRMLS_DC );
};
extern struct pdo_stmt_methods pdo_sqlsrv_stmt_methods;
@ -246,7 +246,7 @@ extern struct pdo_stmt_methods pdo_sqlsrv_stmt_methods;
// a core layer pdo stmt object. This object inherits and overrides the callbacks necessary
struct pdo_sqlsrv_stmt : public sqlsrv_stmt {
pdo_sqlsrv_stmt( sqlsrv_conn* c, SQLHANDLE handle, error_callback e, void* drv TSRMLS_DC ) :
pdo_sqlsrv_stmt( _In_ sqlsrv_conn* c, _In_ SQLHANDLE handle, _In_ error_callback e, _In_ void* drv TSRMLS_DC ) :
sqlsrv_stmt( c, handle, e, drv TSRMLS_CC ),
direct_query( false ),
direct_query_subst_string( NULL ),
@ -264,7 +264,7 @@ struct pdo_sqlsrv_stmt : public sqlsrv_stmt {
// driver specific conversion rules from a SQL Server/ODBC type to one of the SQLSRV_PHPTYPE_* constants
// for PDO, everything is a string, so we return SQLSRV_PHPTYPE_STRING for all SQL types
virtual sqlsrv_phptype sql_type_to_php_type( SQLINTEGER sql_type, SQLUINTEGER size, bool prefer_string_to_stream );
virtual sqlsrv_phptype sql_type_to_php_type( _In_ SQLINTEGER sql_type, _In_ SQLUINTEGER size, _In_ bool prefer_string_to_stream );
bool direct_query; // flag set if the query should be executed directly or prepared
const char* direct_query_subst_string; // if the query is direct, hold the substitution string if using named parameters
@ -292,18 +292,18 @@ struct pdo_error {
// called when an error occurs in the core layer. These routines are set as the error_callback in a
// context. The context is passed to this function since it contains the function
bool pdo_sqlsrv_handle_env_error( sqlsrv_context& ctx, unsigned int sqlsrv_error_code, bool warning TSRMLS_DC,
va_list* print_args );
bool pdo_sqlsrv_handle_dbh_error( sqlsrv_context& ctx, unsigned int sqlsrv_error_code, bool warning TSRMLS_DC,
va_list* print_args );
bool pdo_sqlsrv_handle_stmt_error( sqlsrv_context& ctx, unsigned int sqlsrv_error_code, bool warning TSRMLS_DC,
va_list* print_args );
bool pdo_sqlsrv_handle_env_error( _Inout_ sqlsrv_context& ctx, _In_opt_ unsigned int sqlsrv_error_code, _In_opt_ bool warning TSRMLS_DC,
_In_opt_ va_list* print_args );
bool pdo_sqlsrv_handle_dbh_error( _Inout_ sqlsrv_context& ctx, _In_opt_ unsigned int sqlsrv_error_code, _In_opt_ bool warning TSRMLS_DC,
_In_opt_ va_list* print_args );
bool pdo_sqlsrv_handle_stmt_error( _Inout_ sqlsrv_context& ctx, _In_opt_ unsigned int sqlsrv_error_code, _In_opt_ bool warning TSRMLS_DC,
_In_opt_ va_list* print_args );
// common routine to transfer a sqlsrv_context's error to a PDO zval
void pdo_sqlsrv_retrieve_context_error( sqlsrv_error const* last_error, zval* pdo_zval );
void pdo_sqlsrv_retrieve_context_error( _In_ sqlsrv_error const* last_error, _Out_ zval* pdo_zval );
// reset the errors from the last operation
inline void pdo_reset_dbh_error( pdo_dbh_t* dbh TSRMLS_DC )
inline void pdo_reset_dbh_error( _Inout_ pdo_dbh_t* dbh TSRMLS_DC )
{
strcpy_s( dbh->error_code, sizeof( dbh->error_code ), "00000" ); // 00000 means no error
@ -328,7 +328,7 @@ inline void pdo_reset_dbh_error( pdo_dbh_t* dbh TSRMLS_DC )
#define PDO_RESET_DBH_ERROR pdo_reset_dbh_error( dbh TSRMLS_CC );
inline void pdo_reset_stmt_error( pdo_stmt_t* stmt )
inline void pdo_reset_stmt_error( _Inout_ pdo_stmt_t* stmt )
{
strcpy_s( stmt->error_code, sizeof( stmt->error_code ), "00000" ); // 00000 means no error
@ -415,7 +415,7 @@ namespace pdo {
} // namespace pdo
// logger for pdo_sqlsrv called by the core layer when it wants to log something with the LOG macro
void pdo_sqlsrv_log( unsigned int severity TSRMLS_DC, const char* msg, va_list* print_args );
void pdo_sqlsrv_log( _In_opt_ unsigned int severity TSRMLS_DC, _In_opt_ const char* msg, _In_opt_ va_list* print_args );
#endif /* PHP_PDO_SQLSRV_H */

View file

@ -3,7 +3,7 @@
//
// Contents: Version resource
//
// Microsoft Drivers 4.2 for PHP for SQL Server
// Microsoft Drivers 4.3 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.2 for PHP for SQL Server
// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License

View file

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

View file

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

View file

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

View file

@ -3,7 +3,7 @@
//
// Contents: Core routines that use connection handles shared between sqlsrv and pdo_sqlsrv
//
// Microsoft Drivers 4.1 for PHP for SQL Server
// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -63,14 +63,14 @@ const char CONNECTION_OPTION_MARS_ON[] = "MARS_Connection={Yes};";
// *** internal function prototypes ***
void build_connection_string_and_set_conn_attr( sqlsrv_conn* conn, const char* server, const char* uid, const char* pwd,
HashTable* options_ht, const connection_option valid_conn_opts[],
void build_connection_string_and_set_conn_attr( _Inout_ sqlsrv_conn* conn, _Inout_z_ const char* server, _Inout_opt_z_ const char* uid, _Inout_opt_z_ const char* pwd,
_Inout_opt_ HashTable* options_ht, _In_ const connection_option valid_conn_opts[],
void* driver,_Inout_ std::string& connection_string TSRMLS_DC );
void determine_server_version( sqlsrv_conn* conn TSRMLS_DC );
void determine_server_version( _Inout_ sqlsrv_conn* conn TSRMLS_DC );
const char* get_processor_arch( void );
void get_server_version( sqlsrv_conn* conn, char** server_version, SQLSMALLINT& len TSRMLS_DC );
connection_option const* get_connection_option( sqlsrv_conn* conn, const char* key, SQLULEN key_len TSRMLS_DC );
void common_conn_str_append_func( const char* odbc_name, const char* val, size_t val_len, std::string& conn_str TSRMLS_DC );
void get_server_version( _Inout_ sqlsrv_conn* conn, _Outptr_result_buffer_(len) char** server_version, _Out_ SQLSMALLINT& len TSRMLS_DC );
connection_option const* get_connection_option( sqlsrv_conn* conn, _In_ const char* key, _In_ SQLULEN key_len TSRMLS_DC );
void common_conn_str_append_func( _In_z_ const char* odbc_name, _In_reads_(val_len) const char* val, _Inout_ size_t val_len, _Inout_ std::string& conn_str TSRMLS_DC );
}
@ -89,10 +89,10 @@ void common_conn_str_append_func( const char* odbc_name, const char* val, size_t
// Return
// A sqlsrv_conn structure. An exception is thrown if an error occurs
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 )
sqlsrv_conn* core_sqlsrv_connect( _In_ sqlsrv_context& henv_cp, _In_ sqlsrv_context& henv_ncp, _In_ driver_conn_factory conn_factory,
_Inout_z_ const char* server, _Inout_opt_z_ const char* uid, _Inout_opt_z_ const char* pwd,
_Inout_opt_ HashTable* options_ht, _In_ error_callback err, _In_ const connection_option valid_conn_opts[],
_In_ void* driver, _In_z_ const char* driver_func TSRMLS_DC )
{
SQLRETURN r;
@ -181,16 +181,16 @@ sqlsrv_conn* core_sqlsrv_connect( sqlsrv_context& henv_cp, sqlsrv_context& henv_
memset( const_cast<char*>(conn_str.c_str()), 0, conn_str.size());
memset( wconn_string, 0, wconn_len * sizeof( SQLWCHAR )); // wconn_len is the number of characters, not bytes
conn_str.clear();
if (!SQL_SUCCEEDED(r)) {
if ( !SQL_SUCCEEDED( r )) {
SQLCHAR state[SQL_SQLSTATE_BUFSIZE];
SQLSMALLINT len;
SQLRETURN r = SQLGetDiagField(SQL_HANDLE_DBC, conn->handle(), 1, SQL_DIAG_SQLSTATE, state, SQL_SQLSTATE_BUFSIZE, &len);
bool missing_driver_error = (SQL_SUCCEEDED(r) && state[0] == 'I' && state[1] == 'M' && state[2] == '0' && state[3] == '0' && state[4] == '2');
SQLRETURN sr = SQLGetDiagField( SQL_HANDLE_DBC, conn->handle(), 1, SQL_DIAG_SQLSTATE, state, SQL_SQLSTATE_BUFSIZE, &len );
bool missing_driver_error = ( SQL_SUCCEEDED( sr ) && state[0] == 'I' && state[1] == 'M' && state[2] == '0' && state[3] == '0' && state[4] == '2' );
// if it's a IM002, meaning that the correct ODBC driver is not installed
CHECK_CUSTOM_ERROR(missing_driver_error && (i == DRIVER_VERSION::MAX), conn, SQLSRV_ERROR_DRIVER_NOT_INSTALLED, get_processor_arch()) {
CHECK_CUSTOM_ERROR(missing_driver_error && ( i == DRIVER_VERSION::MAX ), conn, SQLSRV_ERROR_DRIVER_NOT_INSTALLED, get_processor_arch()) {
throw core::CoreException();
}
if (!missing_driver_error) {
if ( !missing_driver_error ) {
break;
}
}
@ -268,7 +268,7 @@ sqlsrv_conn* core_sqlsrv_connect( sqlsrv_context& henv_cp, sqlsrv_context& henv_
// Parameters:
// sqlsrv_conn*: The connection with which the transaction is associated.
void core_sqlsrv_begin_transaction( sqlsrv_conn* conn TSRMLS_DC )
void core_sqlsrv_begin_transaction( _Inout_ sqlsrv_conn* conn TSRMLS_DC )
{
try {
@ -291,7 +291,7 @@ void core_sqlsrv_begin_transaction( sqlsrv_conn* conn TSRMLS_DC )
// Parameters:
// sqlsrv_conn*: The connection on which the transaction is active.
void core_sqlsrv_commit( sqlsrv_conn* conn TSRMLS_DC )
void core_sqlsrv_commit( _Inout_ sqlsrv_conn* conn TSRMLS_DC )
{
try {
@ -316,7 +316,7 @@ void core_sqlsrv_commit( sqlsrv_conn* conn TSRMLS_DC )
// Parameters:
// sqlsrv_conn*: The connection on which the transaction is active.
void core_sqlsrv_rollback( sqlsrv_conn* conn TSRMLS_DC )
void core_sqlsrv_rollback( _Inout_ sqlsrv_conn* conn TSRMLS_DC )
{
try {
@ -337,7 +337,7 @@ void core_sqlsrv_rollback( sqlsrv_conn* conn TSRMLS_DC )
// Called when a connection resource is destroyed by the Zend engine.
// Parameters:
// conn - The current active connection.
void core_sqlsrv_close( sqlsrv_conn* conn TSRMLS_DC )
void core_sqlsrv_close( _Inout_opt_ sqlsrv_conn* conn TSRMLS_DC )
{
// if the connection wasn't successful, just return.
if( conn == NULL )
@ -371,7 +371,7 @@ void core_sqlsrv_close( sqlsrv_conn* conn TSRMLS_DC )
// sql - T-SQL command to prepare
// sql_len - length of the T-SQL string
void core_sqlsrv_prepare( sqlsrv_stmt* stmt, const char* sql, SQLLEN sql_len TSRMLS_DC )
void core_sqlsrv_prepare( _Inout_ sqlsrv_stmt* stmt, _In_reads_bytes_(sql_len) const char* sql, _In_ SQLLEN sql_len TSRMLS_DC )
{
try {
@ -414,7 +414,7 @@ void core_sqlsrv_prepare( sqlsrv_stmt* stmt, const char* sql, SQLLEN sql_len TSR
// conn - The connection resource by which the client and server are connected.
// *server_version - zval for returning results.
void core_sqlsrv_get_server_version( sqlsrv_conn* conn, _Out_ zval *server_version TSRMLS_DC )
void core_sqlsrv_get_server_version( _Inout_ sqlsrv_conn* conn, _Inout_ zval* server_version TSRMLS_DC )
{
try {
@ -441,7 +441,7 @@ void core_sqlsrv_get_server_version( sqlsrv_conn* conn, _Out_ zval *server_versi
// conn - The connection resource by which the client and server are connected.
// *server_info - zval for returning results.
void core_sqlsrv_get_server_info( sqlsrv_conn* conn, _Out_ zval *server_info TSRMLS_DC )
void core_sqlsrv_get_server_info( _Inout_ sqlsrv_conn* conn, _Out_ zval *server_info TSRMLS_DC )
{
try {
@ -481,7 +481,7 @@ void core_sqlsrv_get_server_info( sqlsrv_conn* conn, _Out_ zval *server_info TSR
// conn - The connection resource by which the client and server are connected.
// *client_info - zval for returning the results.
void core_sqlsrv_get_client_info( sqlsrv_conn* conn, _Out_ zval *client_info TSRMLS_DC )
void core_sqlsrv_get_client_info( _Inout_ sqlsrv_conn* conn, _Out_ zval *client_info TSRMLS_DC )
{
try {
@ -527,7 +527,7 @@ void core_sqlsrv_get_client_info( sqlsrv_conn* conn, _Out_ zval *client_info TSR
// Properly escaped means that any '}' should be escaped by a prior '}'. It is assumed that
// the value will be surrounded by { and } by the caller after it has been validated
bool core_is_conn_opt_value_escaped( const char* value, size_t value_len )
bool core_is_conn_opt_value_escaped( _Inout_ const char* value, _Inout_ size_t value_len )
{
// if the value is already quoted, then only analyse the part inside the quotes and return it as
// unquoted since we quote it when adding it to the connection string.
@ -552,7 +552,7 @@ bool core_is_conn_opt_value_escaped( const char* value, size_t value_len )
// 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)
bool core_is_authentication_option_valid( _In_z_ const char* value, _In_ size_t value_len)
{
if (value_len <= 0)
return false;
@ -569,8 +569,8 @@ bool core_is_authentication_option_valid(const char* value, size_t value_len)
namespace {
connection_option const* get_connection_option( sqlsrv_conn* conn, SQLULEN key,
const connection_option conn_opts[] TSRMLS_DC )
connection_option const* get_connection_option( sqlsrv_conn* conn, _In_ SQLULEN key,
_In_ const connection_option conn_opts[] TSRMLS_DC )
{
for( int opt_idx = 0; conn_opts[ opt_idx ].conn_option_key != SQLSRV_CONN_OPTION_INVALID; ++opt_idx ) {
@ -589,9 +589,9 @@ connection_option const* get_connection_option( sqlsrv_conn* conn, SQLULEN key,
// passed to the connection, and then break them out ourselves and either set attributes or put the
// option in the connection string.
void build_connection_string_and_set_conn_attr( sqlsrv_conn* conn, const char* server, const char* uid, const char* pwd,
HashTable* options, const connection_option valid_conn_opts[],
void* driver,_Inout_ std::string& connection_string TSRMLS_DC )
void build_connection_string_and_set_conn_attr( _Inout_ sqlsrv_conn* conn, _Inout_z_ const char* server, _Inout_opt_z_ const char* uid, _Inout_opt_z_ const char* pwd,
_Inout_opt_ HashTable* options, _In_ const connection_option valid_conn_opts[],
void* driver, _Inout_ std::string& connection_string TSRMLS_DC )
{
bool mars_mentioned = false;
connection_option const* conn_opt;
@ -682,7 +682,7 @@ void build_connection_string_and_set_conn_attr( sqlsrv_conn* conn, const char* s
// get_server_version
// Helper function which returns the version of the SQL Server we are connected to.
void get_server_version( sqlsrv_conn* conn, char** server_version, SQLSMALLINT& len TSRMLS_DC )
void get_server_version( _Inout_ sqlsrv_conn* conn, _Outptr_result_buffer_(len) char** server_version, _Out_ SQLSMALLINT& len TSRMLS_DC )
{
try {
@ -752,7 +752,7 @@ const char* get_processor_arch( void )
// Exception is thrown when the server version is either undetermined
// or is invalid (< 2000).
void determine_server_version( sqlsrv_conn* conn TSRMLS_DC )
void determine_server_version( _Inout_ sqlsrv_conn* conn TSRMLS_DC )
{
SQLSMALLINT info_len;
char p[ INFO_BUFFER_LEN ];
@ -776,7 +776,7 @@ void determine_server_version( sqlsrv_conn* conn TSRMLS_DC )
conn->server_version = version_major;
}
void common_conn_str_append_func( const char* odbc_name, const char* val, size_t val_len, std::string& conn_str TSRMLS_DC )
void common_conn_str_append_func( _In_z_ const char* odbc_name, _In_reads_(val_len) const char* val, _Inout_ size_t val_len, _Inout_ std::string& conn_str TSRMLS_DC )
{
// wrap a connection option in a quote. It is presumed that any character that need to be escaped will
// be escaped, such as a closing }.
@ -795,7 +795,7 @@ void common_conn_str_append_func( const char* odbc_name, const char* val, size_t
} // namespace
// simply add the parsed value to the connection string
void conn_str_append_func::func( connection_option const* option, zval* value, sqlsrv_conn* /*conn*/, std::string& conn_str
void conn_str_append_func::func( _In_ connection_option const* option, _In_ zval* value, sqlsrv_conn* /*conn*/, _Inout_ std::string& conn_str
TSRMLS_DC )
{
const char* val_str = Z_STRVAL_P( value );
@ -815,7 +815,7 @@ void conn_null_func::func( connection_option const* /*option*/, zval* /*value*/,
// Values = ("true" or "1") are treated as true values. Everything else is treated as false.
// Returns 1 for true and 0 for false.
size_t core_str_zval_is_true( zval* value_z )
size_t core_str_zval_is_true( _Inout_ zval* value_z )
{
SQLSRV_ASSERT( Z_TYPE_P( value_z ) == IS_STRING, "core_str_zval_is_true: This function only accepts zval of type string." );
@ -824,7 +824,7 @@ size_t core_str_zval_is_true( zval* value_z )
// strip any whitespace at the end (whitespace is the same value in ASCII and UTF-8)
size_t last_char = val_len - 1;
while( isspace( value_in[ last_char ] )) {
while( isspace(( unsigned char )value_in[ last_char ] )) {
value_in[ last_char ] = '\0';
val_len = last_char;
--last_char;

View file

@ -3,7 +3,7 @@
//
// Contents: common initialization routines shared by PDO and sqlsrv
//
// Microsoft Drivers 4.1 for PHP for SQL Server
// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -19,10 +19,9 @@
#include "core_sqlsrv.h"
// module global variables (initialized in minit and freed in mshutdown)
HMODULE g_sqlsrv_hmodule = NULL;
OSVERSIONINFO g_osversion;
bool isVistaOrGreater;
// core_sqlsrv_minit
@ -35,7 +34,7 @@ OSVERSIONINFO g_osversion;
// henv_cp - Environment handle for pooled connection.
// henv_ncp - Environment handle for non-pooled connection.
// err - Driver specific error handler which handles any errors during initialization.
void core_sqlsrv_minit( sqlsrv_context** henv_cp, sqlsrv_context** henv_ncp, error_callback err, const char* driver_func TSRMLS_DC )
void core_sqlsrv_minit( _Outptr_ sqlsrv_context** henv_cp, _Inout_ sqlsrv_context** henv_ncp, _In_ error_callback err, _In_z_ const char* driver_func TSRMLS_DC )
{
SQLSRV_STATIC_ASSERT( sizeof( sqlsrv_sqltype ) == sizeof( zend_long ) );
SQLSRV_STATIC_ASSERT( sizeof( sqlsrv_phptype ) == sizeof( zend_long ));
@ -47,12 +46,7 @@ void core_sqlsrv_minit( sqlsrv_context** henv_cp, sqlsrv_context** henv_ncp, err
#ifdef _WIN32
// get the version of the OS we're running on. For now this governs certain flags used by
// WideCharToMultiByte. It might be relevant to other things in the future.
g_osversion.dwOSVersionInfoSize = sizeof( g_osversion );
BOOL ver_return = GetVersionEx( &g_osversion );
if( !ver_return ) {
LOG( SEV_ERROR, "Failed to retrieve Windows version information." );
throw core::CoreException();
}
isVistaOrGreater = IsWindowsVistaOrGreater( );
#endif //_WIN32
SQLHANDLE henv = SQL_NULL_HANDLE;
@ -142,7 +136,7 @@ void core_sqlsrv_minit( sqlsrv_context** henv_cp, sqlsrv_context** henv_ncp, err
// Parameters:
// henv_cp - Pooled environment handle.
// henv_ncp - Non-pooled environment handle.
void core_sqlsrv_mshutdown( sqlsrv_context& henv_cp, sqlsrv_context& henv_ncp )
void core_sqlsrv_mshutdown( _Inout_ sqlsrv_context& henv_cp, _Inout_ sqlsrv_context& henv_ncp )
{
if( henv_ncp != SQL_NULL_HANDLE ) {
@ -162,7 +156,7 @@ void core_sqlsrv_mshutdown( sqlsrv_context& henv_cp, sqlsrv_context& henv_ncp )
// DllMain for the extension.
#ifdef _WIN32
BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID )
BOOL WINAPI DllMain( _In_ HINSTANCE hinstDLL, _In_ DWORD fdwReason, LPVOID )
{
switch( fdwReason ) {
case DLL_PROCESS_ATTACH:

View file

@ -3,7 +3,7 @@
//
// Contents: Result sets
//
// Microsoft Drivers 4.1 for PHP for SQL Server
// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -51,7 +51,7 @@ const int INITIAL_FIELD_STRING_LEN = 256; // base allocation size when retrie
// return an integral type rounded up to a certain number
template <int align, typename T>
T align_to( T number )
T align_to( _In_ T number )
{
DEBUG_SQLSRV_ASSERT( (number + align) > number, "Number to align overflowed" );
return ((number % align) == 0) ? number : (number + align - (number % align));
@ -59,14 +59,14 @@ T align_to( T number )
// return a pointer address aligned to a certain address boundary
template <int align, typename T>
T* align_to( T* ptr )
T* align_to( _In_ T* ptr )
{
size_t p_value = (size_t) ptr;
return align_to<align, size_t>( p_value );
}
// set the nth bit of the bitstream starting at ptr
void set_bit( void* ptr, unsigned int bit )
void set_bit( _In_ void* ptr, _In_ unsigned int bit )
{
unsigned char* null_bits = reinterpret_cast<unsigned char*>( ptr );
null_bits += bit >> 3;
@ -74,7 +74,7 @@ void set_bit( void* ptr, unsigned int bit )
}
// retrieve the nth bit from the bitstream starting at ptr
bool get_bit( void* ptr, unsigned int bit )
bool get_bit( _In_ void* ptr, _In_ unsigned int bit )
{
unsigned char* null_bits = reinterpret_cast<unsigned char*>( ptr );
null_bits += bit >> 3;
@ -82,13 +82,13 @@ bool get_bit( void* ptr, unsigned int bit )
}
// read in LOB field during buffered result creation
SQLPOINTER read_lob_field( sqlsrv_stmt* stmt, SQLUSMALLINT field_index, sqlsrv_buffered_result_set::meta_data& meta,
zend_long mem_used TSRMLS_DC );
SQLPOINTER read_lob_field( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT field_index, _In_ sqlsrv_buffered_result_set::meta_data& meta,
_In_ zend_long mem_used TSRMLS_DC );
// dtor for each row in the cache
void cache_row_dtor(zval* data);
void cache_row_dtor( _In_ zval* data );
size_t get_float_precision(SQLLEN buffer_length, size_t unitsize)
size_t get_float_precision( _In_ SQLLEN buffer_length, _In_ size_t unitsize)
{
SQLSRV_ASSERT(unitsize != 0, "Invalid unit size!");
@ -121,7 +121,7 @@ size_t get_float_precision(SQLLEN buffer_length, size_t unitsize)
#ifndef _WIN32
// copy the number into a char string using the num_put facet
template <typename Number>
SQLRETURN get_string_from_stream( Number number_data, std::basic_string<char> &str_num, size_t precision, sqlsrv_error_auto_ptr& last_error)
SQLRETURN get_string_from_stream( _In_ Number number_data, _Out_ std::basic_string<char> &str_num, _In_ size_t precision, _Out_ sqlsrv_error_auto_ptr& last_error)
{
//std::locale loc( std::locale(""), new std::num_put<char> ); // By default, SQL Server doesn't take user's locale into consideration
std::locale loc;
@ -144,7 +144,7 @@ SQLRETURN get_string_from_stream( Number number_data, std::basic_string<char> &s
// copy the Char string into the output buffer - check first that it will fit
template <typename Char>
SQLRETURN copy_buffer( _Out_ void* buffer, SQLLEN buffer_length, _Out_ SQLLEN* out_buffer_length, std::basic_string<Char> &str, sqlsrv_error_auto_ptr& last_error )
SQLRETURN copy_buffer( _Out_writes_bytes_to_opt_(out_buffer_lenth, out_buffer_length) void* buffer, _In_ SQLLEN buffer_length, _Out_ SQLLEN* out_buffer_length, _In_reads_bytes_opt_(out_buffer_length) std::basic_string<Char> &str, _Out_ sqlsrv_error_auto_ptr& last_error )
{
*out_buffer_length = str.size() * sizeof( Char ); // NULL terminator is provided subsequently
@ -163,7 +163,7 @@ SQLRETURN copy_buffer( _Out_ void* buffer, SQLLEN buffer_length, _Out_ SQLLEN* o
// There is an extra copy here, but given the size is short (usually <20 bytes) and the complications of
// subclassing a new streambuf just to avoid the copy, it's easier to do the copy
template <typename Char, typename Number>
SQLRETURN number_to_string( Number* number_data, _Out_ void* buffer, SQLLEN buffer_length, _Out_ SQLLEN* out_buffer_length, sqlsrv_error_auto_ptr& last_error )
SQLRETURN number_to_string( _In_ Number* number_data, _Out_writes_bytes_to_opt_(buffer_length, *out_buffer_length) void* buffer, _In_ SQLLEN buffer_length, _Inout_ SQLLEN* out_buffer_length, _Inout_ sqlsrv_error_auto_ptr& last_error )
{
size_t precision = 0;
@ -239,7 +239,7 @@ SQLRETURN number_to_string( Number* number_data, _Out_ void* buffer, SQLLEN buff
#ifndef _WIN32
std::string getUTF8StringFromString( const SQLWCHAR* source )
std::string getUTF8StringFromString( _In_z_ const SQLWCHAR* source )
{
// convert to regular character string first
char c_str[4] = "";
@ -262,7 +262,7 @@ std::string getUTF8StringFromString( const SQLWCHAR* source )
}
std::string getUTF8StringFromString( const char* source )
std::string getUTF8StringFromString( _In_z_ const char* source )
{
return std::string( source );
}
@ -270,8 +270,8 @@ std::string getUTF8StringFromString( const char* source )
#endif // !_WIN32
template <typename Number, typename Char>
SQLRETURN string_to_number( Char* string_data, SQLLEN str_len, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ SQLLEN* out_buffer_length, sqlsrv_error_auto_ptr& last_error )
SQLRETURN string_to_number( _In_z_ Char* string_data, SQLLEN str_len, _Out_writes_bytes_(*out_buffer_length) void* buffer, SQLLEN buffer_length,
_Inout_ SQLLEN* out_buffer_length, _Inout_ sqlsrv_error_auto_ptr& last_error )
{
Number* number_data = reinterpret_cast<Number*>( buffer );
#ifdef _WIN32
@ -333,13 +333,13 @@ struct row_dtor_closure {
sqlsrv_buffered_result_set* results;
BYTE* row_data;
row_dtor_closure( sqlsrv_buffered_result_set* st, BYTE* row ) :
row_dtor_closure( _In_ sqlsrv_buffered_result_set* st, _In_ BYTE* row ) :
results( st ), row_data( row )
{
}
};
sqlsrv_error* odbc_get_diag_rec( sqlsrv_stmt* odbc, SQLSMALLINT record_number )
sqlsrv_error* odbc_get_diag_rec( _In_ sqlsrv_stmt* odbc, _In_ SQLSMALLINT record_number )
{
SQLWCHAR wsql_state[ SQL_SQLSTATE_BUFSIZE ];
SQLWCHAR wnative_message[ SQL_MAX_MESSAGE_LENGTH + 1 ];
@ -379,7 +379,7 @@ sqlsrv_error* odbc_get_diag_rec( sqlsrv_stmt* odbc, SQLSMALLINT record_number )
// base class result set
sqlsrv_result_set::sqlsrv_result_set( sqlsrv_stmt* stmt ) :
sqlsrv_result_set::sqlsrv_result_set( _In_ sqlsrv_stmt* stmt ) :
odbc( stmt )
{
}
@ -388,7 +388,7 @@ sqlsrv_result_set::sqlsrv_result_set( sqlsrv_stmt* stmt ) :
// ODBC result set
// This object simply wraps ODBC function calls
sqlsrv_odbc_result_set::sqlsrv_odbc_result_set( sqlsrv_stmt* stmt ) :
sqlsrv_odbc_result_set::sqlsrv_odbc_result_set( _In_ sqlsrv_stmt* stmt ) :
sqlsrv_result_set( stmt )
{
}
@ -397,30 +397,30 @@ sqlsrv_odbc_result_set::~sqlsrv_odbc_result_set( void )
{
}
SQLRETURN sqlsrv_odbc_result_set::fetch( SQLSMALLINT orientation, SQLLEN offset TSRMLS_DC )
SQLRETURN sqlsrv_odbc_result_set::fetch( _In_ SQLSMALLINT orientation, _In_ SQLLEN offset TSRMLS_DC )
{
SQLSRV_ASSERT( odbc != NULL, "Invalid statement handle" );
return core::SQLFetchScroll( odbc, orientation, offset TSRMLS_CC );
}
SQLRETURN sqlsrv_odbc_result_set::get_data( SQLUSMALLINT field_index, SQLSMALLINT target_type,
_Out_ SQLPOINTER buffer, SQLLEN buffer_length, _Out_ SQLLEN* out_buffer_length,
bool handle_warning TSRMLS_DC )
SQLRETURN sqlsrv_odbc_result_set::get_data( _In_ SQLUSMALLINT field_index, _In_ SQLSMALLINT target_type,
_Out_writes_opt_(buffer_length) SQLPOINTER buffer, _In_ SQLLEN buffer_length, _Inout_ SQLLEN* out_buffer_length,
_In_ bool handle_warning TSRMLS_DC )
{
SQLSRV_ASSERT( odbc != NULL, "Invalid statement handle" );
return core::SQLGetData( odbc, field_index, target_type, buffer, buffer_length, out_buffer_length, handle_warning TSRMLS_CC );
}
SQLRETURN sqlsrv_odbc_result_set::get_diag_field( SQLSMALLINT record_number, SQLSMALLINT diag_identifier,
_Out_ SQLPOINTER diag_info_buffer, SQLSMALLINT buffer_length,
_Out_ SQLSMALLINT* out_buffer_length TSRMLS_DC )
SQLRETURN sqlsrv_odbc_result_set::get_diag_field( _In_ SQLSMALLINT record_number, _In_ SQLSMALLINT diag_identifier,
_Inout_updates_(buffer_length) SQLPOINTER diag_info_buffer, _In_ SQLSMALLINT buffer_length,
_Inout_ SQLSMALLINT* out_buffer_length TSRMLS_DC )
{
SQLSRV_ASSERT( odbc != NULL, "Invalid statement handle" );
return core::SQLGetDiagField( odbc, record_number, diag_identifier, diag_info_buffer, buffer_length,
out_buffer_length TSRMLS_CC );
}
sqlsrv_error* sqlsrv_odbc_result_set::get_diag_rec( SQLSMALLINT record_number )
sqlsrv_error* sqlsrv_odbc_result_set::get_diag_rec( _In_ SQLSMALLINT record_number )
{
SQLSRV_ASSERT( odbc != NULL, "Invalid statement handle" );
return odbc_get_diag_rec( odbc, record_number );
@ -436,7 +436,7 @@ SQLLEN sqlsrv_odbc_result_set::row_count( TSRMLS_D )
// Buffered result set
// This class holds a result set in memory
sqlsrv_buffered_result_set::sqlsrv_buffered_result_set( sqlsrv_stmt* stmt TSRMLS_DC ) :
sqlsrv_buffered_result_set::sqlsrv_buffered_result_set( _Inout_ sqlsrv_stmt* stmt TSRMLS_DC ) :
sqlsrv_result_set( stmt ),
cache(NULL),
col_count(0),
@ -770,7 +770,7 @@ sqlsrv_buffered_result_set::~sqlsrv_buffered_result_set( void )
}
}
SQLRETURN sqlsrv_buffered_result_set::fetch( SQLSMALLINT orientation, SQLLEN offset TSRMLS_DC )
SQLRETURN sqlsrv_buffered_result_set::fetch( _Inout_ SQLSMALLINT orientation, _Inout_opt_ SQLLEN offset TSRMLS_DC )
{
last_error = NULL;
last_field_index = -1;
@ -823,8 +823,8 @@ SQLRETURN sqlsrv_buffered_result_set::fetch( SQLSMALLINT orientation, SQLLEN off
return SQL_SUCCESS;
}
SQLRETURN sqlsrv_buffered_result_set::get_data( SQLUSMALLINT field_index, SQLSMALLINT target_type,
_Out_ SQLPOINTER buffer, SQLLEN buffer_length, _Out_ SQLLEN* out_buffer_length,
SQLRETURN sqlsrv_buffered_result_set::get_data( _In_ SQLUSMALLINT field_index, _In_ SQLSMALLINT target_type,
_Out_writes_bytes_opt_(buffer_length) SQLPOINTER buffer, _In_ SQLLEN buffer_length, _Inout_ SQLLEN* out_buffer_length,
bool handle_warning TSRMLS_DC )
{
last_error = NULL;
@ -857,9 +857,9 @@ SQLRETURN sqlsrv_buffered_result_set::get_data( SQLUSMALLINT field_index, SQLSMA
out_buffer_length );
}
SQLRETURN sqlsrv_buffered_result_set::get_diag_field( SQLSMALLINT record_number, SQLSMALLINT diag_identifier,
_Out_ SQLPOINTER diag_info_buffer, SQLSMALLINT buffer_length,
_Out_ SQLSMALLINT* out_buffer_length TSRMLS_DC )
SQLRETURN sqlsrv_buffered_result_set::get_diag_field( _In_ SQLSMALLINT record_number, _In_ SQLSMALLINT diag_identifier,
_Inout_updates_(buffer_length) SQLPOINTER diag_info_buffer, _In_ SQLSMALLINT buffer_length,
_Inout_ SQLSMALLINT* out_buffer_length TSRMLS_DC )
{
SQLSRV_ASSERT( record_number == 1, "Only record number 1 can be fetched by sqlsrv_buffered_result_set::get_diag_field" );
SQLSRV_ASSERT( diag_identifier == SQL_DIAG_SQLSTATE,
@ -889,7 +889,7 @@ unsigned char* sqlsrv_buffered_result_set::get_row( void )
return cl_ptr->row_data;
}
sqlsrv_error* sqlsrv_buffered_result_set::get_diag_rec( SQLSMALLINT record_number )
sqlsrv_error* sqlsrv_buffered_result_set::get_diag_rec( _In_ SQLSMALLINT record_number )
{
// we only hold a single error if there is one, otherwise return the ODBC error(s)
if( last_error == 0 ) {
@ -918,9 +918,9 @@ SQLLEN sqlsrv_buffered_result_set::row_count( TSRMLS_D )
// private functions
template <typename Char>
SQLRETURN binary_to_string( SQLCHAR* field_data, SQLLEN& read_so_far, _Out_ void* buffer,
SQLLEN buffer_length, _Out_ SQLLEN* out_buffer_length,
sqlsrv_error_auto_ptr& out_error )
SQLRETURN binary_to_string( _Inout_ SQLCHAR* field_data, _Inout_ SQLLEN& read_so_far, _Out_writes_z_(*out_buffer_length) void* buffer,
_In_ SQLLEN buffer_length, _Inout_ SQLLEN* out_buffer_length,
_Inout_ sqlsrv_error_auto_ptr& out_error )
{
// hex characters for the conversion loop below
static char hex_chars[] = "0123456789ABCDEF";
@ -979,8 +979,8 @@ SQLRETURN binary_to_string( SQLCHAR* field_data, SQLLEN& read_so_far, _Out_ voi
return r;
}
SQLRETURN sqlsrv_buffered_result_set::binary_to_system_string( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ SQLLEN* out_buffer_length )
SQLRETURN sqlsrv_buffered_result_set::binary_to_system_string( _In_ SQLSMALLINT field_index, _Out_writes_z_(*out_buffer_length) void* buffer, _In_ SQLLEN buffer_length,
_Inout_ SQLLEN* out_buffer_length )
{
SQLCHAR* row = get_row();
SQLCHAR* field_data = NULL;
@ -997,8 +997,8 @@ SQLRETURN sqlsrv_buffered_result_set::binary_to_system_string( SQLSMALLINT field
return binary_to_string<char>( field_data, read_so_far, buffer, buffer_length, out_buffer_length, last_error );
}
SQLRETURN sqlsrv_buffered_result_set::binary_to_wide_string( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ SQLLEN* out_buffer_length )
SQLRETURN sqlsrv_buffered_result_set::binary_to_wide_string( _In_ SQLSMALLINT field_index, _Out_writes_z_(*out_buffer_length) void* buffer, _In_ SQLLEN buffer_length,
_Inout_ SQLLEN* out_buffer_length )
{
SQLCHAR* row = get_row();
SQLCHAR* field_data = NULL;
@ -1016,8 +1016,8 @@ SQLRETURN sqlsrv_buffered_result_set::binary_to_wide_string( SQLSMALLINT field_i
}
SQLRETURN sqlsrv_buffered_result_set::double_to_long( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ SQLLEN* out_buffer_length )
SQLRETURN sqlsrv_buffered_result_set::double_to_long( _In_ SQLSMALLINT field_index, _Inout_updates_bytes_(*out_buffer_length) void* buffer, _In_ SQLLEN buffer_length,
_Inout_ SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( meta[ field_index ].c_type == SQL_C_DOUBLE, "Invalid conversion to long" );
SQLSRV_ASSERT( buffer_length >= sizeof(SQLLEN), "Buffer length must be able to find a long in "
@ -1045,8 +1045,8 @@ SQLRETURN sqlsrv_buffered_result_set::double_to_long( SQLSMALLINT field_index, _
return SQL_SUCCESS;
}
SQLRETURN sqlsrv_buffered_result_set::double_to_system_string( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ SQLLEN* out_buffer_length )
SQLRETURN sqlsrv_buffered_result_set::double_to_system_string( _In_ SQLSMALLINT field_index, _Out_writes_bytes_to_opt_(buffer_length, *out_buffer_length) void* buffer, _In_ SQLLEN buffer_length,
_Inout_ SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( meta[ field_index ].c_type == SQL_C_DOUBLE, "Invalid conversion to system string" );
SQLSRV_ASSERT( buffer_length > 0, "Buffer length must be > 0 in sqlsrv_buffered_result_set::double_to_system_string" );
@ -1062,8 +1062,8 @@ SQLRETURN sqlsrv_buffered_result_set::double_to_system_string( SQLSMALLINT field
return r;
}
SQLRETURN sqlsrv_buffered_result_set::double_to_wide_string( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ SQLLEN* out_buffer_length )
SQLRETURN sqlsrv_buffered_result_set::double_to_wide_string( _In_ SQLSMALLINT field_index, _Out_writes_bytes_to_opt_(buffer_length, *out_buffer_length) void* buffer, _In_ SQLLEN buffer_length,
_Inout_ SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( meta[ field_index ].c_type == SQL_C_DOUBLE, "Invalid conversion to wide string" );
SQLSRV_ASSERT( buffer_length > 0, "Buffer length must be > 0 in sqlsrv_buffered_result_set::double_to_wide_string" );
@ -1079,7 +1079,7 @@ SQLRETURN sqlsrv_buffered_result_set::double_to_wide_string( SQLSMALLINT field_i
return r;
}
SQLRETURN sqlsrv_buffered_result_set::long_to_double( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
SQLRETURN sqlsrv_buffered_result_set::long_to_double( _In_ SQLSMALLINT field_index, _Out_writes_bytes_(*out_buffer_length) void* buffer, _In_ SQLLEN buffer_length,
_Out_ SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( meta[ field_index ].c_type == SQL_C_LONG, "Invalid conversion to long" );
@ -1094,8 +1094,8 @@ SQLRETURN sqlsrv_buffered_result_set::long_to_double( SQLSMALLINT field_index, _
return SQL_SUCCESS;
}
SQLRETURN sqlsrv_buffered_result_set::long_to_system_string( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ SQLLEN* out_buffer_length )
SQLRETURN sqlsrv_buffered_result_set::long_to_system_string( _In_ SQLSMALLINT field_index, _Out_writes_bytes_to_opt_(buffer_length, *out_buffer_length) void* buffer, _In_ SQLLEN buffer_length,
_Inout_ SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( meta[ field_index ].c_type == SQL_C_LONG, "Invalid conversion to system string" );
SQLSRV_ASSERT( buffer_length > 0, "Buffer length must be > 0 in sqlsrv_buffered_result_set::long_to_system_string" );
@ -1111,8 +1111,8 @@ SQLRETURN sqlsrv_buffered_result_set::long_to_system_string( SQLSMALLINT field_i
return r;
}
SQLRETURN sqlsrv_buffered_result_set::long_to_wide_string( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ SQLLEN* out_buffer_length )
SQLRETURN sqlsrv_buffered_result_set::long_to_wide_string( _In_ SQLSMALLINT field_index, _Out_writes_bytes_to_opt_(buffer_length, *out_buffer_length) void* buffer, _In_ SQLLEN buffer_length,
_Inout_ SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( meta[ field_index ].c_type == SQL_C_LONG, "Invalid conversion to wide string" );
SQLSRV_ASSERT( buffer_length > 0, "Buffer length must be > 0 in sqlsrv_buffered_result_set::long_to_wide_string" );
@ -1128,8 +1128,8 @@ SQLRETURN sqlsrv_buffered_result_set::long_to_wide_string( SQLSMALLINT field_ind
return r;
}
SQLRETURN sqlsrv_buffered_result_set::string_to_double( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ SQLLEN* out_buffer_length )
SQLRETURN sqlsrv_buffered_result_set::string_to_double( _In_ SQLSMALLINT field_index, _Out_writes_bytes_(*out_buffer_length) void* buffer, _In_ SQLLEN buffer_length,
_Inout_ SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( meta[ field_index ].c_type == SQL_C_CHAR, "Invalid conversion from string to double" );
SQLSRV_ASSERT( buffer_length >= sizeof( double ), "Buffer needs to be big enough to hold a double" );
@ -1140,8 +1140,8 @@ SQLRETURN sqlsrv_buffered_result_set::string_to_double( SQLSMALLINT field_index,
return string_to_number<double>( string_data, meta[ field_index ].length, buffer, buffer_length, out_buffer_length, last_error );
}
SQLRETURN sqlsrv_buffered_result_set::wstring_to_double( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ SQLLEN* out_buffer_length )
SQLRETURN sqlsrv_buffered_result_set::wstring_to_double( _In_ SQLSMALLINT field_index, _Out_writes_bytes_(*out_buffer_length) void* buffer, _In_ SQLLEN buffer_length,
_Inout_ SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( meta[ field_index ].c_type == SQL_C_WCHAR, "Invalid conversion from wide string to double" );
SQLSRV_ASSERT( buffer_length >= sizeof( double ), "Buffer needs to be big enough to hold a double" );
@ -1152,8 +1152,8 @@ SQLRETURN sqlsrv_buffered_result_set::wstring_to_double( SQLSMALLINT field_index
return string_to_number<double>( string_data, meta[ field_index ].length, buffer, buffer_length, out_buffer_length, last_error );
}
SQLRETURN sqlsrv_buffered_result_set::string_to_long( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ SQLLEN* out_buffer_length )
SQLRETURN sqlsrv_buffered_result_set::string_to_long( _In_ SQLSMALLINT field_index, _Out_writes_bytes_(*out_buffer_length) void* buffer, _In_ SQLLEN buffer_length,
_Inout_ SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( meta[ field_index ].c_type == SQL_C_CHAR, "Invalid conversion from string to long" );
SQLSRV_ASSERT( buffer_length >= sizeof( LONG ), "Buffer needs to be big enough to hold a long" );
@ -1164,8 +1164,8 @@ SQLRETURN sqlsrv_buffered_result_set::string_to_long( SQLSMALLINT field_index, _
return string_to_number<LONG>( string_data, meta[ field_index ].length, buffer, buffer_length, out_buffer_length, last_error );
}
SQLRETURN sqlsrv_buffered_result_set::wstring_to_long( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ SQLLEN* out_buffer_length )
SQLRETURN sqlsrv_buffered_result_set::wstring_to_long( _In_ SQLSMALLINT field_index, _Out_writes_bytes_(*out_buffer_length) void* buffer, _In_ SQLLEN buffer_length,
_Inout_ SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( meta[ field_index ].c_type == SQL_C_WCHAR, "Invalid conversion from wide string to long" );
SQLSRV_ASSERT( buffer_length >= sizeof( LONG ), "Buffer needs to be big enough to hold a long" );
@ -1176,7 +1176,7 @@ SQLRETURN sqlsrv_buffered_result_set::wstring_to_long( SQLSMALLINT field_index,
return string_to_number<LONG>( string_data, meta[ field_index ].length, buffer, buffer_length, out_buffer_length, last_error );
}
SQLRETURN sqlsrv_buffered_result_set::system_to_wide_string( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
SQLRETURN sqlsrv_buffered_result_set::system_to_wide_string( _In_ SQLSMALLINT field_index, _Out_writes_z_(*out_buffer_length) void* buffer, _In_ SQLLEN buffer_length,
_Out_ SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( last_error == 0, "Pending error for sqlsrv_buffered_results_set::system_to_wide_string" );
@ -1276,7 +1276,7 @@ SQLRETURN sqlsrv_buffered_result_set::system_to_wide_string( SQLSMALLINT field_i
return r;
}
SQLRETURN sqlsrv_buffered_result_set::to_same_string( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
SQLRETURN sqlsrv_buffered_result_set::to_same_string( _In_ SQLSMALLINT field_index, _Out_writes_bytes_to_opt_(buffer_length, *out_buffer_length) void* buffer, _In_ SQLLEN buffer_length,
_Out_ SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( last_error == 0, "Pending error for sqlsrv_buffered_results_set::to_same_string" );
@ -1346,8 +1346,8 @@ SQLRETURN sqlsrv_buffered_result_set::to_same_string( SQLSMALLINT field_index, _
return r;
}
SQLRETURN sqlsrv_buffered_result_set::wide_to_system_string( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ SQLLEN* out_buffer_length )
SQLRETURN sqlsrv_buffered_result_set::wide_to_system_string( _In_ SQLSMALLINT field_index, _Inout_updates_bytes_to_(buffer_length, *out_buffer_length) void* buffer, _In_ SQLLEN buffer_length,
_Inout_ SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( last_error == 0, "Pending error for sqlsrv_buffered_results_set::wide_to_system_string" );
@ -1440,13 +1440,13 @@ SQLRETURN sqlsrv_buffered_result_set::wide_to_system_string( SQLSMALLINT field_i
}
SQLRETURN sqlsrv_buffered_result_set::to_binary_string( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
SQLRETURN sqlsrv_buffered_result_set::to_binary_string( _In_ SQLSMALLINT field_index, _Out_writes_bytes_to_opt_(buffer_length, *out_buffer_length) void* buffer, _In_ SQLLEN buffer_length,
_Out_ SQLLEN* out_buffer_length )
{
return to_same_string( field_index, buffer, buffer_length, out_buffer_length );
}
SQLRETURN sqlsrv_buffered_result_set::to_long( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
SQLRETURN sqlsrv_buffered_result_set::to_long( _In_ SQLSMALLINT field_index, _Out_writes_bytes_to_opt_(buffer_length, *out_buffer_length) void* buffer, _In_ SQLLEN buffer_length,
_Out_ SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( meta[ field_index ].c_type == SQL_C_LONG, "Invalid conversion to long" );
@ -1460,7 +1460,7 @@ SQLRETURN sqlsrv_buffered_result_set::to_long( SQLSMALLINT field_index, _Out_ vo
return SQL_SUCCESS;
}
SQLRETURN sqlsrv_buffered_result_set::to_double( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
SQLRETURN sqlsrv_buffered_result_set::to_double( _In_ SQLSMALLINT field_index, _Out_writes_bytes_to_opt_(buffer_length, *out_buffer_length) void* buffer, _In_ SQLLEN buffer_length,
_Out_ SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( meta[ field_index ].c_type == SQL_C_DOUBLE, "Invalid conversion to double" );
@ -1477,7 +1477,7 @@ SQLRETURN sqlsrv_buffered_result_set::to_double( SQLSMALLINT field_index, _Out_
namespace {
// called for each row in the cache when the cache is destroyed in the destructor
void cache_row_dtor( zval* data )
void cache_row_dtor( _In_ zval* data )
{
row_dtor_closure* cl = reinterpret_cast<row_dtor_closure*>( Z_PTR_P( data ) );
BYTE* row = cl->row_data;
@ -1497,8 +1497,8 @@ void cache_row_dtor( zval* data )
sqlsrv_free( cl );
}
SQLPOINTER read_lob_field( sqlsrv_stmt* stmt, SQLUSMALLINT field_index, sqlsrv_buffered_result_set::meta_data& meta,
zend_long mem_used TSRMLS_DC )
SQLPOINTER read_lob_field( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT field_index, _In_ sqlsrv_buffered_result_set::meta_data& meta,
_In_ zend_long mem_used TSRMLS_DC )
{
SQLSMALLINT extra = 0;
SQLULEN* output_buffer_len = NULL;

View file

@ -6,7 +6,7 @@
//
// Contents: Core routines and constants shared by the Microsoft Drivers for PHP for SQL Server
//
// Microsoft Drivers 4.1 for PHP for SQL Server
// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -37,10 +37,12 @@
#include "ext/standard/php_standard.h"
#include "ext/standard/info.h"
#ifndef _WIN32
#ifndef _WIN32 // !_WIN32
#include "FormattedPrint.h"
#include "StringFunctions.h"
#endif // !_WIN32
#else
#include "VersionHelpers.h"
#endif
#ifdef HAVE_CONFIG_H
#include "config.h"
@ -258,7 +260,7 @@ template <bool b>
struct sqlsrv_static_assert;
template <>
struct sqlsrv_static_assert<true> { static const int value = 1; };
struct sqlsrv_static_assert<true> { _In_ static const int value = 1; };
#define SQLSRV_STATIC_ASSERT( c ) (sqlsrv_static_assert<(c) != 0>() )
@ -271,13 +273,13 @@ struct sqlsrv_static_assert<true> { static const int value = 1; };
// severity - severity of the message: notice, warning, or error
// msg - the message to log in a FormatMessage style formatting
// print_args - args to the message
typedef void (*log_callback)( unsigned int severity TSRMLS_DC, const char* msg, va_list* print_args );
typedef void (*log_callback)( _In_ unsigned int severity TSRMLS_DC, _In_ const char* msg, _In_opt_ va_list* print_args );
// each driver must register a log callback. This should be the first thing a driver does.
void core_sqlsrv_register_logger( log_callback );
void core_sqlsrv_register_logger( _In_ log_callback );
// a simple wrapper around a PHP error logging function.
void write_to_log( unsigned int severity TSRMLS_DC, const char* msg, ... );
void write_to_log( _In_ unsigned int severity TSRMLS_DC, _In_ const char* msg, ... );
// a macro to make it convenient to use the function.
#define LOG( severity, msg, ...) write_to_log( severity TSRMLS_CC, msg, ## __VA_ARGS__ )
@ -291,7 +293,7 @@ enum logging_severity {
};
// Kill the PHP process and log the message to PHP
void die( const char* msg, ... );
void die( _In_opt_ const char* msg, ... );
#define DIE( msg, ... ) { die( msg, ## __VA_ARGS__ ); }
@ -312,14 +314,14 @@ void die( const char* msg, ... );
// #define SQLSRV_MEM_DEBUG 1
#if defined( PHP_DEBUG ) && !defined( ZTS ) && defined( SQLSRV_MEM_DEBUG )
inline void* sqlsrv_malloc_trace( size_t size, const char* file, int line )
inline void* sqlsrv_malloc_trace( _In_ size_t size, _In_ const char* file, _In_ int line )
{
void* ptr = emalloc( size );
LOG( SEV_NOTICE, "emalloc returned %4!08x!: %1!d! bytes at %2!s!:%3!d!", size, file, line, ptr );
return ptr;
}
inline void* sqlsrv_malloc_trace( size_t element_count, size_t element_size, size_t extra, const char* file, int line )
inline void* sqlsrv_malloc_trace( _In_ size_t element_count, _In_ size_t element_size, _In_ size_t extra, _In_ const char* file, _In_ int line )
{
OACR_WARNING_SUPPRESS( ALLOC_SIZE_OVERFLOW_IN_ALLOC_WRAPPER, "Overflow verified below" );
@ -341,14 +343,14 @@ inline void* sqlsrv_malloc_trace( size_t element_count, size_t element_size, siz
return ptr;
}
inline void* sqlsrv_realloc_trace( void* buffer, size_t size, const char* file, int line )
inline void* sqlsrv_realloc_trace( void* buffer, _In_ size_t size, _In_ const char* file, _In_ int line )
{
void* ptr = erealloc( original, size );
LOG( SEV_NOTICE, "erealloc returned %5!08x! from %4!08x!: %1!d! bytes at %2!s!:%3!d!", size, file, line, ptr, original );
return ptr;
}
inline void sqlsrv_free_trace( void* ptr, const char* file, int line )
inline void sqlsrv_free_trace( _Inout_ void* ptr, _In_ const char* file, _In_ int line )
{
LOG( SEV_NOTICE, "efree %1!08x! at %2!s!:%3!d!", ptr, file, line );
efree( ptr );
@ -361,12 +363,12 @@ inline void sqlsrv_free_trace( void* ptr, const char* file, int line )
#else
inline void* sqlsrv_malloc( size_t size )
inline void* sqlsrv_malloc( _In_ size_t size )
{
return emalloc( size );
}
inline void* sqlsrv_malloc( size_t element_count, size_t element_size, size_t extra )
inline void* sqlsrv_malloc( _In_ size_t element_count, _In_ size_t element_size, _In_ size_t extra )
{
OACR_WARNING_SUPPRESS( ALLOC_SIZE_OVERFLOW_IN_ALLOC_WRAPPER, "Overflow verified below" );
@ -386,12 +388,12 @@ inline void* sqlsrv_malloc( size_t element_count, size_t element_size, size_t ex
return emalloc( element_size * element_count + extra );
}
inline void* sqlsrv_realloc( void* buffer, size_t size )
inline void* sqlsrv_realloc( _Inout_ void* buffer, _In_ size_t size )
{
return erealloc( buffer, size );
}
inline void sqlsrv_free( void* ptr )
inline void sqlsrv_free( _Inout_ void* ptr )
{
efree( ptr );
}
@ -436,24 +438,24 @@ struct sqlsrv_allocator {
inline sqlsrv_allocator( sqlsrv_allocator<U> const& ) {}
// address (doesn't work if the class defines operator&)
inline pointer address( reference r )
inline pointer address( _In_ reference r )
{
return &r;
}
inline const_pointer address( const_reference r )
inline const_pointer address( _In_ const_reference r )
{
return &r;
}
// memory allocation/deallocation
inline pointer allocate( size_type cnt,
inline pointer allocate( _In_ size_type cnt,
typename std::allocator<void>::const_pointer = 0 )
{
return reinterpret_cast<pointer>( sqlsrv_malloc(cnt, sizeof (T), 0));
}
inline void deallocate( pointer p, size_type )
inline void deallocate( _Inout_ pointer p, size_type )
{
sqlsrv_free(p);
}
@ -465,12 +467,12 @@ struct sqlsrv_allocator {
}
// object construction/destruction
inline void construct( pointer p, const T& t )
inline void construct( _In_ pointer p, _In_ const T& t )
{
new(p) T(t);
}
inline void destroy(pointer p)
inline void destroy( _Inout_ pointer p )
{
p->~T();
}
@ -481,7 +483,7 @@ struct sqlsrv_allocator {
return true;
}
inline bool operator!=( sqlsrv_allocator const& a )
inline bool operator!=( _In_ sqlsrv_allocator const& a )
{
return !operator==(a);
}
@ -535,21 +537,21 @@ public:
// there are a number of places where we allocate a block intended to be accessed as
// an array of elements, so this operator allows us to treat the memory as such.
T& operator[]( int index ) const
T& operator[]( _In_ int index ) const
{
return _ptr[ index ];
}
// there are a number of places where we allocate a block intended to be accessed as
// an array of elements, so this operator allows us to treat the memory as such.
T& operator[]( unsigned int index ) const
T& operator[]( _In_ unsigned int index ) const
{
return _ptr[ index ];
}
// there are a number of places where we allocate a block intended to be accessed as
// an array of elements, so this operator allows us to treat the memory as such.
T& operator[]( long index ) const
T& operator[]( _In_ long index ) const
{
return _ptr[ index ];
}
@ -558,7 +560,7 @@ public:
#ifdef __WIN64
// there are a number of places where we allocate a block intended to be accessed as
// an array of elements, so this operator allows us to treat the memory as such.
T& operator[](std::size_t index) const
T& operator[]( _In_ std::size_t index ) const
{
return _ptr[index];
}
@ -566,7 +568,7 @@ public:
// there are a number of places where we allocate a block intended to be accessed as
// an array of elements, so this operator allows us to treat the memory as such.
T& operator[]( unsigned short index ) const
T& operator[]( _In_ unsigned short index ) const
{
return _ptr[ index ];
}
@ -593,12 +595,12 @@ public:
protected:
sqlsrv_auto_ptr( T* ptr ) :
sqlsrv_auto_ptr( _In_opt_ T* ptr ) :
_ptr( ptr )
{
}
sqlsrv_auto_ptr( sqlsrv_auto_ptr& src )
sqlsrv_auto_ptr( _Inout_opt_ sqlsrv_auto_ptr& src )
{
if( _ptr ) {
static_cast<Subclass*>(this)->reset( src._ptr );
@ -608,7 +610,7 @@ protected:
// assign a new pointer to the auto_ptr. It will free the previous memory block
// because ownership is deemed finished.
T* operator=( T* ptr )
T* operator=( _In_opt_ T* ptr )
{
static_cast<Subclass*>( this )->reset( ptr );
@ -634,25 +636,25 @@ public:
{
}
sqlsrv_malloc_auto_ptr( const sqlsrv_malloc_auto_ptr& src ) :
sqlsrv_malloc_auto_ptr( _Inout_opt_ const sqlsrv_malloc_auto_ptr& src ) :
sqlsrv_auto_ptr<T, sqlsrv_malloc_auto_ptr<T> >( src )
{
}
// free the original pointer and assign a new pointer. Use NULL to simply free the pointer.
void reset( T* ptr = NULL )
void reset( _In_opt_ T* ptr = NULL )
{
if( sqlsrv_auto_ptr<T,sqlsrv_malloc_auto_ptr<T> >::_ptr )
sqlsrv_free( (void*) sqlsrv_auto_ptr<T,sqlsrv_malloc_auto_ptr<T> >::_ptr );
sqlsrv_auto_ptr<T,sqlsrv_malloc_auto_ptr<T> >::_ptr = ptr;
}
T* operator=( T* ptr )
T* operator=( _In_opt_ T* ptr )
{
return sqlsrv_auto_ptr<T, sqlsrv_malloc_auto_ptr<T> >::operator=( ptr );
}
void operator=( sqlsrv_malloc_auto_ptr<T>& src )
void operator=( _Inout_opt_ sqlsrv_malloc_auto_ptr<T>& src )
{
T* p = src.get();
src.transferred();
@ -661,7 +663,7 @@ public:
// DO NOT CALL sqlsrv_realloc with a sqlsrv_malloc_auto_ptr. Use the resize member function.
// has the same parameter list as sqlsrv_realloc: new_size is the size in bytes of the newly allocated buffer
void resize( size_t new_size )
void resize( _In_ size_t new_size )
{
sqlsrv_auto_ptr<T,sqlsrv_malloc_auto_ptr<T> >::_ptr = reinterpret_cast<T*>( sqlsrv_realloc( sqlsrv_auto_ptr<T,sqlsrv_malloc_auto_ptr<T> >::_ptr, new_size ));
}
@ -682,7 +684,7 @@ public:
}
// free the original pointer and assign a new pointer. Use NULL to simply free the pointer.
void reset( HashTable* ptr = NULL )
void reset( _In_opt_ HashTable* ptr = NULL )
{
if( _ptr ) {
zend_hash_destroy( _ptr );
@ -691,16 +693,16 @@ public:
_ptr = ptr;
}
HashTable* operator=( HashTable* ptr )
HashTable* operator=( _In_opt_ HashTable* ptr )
{
return sqlsrv_auto_ptr<HashTable, hash_auto_ptr>::operator=( ptr );
}
private:
hash_auto_ptr( HashTable const& hash );
hash_auto_ptr( _In_ HashTable const& hash );
hash_auto_ptr( hash_auto_ptr const& hash );
hash_auto_ptr( _In_ hash_auto_ptr const& hash );
};
@ -717,14 +719,14 @@ public:
}
// free the original pointer and assign a new pointer. Use NULL to simply free the pointer.
void reset( zval* ptr = NULL )
void reset( _In_opt_ zval* ptr = NULL )
{
if( _ptr )
zval_ptr_dtor(_ptr );
_ptr = ptr;
}
zval* operator=( zval* ptr )
zval* operator=( _In_opt_ zval* ptr )
{
return sqlsrv_auto_ptr<zval, zval_auto_ptr>::operator=( ptr );
}
@ -732,7 +734,7 @@ public:
private:
zval_auto_ptr( const zval_auto_ptr& src );
zval_auto_ptr( _In_ const zval_auto_ptr& src );
};
#pragma pop_macro( "max" )
@ -767,7 +769,7 @@ struct sqlsrv_error : public sqlsrv_error_const {
format = false;
}
sqlsrv_error( SQLCHAR* sql_state, SQLCHAR* message, SQLINTEGER code, bool printf_format = false )
sqlsrv_error( _In_ SQLCHAR* sql_state, _In_ SQLCHAR* message, _In_ SQLINTEGER code, _In_ bool printf_format = false )
{
sqlstate = reinterpret_cast<SQLCHAR*>( sqlsrv_malloc( SQL_SQLSTATE_BUFSIZE ));
native_message = reinterpret_cast<SQLCHAR*>( sqlsrv_malloc( SQL_MAX_MESSAGE_LENGTH + 1 ));
@ -777,7 +779,7 @@ struct sqlsrv_error : public sqlsrv_error_const {
format = printf_format;
}
sqlsrv_error( sqlsrv_error_const const& prototype )
sqlsrv_error( _In_ sqlsrv_error_const const& prototype )
{
sqlsrv_error( prototype.sqlstate, prototype.native_message, prototype.native_code, prototype.format );
}
@ -804,13 +806,13 @@ public:
{
}
sqlsrv_error_auto_ptr( sqlsrv_error_auto_ptr const& src ) :
sqlsrv_error_auto_ptr( _Inout_opt_ sqlsrv_error_auto_ptr const& src ) :
sqlsrv_auto_ptr<sqlsrv_error, sqlsrv_error_auto_ptr >( (sqlsrv_error_auto_ptr&) src )
{
}
// free the original pointer and assign a new pointer. Use NULL to simply free the pointer.
void reset( sqlsrv_error* ptr = NULL )
void reset( _In_opt_ sqlsrv_error* ptr = NULL )
{
if( _ptr ) {
_ptr->~sqlsrv_error();
@ -819,14 +821,14 @@ public:
_ptr = ptr;
}
sqlsrv_error* operator=( sqlsrv_error* ptr )
sqlsrv_error* operator=( _In_opt_ sqlsrv_error* ptr )
{
return sqlsrv_auto_ptr<sqlsrv_error, sqlsrv_error_auto_ptr >::operator=( ptr );
}
// unlike traditional assignment operators, the chained assignment of an auto_ptr doesn't make much
// sense. Only the last one would have anything in it.
void operator=( sqlsrv_error_auto_ptr& src )
void operator=( _Inout_opt_ sqlsrv_error_auto_ptr& src )
{
sqlsrv_error* p = src.get();
src.transferred();
@ -846,7 +848,7 @@ struct sqlsrv_conn;
// a driver specific callback for processing errors.
// ctx - the context holding the handles
// sqlsrv_error_code - specific error code to return.
typedef bool (*error_callback)( sqlsrv_context& ctx, unsigned int sqlsrv_error_code, bool error TSRMLS_DC, va_list* print_args );
typedef bool (*error_callback)( _Inout_ sqlsrv_context& ctx, _In_ unsigned int sqlsrv_error_code, _In_ bool error TSRMLS_DC, _In_opt_ va_list* print_args );
// sqlsrv_context
// a context holds relevant information to be passed with a connection and statement objects.
@ -855,7 +857,7 @@ class sqlsrv_context {
public:
sqlsrv_context( SQLSMALLINT type, error_callback e, void* drv, SQLSRV_ENCODING encoding = SQLSRV_ENCODING_INVALID ) :
sqlsrv_context( _In_opt_ SQLSMALLINT type, _In_ error_callback e, _In_opt_ void* drv, _In_ SQLSRV_ENCODING encoding = SQLSRV_ENCODING_INVALID ) :
handle_( SQL_NULL_HANDLE ),
handle_type_( type ),
name_( NULL ),
@ -866,7 +868,7 @@ class sqlsrv_context {
{
}
sqlsrv_context( SQLHANDLE h, SQLSMALLINT t, error_callback e, void* drv, SQLSRV_ENCODING encoding = SQLSRV_ENCODING_INVALID ) :
sqlsrv_context( _In_ SQLHANDLE h, _In_opt_ SQLSMALLINT t, _In_ error_callback e, _In_opt_ void* drv, _In_ SQLSRV_ENCODING encoding = SQLSRV_ENCODING_INVALID ) :
handle_( h ),
handle_type_( t ),
name_( NULL ),
@ -877,7 +879,7 @@ class sqlsrv_context {
{
}
sqlsrv_context( sqlsrv_context const& ctx ) :
sqlsrv_context( _In_ sqlsrv_context const& ctx ) :
handle_( ctx.handle_ ),
handle_type_( ctx.handle_type_ ),
name_( ctx.name_ ),
@ -891,12 +893,12 @@ class sqlsrv_context {
{
}
void set_func( const char* f )
void set_func( _In_z_ const char* f )
{
name_ = f;
}
void set_last_error( sqlsrv_error_auto_ptr& last_error )
void set_last_error( _In_ sqlsrv_error_auto_ptr& last_error )
{
last_error_ = last_error;
}
@ -938,7 +940,7 @@ class sqlsrv_context {
return driver_;
}
void set_driver( void* driver )
void set_driver( _In_ void* driver )
{
this->driver_ = driver;
}
@ -963,7 +965,7 @@ class sqlsrv_context {
return encoding_;
}
void set_encoding( SQLSRV_ENCODING e )
void set_encoding( _In_ SQLSRV_ENCODING e )
{
encoding_ = e;
}
@ -988,7 +990,7 @@ struct sqlsrv_encoding {
unsigned int code_page;
bool not_for_connection;
sqlsrv_encoding( const char* iana, unsigned int code_page, bool not_for_conn = false ):
sqlsrv_encoding( _In_ const char* iana, _In_ unsigned int code_page, _In_ bool not_for_conn = false ):
iana( iana ), iana_len( strlen( iana )), code_page( code_page ), not_for_connection( not_for_conn )
{
}
@ -1000,18 +1002,18 @@ struct sqlsrv_encoding {
//*********************************************************************************************************************************
// variables set during initialization
extern OSVERSIONINFO g_osversion; // used to determine which OS we're running in
extern bool isVistaOrGreater; // used to determine if OS is Vista or Greater
extern HashTable* g_encodings; // encodings supported by this driver
void core_sqlsrv_minit( sqlsrv_context** henv_cp, sqlsrv_context** henv_ncp, error_callback err, const char* driver_func TSRMLS_DC );
void core_sqlsrv_mshutdown( sqlsrv_context& henv_cp, sqlsrv_context& henv_ncp );
void core_sqlsrv_minit( _Outptr_ sqlsrv_context** henv_cp, _Inout_ sqlsrv_context** henv_ncp, _In_ error_callback err, _In_z_ const char* driver_func TSRMLS_DC );
void core_sqlsrv_mshutdown( _Inout_ sqlsrv_context& henv_cp, _Inout_ sqlsrv_context& henv_ncp );
// environment context used by sqlsrv_connect for when a connection error occurs.
struct sqlsrv_henv {
sqlsrv_context ctx;
sqlsrv_henv( SQLHANDLE handle, error_callback e, void* drv ) :
sqlsrv_henv( _In_ SQLHANDLE handle, _In_ error_callback e, _In_opt_ void* drv ) :
ctx( handle, SQL_HANDLE_ENV, e, drv )
{
}
@ -1052,7 +1054,7 @@ struct sqlsrv_conn : public sqlsrv_context {
DRIVER_VERSION driver_version;
// initialize with default values
sqlsrv_conn( SQLHANDLE h, error_callback e, void* drv, SQLSRV_ENCODING encoding TSRMLS_DC ) :
sqlsrv_conn( _In_ SQLHANDLE h, _In_ error_callback e, _In_opt_ void* drv, _In_ SQLSRV_ENCODING encoding TSRMLS_DC ) :
sqlsrv_context( h, SQL_HANDLE_DBC, e, drv, encoding )
{
server_version = SERVER_VERSION_UNKNOWN;
@ -1100,6 +1102,7 @@ const char TraceFile[] = "TraceFile";
const char TraceOn[] = "TraceOn";
const char TrustServerCertificate[] = "TrustServerCertificate";
const char TransactionIsolation[] = "TransactionIsolation";
const char TransparentNetworkIPResolution[] = "TransparentNetworkIPResolution";
const char WSID[] = "WSID";
const char UID[] = "UID";
const char PWD[] = "PWD";
@ -1128,6 +1131,7 @@ enum SQLSRV_CONN_OPTIONS {
SQLSRV_CONN_OPTION_APPLICATION_INTENT,
SQLSRV_CONN_OPTION_MULTI_SUBNET_FAILOVER,
SQLSRV_CONN_OPTION_AUTHENTICATION,
SQLSRV_CONN_OPTION_TRANSPARANT_NETWORK_IP_RESOLUTION,
#ifdef _WIN32
SQLSRV_CONN_OPTION_CONN_RETRY_COUNT,
SQLSRV_CONN_OPTION_CONN_RETRY_INTERVAL,
@ -1170,7 +1174,7 @@ struct connection_option {
// simply add the parsed value to the connection string
struct conn_str_append_func {
static void func( connection_option const* option, zval* value, sqlsrv_conn* /*conn*/, std::string& conn_str TSRMLS_DC );
static void func( _In_ connection_option const* option, _In_ zval* value, sqlsrv_conn* /*conn*/, _Inout_ std::string& conn_str TSRMLS_DC );
};
struct conn_null_func {
@ -1180,24 +1184,24 @@ struct conn_null_func {
};
// factory to create a connection (since they are subclassed to instantiate statements)
typedef sqlsrv_conn* (*driver_conn_factory)( SQLHANDLE h, error_callback e, void* drv TSRMLS_DC );
typedef sqlsrv_conn* (*driver_conn_factory)( _In_ SQLHANDLE h, _In_ error_callback e, _In_ void* drv TSRMLS_DC );
// *** connection functions ***
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 driver_conn_opt_list[],
void* driver, const char* driver_func TSRMLS_DC );
void core_sqlsrv_close( sqlsrv_conn* conn TSRMLS_DC );
void core_sqlsrv_prepare( sqlsrv_stmt* stmt, const char* sql, SQLLEN sql_len TSRMLS_DC );
void core_sqlsrv_begin_transaction( sqlsrv_conn* conn TSRMLS_DC );
void core_sqlsrv_commit( sqlsrv_conn* conn TSRMLS_DC );
void core_sqlsrv_rollback( sqlsrv_conn* conn TSRMLS_DC );
void core_sqlsrv_get_server_info( sqlsrv_conn* conn, _Out_ zval* server_info TSRMLS_DC );
void core_sqlsrv_get_server_version( sqlsrv_conn* conn, _Out_ zval *server_version TSRMLS_DC );
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 );
sqlsrv_conn* core_sqlsrv_connect( _In_ sqlsrv_context& henv_cp, _In_ sqlsrv_context& henv_ncp, _In_ driver_conn_factory conn_factory,
_Inout_z_ const char* server, _Inout_opt_z_ const char* uid, _Inout_opt_z_ const char* pwd,
_Inout_opt_ HashTable* options_ht, _In_ error_callback err, _In_ const connection_option valid_conn_opts[],
_In_ void* driver, _In_z_ const char* driver_func TSRMLS_DC );
void core_sqlsrv_close( _Inout_opt_ sqlsrv_conn* conn TSRMLS_DC );
void core_sqlsrv_prepare( _Inout_ sqlsrv_stmt* stmt, _In_reads_bytes_(sql_len) const char* sql, _In_ SQLLEN sql_len TSRMLS_DC );
void core_sqlsrv_begin_transaction( _Inout_ sqlsrv_conn* conn TSRMLS_DC );
void core_sqlsrv_commit( _Inout_ sqlsrv_conn* conn TSRMLS_DC );
void core_sqlsrv_rollback( _Inout_ sqlsrv_conn* conn TSRMLS_DC );
void core_sqlsrv_get_server_info( _Inout_ sqlsrv_conn* conn, _Out_ zval* server_info TSRMLS_DC );
void core_sqlsrv_get_server_version( _Inout_ sqlsrv_conn* conn, _Inout_ zval *server_version TSRMLS_DC );
void core_sqlsrv_get_client_info( _Inout_ sqlsrv_conn* conn, _Out_ zval *client_info TSRMLS_DC );
bool core_is_conn_opt_value_escaped( _Inout_ const char* value, _Inout_ size_t value_len );
size_t core_str_zval_is_true( _Inout_ zval* str_zval );
bool core_is_authentication_option_valid( _In_z_ const char* value, _In_ size_t value_len );
//*********************************************************************************************************************************
// Statement
@ -1205,22 +1209,22 @@ bool core_is_authentication_option_valid( const char* value, size_t value_len );
struct stmt_option_functor {
virtual void operator()( sqlsrv_stmt* /*stmt*/, stmt_option const* /*opt*/, zval* /*value_z*/ TSRMLS_DC );
virtual void operator()( _Inout_ sqlsrv_stmt* /*stmt*/, stmt_option const* /*opt*/, _In_ zval* /*value_z*/ TSRMLS_DC );
};
struct stmt_option_query_timeout : public stmt_option_functor {
virtual void operator()( sqlsrv_stmt* stmt, stmt_option const* opt, zval* value_z TSRMLS_DC );
virtual void operator()( _Inout_ sqlsrv_stmt* stmt, stmt_option const* opt, _In_ zval* value_z TSRMLS_DC );
};
struct stmt_option_send_at_exec : public stmt_option_functor {
virtual void operator()( sqlsrv_stmt* stmt, stmt_option const* opt, zval* value_z TSRMLS_DC );
virtual void operator()( _Inout_ sqlsrv_stmt* stmt, stmt_option const* opt, _In_ zval* value_z TSRMLS_DC );
};
struct stmt_option_buffered_query_limit : public stmt_option_functor {
virtual void operator()( sqlsrv_stmt* stmt, stmt_option const* opt, zval* value_z TSRMLS_DC );
virtual void operator()( _Inout_ sqlsrv_stmt* stmt, stmt_option const* opt, _In_ zval* value_z TSRMLS_DC );
};
// used to hold the table for statment options
@ -1242,7 +1246,7 @@ struct sqlsrv_stream {
SQLSMALLINT sql_type;
sqlsrv_stmt* stmt;
sqlsrv_stream( zval* str_z, SQLSRV_ENCODING enc ) :
sqlsrv_stream( _In_opt_ zval* str_z, _In_ SQLSRV_ENCODING enc ) :
stream_z( str_z ), encoding( enc ), field_index( 0 ), sql_type( SQL_UNKNOWN_TYPE ), stmt( NULL )
{
}
@ -1272,13 +1276,13 @@ struct sqlsrv_output_param {
bool is_bool;
// string output param constructor
sqlsrv_output_param( zval* p_z, SQLSRV_ENCODING enc, int num, SQLUINTEGER buffer_len ) :
sqlsrv_output_param( _In_ zval* p_z, _In_ SQLSRV_ENCODING enc, _In_ int num, _In_ SQLUINTEGER buffer_len ) :
param_z( p_z ), encoding( enc ), param_num( num ), original_buffer_len( buffer_len ), is_bool( false )
{
}
// every other type output parameter constructor
sqlsrv_output_param( zval* p_z, int num, bool is_bool ) :
sqlsrv_output_param( _In_ zval* p_z, _In_ int num, _In_ bool is_bool ) :
param_z( p_z ),
encoding( SQLSRV_ENCODING_INVALID ),
param_num( num ),
@ -1327,11 +1331,11 @@ struct sqlsrv_stmt : public sqlsrv_context {
zval col_cache; // Used by get_field_as_string not to call SQLColAttribute() after every fetch.
zval active_stream; // the currently active stream reading data from the database
sqlsrv_stmt( sqlsrv_conn* c, SQLHANDLE handle, error_callback e, void* drv TSRMLS_DC );
sqlsrv_stmt( _In_ sqlsrv_conn* c, _In_ SQLHANDLE handle, _In_ error_callback e, _In_opt_ void* drv TSRMLS_DC );
virtual ~sqlsrv_stmt( void );
// driver specific conversion rules from a SQL Server/ODBC type to one of the SQLSRV_PHPTYPE_* constants
virtual sqlsrv_phptype sql_type_to_php_type( SQLINTEGER sql_type, SQLUINTEGER size, bool prefer_string_to_stream ) = 0;
virtual sqlsrv_phptype sql_type_to_php_type( _In_ SQLINTEGER sql_type, _In_ SQLUINTEGER size, _In_ bool prefer_string_to_stream ) = 0;
};
@ -1375,27 +1379,27 @@ const size_t SQLSRV_CURSOR_BUFFERED = 0xfffffffeUL; // arbitrary number that doe
typedef sqlsrv_stmt* (*driver_stmt_factory)( sqlsrv_conn* conn, SQLHANDLE h, error_callback e, void* drv TSRMLS_DC );
// *** statement functions ***
sqlsrv_stmt* core_sqlsrv_create_stmt( sqlsrv_conn* conn, driver_stmt_factory stmt_factory, HashTable* options_ht,
const stmt_option valid_stmt_opts[], error_callback const err, void* driver TSRMLS_DC );
void core_sqlsrv_bind_param( sqlsrv_stmt* stmt, SQLUSMALLINT param_num, SQLSMALLINT direction, zval* param_z,
SQLSRV_PHPTYPE php_out_type, SQLSRV_ENCODING encoding, SQLSMALLINT sql_type, SQLULEN column_size,
SQLSMALLINT decimal_digits TSRMLS_DC );
SQLRETURN core_sqlsrv_execute( sqlsrv_stmt* stmt TSRMLS_DC, const char* sql = NULL, int sql_len = 0 );
field_meta_data* core_sqlsrv_field_metadata( sqlsrv_stmt* stmt, SQLSMALLINT colno TSRMLS_DC );
bool core_sqlsrv_fetch( sqlsrv_stmt* stmt, SQLSMALLINT fetch_orientation, SQLULEN fetch_offset TSRMLS_DC );
void core_sqlsrv_get_field(sqlsrv_stmt* stmt, SQLUSMALLINT field_index, sqlsrv_phptype sqlsrv_phptype, bool prefer_string,
_Out_ void*& field_value, _Out_ SQLLEN* field_length, bool cache_field,
sqlsrv_stmt* core_sqlsrv_create_stmt( _Inout_ sqlsrv_conn* conn, _In_ driver_stmt_factory stmt_factory, _In_opt_ HashTable* options_ht,
_In_opt_ const stmt_option valid_stmt_opts[], _In_ error_callback const err, _In_opt_ void* driver TSRMLS_DC );
void core_sqlsrv_bind_param( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT param_num, _In_ SQLSMALLINT direction, _Inout_ zval* param_z,
_In_ SQLSRV_PHPTYPE php_out_type, _In_ SQLSRV_ENCODING encoding, _Inout_ SQLSMALLINT sql_type, _Inout_ SQLULEN column_size,
_Inout_ SQLSMALLINT decimal_digits TSRMLS_DC );
SQLRETURN core_sqlsrv_execute( _Inout_ sqlsrv_stmt* stmt TSRMLS_DC, _In_reads_bytes_(sql_len) const char* sql = NULL, _In_ int sql_len = 0 );
field_meta_data* core_sqlsrv_field_metadata( _Inout_ sqlsrv_stmt* stmt, _In_ SQLSMALLINT colno TSRMLS_DC );
bool core_sqlsrv_fetch( _Inout_ sqlsrv_stmt* stmt, _In_ SQLSMALLINT fetch_orientation, _In_ SQLULEN fetch_offset TSRMLS_DC );
void core_sqlsrv_get_field( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT field_index, _In_ sqlsrv_phptype sqlsrv_phptype, _In_ bool prefer_string,
_Outref_result_bytebuffer_maybenull_(*field_length) void*& field_value, _Inout_ SQLLEN* field_length, _In_ bool cache_field,
_Out_ SQLSRV_PHPTYPE *sqlsrv_php_type_out TSRMLS_DC);
bool core_sqlsrv_has_any_result( sqlsrv_stmt* stmt TSRMLS_DC );
void core_sqlsrv_next_result( sqlsrv_stmt* stmt TSRMLS_DC, bool finalize_output_params = true, bool throw_on_errors = true );
void core_sqlsrv_post_param( sqlsrv_stmt* stmt, zend_ulong paramno, zval* param_z TSRMLS_DC );
void core_sqlsrv_set_scrollable( sqlsrv_stmt* stmt, unsigned long cursor_type TSRMLS_DC );
void core_sqlsrv_set_query_timeout( sqlsrv_stmt* stmt, long timeout TSRMLS_DC );
void core_sqlsrv_set_query_timeout( sqlsrv_stmt* stmt, zval* value_z TSRMLS_DC );
void core_sqlsrv_set_send_at_exec( sqlsrv_stmt* stmt, zval* value_z TSRMLS_DC );
bool core_sqlsrv_send_stream_packet( sqlsrv_stmt* stmt TSRMLS_DC );
void core_sqlsrv_set_buffered_query_limit( sqlsrv_stmt* stmt, zval* value_z TSRMLS_DC );
void core_sqlsrv_set_buffered_query_limit( sqlsrv_stmt* stmt, SQLLEN limit TSRMLS_DC );
bool core_sqlsrv_has_any_result( _Inout_ sqlsrv_stmt* stmt TSRMLS_DC );
void core_sqlsrv_next_result( _Inout_ sqlsrv_stmt* stmt TSRMLS_DC, _In_ bool finalize_output_params = true, _In_ bool throw_on_errors = true );
void core_sqlsrv_post_param( _Inout_ sqlsrv_stmt* stmt, _In_ zend_ulong paramno, zval* param_z TSRMLS_DC );
void core_sqlsrv_set_scrollable( _Inout_ sqlsrv_stmt* stmt, _In_ unsigned long cursor_type TSRMLS_DC );
void core_sqlsrv_set_query_timeout( _Inout_ sqlsrv_stmt* stmt, _In_ long timeout TSRMLS_DC );
void core_sqlsrv_set_query_timeout( _Inout_ sqlsrv_stmt* stmt, _Inout_ zval* value_z TSRMLS_DC );
void core_sqlsrv_set_send_at_exec( _Inout_ sqlsrv_stmt* stmt, _In_ zval* value_z TSRMLS_DC );
bool core_sqlsrv_send_stream_packet( _Inout_ sqlsrv_stmt* stmt TSRMLS_DC );
void core_sqlsrv_set_buffered_query_limit( _Inout_ sqlsrv_stmt* stmt, _In_ zval* value_z TSRMLS_DC );
void core_sqlsrv_set_buffered_query_limit( _Inout_ sqlsrv_stmt* stmt, _In_ SQLLEN limit TSRMLS_DC );
//*********************************************************************************************************************************
@ -1413,35 +1417,35 @@ struct sqlsrv_result_set {
sqlsrv_stmt* odbc;
explicit sqlsrv_result_set( sqlsrv_stmt* );
explicit sqlsrv_result_set( _In_ sqlsrv_stmt* );
virtual ~sqlsrv_result_set( void ) { }
virtual bool cached( int field_index ) = 0;
virtual SQLRETURN fetch( SQLSMALLINT fetch_orientation, SQLLEN fetch_offset TSRMLS_DC ) = 0;
virtual SQLRETURN get_data( SQLUSMALLINT field_index, SQLSMALLINT target_type,
_Out_ void* buffer, SQLLEN buffer_length, _Out_ SQLLEN* out_buffer_length,
virtual SQLRETURN fetch( _Inout_ SQLSMALLINT fetch_orientation, _Inout_opt_ SQLLEN fetch_offset TSRMLS_DC ) = 0;
virtual SQLRETURN get_data( _In_ SQLUSMALLINT field_index, _In_ SQLSMALLINT target_type,
_Out_writes_bytes_opt_(buffer_length) void* buffer, _In_ SQLLEN buffer_length, _Inout_ SQLLEN* out_buffer_length,
bool handle_warning TSRMLS_DC )= 0;
virtual SQLRETURN get_diag_field( SQLSMALLINT record_number, SQLSMALLINT diag_identifier,
_Out_ SQLPOINTER diag_info_buffer, SQLSMALLINT buffer_length,
_Out_ SQLSMALLINT* out_buffer_length TSRMLS_DC ) = 0;
virtual sqlsrv_error* get_diag_rec( SQLSMALLINT record_number ) = 0;
virtual SQLRETURN get_diag_field( _In_ SQLSMALLINT record_number, _In_ SQLSMALLINT diag_identifier,
_Inout_updates_(buffer_length) SQLPOINTER diag_info_buffer, _In_ SQLSMALLINT buffer_length,
_Inout_ SQLSMALLINT* out_buffer_length TSRMLS_DC ) = 0;
virtual sqlsrv_error* get_diag_rec( _In_ SQLSMALLINT record_number ) = 0;
virtual SQLLEN row_count( TSRMLS_D ) = 0;
};
struct sqlsrv_odbc_result_set : public sqlsrv_result_set {
explicit sqlsrv_odbc_result_set( sqlsrv_stmt* );
explicit sqlsrv_odbc_result_set( _In_ sqlsrv_stmt* );
virtual ~sqlsrv_odbc_result_set( void );
virtual bool cached( int field_index ) { return false; }
virtual SQLRETURN fetch( SQLSMALLINT fetch_orientation, SQLLEN fetch_offset TSRMLS_DC );
virtual SQLRETURN get_data( SQLUSMALLINT field_index, SQLSMALLINT target_type,
_Out_ void* buffer, SQLLEN buffer_length, _Out_ SQLLEN* out_buffer_length,
bool handle_warning TSRMLS_DC );
virtual SQLRETURN get_diag_field( SQLSMALLINT record_number, SQLSMALLINT diag_identifier,
_Out_ SQLPOINTER diag_info_buffer, SQLSMALLINT buffer_length,
_Out_ SQLSMALLINT* out_buffer_length TSRMLS_DC );
virtual sqlsrv_error* get_diag_rec( SQLSMALLINT record_number );
virtual SQLRETURN fetch( _In_ SQLSMALLINT fetch_orientation, _In_ SQLLEN fetch_offset TSRMLS_DC );
virtual SQLRETURN get_data( _In_ SQLUSMALLINT field_index, _In_ SQLSMALLINT target_type,
_Out_writes_opt_(buffer_length) void* buffer, _In_ SQLLEN buffer_length, _Inout_ SQLLEN* out_buffer_length,
_In_ bool handle_warning TSRMLS_DC );
virtual SQLRETURN get_diag_field( _In_ SQLSMALLINT record_number, _In_ SQLSMALLINT diag_identifier,
_Inout_updates_(buffer_length) SQLPOINTER diag_info_buffer, _In_ SQLSMALLINT buffer_length,
_Inout_ SQLSMALLINT* out_buffer_length TSRMLS_DC );
virtual sqlsrv_error* get_diag_rec( _In_ SQLSMALLINT record_number );
virtual SQLLEN row_count( TSRMLS_D );
private:
@ -1468,18 +1472,18 @@ struct sqlsrv_buffered_result_set : public sqlsrv_result_set {
static const zend_long BUFFERED_QUERY_LIMIT_DEFAULT = 10240; // measured in KB
static const zend_long BUFFERED_QUERY_LIMIT_INVALID = 0;
explicit sqlsrv_buffered_result_set( sqlsrv_stmt* odbc TSRMLS_DC );
explicit sqlsrv_buffered_result_set( _Inout_ sqlsrv_stmt* odbc TSRMLS_DC );
virtual ~sqlsrv_buffered_result_set( void );
virtual bool cached( int field_index ) { return true; }
virtual SQLRETURN fetch( SQLSMALLINT fetch_orientation, SQLLEN fetch_offset TSRMLS_DC );
virtual SQLRETURN get_data( SQLUSMALLINT field_index, SQLSMALLINT target_type,
_Out_ void* buffer, SQLLEN buffer_length, _Out_ SQLLEN* out_buffer_length,
virtual SQLRETURN fetch( _Inout_ SQLSMALLINT fetch_orientation, _Inout_opt_ SQLLEN fetch_offset TSRMLS_DC );
virtual SQLRETURN get_data( _In_ SQLUSMALLINT field_index, _In_ SQLSMALLINT target_type,
_Out_writes_bytes_opt_(buffer_length) void* buffer, _In_ SQLLEN buffer_length, _Inout_ SQLLEN* out_buffer_length,
bool handle_warning TSRMLS_DC );
virtual SQLRETURN get_diag_field( SQLSMALLINT record_number, SQLSMALLINT diag_identifier,
_Out_ SQLPOINTER diag_info_buffer, SQLSMALLINT buffer_length,
_Out_ SQLSMALLINT* out_buffer_length TSRMLS_DC );
virtual sqlsrv_error* get_diag_rec( SQLSMALLINT record_number );
virtual SQLRETURN get_diag_field( _In_ SQLSMALLINT record_number, _In_ SQLSMALLINT diag_identifier,
_Inout_updates_(buffer_length) SQLPOINTER diag_info_buffer, _In_ SQLSMALLINT buffer_length,
_Inout_ SQLSMALLINT* out_buffer_length TSRMLS_DC );
virtual sqlsrv_error* get_diag_rec( _In_ SQLSMALLINT record_number );
virtual SQLLEN row_count( TSRMLS_D );
// buffered result set specific
@ -1509,55 +1513,55 @@ struct sqlsrv_buffered_result_set : public sqlsrv_result_set {
sqlsrv_malloc_auto_ptr<SQLCHAR> temp_string; // temp buffer to hold a converted field while in use
SQLLEN temp_length; // number of bytes in the temp conversion buffer
typedef SQLRETURN (sqlsrv_buffered_result_set::*conv_fn)( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ SQLLEN* out_buffer_length );
typedef SQLRETURN (sqlsrv_buffered_result_set::*conv_fn)( _In_ SQLSMALLINT field_index, _Out_writes_z_(*out_buffer_length) void* buffer, _In_ SQLLEN buffer_length,
_Inout_ SQLLEN* out_buffer_length );
typedef std::map< SQLINTEGER, std::map< SQLINTEGER, conv_fn > > conv_matrix_t;
// two dimentional sparse matrix that holds the [from][to] functions that do conversions
static conv_matrix_t conv_matrix;
// string conversion functions
SQLRETURN binary_to_wide_string( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
SQLRETURN binary_to_wide_string( _In_ SQLSMALLINT field_index, _Out_writes_z_(*out_buffer_length) void* buffer, _In_ SQLLEN buffer_length,
_Inout_ SQLLEN* out_buffer_length );
SQLRETURN binary_to_system_string( _In_ SQLSMALLINT field_index, _Out_writes_z_(*out_buffer_length) void* buffer, _In_ SQLLEN buffer_length,
_Inout_ SQLLEN* out_buffer_length );
SQLRETURN system_to_wide_string( _In_ SQLSMALLINT field_index, _Out_writes_z_(*out_buffer_length) void* buffer, _In_ SQLLEN buffer_length,
_Out_ SQLLEN* out_buffer_length );
SQLRETURN binary_to_system_string( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ SQLLEN* out_buffer_length );
SQLRETURN system_to_wide_string( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ SQLLEN* out_buffer_length );
SQLRETURN to_binary_string( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
SQLRETURN to_binary_string( _In_ SQLSMALLINT field_index, _Out_writes_bytes_to_opt_(buffer_length, *out_buffer_length) void* buffer, _In_ SQLLEN buffer_length,
_Out_ SQLLEN* out_buffer_length );
SQLRETURN to_same_string( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
SQLRETURN to_same_string( _In_ SQLSMALLINT field_index, _Out_writes_bytes_to_opt_(buffer_length, *out_buffer_length) void* buffer, _In_ SQLLEN buffer_length,
_Out_ SQLLEN* out_buffer_length );
SQLRETURN wide_to_system_string( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ SQLLEN* out_buffer_length );
SQLRETURN wide_to_system_string( _In_ SQLSMALLINT field_index, _Inout_updates_bytes_to_(buffer_length, *out_buffer_length) void* buffer, _In_ SQLLEN buffer_length,
_Inout_ SQLLEN* out_buffer_length );
// long conversion functions
SQLRETURN to_long( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length, _Out_ SQLLEN* out_buffer_length );
SQLRETURN long_to_system_string( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ SQLLEN* out_buffer_length );
SQLRETURN long_to_wide_string( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ SQLLEN* out_buffer_length );
SQLRETURN long_to_double( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
SQLRETURN to_long( _In_ SQLSMALLINT field_index, _Out_writes_bytes_to_opt_(buffer_length, *out_buffer_length) void* buffer, _In_ SQLLEN buffer_length, _Out_ SQLLEN* out_buffer_length );
SQLRETURN long_to_system_string( _In_ SQLSMALLINT field_index, _Out_writes_bytes_to_opt_(buffer_length, *out_buffer_length) void* buffer, _In_ SQLLEN buffer_length,
_Inout_ SQLLEN* out_buffer_length );
SQLRETURN long_to_wide_string( _In_ SQLSMALLINT field_index, _Out_writes_bytes_to_opt_(buffer_length, *out_buffer_length) void* buffer, _In_ SQLLEN buffer_length,
_Inout_ SQLLEN* out_buffer_length );
SQLRETURN long_to_double( _In_ SQLSMALLINT field_index, _Out_writes_bytes_(*out_buffer_length) void* buffer, _In_ SQLLEN buffer_length,
_Out_ SQLLEN* out_buffer_length );
// double conversion functions
SQLRETURN to_double( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length, _Out_ SQLLEN* out_buffer_length );
SQLRETURN double_to_system_string( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ SQLLEN* out_buffer_length );
SQLRETURN double_to_wide_string( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ SQLLEN* out_buffer_length );
SQLRETURN double_to_long( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ SQLLEN* out_buffer_length );
SQLRETURN to_double( _In_ SQLSMALLINT field_index, _Out_writes_bytes_to_opt_(buffer_length, *out_buffer_length) void* buffer, _In_ SQLLEN buffer_length, _Out_ SQLLEN* out_buffer_length );
SQLRETURN double_to_system_string( _In_ SQLSMALLINT field_index, _Out_writes_bytes_to_opt_(buffer_length, *out_buffer_length) void* buffer, _In_ SQLLEN buffer_length,
_Inout_ SQLLEN* out_buffer_length );
SQLRETURN double_to_wide_string( _In_ SQLSMALLINT field_index, _Out_writes_bytes_to_opt_(buffer_length, *out_buffer_length) void* buffer, _In_ SQLLEN buffer_length,
_Inout_ SQLLEN* out_buffer_length );
SQLRETURN double_to_long( _In_ SQLSMALLINT field_index, _Inout_updates_bytes_(*out_buffer_length) void* buffer, _In_ SQLLEN buffer_length,
_Inout_ SQLLEN* out_buffer_length );
// string to number conversion functions
// Future: See if these can be converted directly to template member functions
SQLRETURN string_to_double( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ SQLLEN* out_buffer_length );
SQLRETURN string_to_long( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ SQLLEN* out_buffer_length );
SQLRETURN wstring_to_double( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ SQLLEN* out_buffer_length );
SQLRETURN wstring_to_long( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ SQLLEN* out_buffer_length );
SQLRETURN string_to_double( _In_ SQLSMALLINT field_index, _Out_writes_bytes_(*out_buffer_length) void* buffer, _In_ SQLLEN buffer_length,
_Inout_ SQLLEN* out_buffer_length );
SQLRETURN string_to_long( _In_ SQLSMALLINT field_index, _Out_writes_bytes_(*out_buffer_length) void* buffer, _In_ SQLLEN buffer_length,
_Inout_ SQLLEN* out_buffer_length );
SQLRETURN wstring_to_double( _In_ SQLSMALLINT field_index, _Out_writes_bytes_(*out_buffer_length) void* buffer, _In_ SQLLEN buffer_length,
_Inout_ SQLLEN* out_buffer_length );
SQLRETURN wstring_to_long( _In_ SQLSMALLINT field_index, _Out_writes_bytes_(*out_buffer_length) void* buffer, _In_ SQLLEN buffer_length,
_Inout_ SQLLEN* out_buffer_length );
// utility functions for conversions
unsigned char* get_row( void );
@ -1575,11 +1579,11 @@ struct sqlsrv_buffered_result_set : public sqlsrv_result_set {
#define MEMCHECK_SILENT 1
// utility functions shared by multiple callers across files
bool convert_string_from_utf16_inplace( SQLSRV_ENCODING encoding, char** string, SQLLEN& len);
bool convert_zval_string_from_utf16(SQLSRV_ENCODING encoding, zval* value_z, SQLLEN& len);
bool validate_string(char* string, SQLLEN& len);
bool convert_string_from_utf16( SQLSRV_ENCODING encoding, const SQLWCHAR* inString, SQLINTEGER cchInLen, char** outString, SQLLEN& cchOutLen );
SQLWCHAR* utf16_string_from_mbcs_string( SQLSRV_ENCODING php_encoding, const char* mbcs_string, unsigned int mbcs_len, _Out_ unsigned int* utf16_len );
bool convert_string_from_utf16_inplace( _In_ SQLSRV_ENCODING encoding, _Inout_updates_z_(len) char** string, _Inout_ SQLLEN& len);
bool convert_zval_string_from_utf16( _In_ SQLSRV_ENCODING encoding, _Inout_ zval* value_z, _Inout_ SQLLEN& len);
bool validate_string( _In_ char* string, _In_ SQLLEN& len);
bool convert_string_from_utf16( _In_ SQLSRV_ENCODING encoding, _In_reads_bytes_(cchInLen) const SQLWCHAR* inString, _In_ SQLINTEGER cchInLen, _Inout_updates_bytes_(cchOutLen) char** outString, _Out_ SQLLEN& cchOutLen );
SQLWCHAR* utf16_string_from_mbcs_string( _In_ SQLSRV_ENCODING php_encoding, _In_reads_bytes_(mbcs_len) const char* mbcs_string, _In_ unsigned int mbcs_len, _Out_ unsigned int* utf16_len );
//*********************************************************************************************************************************
// Error handling routines and Predefined Errors
@ -1657,24 +1661,24 @@ enum error_handling_flags {
// 2/code) driver specific error code
// 3/message) driver specific error message
// The fetch type determines if the indices are numeric, associative, or both.
bool core_sqlsrv_get_odbc_error( sqlsrv_context& ctx, int record_number, _Out_ sqlsrv_error_auto_ptr& error,
logging_severity severity TSRMLS_DC );
bool core_sqlsrv_get_odbc_error( _Inout_ sqlsrv_context& ctx, _In_ int record_number, _Inout_ sqlsrv_error_auto_ptr& error,
_In_ logging_severity severity TSRMLS_DC );
// format and return a driver specfic error
void core_sqlsrv_format_driver_error( sqlsrv_context& ctx, sqlsrv_error_const const* custom_error,
sqlsrv_error_auto_ptr& formatted_error, logging_severity severity TSRMLS_DC, va_list* args );
void core_sqlsrv_format_driver_error( _In_ sqlsrv_context& ctx, _In_ sqlsrv_error_const const* custom_error,
_Out_ sqlsrv_error_auto_ptr& formatted_error, _In_ logging_severity severity TSRMLS_DC, _In_opt_ va_list* args );
// return the message for the HRESULT returned by GetLastError. Some driver errors use this to
// return the Windows error, e.g, when a UTF-8 <-> UTF-16 conversion fails.
const char* get_last_error_message( DWORD last_error = 0 );
const char* get_last_error_message( _Inout_ DWORD last_error = 0 );
// a wrapper around FormatMessage that can take variadic args rather than a a va_arg pointer
DWORD core_sqlsrv_format_message( char* output_buffer, unsigned output_len, const char* format, ... );
DWORD core_sqlsrv_format_message( _Out_ char* output_buffer, _In_ unsigned output_len, _In_opt_ const char* format, ... );
// convenience functions that overload either a reference or a pointer so we can use
// either in the CHECK_* functions.
inline bool call_error_handler( sqlsrv_context& ctx, unsigned long sqlsrv_error_code TSRMLS_DC, bool warning, ... )
inline bool call_error_handler( _Inout_ sqlsrv_context& ctx, _In_ unsigned long sqlsrv_error_code TSRMLS_DC, _In_ bool warning, ... )
{
va_list print_params;
va_start( print_params, warning );
@ -1683,7 +1687,7 @@ inline bool call_error_handler( sqlsrv_context& ctx, unsigned long sqlsrv_error_
return ignored;
}
inline bool call_error_handler( sqlsrv_context* ctx, unsigned long sqlsrv_error_code TSRMLS_DC, bool warning, ... )
inline bool call_error_handler( _Inout_ sqlsrv_context* ctx, _In_ unsigned long sqlsrv_error_code TSRMLS_DC, _In_ bool warning, ... )
{
va_list print_params;
va_start( print_params, warning );
@ -1711,7 +1715,7 @@ inline bool call_error_handler( sqlsrv_context* ctx, unsigned long sqlsrv_error_
#endif
// check to see if the sqlstate is 01004, truncated field retrieved. Used for retrieving large fields.
inline bool is_truncated_warning( SQLCHAR* state )
inline bool is_truncated_warning( _In_ SQLCHAR* state )
{
#if defined(ZEND_DEBUG)
if( state == NULL || strlen( reinterpret_cast<char*>( state )) != 5 ) { \
@ -1796,7 +1800,7 @@ namespace core {
}
};
inline void check_for_mars_error( sqlsrv_stmt* stmt, SQLRETURN r TSRMLS_DC )
inline void check_for_mars_error( _Inout_ sqlsrv_stmt* stmt, _In_ SQLRETURN r TSRMLS_DC )
{
// We check for the 'connection busy' error caused by having MultipleActiveResultSets off
// and return a more helpful message prepended to the ODBC errors if that error occurs
@ -1828,9 +1832,9 @@ namespace core {
// These functions take the sqlsrv_context type. However, since the error handling code can alter
// the context to hold the error, they are not passed as const.
inline SQLRETURN SQLGetDiagField( sqlsrv_context* ctx, SQLSMALLINT record_number, SQLSMALLINT diag_identifier,
_Out_ SQLPOINTER diag_info_buffer, SQLSMALLINT buffer_length,
_Out_ SQLSMALLINT* out_buffer_length TSRMLS_DC )
inline SQLRETURN SQLGetDiagField( _Inout_ sqlsrv_context* ctx, _In_ SQLSMALLINT record_number, _In_ SQLSMALLINT diag_identifier,
_Out_writes_opt_(buffer_length) SQLPOINTER diag_info_buffer, _In_ SQLSMALLINT buffer_length,
_Out_opt_ SQLSMALLINT* out_buffer_length TSRMLS_DC )
{
SQLRETURN r = ::SQLGetDiagField( ctx->handle_type(), ctx->handle(), record_number, diag_identifier,
diag_info_buffer, buffer_length, out_buffer_length );
@ -1842,8 +1846,8 @@ namespace core {
return r;
}
inline void SQLAllocHandle( SQLSMALLINT HandleType, sqlsrv_context& InputHandle,
_Out_writes_(1) SQLHANDLE* OutputHandlePtr TSRMLS_DC )
inline void SQLAllocHandle( _In_ SQLSMALLINT HandleType, _Inout_ sqlsrv_context& InputHandle,
_Out_ SQLHANDLE* OutputHandlePtr TSRMLS_DC )
{
SQLRETURN r;
r = ::SQLAllocHandle( HandleType, InputHandle.handle(), OutputHandlePtr );
@ -1852,16 +1856,16 @@ namespace core {
}
}
inline void SQLBindParameter( sqlsrv_stmt* stmt,
SQLUSMALLINT ParameterNumber,
SQLSMALLINT InputOutputType,
SQLSMALLINT ValueType,
SQLSMALLINT ParameterType,
SQLULEN ColumnSize,
SQLSMALLINT DecimalDigits,
_Inout_ SQLPOINTER ParameterValuePtr,
SQLLEN BufferLength,
_Inout_ SQLLEN * StrLen_Or_IndPtr
inline void SQLBindParameter( _Inout_ sqlsrv_stmt* stmt,
_In_ SQLUSMALLINT ParameterNumber,
_In_ SQLSMALLINT InputOutputType,
_In_ SQLSMALLINT ValueType,
_In_ SQLSMALLINT ParameterType,
_In_ SQLULEN ColumnSize,
_In_ SQLSMALLINT DecimalDigits,
_Inout_opt_ SQLPOINTER ParameterValuePtr,
_Inout_ SQLLEN BufferLength,
_Inout_ SQLLEN * StrLen_Or_IndPtr
TSRMLS_DC )
{
SQLRETURN r;
@ -1874,9 +1878,9 @@ namespace core {
}
inline void SQLColAttribute( sqlsrv_stmt* stmt, SQLUSMALLINT field_index, SQLUSMALLINT field_identifier,
_Out_ SQLPOINTER field_type_char, SQLSMALLINT buffer_length,
_Out_ SQLSMALLINT* out_buffer_length, _Out_ SQLLEN* field_type_num TSRMLS_DC )
inline void SQLColAttribute( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT field_index, _In_ SQLUSMALLINT field_identifier,
_Out_writes_bytes_opt_(buffer_length) SQLPOINTER field_type_char, _In_ SQLSMALLINT buffer_length,
_Out_opt_ SQLSMALLINT* out_buffer_length, _Out_opt_ SQLLEN* field_type_num TSRMLS_DC )
{
SQLRETURN r = ::SQLColAttribute( stmt->handle(), field_index, field_identifier, field_type_char,
buffer_length, out_buffer_length, field_type_num );
@ -1886,9 +1890,9 @@ namespace core {
}
}
inline void SQLColAttributeW( sqlsrv_stmt* stmt, SQLUSMALLINT field_index, SQLUSMALLINT field_identifier,
_Out_ SQLPOINTER field_type_char, SQLSMALLINT buffer_length,
_Out_ SQLSMALLINT* out_buffer_length, _Out_ SQLLEN* field_type_num TSRMLS_DC )
inline void SQLColAttributeW( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT field_index, _In_ SQLUSMALLINT field_identifier,
_Out_writes_bytes_opt_(buffer_length) SQLPOINTER field_type_char, _In_ SQLSMALLINT buffer_length,
_Out_opt_ SQLSMALLINT* out_buffer_length, _Out_opt_ SQLLEN* field_type_num TSRMLS_DC )
{
SQLRETURN r = ::SQLColAttributeW( stmt->handle(), field_index, field_identifier, field_type_char,
buffer_length, out_buffer_length, field_type_num );
@ -1898,9 +1902,9 @@ namespace core {
}
}
inline void SQLDescribeCol( sqlsrv_stmt* stmt, SQLSMALLINT colno, _Out_ SQLCHAR* col_name, SQLSMALLINT col_name_length,
_Out_ SQLSMALLINT* col_name_length_out, SQLSMALLINT* data_type, _Out_ SQLULEN* col_size,
_Out_ SQLSMALLINT* decimal_digits, _Out_ SQLSMALLINT* nullable TSRMLS_DC )
inline void SQLDescribeCol( _Inout_ sqlsrv_stmt* stmt, _In_ SQLSMALLINT colno, _Out_writes_opt_(col_name_length) SQLCHAR* col_name, _In_ SQLSMALLINT col_name_length,
_Out_opt_ SQLSMALLINT* col_name_length_out, _Out_opt_ SQLSMALLINT* data_type, _Out_opt_ SQLULEN* col_size,
_Out_opt_ SQLSMALLINT* decimal_digits, _Out_opt_ SQLSMALLINT* nullable TSRMLS_DC )
{
SQLRETURN r;
r = ::SQLDescribeCol( stmt->handle(), colno, col_name, col_name_length, col_name_length_out,
@ -1911,9 +1915,9 @@ namespace core {
}
}
inline void SQLDescribeColW( sqlsrv_stmt* stmt, SQLSMALLINT colno, _Out_ SQLWCHAR* col_name, SQLSMALLINT col_name_length,
_Out_ SQLSMALLINT* col_name_length_out, SQLSMALLINT* data_type, _Out_ SQLULEN* col_size,
_Out_ SQLSMALLINT* decimal_digits, _Out_ SQLSMALLINT* nullable TSRMLS_DC )
inline void SQLDescribeColW( _Inout_ sqlsrv_stmt* stmt, _In_ SQLSMALLINT colno, _Out_writes_opt_(col_name_length) SQLWCHAR* col_name, _In_ SQLSMALLINT col_name_length,
_Out_opt_ SQLSMALLINT* col_name_length_out, _Out_opt_ SQLSMALLINT* data_type, _Out_opt_ SQLULEN* col_size,
_Out_opt_ SQLSMALLINT* decimal_digits, _Out_opt_ SQLSMALLINT* nullable TSRMLS_DC )
{
SQLRETURN r;
r = ::SQLDescribeColW( stmt->handle(), colno, col_name, col_name_length, col_name_length_out,
@ -1924,7 +1928,7 @@ namespace core {
}
}
inline void SQLEndTran( SQLSMALLINT handleType, sqlsrv_conn* conn, SQLSMALLINT completionType TSRMLS_DC )
inline void SQLEndTran( _In_ SQLSMALLINT handleType, _Inout_ sqlsrv_conn* conn, _In_ SQLSMALLINT completionType TSRMLS_DC )
{
SQLRETURN r = ::SQLEndTran( handleType, conn->handle(), completionType );
@ -1934,7 +1938,7 @@ namespace core {
}
// SQLExecDirect returns the status code since it returns either SQL_NEED_DATA or SQL_NO_DATA besides just errors/success
inline SQLRETURN SQLExecDirect( sqlsrv_stmt* stmt, char* sql TSRMLS_DC )
inline SQLRETURN SQLExecDirect( _Inout_ sqlsrv_stmt* stmt, _In_ char* sql TSRMLS_DC )
{
SQLRETURN r = ::SQLExecDirect( stmt->handle(), reinterpret_cast<SQLCHAR*>( sql ), SQL_NTS );
@ -1947,7 +1951,7 @@ namespace core {
return r;
}
inline SQLRETURN SQLExecDirectW( sqlsrv_stmt* stmt, SQLWCHAR* wsql TSRMLS_DC )
inline SQLRETURN SQLExecDirectW( _Inout_ sqlsrv_stmt* stmt, _In_ SQLWCHAR* wsql TSRMLS_DC )
{
SQLRETURN r;
r = ::SQLExecDirectW( stmt->handle(), reinterpret_cast<SQLWCHAR*>( wsql ), SQL_NTS );
@ -1961,7 +1965,7 @@ namespace core {
}
// SQLExecute returns the status code since it returns either SQL_NEED_DATA or SQL_NO_DATA besides just errors/success
inline SQLRETURN SQLExecute( sqlsrv_stmt* stmt TSRMLS_DC )
inline SQLRETURN SQLExecute( _Inout_ sqlsrv_stmt* stmt TSRMLS_DC )
{
SQLRETURN r;
r = ::SQLExecute( stmt->handle() );
@ -1975,7 +1979,7 @@ namespace core {
return r;
}
inline SQLRETURN SQLFetchScroll( sqlsrv_stmt* stmt, SQLSMALLINT fetch_orientation, SQLLEN fetch_offset TSRMLS_DC )
inline SQLRETURN SQLFetchScroll( _Inout_ sqlsrv_stmt* stmt, _In_ SQLSMALLINT fetch_orientation, _In_ SQLLEN fetch_offset TSRMLS_DC )
{
SQLRETURN r = ::SQLFetchScroll( stmt->handle(), fetch_orientation, fetch_offset );
@ -1987,16 +1991,16 @@ namespace core {
// wrap SQLFreeHandle and report any errors, but don't actually signal an error to the calling routine
inline void SQLFreeHandle( sqlsrv_context& ctx TSRMLS_DC )
inline void SQLFreeHandle( _Inout_ sqlsrv_context& ctx TSRMLS_DC )
{
SQLRETURN r;
r = ::SQLFreeHandle( ctx.handle_type(), ctx.handle() );
CHECK_SQL_ERROR_OR_WARNING( r, ctx ) {}
}
inline SQLRETURN SQLGetData( sqlsrv_stmt* stmt, SQLUSMALLINT field_index, SQLSMALLINT target_type,
_Out_ void* buffer, SQLLEN buffer_length, _Out_ SQLLEN* out_buffer_length,
bool handle_warning TSRMLS_DC )
inline SQLRETURN SQLGetData( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT field_index, _In_ SQLSMALLINT target_type,
_Out_writes_opt_(buffer_length) void* buffer, _In_ SQLLEN buffer_length, _Out_opt_ SQLLEN* out_buffer_length,
_In_ bool handle_warning TSRMLS_DC )
{
SQLRETURN r = ::SQLGetData( stmt->handle(), field_index, target_type, buffer, buffer_length, out_buffer_length );
@ -2017,8 +2021,8 @@ namespace core {
}
inline void SQLGetInfo( sqlsrv_conn* conn, SQLUSMALLINT info_type, _Out_ SQLPOINTER info_value, SQLSMALLINT buffer_len,
_Out_ SQLSMALLINT* str_len TSRMLS_DC )
inline void SQLGetInfo( _Inout_ sqlsrv_conn* conn, _In_ SQLUSMALLINT info_type, _Out_writes_bytes_opt_(buffer_len) SQLPOINTER info_value, _In_ SQLSMALLINT buffer_len,
_Out_opt_ SQLSMALLINT* str_len TSRMLS_DC )
{
SQLRETURN r;
r = ::SQLGetInfo( conn->handle(), info_type, info_value, buffer_len, str_len );
@ -2029,7 +2033,7 @@ namespace core {
}
inline void SQLGetTypeInfo( sqlsrv_stmt* stmt, SQLUSMALLINT data_type TSRMLS_DC )
inline void SQLGetTypeInfo( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT data_type TSRMLS_DC )
{
SQLRETURN r;
r = ::SQLGetTypeInfo( stmt->handle(), data_type );
@ -2041,7 +2045,7 @@ namespace core {
// SQLMoreResults returns the status code since it returns SQL_NO_DATA when there is no more data in a result set.
inline SQLRETURN SQLMoreResults( sqlsrv_stmt* stmt TSRMLS_DC )
inline SQLRETURN SQLMoreResults( _Inout_ sqlsrv_stmt* stmt TSRMLS_DC )
{
SQLRETURN r = ::SQLMoreResults( stmt->handle() );
@ -2052,7 +2056,7 @@ namespace core {
return r;
}
inline SQLSMALLINT SQLNumResultCols( sqlsrv_stmt* stmt TSRMLS_DC )
inline SQLSMALLINT SQLNumResultCols( _Inout_ sqlsrv_stmt* stmt TSRMLS_DC )
{
SQLRETURN r;
SQLSMALLINT num_cols;
@ -2067,7 +2071,7 @@ namespace core {
// SQLParamData returns the status code since it returns either SQL_NEED_DATA or SQL_NO_DATA when there are more
// parameters or when the parameters are all processed.
inline SQLRETURN SQLParamData( sqlsrv_stmt* stmt, _Out_ SQLPOINTER* value_ptr_ptr TSRMLS_DC )
inline SQLRETURN SQLParamData( _Inout_ sqlsrv_stmt* stmt, _Out_opt_ SQLPOINTER* value_ptr_ptr TSRMLS_DC )
{
SQLRETURN r;
r = ::SQLParamData( stmt->handle(), value_ptr_ptr );
@ -2077,7 +2081,7 @@ namespace core {
return r;
}
inline void SQLPrepareW( sqlsrv_stmt* stmt, SQLWCHAR * sql, SQLINTEGER sql_len TSRMLS_DC )
inline void SQLPrepareW( _Inout_ sqlsrv_stmt* stmt, _In_reads_(sql_len) SQLWCHAR * sql, _In_ SQLINTEGER sql_len TSRMLS_DC )
{
SQLRETURN r;
r = ::SQLPrepareW( stmt->handle(), sql, sql_len );
@ -2087,7 +2091,7 @@ namespace core {
}
inline void SQLPutData( sqlsrv_stmt* stmt, SQLPOINTER data_ptr, SQLLEN strlen_or_ind TSRMLS_DC )
inline void SQLPutData( _Inout_ sqlsrv_stmt* stmt, _In_reads_(strlen_or_ind) SQLPOINTER data_ptr, _In_ SQLLEN strlen_or_ind TSRMLS_DC )
{
SQLRETURN r;
r = ::SQLPutData( stmt->handle(), data_ptr, strlen_or_ind );
@ -2097,7 +2101,7 @@ namespace core {
}
inline SQLLEN SQLRowCount( sqlsrv_stmt* stmt TSRMLS_DC )
inline SQLLEN SQLRowCount( _Inout_ sqlsrv_stmt* stmt TSRMLS_DC )
{
SQLRETURN r;
SQLLEN rows_affected;
@ -2124,7 +2128,7 @@ namespace core {
}
inline void SQLSetConnectAttr( sqlsrv_context& ctx, SQLINTEGER attr, SQLPOINTER value_ptr, SQLINTEGER str_len TSRMLS_DC )
inline void SQLSetConnectAttr( _Inout_ sqlsrv_context& ctx, _In_ SQLINTEGER attr, _In_reads_bytes_opt_(str_len) SQLPOINTER value_ptr, _In_ SQLINTEGER str_len TSRMLS_DC )
{
SQLRETURN r;
r = ::SQLSetConnectAttr( ctx.handle(), attr, value_ptr, str_len );
@ -2135,7 +2139,7 @@ namespace core {
}
inline void SQLSetEnvAttr( sqlsrv_context& ctx, SQLINTEGER attr, SQLPOINTER value_ptr, SQLINTEGER str_len TSRMLS_DC )
inline void SQLSetEnvAttr( _Inout_ sqlsrv_context& ctx, _In_ SQLINTEGER attr, _In_reads_bytes_opt_(str_len) SQLPOINTER value_ptr, _In_ SQLINTEGER str_len TSRMLS_DC )
{
SQLRETURN r;
r = ::SQLSetEnvAttr( ctx.handle(), attr, value_ptr, str_len );
@ -2144,7 +2148,7 @@ namespace core {
}
}
inline void SQLSetConnectAttr( sqlsrv_conn* conn, SQLINTEGER attribute, SQLPOINTER value_ptr, SQLINTEGER value_len TSRMLS_DC )
inline void SQLSetConnectAttr( _Inout_ sqlsrv_conn* conn, _In_ SQLINTEGER attribute, _In_reads_bytes_opt_(value_len) SQLPOINTER value_ptr, _In_ SQLINTEGER value_len TSRMLS_DC )
{
SQLRETURN r = ::SQLSetConnectAttr( conn->handle(), attribute, value_ptr, value_len );
@ -2153,7 +2157,7 @@ namespace core {
}
}
inline void SQLSetStmtAttr( sqlsrv_stmt* stmt, SQLINTEGER attr, SQLPOINTER value_ptr, SQLINTEGER str_len TSRMLS_DC )
inline void SQLSetStmtAttr( _Inout_ sqlsrv_stmt* stmt, _In_ SQLINTEGER attr, _In_reads_(str_len) SQLPOINTER value_ptr, _In_ SQLINTEGER str_len TSRMLS_DC )
{
SQLRETURN r;
r = ::SQLSetStmtAttr( stmt->handle(), attr, value_ptr, str_len );
@ -2170,7 +2174,7 @@ namespace core {
// wrapper for ZVAL_STRINGL macro. ZVAL_STRINGL always allocates memory when initialzing new string from char string
// so allocated memory inside of value_z should be released before assigning it to the new string
inline void sqlsrv_zval_stringl(zval* value_z, const char* str, const std::size_t str_len)
inline void sqlsrv_zval_stringl( _Inout_ zval* value_z, _In_reads_(str_len) const char* str, _In_ const std::size_t str_len)
{
if (Z_TYPE_P(value_z) == IS_STRING && Z_STR_P(value_z) != NULL) {
zend_string* temp_zstr = zend_string_init(str, str_len, 0);
@ -2191,7 +2195,7 @@ namespace core {
// If there is a zend function in the source that isn't found here, it is because it returns void and there is no error
// that can be thrown from it.
inline void sqlsrv_add_index_zval( sqlsrv_context& ctx, zval* array, zend_ulong index, zval* value TSRMLS_DC)
inline void sqlsrv_add_index_zval( _Inout_ sqlsrv_context& ctx, _Inout_ zval* array, _In_ zend_ulong index, _In_ zval* value TSRMLS_DC)
{
int zr = ::add_index_zval( array, index, value );
CHECK_ZEND_ERROR( zr, ctx, SQLSRV_ERROR_ZEND_HASH ) {
@ -2199,7 +2203,7 @@ namespace core {
}
}
inline void sqlsrv_add_next_index_zval( sqlsrv_context& ctx, zval* array, zval* value TSRMLS_DC)
inline void sqlsrv_add_next_index_zval( _Inout_ sqlsrv_context& ctx, _Inout_ zval* array, _In_ zval* value TSRMLS_DC)
{
int zr = ::add_next_index_zval( array, value );
CHECK_ZEND_ERROR( zr, ctx, SQLSRV_ERROR_ZEND_HASH ) {
@ -2207,7 +2211,7 @@ namespace core {
}
}
inline void sqlsrv_add_assoc_null( sqlsrv_context& ctx, zval* array_z, const char* key TSRMLS_DC )
inline void sqlsrv_add_assoc_null( _Inout_ sqlsrv_context& ctx, _Inout_ zval* array_z, _In_ const char* key TSRMLS_DC )
{
int zr = ::add_assoc_null( array_z, key );
CHECK_ZEND_ERROR (zr, ctx, SQLSRV_ERROR_ZEND_HASH ) {
@ -2215,7 +2219,7 @@ namespace core {
}
}
inline void sqlsrv_add_assoc_long( sqlsrv_context& ctx, zval* array_z, const char* key, zend_long val TSRMLS_DC )
inline void sqlsrv_add_assoc_long( _Inout_ sqlsrv_context& ctx, _Inout_ zval* array_z, _In_ const char* key, _In_ zend_long val TSRMLS_DC )
{
int zr = ::add_assoc_long( array_z, key, val );
CHECK_ZEND_ERROR (zr, ctx, SQLSRV_ERROR_ZEND_HASH ) {
@ -2223,7 +2227,7 @@ namespace core {
}
}
inline void sqlsrv_add_assoc_string( sqlsrv_context& ctx, zval* array_z, const char* key, char* val, bool duplicate TSRMLS_DC )
inline void sqlsrv_add_assoc_string( _Inout_ sqlsrv_context& ctx, _Inout_ zval* array_z, _In_ const char* key, _Inout_z_ char* val, _In_ bool duplicate TSRMLS_DC )
{
int zr = ::add_assoc_string(array_z, key, val);
CHECK_ZEND_ERROR (zr, ctx, SQLSRV_ERROR_ZEND_HASH ) {
@ -2234,7 +2238,7 @@ namespace core {
}
}
inline void sqlsrv_array_init( sqlsrv_context& ctx, _Out_ zval* new_array TSRMLS_DC)
inline void sqlsrv_array_init( _Inout_ sqlsrv_context& ctx, _Out_ zval* new_array TSRMLS_DC)
{
int zr = ::array_init(new_array);
CHECK_ZEND_ERROR( zr, ctx, SQLSRV_ERROR_ZEND_HASH ) {
@ -2242,7 +2246,7 @@ namespace core {
}
}
inline void sqlsrv_php_stream_from_zval_no_verify( sqlsrv_context& ctx, php_stream*& stream, zval* stream_z TSRMLS_DC )
inline void sqlsrv_php_stream_from_zval_no_verify( _Inout_ sqlsrv_context& ctx, _Outref_result_maybenull_ php_stream*& stream, _In_opt_ zval* stream_z TSRMLS_DC )
{
// this duplicates the macro php_stream_from_zval_no_verify, which we can't use because it has an assignment
php_stream_from_zval_no_verify( stream, stream_z );
@ -2251,7 +2255,7 @@ namespace core {
}
}
inline void sqlsrv_zend_hash_get_current_data(sqlsrv_context& ctx, HashTable* ht, _Out_ zval*& output_data TSRMLS_DC)
inline void sqlsrv_zend_hash_get_current_data( _In_ sqlsrv_context& ctx, _In_ HashTable* ht, _Outref_result_maybenull_ zval*& output_data TSRMLS_DC)
{
int zr = (output_data = ::zend_hash_get_current_data(ht)) != NULL ? SUCCESS : FAILURE;
CHECK_ZEND_ERROR( zr, ctx, SQLSRV_ERROR_ZEND_HASH ) {
@ -2259,7 +2263,7 @@ namespace core {
}
}
inline void sqlsrv_zend_hash_get_current_data_ptr(sqlsrv_context& ctx, HashTable* ht, _Out_ void*& output_data TSRMLS_DC)
inline void sqlsrv_zend_hash_get_current_data_ptr( _Inout_ sqlsrv_context& ctx, _In_ HashTable* ht, _Outref_result_maybenull_ void*& output_data TSRMLS_DC)
{
int zr = (output_data = ::zend_hash_get_current_data_ptr(ht)) != NULL ? SUCCESS : FAILURE;
CHECK_ZEND_ERROR(zr, ctx, SQLSRV_ERROR_ZEND_HASH) {
@ -2267,7 +2271,7 @@ namespace core {
}
}
inline void sqlsrv_zend_hash_index_del( sqlsrv_context& ctx, HashTable* ht, zend_ulong index TSRMLS_DC )
inline void sqlsrv_zend_hash_index_del( _Inout_ sqlsrv_context& ctx, _Inout_ HashTable* ht, _In_ zend_ulong index TSRMLS_DC )
{
int zr = ::zend_hash_index_del( ht, index );
CHECK_ZEND_ERROR( zr, ctx, SQLSRV_ERROR_ZEND_HASH ) {
@ -2275,7 +2279,7 @@ namespace core {
}
}
inline void sqlsrv_zend_hash_index_update( sqlsrv_context& ctx, HashTable* ht, zend_ulong index, zval* data_z TSRMLS_DC )
inline void sqlsrv_zend_hash_index_update( _Inout_ sqlsrv_context& ctx, _Inout_ HashTable* ht, _In_ zend_ulong index, _In_ zval* data_z TSRMLS_DC )
{
int zr = (data_z = ::zend_hash_index_update(ht, index, data_z)) != NULL ? SUCCESS : FAILURE;
CHECK_ZEND_ERROR( zr, ctx, SQLSRV_ERROR_ZEND_HASH ) {
@ -2283,7 +2287,7 @@ namespace core {
}
}
inline void sqlsrv_zend_hash_index_update_ptr(sqlsrv_context& ctx, HashTable* ht, zend_ulong index, void* pData TSRMLS_DC)
inline void sqlsrv_zend_hash_index_update_ptr( _Inout_ sqlsrv_context& ctx, _Inout_ HashTable* ht, _In_ zend_ulong index, _In_ void* pData TSRMLS_DC)
{
int zr = (pData = ::zend_hash_index_update_ptr(ht, index, pData)) != NULL ? SUCCESS : FAILURE;
CHECK_ZEND_ERROR(zr, ctx, SQLSRV_ERROR_ZEND_HASH) {
@ -2292,7 +2296,7 @@ namespace core {
}
inline void sqlsrv_zend_hash_index_update_mem(sqlsrv_context& ctx, HashTable* ht, zend_ulong index, void* pData, std::size_t size TSRMLS_DC)
inline void sqlsrv_zend_hash_index_update_mem( _Inout_ sqlsrv_context& ctx, _Inout_ HashTable* ht, _In_ zend_ulong index, _In_reads_bytes_(size) void* pData, _In_ std::size_t size TSRMLS_DC)
{
int zr = (pData = ::zend_hash_index_update_mem(ht, index, pData, size)) != NULL ? SUCCESS : FAILURE;
CHECK_ZEND_ERROR(zr, ctx, SQLSRV_ERROR_ZEND_HASH) {
@ -2300,7 +2304,7 @@ namespace core {
}
}
inline void sqlsrv_zend_hash_next_index_insert( sqlsrv_context& ctx, HashTable* ht, zval* data TSRMLS_DC )
inline void sqlsrv_zend_hash_next_index_insert( _Inout_ sqlsrv_context& ctx, _Inout_ HashTable* ht, _In_ zval* data TSRMLS_DC )
{
int zr = (data = ::zend_hash_next_index_insert(ht, data)) != NULL ? SUCCESS : FAILURE;
CHECK_ZEND_ERROR( zr, ctx, SQLSRV_ERROR_ZEND_HASH ) {
@ -2308,7 +2312,7 @@ namespace core {
}
}
inline void sqlsrv_zend_hash_next_index_insert_mem(sqlsrv_context& ctx, HashTable* ht, void* data, uint data_size TSRMLS_DC)
inline void sqlsrv_zend_hash_next_index_insert_mem( _Inout_ sqlsrv_context& ctx, _In_ HashTable* ht, _In_reads_bytes_(data_size) void* data, _In_ uint data_size TSRMLS_DC)
{
int zr = (data = ::zend_hash_next_index_insert_mem(ht, data, data_size)) != NULL ? SUCCESS : FAILURE;
CHECK_ZEND_ERROR(zr, ctx, SQLSRV_ERROR_ZEND_HASH) {
@ -2316,7 +2320,7 @@ namespace core {
}
}
inline void sqlsrv_zend_hash_next_index_insert_ptr(sqlsrv_context& ctx, HashTable* ht, void* data TSRMLS_DC)
inline void sqlsrv_zend_hash_next_index_insert_ptr( _Inout_ sqlsrv_context& ctx, _Inout_ HashTable* ht, _In_ void* data TSRMLS_DC)
{
int zr = (data = ::zend_hash_next_index_insert_ptr(ht, data)) != NULL ? SUCCESS : FAILURE;
CHECK_ZEND_ERROR(zr, ctx, SQLSRV_ERROR_ZEND_HASH) {
@ -2324,20 +2328,20 @@ namespace core {
}
}
inline void sqlsrv_zend_hash_init(sqlsrv_context& ctx, HashTable* ht, uint32_t initial_size,
dtor_func_t dtor_fn, zend_bool persistent TSRMLS_DC )
inline void sqlsrv_zend_hash_init(sqlsrv_context& ctx, _Inout_ HashTable* ht, _Inout_ uint32_t initial_size,
_In_ dtor_func_t dtor_fn, _In_ zend_bool persistent TSRMLS_DC )
{
::zend_hash_init(ht, initial_size, NULL, dtor_fn, persistent);
}
template <typename Statement>
sqlsrv_stmt* allocate_stmt( sqlsrv_conn* conn, SQLHANDLE h, error_callback e, void* driver TSRMLS_DC )
sqlsrv_stmt* allocate_stmt( _In_ sqlsrv_conn* conn, _In_ SQLHANDLE h, _In_ error_callback e, _In_ void* driver TSRMLS_DC )
{
return new ( sqlsrv_malloc( sizeof( Statement ))) Statement( conn, h, e, driver TSRMLS_CC );
}
template <typename Connection>
sqlsrv_conn* allocate_conn( SQLHANDLE h, error_callback e, void* driver TSRMLS_DC )
sqlsrv_conn* allocate_conn( _In_ SQLHANDLE h, _In_ error_callback e, _In_ void* driver TSRMLS_DC )
{
return new ( sqlsrv_malloc( sizeof( Connection ))) Connection( h, e, driver TSRMLS_CC );
}
@ -2348,7 +2352,7 @@ sqlsrv_conn* allocate_conn( SQLHANDLE h, error_callback e, void* driver TSRMLS_D
template <unsigned int Attr>
struct str_conn_attr_func {
static void func( connection_option const* /*option*/, zval* value, sqlsrv_conn* conn, std::string& /*conn_str*/ TSRMLS_DC )
static void func( connection_option const* /*option*/, zval* value, _Inout_ sqlsrv_conn* conn, std::string& /*conn_str*/ TSRMLS_DC )
{
try {
core::SQLSetConnectAttr( conn, Attr, reinterpret_cast<SQLPOINTER>( Z_STRVAL_P( value )),

View file

@ -3,7 +3,7 @@
//
// Contents: Core routines that use statement handles shared between sqlsrv and pdo_sqlsrv
//
// Microsoft Drivers 4.1 for PHP for SQL Server
// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -29,7 +29,7 @@ struct field_cache {
SQLLEN len;
sqlsrv_phptype type;
field_cache( void* field_value, SQLLEN field_len, sqlsrv_phptype t )
field_cache( _In_reads_bytes_opt_(field_len) void* field_value, _In_ SQLLEN field_len, _In_ sqlsrv_phptype t )
: type( t )
{
// if the value is NULL, then just record a NULL pointer
@ -53,7 +53,7 @@ struct col_cache {
SQLLEN sql_type;
SQLLEN display_size;
col_cache( SQLLEN col_sql_type, SQLLEN col_display_size )
col_cache( _In_ SQLLEN col_sql_type, _In_ SQLLEN col_display_size )
{
sql_type = col_sql_type;
display_size = col_display_size;
@ -88,43 +88,43 @@ const size_t DATE_FORMAT_LEN = sizeof( DATE_FORMAT );
// *** internal functions ***
// Only declarations are put here. Functions contain the documentation they need at their definition sites.
void calc_string_size( sqlsrv_stmt* stmt, SQLUSMALLINT field_index, SQLLEN sql_type, _Out_ SQLLEN& size TSRMLS_DC );
size_t calc_utf8_missing( sqlsrv_stmt* stmt, const char* buffer, size_t buffer_end TSRMLS_DC );
bool check_for_next_stream_parameter( sqlsrv_stmt* stmt TSRMLS_DC );
bool convert_input_param_to_utf16( zval* input_param_z, zval* convert_param_z );
void core_get_field_common(_Inout_ sqlsrv_stmt* stmt, SQLUSMALLINT field_index, sqlsrv_phptype
sqlsrv_php_type, _Out_ void*& field_value, _Out_ SQLLEN* field_len TSRMLS_DC);
void calc_string_size( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT field_index, _In_ SQLLEN sql_type, _Inout_ SQLLEN& size TSRMLS_DC );
size_t calc_utf8_missing( _Inout_ sqlsrv_stmt* stmt, _In_reads_(buffer_end) const char* buffer, _In_ size_t buffer_end TSRMLS_DC );
bool check_for_next_stream_parameter( _Inout_ sqlsrv_stmt* stmt TSRMLS_DC );
bool convert_input_param_to_utf16( _In_ zval* input_param_z, _Inout_ zval* convert_param_z );
void core_get_field_common(_Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT field_index, _Inout_ sqlsrv_phptype
sqlsrv_php_type, _Inout_updates_bytes_(*field_len) void*& field_value, _Inout_ SQLLEN* field_len TSRMLS_DC);
// returns the ODBC C type constant that matches the PHP type and encoding given
SQLSMALLINT default_c_type( sqlsrv_stmt* stmt, SQLULEN paramno, zval const* param_z, SQLSRV_ENCODING encoding TSRMLS_DC );
void default_sql_size_and_scale( sqlsrv_stmt* stmt, unsigned int paramno, zval* param_z, SQLSRV_ENCODING encoding,
SQLSMALLINT default_c_type( _Inout_ sqlsrv_stmt* stmt, _In_opt_ SQLULEN paramno, _In_ zval const* param_z, _In_ SQLSRV_ENCODING encoding TSRMLS_DC );
void default_sql_size_and_scale( _Inout_ sqlsrv_stmt* stmt, _In_opt_ unsigned int paramno, _In_ zval* param_z, _In_ SQLSRV_ENCODING encoding,
_Out_ SQLULEN& column_size, _Out_ SQLSMALLINT& decimal_digits TSRMLS_DC );
// given a zval and encoding, determine the appropriate sql type, column size, and decimal scale (if appropriate)
void default_sql_type( sqlsrv_stmt* stmt, SQLULEN paramno, zval* param_z, SQLSRV_ENCODING encoding,
void default_sql_type( _Inout_ sqlsrv_stmt* stmt, _In_opt_ SQLULEN paramno, _In_ zval* param_z, _In_ SQLSRV_ENCODING encoding,
_Out_ SQLSMALLINT& sql_type TSRMLS_DC );
void col_cache_dtor( zval* data_z );
void field_cache_dtor( zval* data_z );
void finalize_output_parameters( sqlsrv_stmt* stmt TSRMLS_DC );
void get_field_as_string( sqlsrv_stmt* stmt, SQLUSMALLINT field_index, sqlsrv_phptype sqlsrv_php_type,
_Out_ void*& field_value, _Out_ SQLLEN* field_len TSRMLS_DC );
stmt_option const* get_stmt_option( sqlsrv_conn const* conn, zend_ulong key, const stmt_option stmt_opts[] TSRMLS_DC );
bool is_valid_sqlsrv_phptype( sqlsrv_phptype type );
void col_cache_dtor( _Inout_ zval* data_z );
void field_cache_dtor( _Inout_ zval* data_z );
void finalize_output_parameters( _Inout_ sqlsrv_stmt* stmt TSRMLS_DC );
void get_field_as_string( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT field_index, _Inout_ sqlsrv_phptype sqlsrv_php_type,
_Inout_updates_bytes_(*field_len) void*& field_value, _Inout_ SQLLEN* field_len TSRMLS_DC );
stmt_option const* get_stmt_option( sqlsrv_conn const* conn, _In_ zend_ulong key, _In_ const stmt_option stmt_opts[] TSRMLS_DC );
bool is_valid_sqlsrv_phptype( _In_ sqlsrv_phptype type );
// assure there is enough space for the output parameter string
void resize_output_buffer_if_necessary( sqlsrv_stmt* stmt, zval* param_z, SQLULEN paramno, SQLSRV_ENCODING encoding,
SQLSMALLINT c_type, SQLSMALLINT sql_type, SQLULEN column_size, SQLPOINTER& buffer,
SQLLEN& buffer_len TSRMLS_DC );
void save_output_param_for_later( sqlsrv_stmt* stmt, sqlsrv_output_param& param TSRMLS_DC );
void resize_output_buffer_if_necessary( _Inout_ sqlsrv_stmt* stmt, _Inout_ zval* param_z, _In_ SQLULEN paramno, SQLSRV_ENCODING encoding,
_In_ SQLSMALLINT c_type, _In_ SQLSMALLINT sql_type, _In_ SQLULEN column_size, _Out_writes_(buffer_len) SQLPOINTER& buffer,
_Out_ SQLLEN& buffer_len TSRMLS_DC );
void save_output_param_for_later( _Inout_ sqlsrv_stmt* stmt, _Inout_ sqlsrv_output_param& param TSRMLS_DC );
// send all the stream data
void send_param_streams( sqlsrv_stmt* stmt TSRMLS_DC );
void send_param_streams( _Inout_ sqlsrv_stmt* stmt TSRMLS_DC );
// called when a bound output string parameter is to be destroyed
void sqlsrv_output_param_dtor( zval* data );
void sqlsrv_output_param_dtor( _Inout_ zval* data );
// called when a bound stream parameter is to be destroyed.
void sqlsrv_stream_dtor( zval* data );
bool is_streamable_type( SQLINTEGER sql_type );
void sqlsrv_stream_dtor( _Inout_ zval* data );
bool is_streamable_type( _In_ SQLINTEGER sql_type );
}
// constructor for sqlsrv_stmt. Here so that we can use functions declared earlier.
sqlsrv_stmt::sqlsrv_stmt( sqlsrv_conn* c, SQLHANDLE handle, error_callback e, void* drv TSRMLS_DC ) :
sqlsrv_stmt::sqlsrv_stmt( _In_ sqlsrv_conn* c, _In_ SQLHANDLE handle, _In_ error_callback e, _In_opt_ void* drv TSRMLS_DC ) :
sqlsrv_context( handle, SQL_HANDLE_STMT, e, drv, SQLSRV_ENCODING_DEFAULT ),
conn( c ),
executed( false ),
@ -251,8 +251,8 @@ void sqlsrv_stmt::new_result_set( TSRMLS_D )
// Return
// Returns the created statement
sqlsrv_stmt* core_sqlsrv_create_stmt( sqlsrv_conn* conn, driver_stmt_factory stmt_factory, HashTable* options_ht,
const stmt_option valid_stmt_opts[], error_callback const err, void* driver TSRMLS_DC )
sqlsrv_stmt* core_sqlsrv_create_stmt( _Inout_ sqlsrv_conn* conn, _In_ driver_stmt_factory stmt_factory, _In_opt_ HashTable* options_ht,
_In_opt_ const stmt_option valid_stmt_opts[], _In_ error_callback const err, _In_opt_ void* driver TSRMLS_DC )
{
sqlsrv_malloc_auto_ptr<sqlsrv_stmt> stmt;
SQLHANDLE stmt_h = SQL_NULL_HANDLE;
@ -271,7 +271,7 @@ sqlsrv_stmt* core_sqlsrv_create_stmt( sqlsrv_conn* conn, driver_stmt_factory stm
stmt_h = SQL_NULL_HANDLE;
// process the options array given to core_sqlsrv_prepare.
if( options_ht && zend_hash_num_elements( options_ht ) > 0 ) {
if( options_ht && zend_hash_num_elements( options_ht ) > 0 && valid_stmt_opts ) {
zend_ulong index = -1;
zend_string *key = NULL;
zval* value_z = NULL;
@ -336,9 +336,9 @@ sqlsrv_stmt* core_sqlsrv_create_stmt( sqlsrv_conn* conn, driver_stmt_factory stm
// The php type of the parameter is taken from the zval.
// The sql type is given as a hint if the driver provides it.
void core_sqlsrv_bind_param( sqlsrv_stmt* stmt, SQLUSMALLINT param_num, SQLSMALLINT direction, zval* param_z,
SQLSRV_PHPTYPE php_out_type, SQLSRV_ENCODING encoding, SQLSMALLINT sql_type, SQLULEN column_size,
SQLSMALLINT decimal_digits TSRMLS_DC )
void core_sqlsrv_bind_param( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT param_num, _In_ SQLSMALLINT direction, _Inout_ zval* param_z,
_In_ SQLSRV_PHPTYPE php_out_type, _In_ SQLSRV_ENCODING encoding, _Inout_ SQLSMALLINT sql_type, _Inout_ SQLULEN column_size,
_Inout_ SQLSMALLINT decimal_digits TSRMLS_DC )
{
SQLSMALLINT c_type;
SQLPOINTER buffer = NULL;
@ -594,7 +594,7 @@ void core_sqlsrv_bind_param( sqlsrv_stmt* stmt, SQLUSMALLINT param_num, SQLSMALL
zend_class_entry *class_entry = Z_OBJCE_P( param_z TSRMLS_CC );
while( class_entry != NULL ) {
SQLSRV_ASSERT( class_entry->name != NULL, "core_sqlsrv_bind_param: class_entry->name is NULL." );
if( class_entry->name->len == DateTime::DATETIME_CLASS_NAME_LEN && class_entry->name != NULL &&
stricmp( class_entry->name->val, DateTime::DATETIME_CLASS_NAME ) == 0 ) {
valid_class_name_found = true;
@ -676,7 +676,7 @@ void core_sqlsrv_bind_param( sqlsrv_stmt* stmt, SQLUSMALLINT param_num, SQLSMALL
// Return:
// true if there is data, false if there is not
SQLRETURN core_sqlsrv_execute( sqlsrv_stmt* stmt TSRMLS_DC, const char* sql, int sql_len )
SQLRETURN core_sqlsrv_execute( _Inout_ sqlsrv_stmt* stmt TSRMLS_DC, _In_reads_bytes_(sql_len) const char* sql, _In_ int sql_len )
{
SQLRETURN r = SQL_ERROR;
@ -757,7 +757,7 @@ SQLRETURN core_sqlsrv_execute( sqlsrv_stmt* stmt TSRMLS_DC, const char* sql, int
// Nothing, exception thrown if an error. stmt->past_fetch_end is set to true if the
// user scrolls past a non-scrollable result set
bool core_sqlsrv_fetch( sqlsrv_stmt* stmt, SQLSMALLINT fetch_orientation, SQLULEN fetch_offset TSRMLS_DC )
bool core_sqlsrv_fetch( _Inout_ sqlsrv_stmt* stmt, _In_ SQLSMALLINT fetch_orientation, _In_ SQLULEN fetch_offset TSRMLS_DC )
{
// pre-condition check
SQLSRV_ASSERT( fetch_orientation >= SQL_FETCH_NEXT || fetch_orientation <= SQL_FETCH_RELATIVE,
@ -827,7 +827,7 @@ bool core_sqlsrv_fetch( sqlsrv_stmt* stmt, SQLSMALLINT fetch_orientation, SQLULE
// Return:
// A field_meta_data* consisting of the field metadata.
field_meta_data* core_sqlsrv_field_metadata( sqlsrv_stmt* stmt, SQLSMALLINT colno TSRMLS_DC )
field_meta_data* core_sqlsrv_field_metadata( _Inout_ sqlsrv_stmt* stmt, _In_ SQLSMALLINT colno TSRMLS_DC )
{
// pre-condition check
SQLSRV_ASSERT( colno >= 0, "core_sqlsrv_field_metadata: Invalid column number provided." );
@ -882,7 +882,7 @@ field_meta_data* core_sqlsrv_field_metadata( sqlsrv_stmt* stmt, SQLSMALLINT coln
}
// Set the field name lenth
meta_data->field_name_len = field_name_len;
meta_data->field_name_len = static_cast<SQLSMALLINT>( field_name_len );
field_meta_data* result_field_meta_data = meta_data;
meta_data.transferred();
@ -901,8 +901,8 @@ field_meta_data* core_sqlsrv_field_metadata( sqlsrv_stmt* stmt, SQLSMALLINT coln
// Returns:
// Nothing, excpetion thrown if an error occurs
void core_sqlsrv_get_field( sqlsrv_stmt* stmt, SQLUSMALLINT field_index, sqlsrv_phptype sqlsrv_php_type_in, bool prefer_string,
_Out_ void*& field_value, _Out_ SQLLEN* field_len, bool cache_field,
void core_sqlsrv_get_field( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT field_index, _In_ sqlsrv_phptype sqlsrv_php_type_in, _In_ bool prefer_string,
_Outref_result_bytebuffer_maybenull_(*field_len) void*& field_value, _Inout_ SQLLEN* field_len, _In_ bool cache_field,
_Out_ SQLSRV_PHPTYPE *sqlsrv_php_type_out TSRMLS_DC)
{
try {
@ -1004,7 +1004,7 @@ void core_sqlsrv_get_field( sqlsrv_stmt* stmt, SQLUSMALLINT field_index, sqlsrv_
// Return:
// true if any results are present, false otherwise.
bool core_sqlsrv_has_any_result( sqlsrv_stmt* stmt TSRMLS_DC )
bool core_sqlsrv_has_any_result( _Inout_ sqlsrv_stmt* stmt TSRMLS_DC )
{
// Use SQLNumResultCols to determine if we have rows or not.
SQLSMALLINT num_cols = core::SQLNumResultCols( stmt TSRMLS_CC );
@ -1020,7 +1020,7 @@ bool core_sqlsrv_has_any_result( sqlsrv_stmt* stmt TSRMLS_DC )
// Returns
// Nothing, exception thrown if problem occurs
void core_sqlsrv_next_result( sqlsrv_stmt* stmt TSRMLS_DC, bool finalize_output_params, bool throw_on_errors )
void core_sqlsrv_next_result( _Inout_ sqlsrv_stmt* stmt TSRMLS_DC, _In_ bool finalize_output_params, _In_ bool throw_on_errors )
{
try {
@ -1077,7 +1077,7 @@ void core_sqlsrv_next_result( sqlsrv_stmt* stmt TSRMLS_DC, bool finalize_output_
// Returns:
// Nothing, exception thrown if problem occurs
void core_sqlsrv_post_param( sqlsrv_stmt* stmt, zend_ulong param_num, zval* param_z TSRMLS_DC )
void core_sqlsrv_post_param( _Inout_ sqlsrv_stmt* stmt, _In_ zend_ulong param_num, zval* param_z TSRMLS_DC )
{
SQLSRV_ASSERT( Z_TYPE( stmt->param_input_strings ) == IS_ARRAY, "Statement input parameter UTF-16 buffers array invalid." );
SQLSRV_ASSERT( Z_TYPE( stmt->param_streams ) == IS_ARRAY, "Statement input parameter streams array invalid." );
@ -1096,7 +1096,7 @@ void core_sqlsrv_post_param( sqlsrv_stmt* stmt, zend_ulong param_num, zval* para
}
//Calls SQLSetStmtAttr to set a cursor.
void core_sqlsrv_set_scrollable( sqlsrv_stmt* stmt, unsigned long cursor_type TSRMLS_DC )
void core_sqlsrv_set_scrollable( _Inout_ sqlsrv_stmt* stmt, _In_ unsigned long cursor_type TSRMLS_DC )
{
try {
@ -1140,7 +1140,7 @@ void core_sqlsrv_set_scrollable( sqlsrv_stmt* stmt, unsigned long cursor_type TS
}
}
void core_sqlsrv_set_buffered_query_limit( sqlsrv_stmt* stmt, zval* value_z TSRMLS_DC )
void core_sqlsrv_set_buffered_query_limit( _Inout_ sqlsrv_stmt* stmt, _In_ zval* value_z TSRMLS_DC )
{
if( Z_TYPE_P( value_z ) != IS_LONG ) {
@ -1150,7 +1150,7 @@ void core_sqlsrv_set_buffered_query_limit( sqlsrv_stmt* stmt, zval* value_z TSRM
core_sqlsrv_set_buffered_query_limit( stmt, Z_LVAL_P( value_z ) TSRMLS_CC );
}
void core_sqlsrv_set_buffered_query_limit( sqlsrv_stmt* stmt, SQLLEN limit TSRMLS_DC )
void core_sqlsrv_set_buffered_query_limit( _Inout_ sqlsrv_stmt* stmt, _In_ SQLLEN limit TSRMLS_DC )
{
if( limit <= 0 ) {
@ -1164,7 +1164,7 @@ void core_sqlsrv_set_buffered_query_limit( sqlsrv_stmt* stmt, SQLLEN limit TSRML
// Overloaded. Extracts the long value and calls the core_sqlsrv_set_query_timeout
// which accepts timeout parameter as a long. If the zval is not of type long
// than throws error.
void core_sqlsrv_set_query_timeout( sqlsrv_stmt* stmt, zval* value_z TSRMLS_DC )
void core_sqlsrv_set_query_timeout( _Inout_ sqlsrv_stmt* stmt, _Inout_ zval* value_z TSRMLS_DC )
{
try {
@ -1183,7 +1183,7 @@ void core_sqlsrv_set_query_timeout( sqlsrv_stmt* stmt, zval* value_z TSRMLS_DC )
}
// Overloaded. Accepts the timeout as a long.
void core_sqlsrv_set_query_timeout( sqlsrv_stmt* stmt, long timeout TSRMLS_DC )
void core_sqlsrv_set_query_timeout( _Inout_ sqlsrv_stmt* stmt, _In_ long timeout TSRMLS_DC )
{
try {
@ -1212,7 +1212,7 @@ void core_sqlsrv_set_query_timeout( sqlsrv_stmt* stmt, long timeout TSRMLS_DC )
}
}
void core_sqlsrv_set_send_at_exec( sqlsrv_stmt* stmt, zval* value_z TSRMLS_DC )
void core_sqlsrv_set_send_at_exec( _Inout_ sqlsrv_stmt* stmt, _In_ zval* value_z TSRMLS_DC )
{
TSRMLS_C;
@ -1232,7 +1232,7 @@ void core_sqlsrv_set_send_at_exec( sqlsrv_stmt* stmt, zval* value_z TSRMLS_DC )
// Returns:
// true if more data remains to be sent, false if all data processed
bool core_sqlsrv_send_stream_packet( sqlsrv_stmt* stmt TSRMLS_DC )
bool core_sqlsrv_send_stream_packet( _Inout_ sqlsrv_stmt* stmt TSRMLS_DC )
{
// if there no current parameter to process, get the next one
// (probably because this is the first call to sqlsrv_send_stream_data)
@ -1341,7 +1341,7 @@ bool core_sqlsrv_send_stream_packet( sqlsrv_stmt* stmt TSRMLS_DC )
return true;
}
void stmt_option_functor::operator()( sqlsrv_stmt* /*stmt*/, stmt_option const* /*opt*/, zval* /*value_z*/ TSRMLS_DC )
void stmt_option_functor::operator()( _Inout_ sqlsrv_stmt* /*stmt*/, stmt_option const* /*opt*/, _In_ zval* /*value_z*/ TSRMLS_DC )
{
TSRMLS_C;
@ -1349,17 +1349,17 @@ void stmt_option_functor::operator()( sqlsrv_stmt* /*stmt*/, stmt_option const*
DIE( "Not implemented." );
}
void stmt_option_query_timeout:: operator()( sqlsrv_stmt* stmt, stmt_option const* /**/, zval* value_z TSRMLS_DC )
void stmt_option_query_timeout:: operator()( _Inout_ sqlsrv_stmt* stmt, stmt_option const* /**/, _In_ zval* value_z TSRMLS_DC )
{
core_sqlsrv_set_query_timeout( stmt, value_z TSRMLS_CC );
}
void stmt_option_send_at_exec:: operator()( sqlsrv_stmt* stmt, stmt_option const* /*opt*/, zval* value_z TSRMLS_DC )
void stmt_option_send_at_exec:: operator()( _Inout_ sqlsrv_stmt* stmt, stmt_option const* /*opt*/, _In_ zval* value_z TSRMLS_DC )
{
core_sqlsrv_set_send_at_exec( stmt, value_z TSRMLS_CC );
}
void stmt_option_buffered_query_limit:: operator()( sqlsrv_stmt* stmt, stmt_option const* /*opt*/, zval* value_z TSRMLS_DC )
void stmt_option_buffered_query_limit:: operator()( _Inout_ sqlsrv_stmt* stmt, stmt_option const* /*opt*/, _In_ zval* value_z TSRMLS_DC )
{
core_sqlsrv_set_buffered_query_limit( stmt, value_z TSRMLS_CC );
}
@ -1391,7 +1391,7 @@ void close_active_stream( _Inout_ sqlsrv_stmt* stmt TSRMLS_DC )
namespace {
bool is_streamable_type( SQLLEN sql_type )
bool is_streamable_type( _In_ SQLLEN sql_type )
{
switch( sql_type ) {
case SQL_CHAR:
@ -1410,7 +1410,7 @@ bool is_streamable_type( SQLLEN sql_type )
return false;
}
void calc_string_size( sqlsrv_stmt* stmt, SQLUSMALLINT field_index, SQLLEN sql_type, _Out_ SQLLEN& size TSRMLS_DC )
void calc_string_size( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT field_index, _In_ SQLLEN sql_type, _Inout_ SQLLEN& size TSRMLS_DC )
{
try {
@ -1471,7 +1471,7 @@ void calc_string_size( sqlsrv_stmt* stmt, SQLUSMALLINT field_index, SQLLEN sql_t
// calculates how many characters were cut off from the end of a buffer when reading
// in UTF-8 encoded text
size_t calc_utf8_missing( sqlsrv_stmt* stmt, const char* buffer, size_t buffer_end TSRMLS_DC )
size_t calc_utf8_missing( _Inout_ sqlsrv_stmt* stmt, _In_reads_(buffer_end) const char* buffer, _In_ size_t buffer_end TSRMLS_DC )
{
const char* last_char = buffer + buffer_end - 1;
size_t need_to_read = 0;
@ -1509,8 +1509,8 @@ size_t calc_utf8_missing( sqlsrv_stmt* stmt, const char* buffer, size_t buffer_e
// The memory allocation has to happen in the core layer because otherwise
// the driver layer would have to calculate size of the field_value
// to decide the amount of memory allocation.
void core_get_field_common( _Inout_ sqlsrv_stmt* stmt, SQLUSMALLINT field_index, sqlsrv_phptype
sqlsrv_php_type, _Out_ void*& field_value, _Out_ SQLLEN* field_len TSRMLS_DC )
void core_get_field_common( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT field_index, _Inout_ sqlsrv_phptype
sqlsrv_php_type, _Inout_updates_bytes_(*field_len) void*& field_value, _Inout_ SQLLEN* field_len TSRMLS_DC )
{
try {
@ -1738,7 +1738,7 @@ bool check_for_next_stream_parameter( _Inout_ sqlsrv_stmt* stmt TSRMLS_DC )
// utility routine to convert an input parameter from UTF-8 to UTF-16
bool convert_input_param_to_utf16( zval* input_param_z, zval* converted_param_z )
bool convert_input_param_to_utf16( _In_ zval* input_param_z, _Inout_ zval* converted_param_z )
{
SQLSRV_ASSERT( input_param_z == converted_param_z || Z_TYPE_P( converted_param_z ) == IS_NULL,
"convert_input_param_z called with invalid parameter states" );
@ -1795,7 +1795,7 @@ bool convert_input_param_to_utf16( zval* input_param_z, zval* converted_param_z
// returns the ODBC C type constant that matches the PHP type and encoding given
SQLSMALLINT default_c_type( sqlsrv_stmt* stmt, SQLULEN paramno, zval const* param_z, SQLSRV_ENCODING encoding TSRMLS_DC )
SQLSMALLINT default_c_type( _Inout_ sqlsrv_stmt* stmt, _In_opt_ SQLULEN paramno, _In_ zval const* param_z, _In_ SQLSRV_ENCODING encoding TSRMLS_DC )
{
SQLSMALLINT sql_c_type = SQL_UNKNOWN_TYPE;
int php_type = Z_TYPE_P( param_z );
@ -1865,7 +1865,7 @@ SQLSMALLINT default_c_type( sqlsrv_stmt* stmt, SQLULEN paramno, zval const* para
// given a zval and encoding, determine the appropriate sql type
void default_sql_type( sqlsrv_stmt* stmt, SQLULEN paramno, zval* param_z, SQLSRV_ENCODING encoding,
void default_sql_type( _Inout_ sqlsrv_stmt* stmt, _In_opt_ SQLULEN paramno, _In_ zval* param_z, _In_ SQLSRV_ENCODING encoding,
_Out_ SQLSMALLINT& sql_type TSRMLS_DC )
{
sql_type = SQL_UNKNOWN_TYPE;
@ -1943,7 +1943,7 @@ void default_sql_type( sqlsrv_stmt* stmt, SQLULEN paramno, zval* param_z, SQLSRV
// given a zval and encoding, determine the appropriate column size, and decimal scale (if appropriate)
void default_sql_size_and_scale( sqlsrv_stmt* stmt, unsigned int paramno, zval* param_z, SQLSRV_ENCODING encoding,
void default_sql_size_and_scale( _Inout_ sqlsrv_stmt* stmt, _In_opt_ unsigned int paramno, _In_ zval* param_z, _In_ SQLSRV_ENCODING encoding,
_Out_ SQLULEN& column_size, _Out_ SQLSMALLINT& decimal_digits TSRMLS_DC )
{
int php_type = Z_TYPE_P( param_z );
@ -1996,13 +1996,13 @@ void default_sql_size_and_scale( sqlsrv_stmt* stmt, unsigned int paramno, zval*
}
}
void col_cache_dtor( zval* data_z )
void col_cache_dtor( _Inout_ zval* data_z )
{
col_cache* cache = static_cast<col_cache*>( Z_PTR_P( data_z ));
sqlsrv_free( cache );
}
void field_cache_dtor( zval* data_z )
void field_cache_dtor( _Inout_ zval* data_z )
{
field_cache* cache = static_cast<field_cache*>( Z_PTR_P( data_z ));
if( cache->value )
@ -2019,7 +2019,7 @@ void field_cache_dtor( zval* data_z )
// parameters passed to SQLBindParameter. It also converts output strings from UTF-16 to UTF-8 if necessary.
// For integer or float parameters, it sets those to NULL if a NULL was returned by SQL Server
void finalize_output_parameters( sqlsrv_stmt* stmt TSRMLS_DC )
void finalize_output_parameters( _Inout_ sqlsrv_stmt* stmt TSRMLS_DC )
{
if( Z_ISUNDEF(stmt->output_params) )
return;
@ -2127,14 +2127,14 @@ void finalize_output_parameters( sqlsrv_stmt* stmt TSRMLS_DC )
return;
}
void get_field_as_string( sqlsrv_stmt* stmt, SQLUSMALLINT field_index, sqlsrv_phptype sqlsrv_php_type,
_Out_ void*& field_value, _Out_ SQLLEN* field_len TSRMLS_DC )
void get_field_as_string( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT field_index, _Inout_ sqlsrv_phptype sqlsrv_php_type,
_Inout_updates_bytes_(*field_len) void*& field_value, _Inout_ SQLLEN* field_len TSRMLS_DC )
{
SQLRETURN r;
SQLSMALLINT c_type;
SQLLEN sql_field_type = 0;
SQLSMALLINT extra = 0;
SQLLEN field_len_temp;
SQLLEN field_len_temp = 0;
SQLLEN sql_display_size = 0;
char* field_value_temp = NULL;
@ -2205,8 +2205,8 @@ void get_field_as_string( sqlsrv_stmt* stmt, SQLUSMALLINT field_index, sqlsrv_ph
if( r == SQL_SUCCESS_WITH_INFO ) {
SQLCHAR state[ SQL_SQLSTATE_BUFSIZE ];
SQLSMALLINT len;
SQLCHAR state[SQL_SQLSTATE_BUFSIZE] = { 0 };
SQLSMALLINT len = 0;
stmt->current_results->get_diag_field( 1, SQL_DIAG_SQLSTATE, state, SQL_SQLSTATE_BUFSIZE, &len TSRMLS_CC );
@ -2218,7 +2218,7 @@ void get_field_as_string( sqlsrv_stmt* stmt, SQLUSMALLINT field_index, sqlsrv_ph
if( is_truncated_warning( state ) ) {
#endif // !_WIN32
SQLLEN dummy_field_len;
SQLLEN dummy_field_len = 0;
// for XML (and possibly other conditions) the field length returned is not the real field length, so
// in every pass, we double the allocation size to retrieve all the contents.
@ -2391,7 +2391,7 @@ void get_field_as_string( sqlsrv_stmt* stmt, SQLUSMALLINT field_index, sqlsrv_ph
// return the option from the stmt_opts array that matches the key. If no option found,
// NULL is returned.
stmt_option const* get_stmt_option( sqlsrv_conn const* conn, zend_ulong key, const stmt_option stmt_opts[] TSRMLS_DC )
stmt_option const* get_stmt_option( sqlsrv_conn const* conn, _In_ zend_ulong key, _In_ const stmt_option stmt_opts[] TSRMLS_DC )
{
for( int i = 0; stmt_opts[ i ].key != SQLSRV_STMT_OPTION_INVALID; ++i ) {
@ -2407,7 +2407,7 @@ stmt_option const* get_stmt_option( sqlsrv_conn const* conn, zend_ulong key, con
// is_fixed_size_type
// returns true if the SQL data type is a fixed length, as opposed to a variable length data type such as varchar or varbinary
bool is_fixed_size_type( SQLINTEGER sql_type )
bool is_fixed_size_type( _In_ SQLINTEGER sql_type )
{
switch( sql_type ) {
@ -2428,7 +2428,7 @@ bool is_fixed_size_type( SQLINTEGER sql_type )
return true;
}
bool is_valid_sqlsrv_phptype( sqlsrv_phptype type )
bool is_valid_sqlsrv_phptype( _In_ sqlsrv_phptype type )
{
switch( type.typeinfo.type ) {
@ -2457,9 +2457,9 @@ bool is_valid_sqlsrv_phptype( sqlsrv_phptype type )
// string is place in the stmt->output_params. param_z is modified to hold the new buffer, and buffer, buffer_len and
// stmt->param_ind_ptrs are modified to hold the correct values for SQLBindParameter
void resize_output_buffer_if_necessary( sqlsrv_stmt* stmt, zval* param_z, SQLULEN paramno, SQLSRV_ENCODING encoding,
SQLSMALLINT c_type, SQLSMALLINT sql_type, SQLULEN column_size, SQLPOINTER& buffer,
SQLLEN& buffer_len TSRMLS_DC )
void resize_output_buffer_if_necessary( _Inout_ sqlsrv_stmt* stmt, _Inout_ zval* param_z, _In_ SQLULEN paramno, SQLSRV_ENCODING encoding,
_In_ SQLSMALLINT c_type, _In_ SQLSMALLINT sql_type, _In_ SQLULEN column_size, _Out_writes_(buffer_len) SQLPOINTER& buffer,
_Out_ SQLLEN& buffer_len TSRMLS_DC )
{
SQLSRV_ASSERT( column_size != SQLSRV_UNKNOWN_SIZE, "column size should be set to a known value." );
buffer_len = Z_STRLEN_P( param_z );
@ -2528,7 +2528,7 @@ void resize_output_buffer_if_necessary( sqlsrv_stmt* stmt, zval* param_z, SQLULE
// while the query is executed and processed. They are saved in the statement so that
// their reference count may be decremented later (after results are processed)
void save_output_param_for_later( sqlsrv_stmt* stmt, sqlsrv_output_param& param TSRMLS_DC )
void save_output_param_for_later( _Inout_ sqlsrv_stmt* stmt, _Inout_ sqlsrv_output_param& param TSRMLS_DC )
{
HashTable* param_ht = Z_ARRVAL( stmt->output_params );
zend_ulong paramno = static_cast<zend_ulong>( param.param_num );
@ -2539,14 +2539,14 @@ void save_output_param_for_later( sqlsrv_stmt* stmt, sqlsrv_output_param& param
// send all the stream data
void send_param_streams( sqlsrv_stmt* stmt TSRMLS_DC )
void send_param_streams( _Inout_ sqlsrv_stmt* stmt TSRMLS_DC )
{
while( core_sqlsrv_send_stream_packet( stmt TSRMLS_CC )) { }
}
// called by Zend for each parameter in the sqlsrv_stmt::output_params hash table when it is cleaned/destroyed
void sqlsrv_output_param_dtor( zval* data )
void sqlsrv_output_param_dtor( _Inout_ zval* data )
{
sqlsrv_output_param *output_param = static_cast<sqlsrv_output_param*>( Z_PTR_P( data ));
zval_ptr_dtor( output_param->param_z ); // undo the reference to the string we will no longer hold
@ -2554,7 +2554,7 @@ void sqlsrv_output_param_dtor( zval* data )
}
// called by Zend for each stream in the sqlsrv_stmt::param_streams hash table when it is cleaned/destroyed
void sqlsrv_stream_dtor( zval* data )
void sqlsrv_stream_dtor( _Inout_ zval* data )
{
sqlsrv_stream* stream_encoding = static_cast<sqlsrv_stream*>( Z_PTR_P( data ));
zval_ptr_dtor( stream_encoding->stream_z ); // undo the reference to the stream we will no longer hold

View file

@ -3,7 +3,7 @@
//
// Contents: Implementation of PHP streams for reading SQL Server data
//
// Microsoft Drivers 4.1 for PHP for SQL Server
// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -23,7 +23,7 @@ namespace {
// close a stream and free the PHP resources used by it
int sqlsrv_stream_close( php_stream* stream, int /*close_handle*/ TSRMLS_DC )
int sqlsrv_stream_close( _Inout_ php_stream* stream, int /*close_handle*/ TSRMLS_DC )
{
sqlsrv_stream* ss = static_cast<sqlsrv_stream*>( stream->abstract );
SQLSRV_ASSERT( ss != NULL, "sqlsrv_stream_close: sqlsrv_stream* ss was null." );
@ -44,7 +44,7 @@ int sqlsrv_stream_close( php_stream* stream, int /*close_handle*/ TSRMLS_DC )
// read from a sqlsrv stream into the buffer provided by Zend. The parameters for binary vs. char are
// set when sqlsrv_get_field is called by the user specifying which field type they want.
size_t sqlsrv_stream_read( php_stream* stream, _Out_writes_bytes_(count) char* buf, size_t count TSRMLS_DC )
size_t sqlsrv_stream_read( _Inout_ php_stream* stream, _Out_writes_bytes_(count) char* buf, _Inout_ size_t count TSRMLS_DC )
{
SQLLEN read = 0;
SQLSMALLINT c_type = SQL_C_CHAR;
@ -106,8 +106,8 @@ size_t sqlsrv_stream_read( php_stream* stream, _Out_writes_bytes_(count) char* b
// if it's not a binary encoded field
if( r == SQL_SUCCESS_WITH_INFO ) {
SQLCHAR state[ SQL_SQLSTATE_BUFSIZE ];
SQLSMALLINT len;
SQLCHAR state[SQL_SQLSTATE_BUFSIZE] = { 0 };
SQLSMALLINT len = 0;
ss->stmt->current_results->get_diag_field( 1, SQL_DIAG_SQLSTATE, state, SQL_SQLSTATE_BUFSIZE, &len TSRMLS_CC );
@ -155,7 +155,7 @@ size_t sqlsrv_stream_read( php_stream* stream, _Out_writes_bytes_(count) char* b
// convert to UTF-8
#ifdef _WIN32
DWORD flags = 0;
if( g_osversion.dwMajorVersion >= SQLSRV_OS_VISTA_OR_LATER ) {
if( isVistaOrGreater ) {
// Vista (and later) will detect invalid UTF-16 characters and raise an error.
flags = WC_ERR_INVALID_CHARS;
}
@ -181,7 +181,7 @@ size_t sqlsrv_stream_read( php_stream* stream, _Out_writes_bytes_(count) char* b
read = enc_len;
}
return read;
return static_cast<size_t>( read );
}
catch( core::CoreException& ) {
@ -211,8 +211,8 @@ php_stream_ops sqlsrv_stream_ops = {
// open a stream and return the sqlsrv_stream_ops function table as part of the
// return value. There is only one valid way to open a stream, using sqlsrv_get_field on
// certain field types. A sqlsrv stream may only be opened in read mode.
static php_stream* sqlsrv_stream_opener( php_stream_wrapper* wrapper, _In_ const char*, _In_ const char* mode,
int options, _In_ zend_string **, php_stream_context* STREAMS_DC TSRMLS_DC )
static php_stream* sqlsrv_stream_opener( _In_opt_ php_stream_wrapper* wrapper, _In_ const char*, _In_ const char* mode,
_In_opt_ int options, _In_ zend_string **, php_stream_context* STREAMS_DC TSRMLS_DC )
{
#if ZEND_DEBUG

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.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -31,10 +31,10 @@ SQLCHAR INTERNAL_FORMAT_ERROR[] = "An internal error occurred. FormatMessage fa
char last_err_msg[ 2048 ]; // 2k to hold the error messages
// routine used by utf16_string_from_mbcs_string
unsigned int convert_string_from_default_encoding( unsigned int php_encoding, _In_reads_bytes_(mbcs_len) char const* mbcs_in_string,
unsigned int mbcs_len,
unsigned int convert_string_from_default_encoding( _In_ unsigned int php_encoding, _In_reads_bytes_(mbcs_len) char const* mbcs_in_string,
_In_ unsigned int mbcs_len,
_Out_writes_(utf16_len) __transfer( mbcs_in_string ) SQLWCHAR* utf16_out_string,
unsigned int utf16_len );
_In_ unsigned int utf16_len );
}
// SQLSTATE for all internal errors
@ -45,7 +45,7 @@ SQLCHAR SSPWARN[] = "01SSP";
// write to the php log if the severity and subsystem match the filters currently set in the INI or
// the script (sqlsrv_configure).
void write_to_log( unsigned int severity TSRMLS_DC, const char* msg, ...)
void write_to_log( _In_ unsigned int severity TSRMLS_DC, _In_ const char* msg, ...)
{
SQLSRV_ASSERT( !(g_driver_log == NULL), "Must register a driver log function." );
@ -57,7 +57,7 @@ void write_to_log( unsigned int severity TSRMLS_DC, const char* msg, ...)
va_end( args );
}
void core_sqlsrv_register_logger( log_callback driver_logger )
void core_sqlsrv_register_logger( _In_ log_callback driver_logger )
{
g_driver_log = driver_logger;
}
@ -68,7 +68,7 @@ void core_sqlsrv_register_logger( log_callback driver_logger )
// utf-16 string is released by this function if no errors occurred. Otherwise the parameters are not changed
// and false is returned.
bool convert_string_from_utf16_inplace( SQLSRV_ENCODING encoding, char** string, SQLLEN& len)
bool convert_string_from_utf16_inplace( _In_ SQLSRV_ENCODING encoding, _Inout_updates_z_(len) char** string, _Inout_ SQLLEN& len)
{
SQLSRV_ASSERT( string != NULL, "String must be specified" );
@ -91,7 +91,7 @@ bool convert_string_from_utf16_inplace( SQLSRV_ENCODING encoding, char** string,
return result;
}
bool convert_zval_string_from_utf16(SQLSRV_ENCODING encoding, zval* value_z, SQLLEN& len)
bool convert_zval_string_from_utf16( _In_ SQLSRV_ENCODING encoding, _Inout_ zval* value_z, _Inout_ SQLLEN& len)
{
char* string = Z_STRVAL_P(value_z);
@ -110,7 +110,7 @@ bool convert_zval_string_from_utf16(SQLSRV_ENCODING encoding, zval* value_z, SQL
return result;
}
bool validate_string(char* string, SQLLEN& len)
bool validate_string( _In_ char* string, _In_ SQLLEN& len )
{
SQLSRV_ASSERT(string != NULL, "String must be specified");
@ -125,7 +125,7 @@ bool validate_string(char* string, SQLLEN& len)
return false;
}
bool convert_string_from_utf16( SQLSRV_ENCODING encoding, const SQLWCHAR* inString, SQLINTEGER cchInLen, char** outString, SQLLEN& cchOutLen )
bool convert_string_from_utf16( _In_ SQLSRV_ENCODING encoding, _In_reads_bytes_(cchInLen) const SQLWCHAR* inString, _In_ SQLINTEGER cchInLen, _Inout_updates_bytes_(cchOutLen) char** outString, _Out_ SQLLEN& cchOutLen )
{
SQLSRV_ASSERT( inString != NULL, "Input string must be specified" );
SQLSRV_ASSERT( outString != NULL, "Output buffer pointer must be specified" );
@ -141,7 +141,7 @@ bool convert_string_from_utf16( SQLSRV_ENCODING encoding, const SQLWCHAR* inStri
// flags set to 0 by default, which means that any invalid characters are dropped rather than causing
// an error. This happens only on XP.
DWORD flags = 0;
if( encoding == CP_UTF8 && g_osversion.dwMajorVersion >= SQLSRV_OS_VISTA_OR_LATER ) {
if( encoding == CP_UTF8 && isVistaOrGreater ) {
// Vista (and later) will detect invalid UTF-16 characters and raise an error.
flags = WC_ERR_INVALID_CHARS;
}
@ -182,8 +182,8 @@ bool convert_string_from_utf16( SQLSRV_ENCODING encoding, const SQLWCHAR* inStri
// thin wrapper around convert_string_from_default_encoding that handles
// allocation of the destination string. An empty string passed in returns
// failure since it's a failure case for convert_string_from_default_encoding.
SQLWCHAR* utf16_string_from_mbcs_string( SQLSRV_ENCODING php_encoding, const char* mbcs_string, unsigned int mbcs_len,
unsigned int* utf16_len )
SQLWCHAR* utf16_string_from_mbcs_string( _In_ SQLSRV_ENCODING php_encoding, _In_reads_bytes_(mbcs_len) const char* mbcs_string, _In_ unsigned int mbcs_len,
_Out_ unsigned int* utf16_len )
{
*utf16_len = (mbcs_len + 1);
SQLWCHAR* utf16_string = reinterpret_cast<SQLWCHAR*>( sqlsrv_malloc( *utf16_len * sizeof( SQLWCHAR )));
@ -207,7 +207,7 @@ SQLWCHAR* utf16_string_from_mbcs_string( SQLSRV_ENCODING php_encoding, const cha
// 3/message) driver specific error message
// The fetch type determines if the indices are numeric, associative, or both.
bool core_sqlsrv_get_odbc_error( sqlsrv_context& ctx, int record_number, sqlsrv_error_auto_ptr& error, logging_severity severity
bool core_sqlsrv_get_odbc_error( _Inout_ sqlsrv_context& ctx, _In_ int record_number, _Inout_ sqlsrv_error_auto_ptr& error, _In_ logging_severity severity
TSRMLS_DC )
{
SQLHANDLE h = ctx.handle();
@ -284,8 +284,8 @@ bool core_sqlsrv_get_odbc_error( sqlsrv_context& ctx, int record_number, sqlsrv_
}
// format and return a driver specfic error
void core_sqlsrv_format_driver_error( sqlsrv_context& ctx, sqlsrv_error_const const* custom_error,
sqlsrv_error_auto_ptr& formatted_error, logging_severity severity TSRMLS_DC, va_list* args )
void core_sqlsrv_format_driver_error( _In_ sqlsrv_context& ctx, _In_ sqlsrv_error_const const* custom_error,
_Out_ sqlsrv_error_auto_ptr& formatted_error, _In_ logging_severity severity TSRMLS_DC, _In_opt_ va_list* args )
{
// allocate space for the formatted message
formatted_error = new (sqlsrv_malloc( sizeof( sqlsrv_error ))) sqlsrv_error();
@ -309,7 +309,7 @@ void core_sqlsrv_format_driver_error( sqlsrv_context& ctx, sqlsrv_error_const co
LOG( severity, "%1!s!: message = %2!s!", ctx.func(), formatted_error->native_message );
}
DWORD core_sqlsrv_format_message( char* output_buffer, unsigned output_len, const char* format, ... )
DWORD core_sqlsrv_format_message( _Out_ char* output_buffer, _In_ unsigned output_len, _In_opt_ const char* format, ... )
{
va_list format_args;
va_start( format_args, format );
@ -321,7 +321,7 @@ DWORD core_sqlsrv_format_message( char* output_buffer, unsigned output_len, cons
// return an error message for GetLastError using FormatMessage.
// this function returns the msg pointer so that it may be used within
// another function call such as handle_error
const char* get_last_error_message( DWORD last_error )
const char* get_last_error_message( _Inout_ DWORD last_error )
{
if( last_error == 0 ) {
last_error = GetLastError();
@ -346,7 +346,7 @@ const char* get_last_error_message( DWORD last_error )
// places where we were using the FormatMessage syntax inadvertently with DIE which left messages without
// proper information. Rather than convert those messages and try and remember the difference between LOG and
// DIE, it is simpler to make the format syntax common between them.
void die( const char* msg, ... )
void die( _In_opt_ const char* msg, ... )
{
va_list format_args;
va_start( format_args, msg );
@ -367,9 +367,9 @@ namespace {
// returned in utf16_out_string. An empty string passed in will result as
// a failure since MBTWC returns 0 for both an empty string and failure
// to convert.
unsigned int convert_string_from_default_encoding( unsigned int php_encoding, _In_reads_bytes_(mbcs_len) char const* mbcs_in_string,
unsigned int mbcs_len, _Out_writes_(utf16_len) __transfer( mbcs_in_string ) SQLWCHAR* utf16_out_string,
unsigned int utf16_len )
unsigned int convert_string_from_default_encoding( _In_ unsigned int php_encoding, _In_reads_bytes_(mbcs_len) char const* mbcs_in_string,
_In_ unsigned int mbcs_len, _Out_writes_(utf16_len) __transfer( mbcs_in_string ) SQLWCHAR* utf16_out_string,
_In_ unsigned int utf16_len )
{
unsigned int win_encoding = CP_ACP;
switch( php_encoding ) {

View file

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

View file

@ -4,7 +4,7 @@
// Contents: Contains a portable abstraction for interlocked, atomic
// operations on int32_t and pointer types.
//
// Microsoft Drivers 4.2 for PHP for SQL Server
// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License

View file

@ -4,7 +4,7 @@
// Contents: Contains a portable abstraction for interlocked, atomic
// operations on int32_t and pointer types.
//
// Microsoft Drivers 4.2 for PHP for SQL Server
// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License

View file

@ -4,7 +4,7 @@
// Contents: Contains a portable abstraction for interlocked, singly
// linked list.
//
// Microsoft Drivers 4.2 for PHP for SQL Server
// Microsoft Drivers 4.3 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.2 for PHP for SQL Server
// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License

View file

@ -5,7 +5,7 @@
// 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.2 for PHP for SQL Server
// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License

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.2 for PHP for SQL Server
// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License

View file

@ -3,7 +3,7 @@
//
// Contents: Contains the minimal definitions to build on non-Windows platforms
//
// Microsoft Drivers 4.2 for PHP for SQL Server
// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -525,7 +525,9 @@
#define _In_opt_z_count_c_(size)
#define _In_ptrdiff_count_(size)
#define _In_range_(lb,ub)
#define _In_reads_(size)
#define _In_reads_bytes_(size)
#define _In_reads_bytes_opt_(size)
#define _In_z_
#define _In_z_bytecount_(size)
#define _In_z_bytecount_c_(size)
@ -570,6 +572,10 @@
#define _Inout_opt_z_count_(size)
#define _Inout_opt_z_count_c_(size)
#define _Inout_ptrdiff_count_(size)
#define _Inout_updates_(size)
#define _Inout_updates_bytes_(size)
#define _Inout_updates_bytes_to_(size,count)
#define _Inout_updates_z_(size)
#define _Inout_z_
#define _Inout_z_bytecap_(size)
#define _Inout_z_bytecap_c_(size)
@ -626,6 +632,10 @@
#define _Out_range_(lb,ub)
#define _Out_writes_(size)
#define _Out_writes_bytes_(count)
#define _Out_writes_bytes_opt_(size)
#define _Out_writes_bytes_to_opt_(size,count)
#define _Out_writes_opt_(size)
#define _Out_writes_z_(size)
#define _Out_z_bytecap_(size)
#define _Out_z_bytecap_c_(size)
#define _Out_z_bytecap_post_bytecount_(cap,count)
@ -637,6 +647,9 @@
#define _Out_z_cap_post_count_(cap,count)
#define _Out_z_cap_x_(size)
#define _Out_z_capcount_(capcount)
#define _Outptr_result_buffer_(size)
#define _Outref_result_bytebuffer_maybenull_(size)
#define _Outref_result_maybenull_
#define _Post_bytecap_(size)
#define _Post_bytecount_(size)
#define _Post_bytecount_c_(size)

View file

@ -1,7 +1,7 @@
//---------------------------------------------------------------------------------------------------------------------------------
// File: typedefs_for_linux.h
//
// Microsoft Drivers 4.2 for PHP for SQL Server
// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License

View file

@ -4,7 +4,7 @@
// File: version.h
// Contents: Version number constants
//
// Microsoft Drivers 4.2 for PHP for SQL Server
// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -22,14 +22,21 @@
#define STRINGIFY(a) TOSTRING(a)
#define TOSTRING(a) #a
// Increase Major number with backward incompatible breaking changes.
// Increase Minor with backward compatible new functionalities and API changes.
// Increase Patch for backward compatible fixes.
#define SQLVERSION_MAJOR 4
#define SQLVERSION_MINOR 2
#define SQLVERSION_MINOR 3
#define SQLVERSION_PATCH 0
#define SQLVERSION_BUILD 0
// Semantic versioning pre-release, for stable releases should be empty
#define SEMVER_PRERELEASE "preview"
// Semantic versioning build metadata
// Semantic versioning pre-release
// for stable releases should be empty
// "-RC" for release candidates
// "-preview" for ETP
#define SEMVER_PRERELEASE
// Semantic versioning build metadata, build meta data is not counted in precedence order.
#define SEMVER_BUILDMETA
#if SQLVERSION_BUILD > 0
@ -37,11 +44,11 @@
#define SEMVER_BUILDMETA "+" STRINGIFY( SQLVERSION_BUILD )
#endif
// Main version
// Main version, dot separated 3 digits, Major.Minor.Patch
#define VER_APIVERSION_STR STRINGIFY( SQLVERSION_MAJOR ) "." STRINGIFY( SQLVERSION_MINOR ) "." STRINGIFY( SQLVERSION_PATCH )
// Remove "-" if SEMVER_PRERELEASE is empty (for stable releases)
#define VER_FILEVERSION_STR VER_APIVERSION_STR "-" SEMVER_PRERELEASE SEMVER_BUILDMETA
#define VER_FILEVERSION_STR VER_APIVERSION_STR SEMVER_PRERELEASE SEMVER_BUILDMETA
#define _FILEVERSION SQLVERSION_MAJOR,SQLVERSION_MINOR,SQLVERSION_PATCH,SQLVERSION_BUILD
// PECL package version macros (can't have '-' or '+')

View file

@ -3,7 +3,7 @@
//
// Contents: include for definition of Windows types for non-Windows platforms
//
// Microsoft Drivers 4.2 for PHP for SQL Server
// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License

View file

@ -4,7 +4,7 @@
// Contents: This module defines helper functions to prevent
// integer overflow bugs.
//
// Microsoft Drivers 4.2 for PHP for SQL Server
// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License

View file

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

View file

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

View file

@ -27,9 +27,16 @@ if test "$PHP_SQLSRV" != "no"; then
else
AC_MSG_ERROR([Cannot find SQLSRV headers])
fi
AC_MSG_RESULT($sqlsrv_inc_path)
AC_MSG_RESULT($sqlsrv_inc_path)
HOST_OS_ARCH=`uname`
if test "${HOST_OS_ARCH}" = "Darwin"; then
MACOSX_DEPLOYMENT_TARGET=`sw_vers -productVersion`
fi
CXXFLAGS="$CXXFLAGS -std=c++11"
CXXFLAGS="$CXXFLAGS -D_FORTIFY_SOURCE=2 -O2"
CXXFLAGS="$CXXFLAGS -fstack-protector"
PHP_REQUIRE_CXX()
PHP_ADD_LIBRARY(stdc++, 1, SQLSRV_SHARED_LIBADD)
PHP_ADD_LIBRARY(odbc, 1, SQLSRV_SHARED_LIBADD)

View file

@ -3,7 +3,7 @@
//
// Contents: JScript build configuration used by buildconf.bat
//
// Microsoft Drivers 4.2 for PHP for SQL Server
// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -35,6 +35,7 @@ if( PHP_SQLSRV != "no" ) {
ADD_FLAG( "CFLAGS_SQLSRV", "/EHsc" );
ADD_FLAG( "CFLAGS_SQLSRV", "/GS" );
ADD_FLAG( "CFLAGS_SQLSRV", "/Zi" );
ADD_FLAG( "CFLAGS_SQLSRV", "/O2" );
EXTENSION("sqlsrv", sqlsrv_src_class , PHP_SQLSRV_SHARED, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1");
} else {
WARNING("sqlsrv not enabled; libraries and headers not found");

View file

@ -3,7 +3,7 @@
//
// Contents: Routines that use connection handles
//
// Microsoft Drivers 4.2 for PHP for SQL Server
// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -31,7 +31,7 @@ unsigned int current_log_subsystem = LOG_CONN;
struct date_as_string_func {
static void func( connection_option const* /*option*/, zval* value, sqlsrv_conn* conn, std::string& /*conn_str*/ TSRMLS_DC )
static void func( connection_option const* /*option*/, _In_ zval* value, _Inout_ sqlsrv_conn* conn, std::string& /*conn_str*/ TSRMLS_DC )
{
TSRMLS_C; // show as used to avoid a warning
@ -48,7 +48,7 @@ struct date_as_string_func {
struct conn_char_set_func {
static void func( connection_option const* /*option*/, zval* value, sqlsrv_conn* conn, std::string& /*conn_str*/ TSRMLS_DC )
static void func( connection_option const* /*option*/, _Inout_ zval* value, _Inout_ sqlsrv_conn* conn, std::string& /*conn_str*/ TSRMLS_DC )
{
convert_to_string( value );
const char* encoding = Z_STRVAL_P( value );
@ -78,7 +78,7 @@ struct conn_char_set_func {
struct bool_conn_str_func {
static void func( connection_option const* option, zval* value, sqlsrv_conn* /*conn*/, std::string& conn_str TSRMLS_DC )
static void func( _In_ connection_option const* option, _In_ zval* value, sqlsrv_conn* /*conn*/, _Out_ std::string& conn_str TSRMLS_DC )
{
TSRMLS_C;
char const* val_str;
@ -98,7 +98,7 @@ struct bool_conn_str_func {
#ifdef _WIN32
struct int_conn_str_func {
static void func( connection_option const* option, zval* value, sqlsrv_conn* /*conn*/, std::string& conn_str TSRMLS_DC )
static void func( _In_ connection_option const* option, _In_ zval* value, sqlsrv_conn* /*conn*/, _Out_ std::string& conn_str TSRMLS_DC )
{
TSRMLS_C;
SQLSRV_ASSERT( Z_TYPE_P( value ) == IS_LONG, "An integer is expected for this keyword" )
@ -116,7 +116,7 @@ struct int_conn_str_func {
template <unsigned int Attr>
struct int_conn_attr_func {
static void func( connection_option const* /*option*/, zval* value, sqlsrv_conn* conn, std::string& /*conn_str*/ TSRMLS_DC )
static void func( connection_option const* /*option*/, _In_ zval* value, _Inout_ sqlsrv_conn* conn, std::string& /*conn_str*/ TSRMLS_DC )
{
try {
@ -131,7 +131,7 @@ struct int_conn_attr_func {
template <unsigned int Attr>
struct bool_conn_attr_func {
static void func( connection_option const* /*option*/, zval* value, sqlsrv_conn* conn, std::string& /*conn_str*/ TSRMLS_DC )
static void func( connection_option const* /*option*/, _In_ zval* value, _Inout_ sqlsrv_conn* conn, std::string& /*conn_str*/ TSRMLS_DC )
{
try {
core::SQLSetConnectAttr(conn, Attr, reinterpret_cast<SQLPOINTER>((zend_long)zend_is_true(value)),
@ -147,15 +147,15 @@ struct bool_conn_attr_func {
//// *** internal functions ***
void sqlsrv_conn_close_stmts( ss_sqlsrv_conn* conn TSRMLS_DC );
void validate_conn_options( sqlsrv_context& ctx, zval* user_options_z, _Out_ char** uid, _Out_ char** pwd,
void sqlsrv_conn_close_stmts( _Inout_ ss_sqlsrv_conn* conn TSRMLS_DC );
void validate_conn_options( _Inout_ sqlsrv_context& ctx, _In_ zval* user_options_z, _Inout_ char** uid, _Inout_ char** pwd,
_Inout_ HashTable* ss_conn_options_ht TSRMLS_DC );
void validate_stmt_options( sqlsrv_context& ctx, zval* stmt_options, _Inout_ HashTable* ss_stmt_options_ht TSRMLS_DC );
void add_conn_option_key( sqlsrv_context& ctx, zend_string* key, size_t key_len,
HashTable* options_ht, zval* data TSRMLS_DC );
void add_stmt_option_key( sqlsrv_context& ctx, zend_string* key, size_t key_len, HashTable* options_ht, zval* data TSRMLS_DC );
int get_conn_option_key( sqlsrv_context& ctx, zend_string* key, size_t key_len, zval const* value_z TSRMLS_DC );
int get_stmt_option_key( zend_string* key, size_t key_len TSRMLS_DC );
void validate_stmt_options( _Inout_ sqlsrv_context& ctx, _Inout_ zval* stmt_options, _Inout_ HashTable* ss_stmt_options_ht TSRMLS_DC );
void add_conn_option_key( _Inout_ sqlsrv_context& ctx, _In_ zend_string* key, _In_ size_t key_len,
_Inout_ HashTable* options_ht, _Inout_ zval* data TSRMLS_DC );
void add_stmt_option_key( _Inout_ sqlsrv_context& ctx, _In_ zend_string* key, _In_ size_t key_len, _Inout_ HashTable* options_ht, _Inout_ zval* data TSRMLS_DC );
int get_conn_option_key( _Inout_ sqlsrv_context& ctx, _In_ zend_string* key, _In_ size_t key_len, _Inout_ zval const* value_z TSRMLS_DC );
int get_stmt_option_key( _In_ zend_string* key, _In_ size_t key_len TSRMLS_DC );
}
@ -205,6 +205,7 @@ const char TraceFile[] = "TraceFile";
const char TraceOn[] = "TraceOn";
const char TrustServerCertificate[] = "TrustServerCertificate";
const char TransactionIsolation[] = "TransactionIsolation";
const char TransparentNetworkIPResolution[] = "TransparentNetworkIPResolution";
const char UID[] = "UID";
const char WSID[] = "WSID";
@ -420,6 +421,15 @@ const connection_option SS_CONN_OPTS[] = {
CONN_ATTR_BOOL,
bool_conn_str_func::func
},
{
SSConnOptionNames::TransparentNetworkIPResolution,
sizeof(SSConnOptionNames::TransparentNetworkIPResolution),
SQLSRV_CONN_OPTION_TRANSPARANT_NETWORK_IP_RESOLUTION,
ODBCConnOptions::TransparentNetworkIPResolution,
sizeof(ODBCConnOptions::TransparentNetworkIPResolution),
CONN_ATTR_STRING,
conn_str_append_func::func
},
{
SSConnOptionNames::WSID,
sizeof( SSConnOptionNames::WSID ),
@ -637,7 +647,7 @@ PHP_FUNCTION( sqlsrv_close )
THROW_CORE_ERROR( error_ctx, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_ );
}
}
SQLSRV_ASSERT( conn_r != NULL, "sqlsrv_close: conn_r was null" );
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.
@ -658,7 +668,11 @@ PHP_FUNCTION( sqlsrv_close )
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 ));
}
// when conn_r is first parsed in zend_parse_parameters, conn_r becomes a zval that points to a zend_resource with a refcount of 2
// need to DELREF here so the refcount becomes 1 and conn_r can be appropriate destroyed by the garbage collector when it goes out of scope
// zend_list_close only destroy the resource pointed to by Z_RES_P( conn_r ), not the zend_resource itself
Z_TRY_DELREF_P(conn_r);
ZVAL_NULL( conn_r );
RETURN_TRUE;
@ -673,7 +687,7 @@ PHP_FUNCTION( sqlsrv_close )
}
}
void __cdecl sqlsrv_conn_dtor( zend_resource *rsrc TSRMLS_DC )
void __cdecl sqlsrv_conn_dtor( _Inout_ zend_resource *rsrc TSRMLS_DC )
{
LOG_FUNCTION( "sqlsrv_conn_dtor" );
@ -1111,7 +1125,7 @@ PHP_FUNCTION( sqlsrv_query )
}
}
void free_stmt_resource( zval* stmt_z TSRMLS_DC )
void free_stmt_resource( _Inout_ zval* stmt_z TSRMLS_DC )
{
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));
@ -1127,7 +1141,7 @@ namespace {
// must close all statement handles opened by this connection before closing the connection
// no errors are returned, since close should always succeed
void sqlsrv_conn_close_stmts( ss_sqlsrv_conn* conn TSRMLS_DC )
void sqlsrv_conn_close_stmts( _Inout_ ss_sqlsrv_conn* conn TSRMLS_DC )
{
//pre-condition check
SQLSRV_ASSERT(( conn->handle() != NULL ), "sqlsrv_conn_close_stmts: Connection handle is NULL. Trying to destroy an "
@ -1175,7 +1189,7 @@ void sqlsrv_conn_close_stmts( ss_sqlsrv_conn* conn TSRMLS_DC )
conn->stmts = NULL;
}
int get_conn_option_key( sqlsrv_context& ctx, zend_string* key, size_t key_len, zval const* value_z TSRMLS_DC )
int get_conn_option_key( _Inout_ sqlsrv_context& ctx, _In_ zend_string* key, _In_ size_t key_len, _Inout_ zval const* value_z TSRMLS_DC )
{
for( int i=0; SS_CONN_OPTS[ i ].conn_option_key != SQLSRV_CONN_OPTION_INVALID; ++i )
{
@ -1236,7 +1250,7 @@ int get_conn_option_key( sqlsrv_context& ctx, zend_string* key, size_t key_len,
return SQLSRV_CONN_OPTION_INVALID;
}
int get_stmt_option_key( zend_string* key, size_t key_len TSRMLS_DC )
int get_stmt_option_key( _In_ zend_string* key, _In_ size_t key_len TSRMLS_DC )
{
for( int i = 0; SS_STMT_OPTS[ i ].key != SQLSRV_STMT_OPTION_INVALID; ++i )
{
@ -1247,8 +1261,8 @@ int get_stmt_option_key( zend_string* key, size_t key_len TSRMLS_DC )
return SQLSRV_STMT_OPTION_INVALID;
}
void add_stmt_option_key( sqlsrv_context& ctx, zend_string* key, size_t key_len,
HashTable* options_ht, zval* data TSRMLS_DC )
void add_stmt_option_key( _Inout_ sqlsrv_context& ctx, _In_ zend_string* key, _In_ size_t key_len,
_Inout_ HashTable* options_ht, _Inout_ zval* data TSRMLS_DC )
{
int option_key = ::get_stmt_option_key( key, key_len TSRMLS_CC );
@ -1261,8 +1275,8 @@ void add_stmt_option_key( sqlsrv_context& ctx, zend_string* key, size_t key_len,
core::sqlsrv_zend_hash_index_update( ctx, options_ht, option_key, data TSRMLS_CC );
}
void add_conn_option_key( sqlsrv_context& ctx, zend_string* key, size_t key_len,
HashTable* options_ht, zval* data TSRMLS_DC )
void add_conn_option_key( _Inout_ sqlsrv_context& ctx, _In_ zend_string* key, _In_ size_t key_len,
_Inout_ HashTable* options_ht, _Inout_ zval* data TSRMLS_DC )
{
int option_key = ::get_conn_option_key( ctx, key, key_len, data TSRMLS_CC );
CHECK_CUSTOM_ERROR((option_key == SQLSRV_STMT_OPTION_INVALID ), ctx, SS_SQLSRV_ERROR_INVALID_OPTION, ZSTR_VAL( key ) ) {
@ -1278,7 +1292,7 @@ void add_conn_option_key( sqlsrv_context& ctx, zend_string* key, size_t key_len,
// against the list of supported statement options by this driver. After validation
// creates a Hashtable of statement options to be sent to the core layer for processing.
void validate_stmt_options( sqlsrv_context& ctx, zval* stmt_options, _Inout_ HashTable* ss_stmt_options_ht TSRMLS_DC )
void validate_stmt_options( _Inout_ sqlsrv_context& ctx, _Inout_ zval* stmt_options, _Inout_ HashTable* ss_stmt_options_ht TSRMLS_DC )
{
try {
if( stmt_options ) {
@ -1298,8 +1312,13 @@ void validate_stmt_options( sqlsrv_context& ctx, zval* stmt_options, _Inout_ Has
throw core::CoreException();
}
}
key_len = ZSTR_LEN(key) + 1;
add_stmt_option_key( ctx, key, key_len, ss_stmt_options_ht, data TSRMLS_CC );
else if ( key != NULL ) {
key_len = ZSTR_LEN( key ) + 1;
add_stmt_option_key( ctx, key, key_len, ss_stmt_options_ht, data TSRMLS_CC );
}
else {
DIE( "validate_stmt_options: key was null." );
}
} ZEND_HASH_FOREACH_END();
}
}
@ -1313,7 +1332,7 @@ void validate_stmt_options( sqlsrv_context& ctx, zval* stmt_options, _Inout_ Has
// against the predefined list of supported connection options by this driver. After validation
// creates a Hashtable of connection options to be sent to the core layer for processing.
void validate_conn_options( sqlsrv_context& ctx, zval* user_options_z, _Out_ char** uid, _Out_ char** pwd, _Inout_ HashTable* ss_conn_options_ht TSRMLS_DC )
void validate_conn_options( _Inout_ sqlsrv_context& ctx, _In_ zval* user_options_z, _Inout_ char** uid, _Inout_ char** pwd, _Inout_ HashTable* ss_conn_options_ht TSRMLS_DC )
{
try {
@ -1334,21 +1353,25 @@ void validate_conn_options( sqlsrv_context& ctx, zval* user_options_z, _Out_ cha
CHECK_CUSTOM_ERROR(( type != HASH_KEY_IS_STRING ), ctx, SS_SQLSRV_ERROR_INVALID_CONNECTION_KEY ) {
throw ss::SSException();
}
if ( key != NULL ) {
// 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 );
::add_conn_option_key( ctx, key, key_len, ss_conn_options_ht, data TSRMLS_CC );
}
}
else {
::add_conn_option_key( ctx, key, key_len, ss_conn_options_ht, data TSRMLS_CC );
DIE( "validate_conn_options: key was null." );
}
} ZEND_HASH_FOREACH_END();
}

View file

@ -2,7 +2,7 @@
// File: init.cpp
// Contents: initialization routines for the extension
//
// Microsoft Drivers 4.2 for PHP for SQL Server
// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -37,8 +37,8 @@ HashTable* g_ss_warnings_to_ignore_ht = NULL;
HashTable* g_ss_encodings_ht = NULL;
// Destructors called by Zend for each element in the hashtable
void sqlsrv_error_const_dtor( zval* element );
void sqlsrv_encoding_dtor( zval* element );
void sqlsrv_error_const_dtor( _Inout_ zval* element );
void sqlsrv_encoding_dtor( _Inout_ zval* element );
// henv context for creating connections
sqlsrv_context* g_ss_henv_cp;
@ -569,13 +569,13 @@ PHP_MINIT_FUNCTION(sqlsrv)
}
// called by Zend for each parameter in the g_ss_warnings_to_ignore_ht and g_ss_errors_ht hash table when it is destroyed
void sqlsrv_error_const_dtor( zval* elem ) {
void sqlsrv_error_const_dtor( _Inout_ zval* elem ) {
sqlsrv_error_const* error_to_ignore = static_cast<sqlsrv_error_const*>( Z_PTR_P(elem) );
pefree(error_to_ignore, 1);
}
// called by Zend for each parameter in the g_ss_encodings_ht hash table when it is destroyed
void sqlsrv_encoding_dtor( zval* elem ) {
void sqlsrv_encoding_dtor( _Inout_ zval* elem ) {
sqlsrv_encoding* sql_enc = static_cast<sqlsrv_encoding*>( Z_PTR_P(elem) );
pefree(sql_enc, 1);
}

View file

@ -8,7 +8,7 @@
//
// Comments: Also contains "internal" declarations shared across source files.
//
// Microsoft Drivers 4.2 for PHP for SQL Server
// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -99,7 +99,7 @@ extern HMODULE g_sqlsrv_hmodule; // used for getting the versio
extern sqlsrv_context* g_ss_henv_cp;
extern sqlsrv_context* g_ss_henv_ncp;
extern OSVERSIONINFO g_osversion; // used to determine which OS we're running in
extern bool isVistaOrGreater; // used to determine if OS is Vista or Greater
#define phpext_sqlsrv_ptr &g_sqlsrv_module_entry
@ -138,7 +138,7 @@ struct ss_sqlsrv_conn : sqlsrv_conn
static int descriptor;
// initialize with default values
ss_sqlsrv_conn( SQLHANDLE h, error_callback e, void* drv TSRMLS_DC ) :
ss_sqlsrv_conn( _In_ SQLHANDLE h, _In_ error_callback e, _In_ void* drv TSRMLS_DC ) :
sqlsrv_conn( h, e, drv, SQLSRV_ENCODING_SYSTEM TSRMLS_CC ),
stmts( NULL ),
date_as_string( false ),
@ -148,7 +148,7 @@ struct ss_sqlsrv_conn : sqlsrv_conn
};
// resource destructor
void __cdecl sqlsrv_conn_dtor( zend_resource *rsrc TSRMLS_DC );
void __cdecl sqlsrv_conn_dtor( _Inout_ zend_resource *rsrc TSRMLS_DC );
//*********************************************************************************************************************************
// Statement
@ -162,20 +162,20 @@ struct sqlsrv_fetch_field_name {
struct stmt_option_ss_scrollable : public stmt_option_functor {
virtual void operator()( sqlsrv_stmt* stmt, stmt_option const* /*opt*/, zval* value_z TSRMLS_DC );
virtual void operator()( _Inout_ sqlsrv_stmt* stmt, stmt_option const* /*opt*/, _In_ zval* value_z TSRMLS_DC );
};
// This object inherits and overrides the callbacks necessary
struct ss_sqlsrv_stmt : public sqlsrv_stmt {
ss_sqlsrv_stmt( sqlsrv_conn* c, SQLHANDLE handle, error_callback e, void* drv TSRMLS_DC );
ss_sqlsrv_stmt( _In_ sqlsrv_conn* c, _In_ SQLHANDLE handle, _In_ error_callback e, _In_ void* drv TSRMLS_DC );
virtual ~ss_sqlsrv_stmt( void );
void new_result_set( TSRMLS_D );
// driver specific conversion rules from a SQL Server/ODBC type to one of the SQLSRV_PHPTYPE_* constants
sqlsrv_phptype sql_type_to_php_type( SQLINTEGER sql_type, SQLUINTEGER size, bool prefer_string_to_stream );
sqlsrv_phptype sql_type_to_php_type( _In_ SQLINTEGER sql_type, _In_ SQLUINTEGER size, _In_ bool prefer_string_to_stream );
bool prepared; // whether the statement has been prepared yet (used for error messages)
zend_ulong conn_index; // index into the connection hash that contains this statement structure
@ -200,7 +200,7 @@ struct sqlsrv_stream_encoding {
zval* stream_z;
unsigned int encoding;
sqlsrv_stream_encoding( zval* str_z, unsigned int enc ) :
sqlsrv_stream_encoding( _In_ zval* str_z, _In_ unsigned int enc ) :
stream_z( str_z ), encoding( enc )
{
}
@ -223,14 +223,14 @@ PHP_FUNCTION(sqlsrv_rows_affected);
PHP_FUNCTION(sqlsrv_send_stream_data);
// resource destructor
void __cdecl sqlsrv_stmt_dtor( zend_resource *rsrc TSRMLS_DC );
void __cdecl sqlsrv_stmt_dtor( _Inout_ zend_resource *rsrc TSRMLS_DC );
// "internal" statement functions shared by functions in conn.cpp and stmt.cpp
void bind_params( ss_sqlsrv_stmt* stmt TSRMLS_DC );
void bind_params( _Inout_ ss_sqlsrv_stmt* stmt TSRMLS_DC );
bool sqlsrv_stmt_common_execute( sqlsrv_stmt* s, const SQLCHAR* sql_string, int sql_len, bool direct, const char* function
TSRMLS_DC );
void free_odbc_resources( ss_sqlsrv_stmt* stmt TSRMLS_DC );
void free_stmt_resource( zval* stmt_z TSRMLS_DC );
void free_stmt_resource( _Inout_ zval* stmt_z TSRMLS_DC );
//*********************************************************************************************************************************
// Type Functions
@ -358,7 +358,7 @@ enum SS_ERROR_CODES {
extern ss_error SS_ERRORS[];
bool ss_error_handler( sqlsrv_context& ctx, unsigned int sqlsrv_error_code, bool warning TSRMLS_DC, va_list* print_args );
bool ss_error_handler( _Inout_ sqlsrv_context& ctx, _In_ unsigned int sqlsrv_error_code, _In_ bool warning TSRMLS_DC, _In_opt_ va_list* print_args );
// *** extension error functions ***
PHP_FUNCTION(sqlsrv_errors);
@ -367,14 +367,14 @@ PHP_FUNCTION(sqlsrv_errors);
// connection option to UTF-16. mbcs_len and utf16_len are sizes in
// bytes. The return is the number of UTF-16 characters in the string
// returned in utf16_out_string.
unsigned int convert_string_from_default_encoding( unsigned int php_encoding, char const* mbcs_in_string,
unsigned int mbcs_len, _Out_ wchar_t* utf16_out_string,
unsigned int utf16_len );
unsigned int convert_string_from_default_encoding( _In_ unsigned int php_encoding, _In_reads_bytes_(mbcs_len) char const* mbcs_in_string,
_In_ unsigned int mbcs_len, _Out_writes_(utf16_len) __transfer(mbcs_in_string) wchar_t* utf16_out_string,
_In_ unsigned int utf16_len );
// create a wide char string from the passed in mbcs string. NULL is returned if the string
// could not be created. No error is posted by this function. utf16_len is the number of
// wchar_t characters, not the number of bytes.
SQLWCHAR* utf16_string_from_mbcs_string( unsigned int php_encoding, const char* mbcs_string,
unsigned int mbcs_len, _Out_ unsigned int* utf16_len );
SQLWCHAR* utf16_string_from_mbcs_string( _In_ unsigned int php_encoding, _In_reads_bytes_(mbcs_len) const char* mbcs_string,
_In_ unsigned int mbcs_len, _Out_ unsigned int* utf16_len );
// *** internal error macros and functions ***
bool handle_error( sqlsrv_context const* ctx, int log_subsystem, const char* function,
@ -420,13 +420,13 @@ public:
{
}
sqlsrv_context_auto_ptr( const sqlsrv_context_auto_ptr& src ) :
sqlsrv_context_auto_ptr( _Inout_opt_ const sqlsrv_context_auto_ptr& src ) :
sqlsrv_auto_ptr< sqlsrv_context, sqlsrv_context_auto_ptr >( src )
{
}
// free the original pointer and assign a new pointer. Use NULL to simply free the pointer.
void reset( sqlsrv_context* ptr = NULL )
void reset( _In_opt_ sqlsrv_context* ptr = NULL )
{
if( _ptr ) {
_ptr->~sqlsrv_context();
@ -435,12 +435,12 @@ public:
_ptr = ptr;
}
sqlsrv_context* operator=( sqlsrv_context* ptr )
sqlsrv_context* operator=( _In_opt_ sqlsrv_context* ptr )
{
return sqlsrv_auto_ptr< sqlsrv_context, sqlsrv_context_auto_ptr >::operator=( ptr );
}
void operator=( sqlsrv_context_auto_ptr& src )
void operator=( _Inout_opt_ sqlsrv_context_auto_ptr& src )
{
sqlsrv_context* p = src.get();
src.transferred();
@ -464,7 +464,7 @@ public:
}
// logger for ss_sqlsrv called by the core layer when it wants to log something with the LOG macro
void ss_sqlsrv_log( unsigned int severity TSRMLS_DC, const char* msg, va_list* print_args );
void ss_sqlsrv_log( _In_ unsigned int severity TSRMLS_DC, _In_opt_ const char* msg, _In_opt_ va_list* print_args );
// subsystems that may report log messages. These may be used to filter which systems write to the log to prevent noise.
enum logging_subsystems {
@ -490,7 +490,7 @@ namespace ss {
}
};
inline void zend_register_resource(_Out_ zval& rsrc_result, void* rsrc_pointer, int rsrc_type, const char* rsrc_name TSRMLS_DC)
inline void zend_register_resource( _Inout_ zval& rsrc_result, _Inout_ void* rsrc_pointer, _In_ int rsrc_type, _In_opt_ const char* rsrc_name TSRMLS_DC)
{
int zr = (NULL != (Z_RES(rsrc_result) = ::zend_register_resource(rsrc_pointer, rsrc_type)) ? SUCCESS : FAILURE);
CHECK_CUSTOM_ERROR(( zr == FAILURE ), reinterpret_cast<sqlsrv_context*>( rsrc_pointer ), SS_SQLSRV_ERROR_REGISTER_RESOURCE,
@ -508,7 +508,7 @@ namespace ss {
// generic function used to validate parameters to a PHP function.
// Register an invalid parameter error and returns NULL when parameters don't match the spec given.
template <typename H>
inline H* process_params( INTERNAL_FUNCTION_PARAMETERS, char const* param_spec, const char* calling_func, size_t param_count, ... )
inline H* process_params( INTERNAL_FUNCTION_PARAMETERS, _In_ char const* param_spec, _In_ const char* calling_func, _In_ size_t param_count, ... )
{
SQLSRV_UNUSED( return_value );

View file

@ -3,7 +3,7 @@
//
// Contents: Routines that use statement handles
//
// Microsoft Drivers 4.2 for PHP for SQL Server
// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -90,23 +90,23 @@ const char SS_SQLSRV_WARNING_PARAM_VAR_NOT_REF[] = "Variable parameter %d not pa
/* internal functions */
void convert_to_zval( sqlsrv_stmt* stmt, SQLSRV_PHPTYPE sqlsrv_php_type, void* in_val, SQLLEN field_len, zval& out_zval );
void convert_to_zval( _Inout_ sqlsrv_stmt* stmt, _In_ SQLSRV_PHPTYPE sqlsrv_php_type, _In_opt_ void* in_val, _In_ SQLLEN field_len, _Inout_ zval& out_zval );
void fetch_fields_common( _Inout_ ss_sqlsrv_stmt* stmt, zend_long fetch_type, _Out_ zval& fields, bool allow_empty_field_names
void fetch_fields_common( _Inout_ ss_sqlsrv_stmt* stmt, _In_ zend_long fetch_type, _Out_ zval& fields, _In_ bool allow_empty_field_names
TSRMLS_DC );
bool determine_column_size_or_precision( sqlsrv_stmt const* stmt, sqlsrv_sqltype sqlsrv_type, _Out_ SQLULEN* column_size,
bool determine_column_size_or_precision( sqlsrv_stmt const* stmt, _In_ sqlsrv_sqltype sqlsrv_type, _Inout_ SQLULEN* column_size,
_Out_ SQLSMALLINT* decimal_digits );
sqlsrv_phptype determine_sqlsrv_php_type( sqlsrv_stmt const* stmt, SQLINTEGER sql_type, SQLUINTEGER size, bool prefer_string );
void determine_stmt_has_rows( ss_sqlsrv_stmt* stmt TSRMLS_DC );
bool is_valid_sqlsrv_phptype( sqlsrv_phptype type );
bool is_valid_sqlsrv_sqltype( sqlsrv_sqltype type );
void parse_param_array( ss_sqlsrv_stmt* stmt, _Inout_ zval* param_array, zend_ulong index, _Out_ SQLSMALLINT& direction,
void determine_stmt_has_rows( _Inout_ ss_sqlsrv_stmt* stmt TSRMLS_DC );
bool is_valid_sqlsrv_phptype( _In_ sqlsrv_phptype type );
bool is_valid_sqlsrv_sqltype( _In_ sqlsrv_sqltype type );
void parse_param_array( _Inout_ ss_sqlsrv_stmt* stmt, _Inout_ zval* param_array, zend_ulong index, _Out_ SQLSMALLINT& direction,
_Out_ SQLSRV_PHPTYPE& php_out_type, _Out_ SQLSRV_ENCODING& encoding, _Out_ SQLSMALLINT& sql_type,
_Out_ SQLULEN& column_size, _Out_ SQLSMALLINT& decimal_digits TSRMLS_DC );
void type_and_encoding( INTERNAL_FUNCTION_PARAMETERS, int type );
void type_and_size_calc( INTERNAL_FUNCTION_PARAMETERS, int type );
void type_and_precision_calc( INTERNAL_FUNCTION_PARAMETERS, int type );
bool verify_and_set_encoding( const char* encoding_string, _Out_ sqlsrv_phptype& phptype_encoding TSRMLS_DC );
void type_and_encoding( INTERNAL_FUNCTION_PARAMETERS, _In_ int type );
void type_and_size_calc( INTERNAL_FUNCTION_PARAMETERS, _In_ int type );
void type_and_precision_calc( INTERNAL_FUNCTION_PARAMETERS, _In_ int type );
bool verify_and_set_encoding( _In_ const char* encoding_string, _Inout_ sqlsrv_phptype& phptype_encoding TSRMLS_DC );
}
@ -120,7 +120,7 @@ namespace SSCursorTypes {
const char QUERY_OPTION_SCROLLABLE_BUFFERED[] = "buffered";
}
ss_sqlsrv_stmt::ss_sqlsrv_stmt( sqlsrv_conn* c, SQLHANDLE handle, error_callback e, void* drv TSRMLS_DC ) :
ss_sqlsrv_stmt::ss_sqlsrv_stmt( _In_ sqlsrv_conn* c, _In_ SQLHANDLE handle, _In_ error_callback e, _In_ void* drv TSRMLS_DC ) :
sqlsrv_stmt( c, handle, e, drv TSRMLS_CC ),
prepared( false ),
conn_index( -1 ),
@ -166,7 +166,7 @@ void ss_sqlsrv_stmt::new_result_set( TSRMLS_D )
}
// Returns a php type for a given sql type. Also sets the encoding wherever applicable.
sqlsrv_phptype ss_sqlsrv_stmt::sql_type_to_php_type( SQLINTEGER sql_type, SQLUINTEGER size, bool prefer_string_to_stream )
sqlsrv_phptype ss_sqlsrv_stmt::sql_type_to_php_type( _In_ SQLINTEGER sql_type, _In_ SQLUINTEGER size, _In_ bool prefer_string_to_stream )
{
sqlsrv_phptype ss_phptype;
ss_phptype.typeinfo.type = SQLSRV_PHPTYPE_INVALID;
@ -1168,7 +1168,7 @@ PHP_FUNCTION(SQLSRV_SQLTYPE_VARCHAR)
type_and_size_calc( INTERNAL_FUNCTION_PARAM_PASSTHRU, SQL_VARCHAR );
}
void bind_params( ss_sqlsrv_stmt* stmt TSRMLS_DC )
void bind_params( _Inout_ ss_sqlsrv_stmt* stmt TSRMLS_DC )
{
// if there's nothing to do, just return
if( stmt->params_z == NULL ) {
@ -1225,6 +1225,7 @@ void bind_params( ss_sqlsrv_stmt* stmt TSRMLS_DC )
value_z = param_z;
}
// bind the parameter
SQLSRV_ASSERT( value_z != NULL, "bind_params: value_z is null." );
core_sqlsrv_bind_param( stmt, index, direction, value_z, php_out_type, encoding, sql_type, column_size,
decimal_digits TSRMLS_CC );
@ -1282,7 +1283,7 @@ PHP_FUNCTION( sqlsrv_cancel )
}
}
void __cdecl sqlsrv_stmt_dtor(zend_resource *rsrc TSRMLS_DC)
void __cdecl sqlsrv_stmt_dtor( _Inout_ zend_resource *rsrc TSRMLS_DC )
{
LOG_FUNCTION( "sqlsrv_stmt_dtor" );
@ -1362,6 +1363,7 @@ PHP_FUNCTION( sqlsrv_free_stmt )
// if sqlsrv_free_stmt was called on an already closed statment then we just return success.
// zend_list_close sets the type of the closed statment to -1.
SQLSRV_ASSERT( stmt_r != NULL, "sqlsrv_free_stmt: stmt_r is null." );
if ( Z_RES_TYPE_P( stmt_r ) == RSRC_INVALID_TYPE ) {
RETURN_TRUE;
}
@ -1376,6 +1378,10 @@ PHP_FUNCTION( sqlsrv_free_stmt )
LOG( SEV_ERROR, "Failed to remove stmt resource %1!d!", Z_RES_P( stmt_r )->handle);
}
// when stmt_r is first parsed in zend_parse_parameters, stmt_r becomes a zval that points to a zend_resource with a refcount of 2
// need to DELREF here so the refcount becomes 1 and stmt_r can be appropriate destroyed by the garbage collector when it goes out of scope
// zend_list_close only destroy the resource pointed to by Z_RES_P( stmt_r ), not the zend_resource itself
Z_TRY_DELREF_P(stmt_r);
ZVAL_NULL( stmt_r );
RETURN_TRUE;
@ -1392,7 +1398,7 @@ PHP_FUNCTION( sqlsrv_free_stmt )
}
}
void stmt_option_ss_scrollable:: operator()( sqlsrv_stmt* stmt, stmt_option const* /*opt*/, zval* value_z TSRMLS_DC )
void stmt_option_ss_scrollable:: operator()( _Inout_ sqlsrv_stmt* stmt, stmt_option const* /*opt*/, _In_ zval* value_z TSRMLS_DC )
{
CHECK_CUSTOM_ERROR(( Z_TYPE_P( value_z ) != IS_STRING ), stmt, SQLSRV_ERROR_INVALID_OPTION_SCROLLABLE ) {
throw ss::SSException();
@ -1438,7 +1444,7 @@ void stmt_option_ss_scrollable:: operator()( sqlsrv_stmt* stmt, stmt_option cons
namespace {
void convert_to_zval(sqlsrv_stmt* stmt, SQLSRV_PHPTYPE sqlsrv_php_type, void* in_val, SQLLEN field_len, zval& out_zval)
void convert_to_zval( _Inout_ sqlsrv_stmt* stmt, _In_ SQLSRV_PHPTYPE sqlsrv_php_type, _In_opt_ void* in_val, _In_ SQLLEN field_len, _Inout_ zval& out_zval)
{
if ( in_val == NULL ) {
ZVAL_NULL( &out_zval);
@ -1494,7 +1500,7 @@ void convert_to_zval(sqlsrv_stmt* stmt, SQLSRV_PHPTYPE sqlsrv_php_type, void* in
// put in the column size and scale/decimal digits of the sql server type
// these values are taken from the MSDN page at http://msdn2.microsoft.com/en-us/library/ms711786(VS.85).aspx
// for SQL_VARBINARY, SQL_VARCHAR, and SQL_WLONGVARCHAR types, see https://msdn.microsoft.com/en-CA/library/ms187993.aspx
bool determine_column_size_or_precision( sqlsrv_stmt const* stmt, sqlsrv_sqltype sqlsrv_type, _Out_ SQLULEN* column_size,
bool determine_column_size_or_precision( sqlsrv_stmt const* stmt, _In_ sqlsrv_sqltype sqlsrv_type, _Inout_ SQLULEN* column_size,
_Out_ SQLSMALLINT* decimal_digits )
{
*decimal_digits = 0;
@ -1599,7 +1605,7 @@ bool determine_column_size_or_precision( sqlsrv_stmt const* stmt, sqlsrv_sqltype
// given a SQL Server type, return a sqlsrv php type
sqlsrv_phptype determine_sqlsrv_php_type( ss_sqlsrv_stmt const* stmt, SQLINTEGER sql_type, SQLUINTEGER size, bool prefer_string )
sqlsrv_phptype determine_sqlsrv_php_type( _In_ ss_sqlsrv_stmt const* stmt, _In_ SQLINTEGER sql_type, _In_ SQLUINTEGER size, _In_ bool prefer_string )
{
sqlsrv_phptype sqlsrv_phptype;
sqlsrv_phptype.typeinfo.type = PHPTYPE_INVALID;
@ -1696,7 +1702,7 @@ sqlsrv_phptype determine_sqlsrv_php_type( ss_sqlsrv_stmt const* stmt, SQLINTEGER
// The return value simply states whether or not if an error occurred during the determination.
// (All errors are posted here before returning.)
void determine_stmt_has_rows( ss_sqlsrv_stmt* stmt TSRMLS_DC )
void determine_stmt_has_rows( _Inout_ ss_sqlsrv_stmt* stmt TSRMLS_DC )
{
SQLRETURN r = SQL_SUCCESS;
@ -1745,7 +1751,7 @@ void determine_stmt_has_rows( ss_sqlsrv_stmt* stmt TSRMLS_DC )
}
}
void fetch_fields_common( _Inout_ ss_sqlsrv_stmt* stmt, zend_long fetch_type, _Out_ zval& fields, bool allow_empty_field_names
void fetch_fields_common( _Inout_ ss_sqlsrv_stmt* stmt, _In_ zend_long fetch_type, _Out_ zval& fields, _In_ bool allow_empty_field_names
TSRMLS_DC )
{
void* field_value = NULL;
@ -1845,7 +1851,7 @@ void fetch_fields_common( _Inout_ ss_sqlsrv_stmt* stmt, zend_long fetch_type, _O
}
void parse_param_array( ss_sqlsrv_stmt* stmt, _Inout_ zval* param_array, zend_ulong index, _Out_ SQLSMALLINT& direction,
void parse_param_array( _Inout_ ss_sqlsrv_stmt* stmt, _Inout_ zval* param_array, zend_ulong index, _Out_ SQLSMALLINT& direction,
_Out_ SQLSRV_PHPTYPE& php_out_type, _Out_ SQLSRV_ENCODING& encoding, _Out_ SQLSMALLINT& sql_type,
_Out_ SQLULEN& column_size, _Out_ SQLSMALLINT& decimal_digits TSRMLS_DC )
@ -2018,7 +2024,7 @@ void parse_param_array( ss_sqlsrv_stmt* stmt, _Inout_ zval* param_array, zend_ul
}
}
bool is_valid_sqlsrv_phptype( sqlsrv_phptype type )
bool is_valid_sqlsrv_phptype( _In_ sqlsrv_phptype type )
{
switch( type.typeinfo.type ) {
@ -2043,7 +2049,7 @@ bool is_valid_sqlsrv_phptype( sqlsrv_phptype type )
// return if the type is a valid sql server type not including
// size, precision or scale. Use determine_precision_and_scale for that.
bool is_valid_sqlsrv_sqltype( sqlsrv_sqltype sql_type )
bool is_valid_sqlsrv_sqltype( _In_ sqlsrv_sqltype sql_type )
{
switch( sql_type.typeinfo.type ) {
case SQL_BIGINT:
@ -2080,21 +2086,23 @@ bool is_valid_sqlsrv_sqltype( sqlsrv_sqltype sql_type )
// verify an encoding given to type_and_encoding by looking through the list
// of standard encodings created at module initialization time
bool verify_and_set_encoding( const char* encoding_string, _Out_ sqlsrv_phptype& phptype_encoding TSRMLS_DC )
bool verify_and_set_encoding( _In_ const char* encoding_string, _Inout_ sqlsrv_phptype& phptype_encoding TSRMLS_DC )
{
void* encoding_temp = NULL;
zend_ulong index = -1;
zend_string* key = NULL;
ZEND_HASH_FOREACH_KEY_PTR( g_ss_encodings_ht, index, key, encoding_temp ) {
if ( !encoding_temp ) {
DIE( "Fatal: Error retrieving encoding from encoding hash table." );
}
sqlsrv_encoding* encoding = reinterpret_cast<sqlsrv_encoding*>( encoding_temp );
encoding_temp = NULL;
if( !stricmp( encoding_string, encoding->iana )) {
phptype_encoding.typeinfo.encoding = encoding->code_page;
return true;
}
if (encoding_temp) {
sqlsrv_encoding* encoding = reinterpret_cast<sqlsrv_encoding*>(encoding_temp);
encoding_temp = NULL;
if (!stricmp(encoding_string, encoding->iana)) {
phptype_encoding.typeinfo.encoding = encoding->code_page;
return true;
}
}
else {
DIE("Fatal: Error retrieving encoding from encoding hash table.");
}
} ZEND_HASH_FOREACH_END();
return false;
@ -2102,7 +2110,7 @@ bool verify_and_set_encoding( const char* encoding_string, _Out_ sqlsrv_phptype&
// called when one of the SQLSRV_SQLTYPE type functions is called. Encodes the type and size
// into a sqlsrv_sqltype bit fields (see php_sqlsrv.h).
void type_and_size_calc( INTERNAL_FUNCTION_PARAMETERS, int type )
void type_and_size_calc( INTERNAL_FUNCTION_PARAMETERS, _In_ int type )
{
char* size_p = NULL;
size_t size_len = 0;
@ -2112,20 +2120,24 @@ void type_and_size_calc( INTERNAL_FUNCTION_PARAMETERS, int type )
return;
}
if( !strnicmp( "max", size_p, sizeof( "max" ) / sizeof(char)) ) {
size = SQLSRV_SIZE_MAX_TYPE;
if (size_p) {
if (!strnicmp("max", size_p, sizeof("max") / sizeof(char))) {
size = SQLSRV_SIZE_MAX_TYPE;
}
else {
#ifndef _WIN32
errno = 0;
#else
_set_errno(0); // reset errno for atol
#endif // !_WIN32
size = atol(size_p);
if (errno != 0) {
size = SQLSRV_INVALID_SIZE;
}
}
}
else {
#ifndef _WIN32
errno = 0;
#else
_set_errno(0); // reset errno for atol
#endif // !_WIN32
size = atol( size_p );
if( errno != 0 ) {
size = SQLSRV_INVALID_SIZE;
}
DIE("type_and_size_calc: size_p is null.");
}
int max_size = SQL_SERVER_MAX_FIELD_SIZE;
@ -2150,7 +2162,7 @@ void type_and_size_calc( INTERNAL_FUNCTION_PARAMETERS, int type )
// called when the user gives SQLSRV_SQLTYPE_DECIMAL or SQLSRV_SQLTYPE_NUMERIC sql types as the type of the
// field. encodes these into a sqlsrv_sqltype structure (see php_sqlsrv.h)
void type_and_precision_calc( INTERNAL_FUNCTION_PARAMETERS, int type )
void type_and_precision_calc( INTERNAL_FUNCTION_PARAMETERS, _In_ int type )
{
zend_long prec = SQLSRV_INVALID_PRECISION;
zend_long scale = SQLSRV_INVALID_SCALE;
@ -2185,7 +2197,7 @@ void type_and_precision_calc( INTERNAL_FUNCTION_PARAMETERS, int type )
// common code for SQLSRV_PHPTYPE_STREAM and SQLSRV_PHPTYPE_STRING php types given as parameters.
// encodes the type and encoding into a sqlsrv_phptype structure (see php_sqlsrv.h)
void type_and_encoding( INTERNAL_FUNCTION_PARAMETERS, int type )
void type_and_encoding( INTERNAL_FUNCTION_PARAMETERS, _In_ int type )
{
SQLSRV_ASSERT(( type == SQLSRV_PHPTYPE_STREAM || type == SQLSRV_PHPTYPE_STRING ), "type_and_encoding: Invalid type passed." );

View file

@ -3,7 +3,7 @@
//
// Contents: Version resource
//
// Microsoft Drivers 4.2 for PHP for SQL Server
// Microsoft Drivers 4.3 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.2 for PHP for SQL Server
// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -34,15 +34,15 @@ char log_msg[ LOG_MSG_SIZE ];
SQLCHAR INTERNAL_FORMAT_ERROR[] = "An internal error occurred. FormatMessage failed writing an error message.";
// *** internal functions ***
sqlsrv_error_const* get_error_message( unsigned int sqlsrv_error_code );
sqlsrv_error_const* get_error_message( _In_ unsigned int sqlsrv_error_code );
void copy_error_to_zval( zval* error_z, sqlsrv_error_const* error, zval* reported_chain, zval* ignored_chain,
bool warning TSRMLS_DC );
bool ignore_warning( char* sql_state, int native_code TSRMLS_DC );
bool handle_errors_and_warnings( sqlsrv_context& ctx, zval* reported_chain, zval* ignored_chain, logging_severity log_severity,
unsigned int sqlsrv_error_code, bool warning, va_list* print_args TSRMLS_DC );
void copy_error_to_zval( _Inout_ zval* error_z, _In_ sqlsrv_error_const* error, _Inout_ zval* reported_chain, _Inout_ zval* ignored_chain,
_In_ bool warning TSRMLS_DC );
bool ignore_warning( _In_ char* sql_state, _In_ int native_code TSRMLS_DC );
bool handle_errors_and_warnings( _Inout_ sqlsrv_context& ctx, _Inout_ zval* reported_chain, _Inout_ zval* ignored_chain, _In_ logging_severity log_severity,
_In_ unsigned int sqlsrv_error_code, _In_ bool warning, _In_opt_ va_list* print_args TSRMLS_DC );
int sqlsrv_merge_zend_hash_dtor( zval* dest TSRMLS_DC );
int sqlsrv_merge_zend_hash_dtor( _Inout_ zval* dest TSRMLS_DC );
bool sqlsrv_merge_zend_hash( _Inout_ zval* dest_z, zval const* src_z TSRMLS_DC );
}
@ -382,7 +382,7 @@ ss_error SS_ERRORS[] = {
};
// Formats an error message and finally writes it to the php log.
void ss_sqlsrv_log( unsigned int severity TSRMLS_DC, const char* msg, va_list* print_args )
void ss_sqlsrv_log( _In_ unsigned int severity TSRMLS_DC, _In_opt_ const char* msg, _In_opt_ va_list* print_args )
{
if(( severity & SQLSRV_G( log_severity )) && ( SQLSRV_G( current_subsystem ) & SQLSRV_G( log_subsystems ))) {
@ -398,7 +398,7 @@ void ss_sqlsrv_log( unsigned int severity TSRMLS_DC, const char* msg, va_list* p
}
}
bool ss_error_handler(sqlsrv_context& ctx, unsigned int sqlsrv_error_code, bool warning TSRMLS_DC, va_list* print_args )
bool ss_error_handler( _Inout_ sqlsrv_context& ctx, _In_ unsigned int sqlsrv_error_code, _In_ bool warning TSRMLS_DC, _In_opt_ va_list* print_args )
{
logging_severity severity = SEV_ERROR;
if( warning && !SQLSRV_G( warnings_return_as_errors )) {
@ -528,6 +528,7 @@ PHP_FUNCTION( sqlsrv_configure )
}
// WarningsReturnAsErrors
SQLSRV_ASSERT( option[option_len] == '\0', "sqlsrv_configure: option was not null terminated." );
if( !stricmp( option, INI_WARNINGS_RETURN_AS_ERRORS )) {
SQLSRV_G( warnings_return_as_errors ) = zend_is_true( value_z ) ? true : false;
@ -645,7 +646,7 @@ PHP_FUNCTION( sqlsrv_get_config )
throw ss::SSException();
}
SQLSRV_ASSERT( option != NULL, "sqlsrv_get_config: option was null." );
if( !stricmp( option, INI_WARNINGS_RETURN_AS_ERRORS )) {
ZVAL_BOOL( return_value, SQLSRV_G( warnings_return_as_errors ));
@ -684,9 +685,7 @@ PHP_FUNCTION( sqlsrv_get_config )
namespace {
// Workaround for name collision problem between the SQLSRV and PDO_SQLSRV drivers on Mac
// Place get_error_message into the anonymous namespace in util.cpp
sqlsrv_error_const* get_error_message( unsigned int sqlsrv_error_code ) {
sqlsrv_error_const* get_error_message( _In_ unsigned int sqlsrv_error_code ) {
sqlsrv_error_const *error_message = NULL;
@ -700,8 +699,8 @@ sqlsrv_error_const* get_error_message( unsigned int sqlsrv_error_code ) {
return error_message;
}
void copy_error_to_zval( zval* error_z, sqlsrv_error_const* error, zval* reported_chain, zval* ignored_chain,
bool warning TSRMLS_DC )
void copy_error_to_zval( _Inout_ zval* error_z, _In_ sqlsrv_error_const* error, _Inout_ zval* reported_chain, _Inout_ zval* ignored_chain,
_In_ bool warning TSRMLS_DC )
{
if( array_init( error_z ) == FAILURE ) {
@ -777,8 +776,8 @@ void copy_error_to_zval( zval* error_z, sqlsrv_error_const* error, zval* reporte
}
}
bool handle_errors_and_warnings( sqlsrv_context& ctx, zval* reported_chain, zval* ignored_chain, logging_severity log_severity,
unsigned int sqlsrv_error_code, bool warning, va_list* print_args TSRMLS_DC )
bool handle_errors_and_warnings( _Inout_ sqlsrv_context& ctx, _Inout_ zval* reported_chain, _Inout_ zval* ignored_chain, _In_ logging_severity log_severity,
_In_ unsigned int sqlsrv_error_code, _In_ bool warning, _In_opt_ va_list* print_args TSRMLS_DC )
{
bool result = true;
bool errors_ignored = false;
@ -865,7 +864,7 @@ bool handle_errors_and_warnings( sqlsrv_context& ctx, zval* reported_chain, zval
// return whether or not a warning should be ignored or returned as an error if WarningsReturnAsErrors is true
// see RINIT in init.cpp for information about which errors are ignored.
bool ignore_warning( char* sql_state, int native_code TSRMLS_DC )
bool ignore_warning( _In_ char* sql_state, _In_ int native_code TSRMLS_DC )
{
zend_ulong index = -1;
zend_string* key = NULL;
@ -886,7 +885,7 @@ bool ignore_warning( char* sql_state, int native_code TSRMLS_DC )
return false;
}
int sqlsrv_merge_zend_hash_dtor( zval* dest TSRMLS_DC )
int sqlsrv_merge_zend_hash_dtor( _Inout_ zval* dest TSRMLS_DC )
{
zval_ptr_dtor( dest );
return ZEND_HASH_APPLY_REMOVE;

View file

@ -35,5 +35,5 @@ Array
\[DriverDllName\] => msodbcsql[0-9]{2}\.dll|libmsodbcsql-[0-9]{2}\.[0-9]\.so\.[0-9]\.[0-9]
\[DriverODBCVer\] => [0-9]{1,2}\.[0-9]{1,2}
\[DriverVer\] => [0-9]{1,2}\.[0-9]{1,2}\.[0-9]{4}
\[ExtensionVer\] => [0-9]\.[0-9]\.[0-9](\-((rc)|(preview))(\.[0-9]+)?)?(\+[0-9]+)?
\[ExtensionVer\] => [0-9].[0-9]\.[0-9](-(RC[0-9]?|preview))?(\.[0-9]+)?(\+[0-9]+)?
\)

View file

@ -32,4 +32,4 @@ sqlsrv_close( $conn);
DriverDllName: msodbcsql[0-9]{2}\.dll|libmsodbcsql-[0-9]{2}\.[0-9]\.so\.[0-9]\.[0-9]
DriverODBCVer: [0-9]{1,2}\.[0-9]{1,2}
DriverVer: [0-9]{1,2}\.[0-9]{1,2}\.[0-9]{4}
ExtensionVer: [0-9]\.[0-9]\.[0-9](\-((rc)|(preview))(\.[0-9]+)?)?(\+[0-9]+)?
ExtensionVer: [0-9].[0-9]\.[0-9](-(RC[0-9]?|preview))?(\.[0-9]+)?(\+[0-9]+)?

View file

@ -0,0 +1,1539 @@
<?php
/*
Microsoft SQL Server Driver for PHP - Unit Test Framework
Copyright (c) Microsoft Corporation. All rights reserved.
Description:
Common functions (shared by all tests).
*/
//
// looks like an additional file (in addition to pdo_test_base.inc) may be needed for these PHPTs
// to be runnable from the MSSQL teams' internal proprietary test running system
//
require 'MsData.inc';
function connect($options=array())
{
try
{
// simply use $databaseName from MsSetup.inc to facilitate testing in Azure,
// which does not support switching databases
require 'MsSetup.inc';
$conn = new PDO( "sqlsrv:Server=$server;database=$databaseName;ConnectionPooling=false;" , $uid, $pwd, $options);
$conn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
create_and_insert_table1($conn);
create_and_insert_table2($conn);
return $conn;
}
catch( PDOException $e )
{
var_dump( $e );
exit;
}
catch(Exception $e)
{
var_dump( $e );
exit;
}
}
// Create and insert
function create_and_insert_table1( $conn )
{
global $string_col, $date_col, $large_string_col, $xml_col, $binary_col, $int_col, $decimal_col, $guid_col, $null_col, $comma, $closing_brace, $table1;
try
{
$create_query =
"IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'" . $table1 . "') AND type in (N'U'))
DROP TABLE " . $table1 .
" CREATE TABLE [dbo].[" . $table1 . "](
[IntCol] [int] NULL,
[CharCol] [char](10) NULL,
[NCharCol] [nchar](10) NULL,
[DateTimeCol] [datetime] NULL,
[VarcharCol] [varchar](50) NULL,
[NVarCharCol] [nvarchar](50) NULL,
[FloatCol] [float] NULL,
[XmlCol] [xml] NULL
) ON [PRIMARY]
";
$conn->query( $create_query );
for ($i = 0 ; $i <= 1; ++ $i)
{
$insert_query =
"INSERT INTO PDO_Types_1 VALUES (".
$int_col[$i] . $comma .
$string_col[$i] . $comma .
$string_col[$i] . $comma .
"Convert(datetime, ". $date_col[$i] . ")" . $comma .
$string_col[$i] . $comma .
$string_col[$i] . $comma .
$decimal_col[$i] . $comma .
$xml_col[$i] .
")";
$conn->query ( $insert_query );
}
}
catch(Exception $e)
{
var_dump( $e);
exit;
}
}
function create_and_insert_table2( $conn )
{
try
{
//Timestamp is not present.
//VARIANT is not supported.
global $string_col, $date_col, $large_string_col, $xml_col, $binary_col, $int_col, $decimal_col, $guid_col, $null_col, $comma, $closing_brace, $table1, $table2;
$create_query =
"IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'".$table2."') AND type in (N'U')) DROP TABLE " . $table2 .
" CREATE TABLE " .$table2 . " (
[BigIntCol] [bigint] NULL,
[BinaryCol] [binary](5) NULL,
[BitCol] [bit] NULL,
[CharCol] [char](10) NULL,
[DateCol] [date] NULL,
[DateTimeCol] [datetime] NULL,
[DateTime2Col] [datetime2](7) NULL,
[DTOffsetCol] [datetimeoffset](7) NULL,
[DecimalCol] [decimal](18, 0) NULL,
[FloatCol] [float] NULL,
[ImageCol] [image] NULL,
[IntCol] [int] NULL,
[MoneyCol] [money] NULL,
[NCharCol] [nchar](10) NULL,
[NTextCol] [ntext] NULL,
[NumCol] [numeric](18, 0) NULL,
[NVarCharCol] [nvarchar](50) NULL,
[NVarCharMaxCol] [nvarchar](max) NULL,
[RealCol] [real] NULL,
[SmallDTCol] [smalldatetime] NULL,
[SmallIntCol] [smallint] NULL,
[SmallMoneyCol] [smallmoney] NULL,
[TextCol] [text] NULL,
[TimeCol] [time](7) NULL,
[TinyIntCol] [tinyint] NULL,
[Guidcol] [uniqueidentifier] NULL,
[VarbinaryCol] [varbinary](50) NULL,
[VarbinaryMaxCol] [varbinary](max) NULL,
[VarcharCol] [varchar](50) NULL,
[VarcharMaxCol] [varchar](max) NULL,
[XmlCol] [xml] NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
";
$stmt = $conn->query( $create_query );
for ($i =0; $i<= 0 ; ++ $i)
{
$insert_query =
" INSERT INTO " .$table2 . " VALUES (".
$int_col[$i] . $comma .
$binary_col[$i] . $comma .
"0" . $comma .
$string_col[$i] . $comma .
"Convert(date, ". $date_col[$i] . $closing_brace .
"Convert(datetime, ". $date_col[$i] . $closing_brace .
"Convert(datetime2(7),". $date_col[$i] . $closing_brace .
"Convert(datetimeoffset(7)," . $date_col[$i] . $closing_brace .
$decimal_col[$i] . $comma .
$decimal_col[$i] .$comma .
$binary_col[$i] . $comma .
$int_col[$i] . $comma .
$decimal_col[$i] . $comma .
$string_col[$i]. $comma .
$large_string_col[$i]. $comma.
$int_col[$i]. $comma .
$string_col[$i]. $comma .
$large_string_col[$i]. $comma .
$decimal_col[$i]. $comma .
"Convert(smalldatetime, ". $date_col[$i]. $closing_brace .
$int_col[$i]. $comma .
$decimal_col[$i]. $comma .
$large_string_col[$i]. $comma .
"Convert(time(7), ". $date_col[$i] . $closing_brace .
$int_col[$i] . $comma .
$guid_col[$i] . $comma .
$binary_col[$i] . $comma .
$binary_col[$i] . $comma .
$string_col[$i] . $comma .
$large_string_col[$i] . $comma .
$xml_col[$i] .
")";
$stmt = $conn->query ($insert_query );
}
}
catch(Exception $e)
{
var_dump( $e);
exit;
}
}
function teardown()
{
// TBD
}
function my_print_r( $to_print )
{
global $verbose;
if($verbose)
print_r($to_print);
}
function TestMode()
{
$testMode = getenv('PHPT_EXEC');
return ($testMode ? true : false);
}
function IsPdoMode()
{
require 'MsSetup.inc';
return (($driverType === true) ? true : false);
}
function TraceMode()
{
require 'MsSetup.inc';
return ((!TestMode() && $traceEnabled) ? true : false);
}
function IsMarsSupported()
{
require 'MsSetup.inc';
return ($marsMode ? true : false);
}
function IsDaasMode()
{
require 'MsSetup.inc';
return ($daasMode ? true : false);
}
function FatalError($errorMsg)
{
if (!IsPdoMode())
{
handle_errors();
}
die("$errorMsg\n");
}
function Trace($msg)
{
if (TraceMode())
{
echo $msg;
}
}
function TraceEx($msg, $exitMode)
{
if ($exitMode)
{
FatalError($msg);
}
else
{
Trace("$msg\n");
}
}
function TraceData($sqlType, $data)
{
if (TraceMode())
{
$msg = strtoupper(" $sqlType:");
echo "$msg\t";
if (strlen($msg) <= 7)
{
echo "\t";
}
if (strlen($msg) <= 15)
{
echo "\t";
}
echo "$data\n"
;
}
}
function StartTest($testName)
{
require 'MsSetup.inc';
if (TraceMode())
{
echo "$PhpDriver: starting \"$testName\" test...\n\n";
}
if (!extension_loaded(IsPdoMode() ? "pdo" : "sqlsrv"))
{
die("$PhpDriver cannot be loaded.");
}
// Set timezone
$tz = ini_get('date.timezone');
if (strcmp($tz, "") == 0)
{
date_default_timezone_set('America/Los_Angeles');
$tz = date_default_timezone_get();
}
Trace("Timezone: $tz.\n");
}
function EndTest($testName)
{
require 'MsSetup.inc';
if (TraceMode())
{
echo "\n$PhpDriver: "
;
}
echo "Test \"$testName\" completed successfully.\n"
;
}
function Setup()
{
set_time_limit(0);
if (IsPdoMode())
{ // PDO setup
}
else
{ // PHP setup
sqlsrv_configure('LogSubsystems', SQLSRV_LOG_SYSTEM_ALL);
sqlsrv_configure('LogSeverity', SQLSRV_LOG_SEVERITY_ALL);
sqlsrv_configure('WarningsReturnAsErrors', 1);
}
}
function Configure($param, $expected)
{
if (!IsPdoMode())
{
sqlsrv_configure($param, $expected);
$actual = sqlsrv_get_config($param);
if ($actual == $expected)
{
Trace("Set configuration parameter $param = $actual.\n");
}
else
{
die("Failed to set configuration parameter $param = $expected.");
}
}
}
function GetTempTableName($table = '', $temporary = true)
{
// A temporary table name with the '#' prefix will be automatically
// dropped once the connection is closed. Otherwise, the caller
// should take care of dropping the temp table afterwards.
$timestamp = round(microtime(true)*1000);
$prefix = '';
if ($temporary)
$prefix = '#';
if (strlen($table) == 0)
$table = 'php_test_table';
return $prefix . $table . '_' . $timestamp;
}
function GetTempProcName($proc = '', $temporary = true)
{
// A temporary stored procedure name with the '#' prefix will be
// automatically dropped once the connection is closed. Otherwise,
// the caller should take care of dropping the temp procedure afterwards.
$timestamp = round(microtime(true)*1000);
$prefix = '';
if ($temporary)
$prefix = '#';
if (strlen($proc) == 0)
$proc = 'php_test_proc';
return $prefix . $proc . '_' . $timestamp;
}
function PDOConnect($className, $serverName, $user, $pwd, $exitMode)
{
require 'MsSetup.inc';
$conn = null;
try
{
// simply use $databaseName from MsSetup.inc to facilitate testing in Azure,
// which does not support switching databases
$conn = new $className("sqlsrv:Server=$serverName;Database=$databaseName", $user, $pwd, $connectionOptions);
$conn->setAttribute(PDO::SQLSRV_ATTR_ENCODING, PDO::SQLSRV_ENCODING_SYSTEM);
}
catch (PDOException $e)
{
$conn = null;
TraceEx("\nFailed to connect to $serverName: ".$e->getMessage(), $exitMode);
}
return ($conn);
}
function ExecuteQuery($conn, $tsql)
{
$stmt = null;
if (IsPdoMode())
{ // PDO
try
{
$stmt = $conn->query($tsql);
}
catch (PDOException $e)
{
$stmt = null;
FatalError("Query execution failed for $tsql: ".$e->getMessage());
}
}
else
{ // PHP
$stmt = sqlsrv_query($conn, $tsql);
if ($stmt === false)
{
FatalError("Query execution failed for $tsql");
}
}
return ($stmt);
}
function PrepareQuery($conn, $tsql)
{
$stmt = null;
if (IsPdoMode())
{ // PDO
try
{
$stmt = $conn->prepare($tsql);
}
catch (PDOException $e)
{
$stmt = null;
FatalError("Query preparation failed for $tsql: ".$e->getMessage());
}
}
else
{ // PHP
$stmt = sqlsrv_prepare($conn, $tsql);
if ($stmt === false)
{
FatalError("Query preparation failed for $tsql");
}
}
return ($stmt);
}
function ExecuteQueryEx($conn, $tsql, $modeDirect)
{
$stmt = null;
if ($modeDirect)
{ // direct execution
if (IsPdoMode())
{ // PDO
try
{
$stmt = $conn->query($tsql);
}
catch (PDOException $e)
{
$stmt = null;
}
}
else
{ // PHP
$stmt = sqlsrv_query($conn, $tsql);
}
}
else
{
$stmt = PrepareQuery($conn, $tsql);
if (IsPdoMode())
{
$stmt->execute();
}
else
{
sqlsrv_execute($stmt);
}
}
return ($stmt);
}
function GetSqlType($k)
{
switch ($k)
{
case 1: return ("int");
case 2: return ("tinyint");
case 3: return ("smallint");
case 4: return ("bigint");
case 5: return ("bit");
case 6: return ("float");
case 7: return ("real");
case 8: return ("decimal(28,4)");
case 9: return ("numeric(32,4)");
case 10: return ("money");
case 11: return ("smallmoney");
case 12: return ("char(512)");
case 13: return ("varchar(512)");
case 14: return ("varchar(max)");
case 15: return ("nchar(512)");
case 16: return ("nvarchar(512)");
case 17: return ("nvarchar(max)");
case 18: return ("text");
case 19: return ("ntext");
case 20: return ("binary(512)");
case 21: return ("varbinary(512)");
case 22: return ("varbinary(max)");
case 23: return ("image");
case 24: return ("uniqueidentifier");
case 25: return ("datetime");
case 26: return ("smalldatetime");
case 27: return ("timestamp");
case 28: return ("xml");
default: break;
}
return ("udt");
}
function GetDriverType($k, $dataSize)
{
switch ($k)
{
case 1: return (SQLSRV_SQLTYPE_INT);
case 2: return (SQLSRV_SQLTYPE_TINYINT);
case 3: return (SQLSRV_SQLTYPE_SMALLINT);
case 4: return (SQLSRV_SQLTYPE_BIGINT);
case 5: return (SQLSRV_SQLTYPE_BIT);
case 6: return (SQLSRV_SQLTYPE_FLOAT);
case 7: return (SQLSRV_SQLTYPE_REAL);
case 8: return (SQLSRV_SQLTYPE_DECIMAL(28, 4));
case 9: return (SQLSRV_SQLTYPE_NUMERIC(32, 4));
case 10: return (SQLSRV_SQLTYPE_MONEY);
case 11: return (SQLSRV_SQLTYPE_SMALLMONEY);
case 12: return (SQLSRV_SQLTYPE_CHAR($dataSize));
case 13: return (SQLSRV_SQLTYPE_VARCHAR($dataSize));
case 14: return (SQLSRV_SQLTYPE_VARCHAR('max'));
case 15: return (SQLSRV_SQLTYPE_NCHAR($dataSize));
case 16: return (SQLSRV_SQLTYPE_NVARCHAR($dataSize));
case 17: return (SQLSRV_SQLTYPE_NVARCHAR('max'));
case 18: return (SQLSRV_SQLTYPE_TEXT);
case 19: return (SQLSRV_SQLTYPE_NTEXT);
case 20: return (SQLSRV_SQLTYPE_BINARY($dataSize));
case 21: return (SQLSRV_SQLTYPE_VARBINARY($dataSize));
case 22: return (SQLSRV_SQLTYPE_VARBINARY('max'));
case 23: return (SQLSRV_SQLTYPE_IMAGE);
case 24: return (SQLSRV_SQLTYPE_UNIQUEIDENTIFIER);
case 25: return (SQLSRV_SQLTYPE_DATETIME);
case 26: return (SQLSRV_SQLTYPE_SMALLDATETIME);
case 27: return (SQLSRV_SQLTYPE_TIMESTAMP);
case 28: return (SQLSRV_SQLTYPE_XML);
default: break;
}
return (SQLSRV_SQLTYPE_UDT);
}
function IsStreamable($k)
{
switch ($k)
{
case 12: return (true); // nchar(512)
case 13: return (true); // varchar(512)
case 14: return (true); // varchar(max)
case 15: return (true); // nchar(512)
case 16: return (true); // nvarchar(512)
case 17: return (true); // nvarchar(max)
case 18: return (true); // text
case 19: return (true); // ntext
case 20: return (true); // binary
case 21: return (true); // varbinary(512)
case 22: return (true); // varbinary(max)
case 23: return (true); // image
case 28: return (true); // xml
default: break;
}
return (false);
}
function IsNumeric($k)
{
switch ($k)
{
case 1: return (true); // int
case 2: return (true); // tinyint
case 3: return (true); // smallint
case 4: return (true); // bigint
case 5: return (true); // bit
case 6: return (true); // float
case 7: return (true); // real
case 8: return (true); // decimal(28,4)
case 9: return (true); // numeric(32,4)
case 10: return (true); // money
case 11: return (true); // smallmoney
default: break;
}
return (false);
}
function IsChar($k)
{
switch ($k)
{
case 12: return (true); // nchar(512)
case 13: return (true); // varchar(512)
case 14: return (true); // varchar(max)
case 15: return (true); // nchar(512)
case 16: return (true); // nvarchar(512)
case 17: return (true); // nvarchar(max)
case 18: return (true); // text
case 19: return (true); // ntext
case 28: return (true); // xml
default: break;
}
return (false);
}
function IsBinary($k)
{
switch ($k)
{
case 20: return (true); // binary
case 21: return (true); // varbinary(512)
case 22: return (true); // varbinary(max)
case 23: return (true); // image
default: break;
}
return (false);
}
function IsDateTime($k)
{
switch ($k)
{
case 25: return (true); // datetime
case 26: return (true); // smalldatetime
case 27: return (true); // timestamp
default: break;
}
return (false);
}
function IsUnicode($k)
{
switch ($k)
{
case 15: return (true); // nchar(512)
case 16: return (true); // nvarchar(512)
case 17: return (true); // nvarchar(max)
case 19: return (true); // ntext
default: break;
}
return (false);
}
function IsUpdatable($k)
{
switch ($k)
{
case 27: return (false); // timestamp
default: break;
}
return (true);
}
function IsLiteral($k)
{
switch ($k)
{
case 12: return (true); // nchar(512)
case 13: return (true); // varchar(512)
case 14: return (true); // varchar(max)
case 15: return (true); // nchar(512)
case 16: return (true); // nvarchar(512)
case 17: return (true); // nvarchar(max)
case 18: return (true); // text
case 19: return (true); // ntext
case 24: return (true); // uniqueidentifier
case 25: return (true); // datetime
case 26: return (true); // smalldatetime
case 28: return (true); // xml
default: break;
}
return (false);
}
function GetMetadata($k, $info)
{
if (strcasecmp($info, 'Name') == 0)
{
return (getColName($k));
}
if (strcasecmp($info, 'Size') == 0)
{
return (getColSize($k));
}
if (strcasecmp($info, 'Precision') == 0)
{
return (getColPrecision($k));
}
if (strcasecmp($info, 'Scale') == 0)
{
return (getColScale($k));
}
if (strcasecmp($info, 'Nullable') == 0)
{
return (getColNullable($k));
}
return ("");
}
function GetColName($k)
{
switch ($k)
{
case 1: return ("c1_int");
case 2: return ("c2_tinyint");
case 3: return ("c3_smallint");
case 4: return ("c4_bigint");
case 5: return ("c5_bit");
case 6: return ("c6_float");
case 7: return ("c7_real");
case 8: return ("c8_decimal");
case 9: return ("c9_numeric");
case 10: return ("c10_money");
case 11: return ("c11_smallmoney");
case 12: return ("c12_char");
case 13: return ("c13_varchar");
case 14: return ("c14_varchar_max");
case 15: return ("c15_nchar");
case 16: return ("c16_nvarchar");
case 17: return ("c17_nvarchar_max");
case 18: return ("c18_text");
case 19: return ("c19_ntext");
case 20: return ("c20_binary");
case 21: return ("c21_varbinary");
case 22: return ("c22_varbinary_max");
case 23: return ("c23_image");
case 24: return ("c24_uniqueidentifier");
case 25: return ("c25_datetime");
case 26: return ("c26_smalldatetime");
case 27: return ("c27_timestamp");
case 28: return ("c28_xml");
default: break;
}
return ("");
}
function GetColSize($k)
{
switch ($k)
{
case 12: return ("512");
case 13: return ("512");
case 14: return ("0");
case 15: return ("512");
case 16: return ("512");
case 17: return ("0");
case 18: return ("2147483647");
case 19: return ("1073741823");
case 20: return ("512");
case 21: return ("512");
case 22: return ("0)");
case 23: return ("2147483647");
case 24: return ("36");
//case 25: return ("23");
//case 26: return ("16");
case 27: return ("8");
case 28: return ("0");
default: break;
}
return ("");
}
function GetColPrecision($k)
{
switch ($k)
{
case 1: return ("10");
case 2: return ("3");
case 3: return ("5");
case 4: return ("19");
case 5: return ("1");
case 6: return ("53");
case 7: return ("24");
case 8: return ("28");
case 9: return ("32");
case 10: return ("19");
case 11: return ("10");
case 25: return ("23");
case 26: return ("16");
default: break;
}
return ("");
}
function GetColScale($k)
{
switch ($k)
{
case 8: return ("4");
case 9: return ("4");
case 10: return ("4");
case 11: return ("4");
case 25: return ("3");
case 26: return ("0");
default: break;
}
return ("");
}
function GetColNullable($k)
{
return (IsUpdatable($k) ? "1" : "0");
}
function GetSampleData($k)
{
switch ($k)
{
case 1: // int
return ("123456789");
case 2: // tinyint
return ("234");
case 3: // smallint
return ("5678");
case 4: // bigint
return ("123456789987654321");
case 5: // bit
return ("1");
case 6: // float
return ("123.456");
case 7: // real
return ("789.012");
case 8: // decimal
return ("12.34");
case 9: // numeric
return ("567.89");
case 10:// money
return ("321.54");
case 11:// smallmoney
return ("67.89");
case 12:// char
case 15:// nchar
return ("The quick brown fox jumps over the lazy dog");
case 13:// varchar
case 16:// nvarchar
return ("The quick brown fox jumps over the lazy dog 9876543210");
case 14:// varchar(max)
case 17:// nvarchar(max)
return ("The quick brown fox jumps over the lazy dog 0123456789");
case 18:// text
case 19:// ntext
return ("0123456789 The quick brown fox jumps over the lazy dog");
case 20:// binary
return ("0123456789");
case 21:// varbinary
return ("01234567899876543210");
case 22:// varbinary(max)
return ("98765432100123456789");
case 23:// image
return ("01234567899876543210");
case 24:// uniqueidentifier
return ("12345678-9012-3456-7890-123456789012");
case 25:// datetime
case 26:// smalldatetime
return (date("Y-m-d"));
case 27:// timestamp
return (null);
case 28:// xml
return ("<XmlTestData><Letters1>The quick brown fox jumps over the lazy dog</Letters1><Digits1>0123456789</Digits1></XmlTestData>");
default:
break;
}
return (null);
}
function CreateDB($conn, $dbName)
{
Trace("Creating database $dbName ...");
$tsql = "CREATE DATABASE [$dbName]";
DropDB($conn, $dbName);
if (IsPdoMode())
{
$outcome = $conn->exec($tsql);
if ($outcome === false)
{
FatalError("Failed to create test database: $dbName");
}
}
else
{
$stmt = sqlsrv_query($conn, $tsql);
if ($stmt === false)
{
FatalError("Failed to create test database: $dbName");
}
sqlsrv_free_stmt($stmt);
}
Trace(" completed successfully.\n");
}
function DropDB($conn, $dbName)
{
$tsql = "DROP DATABASE [$dbName]";
if (IsPdoMode())
{
$mode = $conn->getAttribute(PDO::ATTR_ERRMODE);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
$outcome = $conn->exec($tsql);
$conn->setAttribute(PDO::ATTR_ERRMODE, $mode);
}
else
{
$stmt = sqlsrv_query($conn, $tsql);
if ($stmt === false)
{
}
else
{
sqlsrv_free_stmt($stmt);
}
}
}
function CreateTable($conn, $tableName)
{
$dataType = "[c1_int] int, [c2_tinyint] tinyint, [c3_smallint] smallint, [c4_bigint] bigint, [c5_bit] bit, [c6_float] float, [c7_real] real, [c8_decimal] decimal(28,4), [c9_numeric] numeric(32,4), [c10_money] money, [c11_smallmoney] smallmoney, [c12_char] char(512), [c13_varchar] varchar(512), [c14_varchar_max] varchar(max), [c15_nchar] nchar(512), [c16_nvarchar] nvarchar(512), [c17_nvarchar_max] nvarchar(max), [c18_text] text, [c19_ntext] ntext, [c20_binary] binary(512), [c21_varbinary] varbinary(512), [c22_varbinary_max] varbinary(max), [c23_image] image, [c24_uniqueidentifier] uniqueidentifier, [c25_datetime] datetime, [c26_smalldatetime] smalldatetime, [c27_timestamp] timestamp, [c28_xml] xml";
CreateTableEx($conn, $tableName, $dataType);
if (IsDaasMode())
{
$colIndex = "[c1_int], [c2_tinyint], [c3_smallint], [c4_bigint], [c5_bit], [c6_float], [c7_real], [c8_decimal], [c9_numeric]";
CreateTableIndex($conn, $tableName, $colIndex);
}
}
function CreateTableEx($conn, $tableName, $dataType)
{
Trace("Creating table $tableName ...");
$tsql = "CREATE TABLE [$tableName] ($dataType)";
DropTable($conn,$tableName);
if (IsPdoMode())
{
$outcome = $conn->exec($tsql);
if ($outcome === false)
{
FatalError("Failed to create test table: $tsql");
}
}
else
{
$stmt = sqlsrv_query($conn, $tsql);
if ($stmt === false)
{
FatalError("Failed to create test table: $tsql");
}
sqlsrv_free_stmt($stmt);
}
Trace(" completed successfully.\n");
}
function CreateTableIndex($conn, $tableName, $colIndex)
{
require 'MsSetup.inc';
CreateTableIndexEx($conn, $tableName, $tableIndex, $colIndex);
}
function CreateTableIndexEx($conn, $tableName, $tableIndex, $colIndex)
{
Trace("Creating table index for $tableName ...");
$sqlIndex = "CREATE CLUSTERED INDEX [$tableIndex] ON [$tableName]($colIndex)";
if (IsPdoMode())
{
$outcome = $conn->exec($sqlIndex);
if ($outcome === false)
{
FatalError("Failed to create clustered index for test table: $sqlIndex");
}
}
else
{
$stmt = sqlsrv_query($conn, $sqlIndex);
if ($stmt === false)
{
FatalError("Failed to create clustered index for test table: $sqlIndex");
}
sqlsrv_free_stmt($stmt);
}
Trace(" completed successfully.\n");
}
function CreateUniqueIndex($conn, $tableName, $colIndex)
{
require 'MsSetup.inc';
CreateUniqueIndexEx($conn, $tableName, $tableIndex, $colIndex);
}
function CreateUniqueIndexEx($conn, $tableName, $tableIndex, $colIndex)
{
Trace("Creating unique table index for $tableName ...");
$sqlIndex = "CREATE UNIQUE INDEX [$tableIndex] ON [$tableName]($colIndex)";
if (IsPdoMode())
{
$outcome = $conn->exec($sqlIndex);
if ($outcome === false)
{
FatalError("Failed to create unique index for test table: $sqlIndex");
}
}
else
{
$stmt = sqlsrv_query($conn, $sqlIndex);
if ($stmt === false)
{
FatalError("Failed to create unique index for test table: $sqlIndex");
}
sqlsrv_free_stmt($stmt);
}
Trace(" completed successfully.\n");
}
function DropTable($conn, $tableName)
{
$tsql = "DROP TABLE [$tableName]";
if (IsPdoMode())
{
$mode = $conn->getAttribute(PDO::ATTR_ERRMODE);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
$outcome = $conn->exec($tsql);
$conn->setAttribute(PDO::ATTR_ERRMODE, $mode);
}
else
{
$stmt = sqlsrv_query($conn, $tsql);
if ($stmt === false)
{
}
else
{
sqlsrv_free_stmt($stmt);
}
}
}
function SelectFromTable($conn, $tableName)
{
return (SelectFromTableEx($conn, $tableName, null));
}
function SelectFromTableEx($conn, $tableName, $cond)
{
if (($cond != null) && (strlen($cond) > 0))
{
return (SelectQuery($conn, "SELECT * FROM [$tableName] WHERE $cond"));
}
else
{
return (SelectQuery($conn, "SELECT * FROM [$tableName]"));
}
}
function SelectQuery($conn, $query)
{
return (SelectQueryEx($conn, $query, null));
}
function SelectQueryEx($conn, $query, $options)
{
$numFields = 0;
if (IsPDOMode())
{
$stmt = ExecuteQuery($conn, $query);
$numFields = $stmt->columnCount();
}
else
{
if ($options != null)
{
$stmt = sqlsrv_query($conn, $query, null, $options);
}
else
{
$stmt = sqlsrv_query($conn, $query);
}
if ($stmt === false)
{
FatalError("Failed to query test table");
}
$numFields = sqlsrv_num_fields($stmt);
}
if ($numFields <= 0)
{
die("Unexpected number of fields: .$numFields");
}
return ($stmt);
}
function RowCount($stmt)
{
$rowCount = 0;
if (IsPdoMode())
{
while ($stmt->fetchColumn())
{
$rowCount++;
}
}
else
{
while (sqlsrv_fetch($stmt))
{
$rowCount++;
}
}
return ($rowCount);
}
function NumRows($conn, $tableName)
{
$stmt = SelectFromTable($conn, $tableName);
$rowCount = RowCount($stmt);
if (IsPdoMode())
{
$stmt = null;
}
else
{
sqlsrv_free_stmt($stmt);
}
return ($rowCount);
}
function InsertQuery($tableName)
{
include_once 'MsData_UTF8.inc';
return (InsertQueryExUTF8($tableName, rand(1, 20)));
}
function InsertRows($conn, $tableName, $rowCount)
{
Trace("Inserting $rowCount rows into $tableName ...");
$count = 0;
for($i = 0; $i < $rowCount; $i++)
{
if (InsertRow($conn, $tableName))
{
$count++;
}
}
Trace(" completed successfully.\n");
if ($count != $rowCount)
{
die("$count rows inserted instead of $rowCount\n");
}
return ($count);
}
function InsertRowsByRange($conn, $tableName, $minIndex, $maxIndex)
{
$rowCount = $maxIndex - $minIndex + 1;
if ($rowCount > 0)
{
Trace("Inserting $rowCount rows into $tableName ...");
for($i = $minIndex; $i <= $maxIndex; $i++)
{
InsertRowByIndex($conn, $tableName, $i);
}
Trace(" completed successfully.\n");
}
}
function InsertRow($conn, $tableName)
{
$tsql = InsertQuery($tableName);
$stmt = null;
if (IsPdoMode())
{
$stmt = $conn->exec($tsql);
}
else
{
$stmt = sqlsrv_query($conn, $tsql);
}
return (InsertCheck($stmt));
}
function InsertRowEx($conn, $tableName, $dataCols, $dataValues, $dataOptions)
{
$tsql = "INSERT INTO [$tableName] ($dataCols) VALUES ($dataValues)";
$stmt = null;
if (IsPdoMode())
{
$stmt = $conn->exec($tsql);
}
else
{
$stmt = sqlsrv_query($conn, $tsql, $dataOptions);
}
return (InsertCheck($stmt));
}
function InsertRowByIndex($conn, $tableName, $index)
{
$tsql = InsertQueryEx($tableName, $index);
$stmt = null;
if (IsPdoMode())
{
$stmt = $conn->exec($tsql);
}
else
{
$stmt = sqlsrv_query($conn, $tsql);
}
return (InsertCheck($stmt));
}
function InsertStream($conn, $tableName, $dataCols, $dataValues, $dataOptions, $atExec)
{
$tsql = "INSERT INTO [$tableName] ($dataCols) VALUES ($dataValues)";
$stmt = null;
if (IsPdoMode())
{
$stmt = $conn->exec($tsql);
}
else
{
if ($atExec)
{
$stmt = sqlsrv_query($conn, $tsql, $dataOptions, array('SendStreamParamsAtExec' => 1));
}
else
{
$stmt = sqlsrv_query($conn, $tsql, $dataOptions);
if ($stmt)
{
while (sqlsrv_send_stream_data($stmt))
{
}
}
}
}
return (InsertCheck($stmt));
}
function InsertCheck($stmt)
{
$numRows = 0;
if ($stmt === false)
{
FatalError("Failed to insert row into test table");
}
if (IsPdoMode())
{
$numRows = $stmt;
}
else
{
$numRows = sqlsrv_rows_affected($stmt);
sqlsrv_free_stmt($stmt);
}
if ($numRows != 1)
{
die("Unexpected row count at insert: ".$numRows);
}
return (true);
}
function GetInsertData($rowIndex, $colIndex, $skip)
{
$query = InsertQueryEx("TestTable", $rowIndex);
$data = strstr($query, "((");
$pos = 1;
if ($data === false)
{
die("Failed to retrieve data on row $rowIndex");
}
$data = substr($data, 2);
while ($pos < ($colIndex - $skip))
{
$data = strstr($data, ", (");
$pos++;
if ($data === false)
{
die("Failed to retrieve data on row $rowIndex, column $pos");
}
$data = substr($data, 3);
}
$pos = strpos($data, ")");
if ($pos === false)
{
die("Failed to isolate data on row $rowIndex, column $pos");
}
$data = substr($data, 0, $pos);
if (strcasecmp($data, "null") == 0)
{
$data = "";
}
if (IsUnicode($colIndex))
{ // N'data'
$data = substr($data, 2, strlen($data) - 3);
}
else if (IsLiteral($colIndex))
{ // 'data'
$data = substr($data, 1, strlen($data) - 2);
}
else if (IsBinary($colIndex))
{ // 0xdata
$data = substr($data, 2);
}
return (trim($data));
}
function CreateProc($conn, $procName, $procArgs, $procCode)
{
DropProc($conn,$procName);
if (!IsPdoMode())
{
$stmt = sqlsrv_query($conn, "CREATE PROC [$procName] ($procArgs) AS BEGIN $procCode END");
if ($stmt === false)
FatalError("Failed to create test procedure");
sqlsrv_free_stmt($stmt);
}
else
{
$stmt = $conn->query("CREATE PROC [$procName] ($procArgs) AS BEGIN $procCode END");
}
}
function DropProc($conn, $procName)
{
if (!IsPdoMode())
{
$stmt = sqlsrv_query($conn, "DROP PROC [$procName]");
sqlsrv_free_stmt($stmt);
}
else
{
$query = "IF OBJECT_ID('[$procName]', 'P') IS NOT NULL DROP PROCEDURE [$procName]";
$stmt = $conn->query($query);
}
}
function CallProc($conn, $procName, $procArgs, $procValues)
{
$stmt = CallProcEx($conn, $procName, "", $procArgs, $procValues);
sqlsrv_free_stmt($stmt);
}
function CallProcEx($conn, $procName, $procPrefix, $procArgs, $procValues)
{
$stmt = sqlsrv_query($conn, "{ $procPrefix CALL [$procName] ($procArgs)}", $procValues);
if ($stmt === false)
{
FatalError("Failed to call test procedure");
}
return ($stmt);
}
function CreateFunc($conn, $funcName, $funcArgs, $retType, $funcCode)
{
DropFunc($conn,$funcName);
$stmt = sqlsrv_query($conn, "CREATE FUNCTION [$funcName] ($funcArgs) RETURNS $retType AS BEGIN $funcCode END");
if ($stmt === false)
{
FatalError("Failed to create test function");
}
sqlsrv_free_stmt($stmt);
}
function DropFunc($conn, $funcName)
{
$stmt = sqlsrv_query($conn, "DROP FUNCTION [$funcName]");
if ($stmt === false)
{
}
else
{
sqlsrv_free_stmt($stmt);
}
}
function CallFunc($conn, $funcName, $funcArgs, $funcValues)
{
$stmt = sqlsrv_query($conn, "{ ? = CALL [$funcName]($funcArgs)}", $funcValues);
if ($stmt === false)
{
FatalError("Failed to call test function");
}
sqlsrv_free_stmt($stmt);
}
function handle_errors()
{
$errors = sqlsrv_errors(SQLSRV_ERR_ERRORS);
$count = count($errors);
if($count == 0)
{
$errors = sqlsrv_errors(SQLSRV_ERR_ALL);
$count = count($errors);
}
if($count > 0)
{
for($i = 0; $i < $count; $i++)
{
Trace($errors[$i]['message']."\n");
}
}
}
function str2hex($dataIn)
{
$dataOut = "";
$len = strlen($dataIn);
for ($i = 0; $i < $len; $i++)
{
$ch = strtoupper(substr($dataIn, $i, 1));
if ($ch == "A")
{
$dataOut = $dataOut."41";
}
else if ($ch == "B")
{
$dataOut = $dataOut."42";
}
else if ($ch == "C")
{
$dataOut = $dataOut."43";
}
else if ($ch == "D")
{
$dataOut = $dataOut."44";
}
else if ($ch == "E")
{
$dataOut = $dataOut."45";
}
else if ($ch == "F")
{
$dataOut = $dataOut."46";
}
else
{
$dataOut = $dataOut."3".$ch;
}
}
return ($dataOut);
}
function PhpVersionComponents( &$major, &$minor, &$sub )
{
$str_version = phpversion();
$major = strtok( $str_version, "." );
$minor = strtok( "." );
$sub = strtok( "." );
}
?>

File diff suppressed because one or more lines are too long

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