Added source and binaries for the latest release

This commit is contained in:
Meet Bhagdev 2016-07-06 11:47:05 -07:00
parent ca435f6e62
commit 5ddaaeb728
35 changed files with 1312 additions and 1352 deletions

View file

@ -1,16 +1,27 @@
# Microsoft Drivers for PHP for SQL Server
**Welcome to the Microsoft Drivers for PHP for SQL Server PHP 7 (Release Candidate)**
**Welcome to the Microsoft Drivers for PHP for SQL Server PHP 7**
The Microsoft Drivers for PHP for SQL Server are PHP extensions that allow for the reading and writing of SQL Server data from within PHP scripts. The SQLSRV extension provides a procedural interface while the PDO_SQLSRV extension implements PDO for accessing data in all editions of SQL Server 2005 and later (including Azure SQL DB). These drivers rely on the Microsoft ODBC Driver for SQL Server to handle the low-level communication with SQL Server.
This preview contains the SQLSRV and PDO_SQLSRV drivers for PHP 7 with improvements on both drivers and some limitations (see Limitations below for details). Upcoming release(s) will contain more functionality, bug fixes, and more (see Plans below for more details).
This release contains the SQLSRV and PDO_SQLSRV drivers for PHP 7 with improvements on both drivers and some limitations (see Limitations below for details). Upcoming release(s) will contain more functionality, bug fixes, and more (see Plans below for more details).
The Microsoft Drivers for PHP for SQL Server Team
##Announcements
June 13, 2016 (4.0) Release Candidate: The quality of SQLSRV and PDO_SQLSRV is improved and includes some bug fixes:
June 30, 2016 (4.0.6): The quality of SQLSRV and PDO_SQLSRV is improved and includes some memory leak fixes:
- Fixed a heap corruption when binding parameters in a prepare statement with error
- Fixed leaks in SQLSRV streams and output parameters handling
- Fixed leaks in SQLSRV fetch object
- Fixed leaks in SQLSRV binding object parameters
- Fixed leaks in SQLSRV buffered result set
- Fixed leaks in SQLSRV getting datetime and stream fields
- Fixed leaks in PDO_SQLSRV field cache
- Fixed leaks in PDO_SQLSRV construct when connecting with error
- Fixed leaks in PDO_SQLSRV exception handling
June 13, 2016 (4.0.5): The quality of SQLSRV and PDO_SQLSRV is improved and includes some bug fixes:
- Added ability to connect to Microsoft ODBC Driver 13.
- Fixed some memory leaks in data retrieval.
- Fixed issue with error handling in bound stream parameters when send_stream_at_exec option is set to false.
@ -66,7 +77,7 @@ You must first be able to build PHP 7 without including these extensions. For h
5. To install the resulting build, run `nmake install` or just copy php_sqlsrv.dll and/or php_pdo_sqlsrv.dll to your PHP extension directory.
This software has been compiled and tested under PHP 7.0.7 using the Visual C++ 2015 compiler.
This software has been compiled and tested under PHP 7.0.8 using the Visual C++ 2015 compiler.
## Install
@ -122,7 +133,7 @@ Thank you!
**Q:** What's next?
**A:** On Jan 29, 2016 we released an early technical preview for our PHP Driver and several since. We will continue releasing frequent technical previews until we reach production quality.
**A:** On Jan 29, 2016 we released an early technical preview for our PHP Driver and several since. We will continue to release frequently to improve the quality of our driver.
**Q:** Is Microsoft taking pull requests for this project?
@ -159,3 +170,5 @@ The Microsoft Drivers for PHP for SQL Server are licensed under the MIT license.
[odbc13]: https://www.microsoft.com/en-us/download/details.aspx?id=50420
[phpazure]: https://azure.microsoft.com/en-us/documentation/articles/sql-database-develop-php-simple-windows/
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -57,7 +57,7 @@ const char CONNECTION_OPTION_MARS_ON[] = "MARS_Connection={Yes};";
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* driver,__inout std::string& connection_string TSRMLS_DC );
void* driver,_Inout_ std::string& connection_string TSRMLS_DC );
void determine_server_version( 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 );
@ -377,7 +377,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( sqlsrv_conn* conn, _Out_ zval *server_version TSRMLS_DC )
{
try {
@ -404,7 +404,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( sqlsrv_conn* conn, _Out_ zval *server_info TSRMLS_DC )
{
try {
@ -443,7 +443,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( sqlsrv_conn* conn, _Out_ zval *client_info TSRMLS_DC )
{
try {
@ -534,7 +534,7 @@ connection_option const* get_connection_option( sqlsrv_conn* conn, SQLULEN key,
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* driver,_Inout_ std::string& connection_string TSRMLS_DC )
{
bool credentials_mentioned = false;
bool mars_mentioned = false;
@ -689,7 +689,7 @@ void determine_server_version( sqlsrv_conn* conn TSRMLS_DC )
errno = 0;
char version_major_str[ 3 ];
SERVER_VERSION version_major;
memcpy( version_major_str, p, 2 );
memcpy_s( version_major_str, sizeof( version_major_str ), p, 2 );
version_major_str[ 2 ] = '\0';
version_major = static_cast<SERVER_VERSION>( atoi( version_major_str ));

View file

@ -145,14 +145,14 @@ void core_sqlsrv_mshutdown( sqlsrv_context& henv_cp, sqlsrv_context& henv_ncp )
if( henv_ncp != SQL_NULL_HANDLE ) {
henv_ncp.invalidate();
delete &henv_ncp;
}
delete &henv_ncp;
if( henv_cp != SQL_NULL_HANDLE ) {
henv_cp.invalidate();
delete &henv_cp;
}
delete &henv_cp;
return;
}

View file

@ -85,7 +85,7 @@ void cache_row_dtor(zval* data);
// 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,
SQLRETURN number_to_string( Number* number_data, _Out_ void* buffer, SQLLEN buffer_length, _Out_ SQLLEN* out_buffer_length,
sqlsrv_error_auto_ptr& last_error )
{
std::basic_ostringstream<Char> os;
@ -107,14 +107,14 @@ SQLRETURN number_to_string( Number* number_data, __out void* buffer, SQLLEN buff
}
*out_buffer_length = str_num.size() * sizeof(Char) + sizeof(Char); // include NULL terminator
memcpy( buffer, str_num.c_str(), *out_buffer_length );
memcpy_s( buffer, buffer_length, str_num.c_str(), *out_buffer_length );
return SQL_SUCCESS;
}
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( Char* string_data, SQLLEN str_len, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ SQLLEN* out_buffer_length, sqlsrv_error_auto_ptr& last_error )
{
Number* number_data = reinterpret_cast<Number*>( buffer );
std::locale loc; // default locale should match system
@ -214,7 +214,7 @@ SQLRETURN sqlsrv_odbc_result_set::fetch( SQLSMALLINT orientation, SQLLEN offset
}
SQLRETURN sqlsrv_odbc_result_set::get_data( SQLUSMALLINT field_index, SQLSMALLINT target_type,
__out SQLPOINTER buffer, SQLLEN buffer_length, __out SQLLEN* out_buffer_length,
_Out_ SQLPOINTER buffer, SQLLEN buffer_length, _Out_ SQLLEN* out_buffer_length,
bool handle_warning TSRMLS_DC )
{
SQLSRV_ASSERT( odbc != NULL, "Invalid statement handle" );
@ -222,8 +222,8 @@ SQLRETURN sqlsrv_odbc_result_set::get_data( SQLUSMALLINT field_index, SQLSMALLIN
}
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 )
_Out_ SQLPOINTER diag_info_buffer, SQLSMALLINT buffer_length,
_Out_ 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,
@ -596,7 +596,7 @@ SQLRETURN sqlsrv_buffered_result_set::fetch( SQLSMALLINT orientation, SQLLEN off
}
SQLRETURN sqlsrv_buffered_result_set::get_data( SQLUSMALLINT field_index, SQLSMALLINT target_type,
__out SQLPOINTER buffer, SQLLEN buffer_length, __out SQLLEN* out_buffer_length,
_Out_ SQLPOINTER buffer, SQLLEN buffer_length, _Out_ SQLLEN* out_buffer_length,
bool handle_warning TSRMLS_DC )
{
last_error = NULL;
@ -632,8 +632,8 @@ SQLRETURN sqlsrv_buffered_result_set::get_data( SQLUSMALLINT field_index, SQLSMA
}
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 )
_Out_ SQLPOINTER diag_info_buffer, SQLSMALLINT buffer_length,
_Out_ 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,
@ -648,7 +648,7 @@ SQLRETURN sqlsrv_buffered_result_set::get_diag_field( SQLSMALLINT record_number,
SQLSRV_ASSERT( last_error->sqlstate != NULL,
"Must have a SQLSTATE in a valid last_error in sqlsrv_buffered_result_set::get_diag_field" );
memcpy( diag_info_buffer, last_error->sqlstate, min( buffer_length, SQL_SQLSTATE_BUFSIZE ));
memcpy_s( diag_info_buffer, buffer_length, last_error->sqlstate, min( buffer_length, SQL_SQLSTATE_BUFSIZE ));
return SQL_SUCCESS;
}
@ -684,8 +684,8 @@ 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,
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 )
{
// hex characters for the conversion loop below
@ -745,8 +745,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( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ SQLLEN* out_buffer_length )
{
SQLCHAR* row = get_row();
SQLCHAR* field_data = NULL;
@ -763,8 +763,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( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ SQLLEN* out_buffer_length )
{
SQLCHAR* row = get_row();
SQLCHAR* field_data = NULL;
@ -782,8 +782,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( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ 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 "
@ -811,8 +811,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( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ 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" );
@ -823,8 +823,8 @@ SQLRETURN sqlsrv_buffered_result_set::double_to_system_string( SQLSMALLINT field
return number_to_string<char>( double_data, buffer, buffer_length, out_buffer_length, last_error );
}
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( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ 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" );
@ -835,8 +835,8 @@ SQLRETURN sqlsrv_buffered_result_set::double_to_wide_string( SQLSMALLINT field_i
return number_to_string<WCHAR>( double_data, buffer, buffer_length, out_buffer_length, last_error );
}
SQLRETURN sqlsrv_buffered_result_set::long_to_double( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length )
SQLRETURN sqlsrv_buffered_result_set::long_to_double( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( meta[ field_index ].c_type == SQL_C_LONG, "Invalid conversion to long" );
SQLSRV_ASSERT( buffer_length >= sizeof(double), "Buffer length must be able to find a long in sqlsrv_buffered_result_set::double_to_long" );
@ -850,8 +850,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( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ 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" );
@ -862,8 +862,8 @@ SQLRETURN sqlsrv_buffered_result_set::long_to_system_string( SQLSMALLINT field_i
return number_to_string<char>( long_data, buffer, buffer_length, out_buffer_length, last_error );
}
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( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ 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" );
@ -874,8 +874,8 @@ SQLRETURN sqlsrv_buffered_result_set::long_to_wide_string( SQLSMALLINT field_ind
return number_to_string<WCHAR>( long_data, buffer, buffer_length, out_buffer_length, last_error );
}
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( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ 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" );
@ -886,8 +886,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( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ 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" );
@ -898,8 +898,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( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ 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" );
@ -910,8 +910,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( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ 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" );
@ -922,8 +922,8 @@ 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,
__out SQLLEN* out_buffer_length )
SQLRETURN sqlsrv_buffered_result_set::system_to_wide_string( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( last_error == NULL, "Pending error for sqlsrv_buffered_results_set::system_to_wide_string" );
SQLSRV_ASSERT( buffer_length % 2 == 0, "Odd buffer length passed to sqlsrv_buffered_result_set::system_to_wide_string" );
@ -1015,8 +1015,8 @@ 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,
__out SQLLEN* out_buffer_length )
SQLRETURN sqlsrv_buffered_result_set::to_same_string( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( last_error == NULL, "Pending error for sqlsrv_buffered_results_set::to_same_string" );
@ -1074,19 +1074,19 @@ SQLRETURN sqlsrv_buffered_result_set::to_same_string( SQLSMALLINT field_index, _
SQLSRV_ASSERT( to_copy >= 0, "Negative field length calculated in buffered result set" );
if( to_copy > 0 ) {
memcpy( buffer, field_data + read_so_far, to_copy );
memcpy_s( buffer, buffer_length, field_data + read_so_far, to_copy );
read_so_far += to_copy;
}
if( extra ) {
OACR_WARNING_SUPPRESS( 26001, "Buffer length verified above" );
memcpy( reinterpret_cast<SQLCHAR*>( buffer ) + to_copy, L"\0", extra );
memcpy_s( reinterpret_cast<SQLCHAR*>( buffer ) + to_copy, buffer_length, L"\0", extra );
}
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( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( last_error == NULL, "Pending error for sqlsrv_buffered_results_set::wide_to_system_string" );
@ -1159,7 +1159,7 @@ SQLRETURN sqlsrv_buffered_result_set::wide_to_system_string( SQLSMALLINT field_i
if( to_copy > 0 ) {
memcpy( buffer, temp_string.get() + read_so_far, to_copy );
memcpy_s( buffer, buffer_length, temp_string.get() + read_so_far, to_copy );
}
SQLSRV_ASSERT( to_copy >= 0, "Invalid field copy length" );
OACR_WARNING_SUPPRESS( BUFFER_UNDERFLOW, "Buffer length verified above" );
@ -1170,14 +1170,14 @@ 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,
__out SQLLEN* out_buffer_length )
SQLRETURN sqlsrv_buffered_result_set::to_binary_string( SQLSMALLINT field_index, _Out_ void* buffer, 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,
__out SQLLEN* out_buffer_length )
SQLRETURN sqlsrv_buffered_result_set::to_long( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( meta[ field_index ].c_type == SQL_C_LONG, "Invlid conversion to long" );
SQLSRV_ASSERT( buffer_length >= sizeof( LONG ), "Buffer too small for SQL_C_LONG" ); // technically should ignore this
@ -1185,14 +1185,14 @@ SQLRETURN sqlsrv_buffered_result_set::to_long( SQLSMALLINT field_index, __out vo
unsigned char* row = get_row();
LONG* long_data = reinterpret_cast<LONG*>( &row[ meta[ field_index ].offset ] );
memcpy( buffer, long_data, sizeof( LONG ));
memcpy_s( buffer, buffer_length, long_data, sizeof( LONG ));
*out_buffer_length = sizeof( LONG );
return SQL_SUCCESS;
}
SQLRETURN sqlsrv_buffered_result_set::to_double( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length )
SQLRETURN sqlsrv_buffered_result_set::to_double( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( meta[ field_index ].c_type == SQL_C_DOUBLE, "Invlid conversion to double" );
SQLSRV_ASSERT( buffer_length >= sizeof( double ), "Buffer too small for SQL_C_DOUBLE" ); // technically should ignore this
@ -1200,7 +1200,7 @@ SQLRETURN sqlsrv_buffered_result_set::to_double( SQLSMALLINT field_index, __out
unsigned char* row = get_row();
double* double_data = reinterpret_cast<double*>( &row[ meta[ field_index ].offset ] );
memcpy( buffer, double_data, sizeof( double ));
memcpy_s( buffer, buffer_length, double_data, sizeof( double ));
*out_buffer_length = sizeof( double );
return SQL_SUCCESS;
@ -1211,7 +1211,7 @@ namespace {
// called for each row in the cache when the cache is destroyed in the destructor
void cache_row_dtor( zval* data )
{
row_dtor_closure* cl = reinterpret_cast<row_dtor_closure*>( Z_PTR_P(data) );
row_dtor_closure* cl = reinterpret_cast<row_dtor_closure*>( Z_PTR_P( data ) );
BYTE* row = cl->row_data;
// don't release this here, since this is called from the destructor of the result_set
sqlsrv_buffered_result_set* result_set = cl->results;
@ -1226,6 +1226,7 @@ void cache_row_dtor( zval* data )
}
sqlsrv_free( row );
sqlsrv_free( cl );
}
SQLPOINTER read_lob_field( sqlsrv_stmt* stmt, SQLUSMALLINT field_index, sqlsrv_buffered_result_set::meta_data& meta,

View file

@ -889,6 +889,8 @@ class sqlsrv_context {
{
if( handle_ != SQL_NULL_HANDLE ) {
::SQLFreeHandle( handle_type_, handle_ );
last_error_.reset();
}
handle_ = SQL_NULL_HANDLE;
}
@ -1136,9 +1138,9 @@ void core_sqlsrv_prepare( sqlsrv_stmt* stmt, const char* sql, SQLLEN sql_len TSR
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 );
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 );
@ -1197,7 +1199,7 @@ struct sqlsrv_stream {
};
// close any active stream
void close_active_stream( __inout sqlsrv_stmt* stmt TSRMLS_DC );
void close_active_stream( _Inout_ sqlsrv_stmt* stmt TSRMLS_DC );
extern php_stream_wrapper g_sqlsrv_stream_wrapper;
@ -1323,8 +1325,8 @@ void core_sqlsrv_execute( sqlsrv_stmt* stmt TSRMLS_DC, const char* sql = NULL, i
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,
__out SQLSRV_PHPTYPE *sqlsrv_php_type_out TSRMLS_DC);
_Out_ void*& field_value, _Out_ SQLLEN* field_length, 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 );
@ -1359,11 +1361,11 @@ struct sqlsrv_result_set {
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,
_Out_ void* buffer, SQLLEN buffer_length, _Out_ 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;
_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 SQLLEN row_count( TSRMLS_D ) = 0;
};
@ -1376,11 +1378,11 @@ struct sqlsrv_odbc_result_set : public sqlsrv_result_set {
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,
_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 );
_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 SQLLEN row_count( TSRMLS_D );
@ -1414,11 +1416,11 @@ struct sqlsrv_buffered_result_set : public sqlsrv_result_set {
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,
_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 );
_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 SQLLEN row_count( TSRMLS_D );
@ -1449,55 +1451,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)( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ 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,
__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,
__out SQLLEN* out_buffer_length );
SQLRETURN to_same_string( SQLSMALLINT field_index, __out void* buffer, 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 binary_to_wide_string( SQLSMALLINT field_index, _Out_ void* buffer, 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,
_Out_ SQLLEN* out_buffer_length );
SQLRETURN to_same_string( SQLSMALLINT field_index, _Out_ void* buffer, 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 );
// 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,
__out SQLLEN* out_buffer_length );
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,
_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( 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 );
// 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( 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 );
// utility functions for conversions
unsigned char* get_row( void );
@ -1520,7 +1522,7 @@ bool convert_zval_string_from_utf16(SQLSRV_ENCODING encoding, zval* value_z, SQL
bool validate_string(char* string, SQLLEN& len);
bool convert_string_from_utf16( SQLSRV_ENCODING encoding, const wchar_t* inString, SQLINTEGER cchInLen, char** outString, SQLLEN& cchOutLen );
wchar_t* utf16_string_from_mbcs_string( SQLSRV_ENCODING php_encoding, const char* mbcs_string,
unsigned int mbcs_len, __out unsigned int* utf16_len );
unsigned int mbcs_len, _Out_ unsigned int* utf16_len );
//*********************************************************************************************************************************
// Error handling routines and Predefined Errors
@ -1598,7 +1600,7 @@ 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,
bool core_sqlsrv_get_odbc_error( sqlsrv_context& ctx, int record_number, _Out_ sqlsrv_error_auto_ptr& error,
logging_severity severity TSRMLS_DC );
// format and return a driver specfic error
@ -1754,8 +1756,7 @@ namespace core {
throw CoreException();
}
std::size_t driver_version = stmt->conn->driver_version;
if(( len == sizeof( CONNECTION_BUSY_ODBC_ERROR[driver_version] ) - 1 ) &&
!strcmp( reinterpret_cast<const char*>( err_msg ), CONNECTION_BUSY_ODBC_ERROR[driver_version] )) {
if( !strcmp( reinterpret_cast<const char*>( err_msg ), CONNECTION_BUSY_ODBC_ERROR[driver_version] )) {
THROW_CORE_ERROR( stmt, SQLSRV_ERROR_MARS_OFF );
}
@ -1771,8 +1772,8 @@ namespace core {
// 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 )
_Out_ SQLPOINTER diag_info_buffer, SQLSMALLINT buffer_length,
_Out_ 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 );
@ -1785,7 +1786,7 @@ namespace core {
}
inline void SQLAllocHandle( SQLSMALLINT HandleType, sqlsrv_context& InputHandle,
__out_ecount(1) SQLHANDLE* OutputHandlePtr TSRMLS_DC )
_Out_writes_(1) SQLHANDLE* OutputHandlePtr TSRMLS_DC )
{
SQLRETURN r;
r = ::SQLAllocHandle( HandleType, InputHandle.handle(), OutputHandlePtr );
@ -1801,9 +1802,9 @@ namespace core {
SQLSMALLINT ParameterType,
SQLULEN ColumnSize,
SQLSMALLINT DecimalDigits,
__inout SQLPOINTER ParameterValuePtr,
_Inout_ SQLPOINTER ParameterValuePtr,
SQLLEN BufferLength,
__inout SQLLEN * StrLen_Or_IndPtr
_Inout_ SQLLEN * StrLen_Or_IndPtr
TSRMLS_DC )
{
SQLRETURN r;
@ -1817,8 +1818,8 @@ 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 )
_Out_ SQLPOINTER field_type_char, SQLSMALLINT buffer_length,
_Out_ SQLSMALLINT* out_buffer_length, _Out_ 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 );
@ -1829,9 +1830,9 @@ namespace core {
}
inline void SQLDescribeCol( sqlsrv_stmt* stmt, SQLSMALLINT colno, __out_z 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( 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 )
{
SQLRETURN r;
r = ::SQLDescribeCol( stmt->handle(), colno, col_name, col_name_length, col_name_length_out,
@ -1914,7 +1915,7 @@ namespace core {
}
inline SQLRETURN SQLGetData( sqlsrv_stmt* stmt, SQLUSMALLINT field_index, SQLSMALLINT target_type,
__out void* buffer, SQLLEN buffer_length, __out SQLLEN* out_buffer_length,
_Out_ void* buffer, SQLLEN buffer_length, _Out_ SQLLEN* out_buffer_length,
bool handle_warning TSRMLS_DC )
{
SQLRETURN r = ::SQLGetData( stmt->handle(), field_index, target_type, buffer, buffer_length, out_buffer_length );
@ -1936,8 +1937,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( sqlsrv_conn* conn, SQLUSMALLINT info_type, _Out_ SQLPOINTER info_value, SQLSMALLINT buffer_len,
_Out_ SQLSMALLINT* str_len TSRMLS_DC )
{
SQLRETURN r;
r = ::SQLGetInfo( conn->handle(), info_type, info_value, buffer_len, str_len );
@ -1986,7 +1987,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( sqlsrv_stmt* stmt, _Out_ SQLPOINTER* value_ptr_ptr TSRMLS_DC )
{
SQLRETURN r;
r = ::SQLParamData( stmt->handle(), value_ptr_ptr );
@ -2141,7 +2142,7 @@ namespace core {
}
}
inline void sqlsrv_array_init( sqlsrv_context& ctx, __out zval* new_array TSRMLS_DC)
inline void sqlsrv_array_init( sqlsrv_context& ctx, _Out_ zval* new_array TSRMLS_DC)
{
int zr = ::array_init(new_array);
CHECK_ZEND_ERROR( zr, ctx, SQLSRV_ERROR_ZEND_HASH ) {
@ -2158,7 +2159,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(sqlsrv_context& ctx, HashTable* ht, _Out_ 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 ) {
@ -2166,7 +2167,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(sqlsrv_context& ctx, HashTable* ht, _Out_ 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) {

View file

@ -35,7 +35,7 @@ struct field_cache {
// if the value is NULL, then just record a NULL pointer
if( field_value != NULL ) {
value = sqlsrv_malloc( field_len );
memcpy( value, field_value, field_len );
memcpy_s( value, field_len, field_value, field_len );
len = field_len;
}
else {
@ -76,23 +76,23 @@ 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 );
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 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);
// 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,
__out SQLULEN& column_size, __out SQLSMALLINT& decimal_digits TSRMLS_DC );
_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,
__out SQLSMALLINT& sql_type TSRMLS_DC );
_Out_ SQLSMALLINT& sql_type TSRMLS_DC );
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 );
_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 );
// assure there is enough space for the output parameter string
@ -312,7 +312,7 @@ 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,
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 )
{
@ -342,7 +342,7 @@ void core_sqlsrv_bind_param(sqlsrv_stmt* stmt, SQLUSMALLINT param_num, SQLSMALLI
if ( Z_ISREF_P( param_z ) ) {
ZVAL_DEREF( param_z );
}
bool zval_was_null = ( Z_TYPE_P( param_z ) == IS_NULL);
bool zval_was_null = ( Z_TYPE_P( param_z ) == IS_NULL );
bool zval_was_bool = ( Z_TYPE_P( param_z ) == IS_TRUE || Z_TYPE_P( param_z ) == IS_FALSE );
// if the user asks for for a specific type for input and output, make sure the data type we send matches the data we
// type we expect back, since we can only send and receive the same type. Anything can be converted to a string, so
@ -411,7 +411,7 @@ void core_sqlsrv_bind_param(sqlsrv_stmt* stmt, SQLUSMALLINT param_num, SQLSMALLI
// if the sql type is unknown, then set the default based on the PHP type passed in
if( sql_type == SQL_UNKNOWN_TYPE ) {
default_sql_type(stmt, param_num, param_z, encoding, sql_type TSRMLS_CC);
default_sql_type( stmt, param_num, param_z, encoding, sql_type TSRMLS_CC );
}
// if the size is unknown, then set the default based on the PHP type passed in
@ -456,7 +456,7 @@ void core_sqlsrv_bind_param(sqlsrv_stmt* stmt, SQLUSMALLINT param_num, SQLSMALLI
ind_ptr = buffer_len;
if( direction != SQL_PARAM_INPUT ) {
// save the parameter so that 1) the buffer doesn't go away, and 2) we can set it to NULL if returned
sqlsrv_output_param output_param(param_ref, static_cast<int>( param_num ), false );
sqlsrv_output_param output_param( param_ref, static_cast<int>( param_num ), false );
save_output_param_for_later( stmt, output_param TSRMLS_CC );
}
}
@ -493,11 +493,11 @@ void core_sqlsrv_bind_param(sqlsrv_stmt* stmt, SQLUSMALLINT param_num, SQLSMALLI
// or if the PHP type is a binary encoded string with a N(VAR)CHAR/NTEXTSQL type,
// convert it to wchar first
if( direction == SQL_PARAM_INPUT_OUTPUT &&
(c_type == SQL_C_WCHAR ||
(c_type == SQL_C_BINARY &&
(sql_type == SQL_WCHAR ||
sql_type == SQL_WVARCHAR ||
sql_type == SQL_WLONGVARCHAR )))) {
( c_type == SQL_C_WCHAR ||
( c_type == SQL_C_BINARY &&
( sql_type == SQL_WCHAR ||
sql_type == SQL_WVARCHAR ||
sql_type == SQL_WLONGVARCHAR )))) {
bool converted = convert_input_param_to_utf16( param_z, param_z );
CHECK_CUSTOM_ERROR( !converted, stmt, SQLSRV_ERROR_INPUT_PARAM_ENCODING_TRANSLATE,
@ -546,7 +546,7 @@ void core_sqlsrv_bind_param(sqlsrv_stmt* stmt, SQLUSMALLINT param_num, SQLSMALLI
SQLSRV_ASSERT( direction == SQL_PARAM_INPUT, "Invalid output param type. The driver layer should catch this." );
sqlsrv_stream stream_encoding( param_z, encoding );
HashTable* streams_ht = Z_ARRVAL( stmt->param_streams );
core::sqlsrv_zend_hash_index_update_mem(*stmt, streams_ht, param_num, &stream_encoding, sizeof(stream_encoding) TSRMLS_CC);
core::sqlsrv_zend_hash_index_update_mem( *stmt, streams_ht, param_num, &stream_encoding, sizeof(stream_encoding) TSRMLS_CC );
buffer = reinterpret_cast<SQLPOINTER>( param_num );
Z_TRY_ADDREF_P( param_z ); // so that it doesn't go away while we're using it
buffer_len = 0;
@ -567,7 +567,7 @@ void core_sqlsrv_bind_param(sqlsrv_stmt* stmt, SQLUSMALLINT param_num, SQLSMALLI
bool valid_class_name_found = false;
zend_class_entry *class_entry = Z_OBJCE_P(param_z TSRMLS_CC);
zend_class_entry *class_entry = Z_OBJCE_P( param_z TSRMLS_CC );
while( class_entry != NULL ) {
@ -593,7 +593,7 @@ void core_sqlsrv_bind_param(sqlsrv_stmt* stmt, SQLUSMALLINT param_num, SQLSMALLI
// sql type, it lacks the timezone.
if( sql_type == SQL_SS_TIMESTAMPOFFSET ) {
core::sqlsrv_zval_stringl( &format_z, const_cast<char*>( DateTime::DATETIMEOFFSET_FORMAT ),
DateTime::DATETIMEOFFSET_FORMAT_LEN);
DateTime::DATETIMEOFFSET_FORMAT_LEN );
}
else if( sql_type == SQL_TYPE_DATE ) {
core::sqlsrv_zval_stringl( &format_z, const_cast<char*>( DateTime::DATE_FORMAT ), DateTime::DATE_FORMAT_LEN );
@ -607,11 +607,13 @@ void core_sqlsrv_bind_param(sqlsrv_stmt* stmt, SQLUSMALLINT param_num, SQLSMALLI
// This is equivalent to the PHP code: $param_z->format( $format_z ); where param_z is the
// DateTime object and $format_z is the format string.
int zr = call_user_function( EG( function_table ), param_z, &function_z, &buffer_z, 1, params TSRMLS_CC );
zend_string_release( Z_STR( format_z ));
zend_string_release( Z_STR( function_z ));
CHECK_CUSTOM_ERROR( zr == FAILURE, stmt, SQLSRV_ERROR_INVALID_PARAMETER_PHPTYPE, param_num + 1 ) {
throw core::CoreException();
}
buffer = Z_STRVAL( buffer_z );
zr = add_next_index_zval( &(stmt->param_datetime_buffers), &buffer_z );
zr = add_next_index_zval( &( stmt->param_datetime_buffers ), &buffer_z );
CHECK_CUSTOM_ERROR( zr == FAILURE, stmt, SQLSRV_ERROR_INVALID_PARAMETER_PHPTYPE, param_num + 1 ) {
throw core::CoreException();
}
@ -694,7 +696,7 @@ void core_sqlsrv_execute( sqlsrv_stmt* stmt TSRMLS_DC, const char* sql, int sql_
stmt->executed = true;
// if all the data has been sent and no data was returned then finalize the output parameters
if( stmt->send_streams_at_exec && (r == SQL_NO_DATA || !core_sqlsrv_has_any_result( stmt TSRMLS_CC ))) {
if( stmt->send_streams_at_exec && ( r == SQL_NO_DATA || !core_sqlsrv_has_any_result( stmt TSRMLS_CC ))) {
finalize_output_parameters( stmt TSRMLS_CC );
}
@ -706,8 +708,12 @@ void core_sqlsrv_execute( sqlsrv_stmt* stmt TSRMLS_DC, const char* sql, int sql_
catch( core::CoreException& e ) {
// if the statement executed but failed in a subsequent operation before returning,
// we need to cancel the statement
if( stmt->executed ) {
// we need to cancel the statement and deref the output and stream parameters
if ( stmt->send_streams_at_exec ) {
zend_hash_clean( Z_ARRVAL( stmt->output_params ));
zend_hash_clean( Z_ARRVAL( stmt->param_streams ));
}
if( stmt->executed ) {
SQLCancel( stmt->handle() );
// stmt->executed = false; should this be reset if something fails?
}
@ -864,8 +870,8 @@ field_meta_data* core_sqlsrv_field_metadata( sqlsrv_stmt* stmt, SQLSMALLINT coln
// 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,
__out SQLSRV_PHPTYPE *sqlsrv_php_type_out TSRMLS_DC)
_Out_ void*& field_value, _Out_ SQLLEN* field_len, bool cache_field,
_Out_ SQLSRV_PHPTYPE *sqlsrv_php_type_out TSRMLS_DC)
{
try {
@ -884,7 +890,7 @@ void core_sqlsrv_get_field( sqlsrv_stmt* stmt, SQLUSMALLINT field_index, sqlsrv_
else {
field_value = sqlsrv_malloc( cached->len, sizeof( char ), 1 );
memcpy( field_value, cached->value, cached->len );
memcpy_s( field_value, ( cached->len * sizeof( char )), cached->value, cached->len );
if( cached->type.typeinfo.type == SQLSRV_PHPTYPE_STRING) {
// prevent the 'string not null terminated' warning
reinterpret_cast<char*>( field_value )[ cached->len ] = '\0';
@ -1329,7 +1335,7 @@ void stmt_option_buffered_query_limit:: operator()( sqlsrv_stmt* stmt, stmt_opti
// internal function to release the active stream. Called by each main API function
// that will alter the statement and cancel any retrieval of data from a stream.
void close_active_stream( __inout sqlsrv_stmt* stmt TSRMLS_DC )
void close_active_stream( _Inout_ sqlsrv_stmt* stmt TSRMLS_DC )
{
// if there is no active stream, return
if( Z_TYPE( stmt->active_stream ) == IS_UNDEF ) {
@ -1372,7 +1378,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( sqlsrv_stmt* stmt, SQLUSMALLINT field_index, SQLLEN sql_type, _Out_ SQLLEN& size TSRMLS_DC )
{
try {
@ -1468,8 +1474,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, SQLUSMALLINT field_index, sqlsrv_phptype
sqlsrv_php_type, _Out_ void*& field_value, _Out_ SQLLEN* field_len TSRMLS_DC )
{
try {
@ -1554,13 +1560,10 @@ void core_get_field_common( __inout sqlsrv_stmt* stmt, SQLUSMALLINT field_index,
zval params[1];
zval field_value_temp_z;
zval function_z;
zval_auto_ptr return_value_z;
ZVAL_UNDEF( &field_value_temp_z );
ZVAL_UNDEF( &function_z );
ZVAL_UNDEF( params );
return_value_z = (zval *)sqlsrv_malloc( sizeof( zval ));
ZVAL_UNDEF( return_value_z );
SQLRETURN r = stmt->current_results->get_data( field_index + 1, SQL_C_CHAR, field_value_temp,
MAX_DATETIME_STRING_LEN, field_len, true TSRMLS_CC );
@ -1569,6 +1572,10 @@ void core_get_field_common( __inout sqlsrv_stmt* stmt, SQLUSMALLINT field_index,
throw core::CoreException();
}
zval_auto_ptr return_value_z;
return_value_z = ( zval * )sqlsrv_malloc( sizeof( zval ));
ZVAL_UNDEF( return_value_z );
if( *field_len == SQL_NULL_DATA ) {
ZVAL_NULL( return_value_z );
field_value = reinterpret_cast<void*>( return_value_z.get());
@ -1599,9 +1606,6 @@ void core_get_field_common( __inout sqlsrv_stmt* stmt, SQLUSMALLINT field_index,
case SQLSRV_PHPTYPE_STREAM:
{
zval_auto_ptr return_value_z;
return_value_z = (zval *)sqlsrv_malloc(sizeof(zval));
ZVAL_UNDEF(return_value_z);
php_stream* stream = NULL;
sqlsrv_stream* ss = NULL;
SQLLEN sql_type;
@ -1627,6 +1631,10 @@ void core_get_field_common( __inout sqlsrv_stmt* stmt, SQLUSMALLINT field_index,
ss->sql_type = static_cast<SQLUSMALLINT>( sql_type );
ss->encoding = static_cast<SQLSRV_ENCODING>( sqlsrv_php_type.typeinfo.encoding );
zval_auto_ptr return_value_z;
return_value_z = ( zval * )sqlsrv_malloc( sizeof( zval ));
ZVAL_UNDEF( return_value_z );
// turn our stream into a zval to be returned
php_stream_to_zval( stream, return_value_z );
@ -1659,7 +1667,7 @@ void core_get_field_common( __inout sqlsrv_stmt* stmt, SQLUSMALLINT field_index,
// check_for_next_stream_parameter
// see if there is another stream to be sent. Returns true and sets the stream as current in the statement structure, otherwise
// returns false
bool check_for_next_stream_parameter( __inout sqlsrv_stmt* stmt TSRMLS_DC )
bool check_for_next_stream_parameter( _Inout_ sqlsrv_stmt* stmt TSRMLS_DC )
{
int stream_index = 0;
SQLRETURN r = SQL_SUCCESS;
@ -1810,7 +1818,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,
__out SQLSMALLINT& sql_type TSRMLS_DC )
_Out_ SQLSMALLINT& sql_type TSRMLS_DC )
{
sql_type = SQL_UNKNOWN_TYPE;
int php_type = Z_TYPE_P(param_z);
@ -1880,7 +1888,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,
__out SQLULEN& column_size, __out SQLSMALLINT& decimal_digits TSRMLS_DC )
_Out_ SQLULEN& column_size, _Out_ SQLSMALLINT& decimal_digits TSRMLS_DC )
{
int php_type = Z_TYPE_P( param_z );
column_size = 0;
@ -1933,11 +1941,12 @@ void default_sql_size_and_scale( sqlsrv_stmt* stmt, unsigned int paramno, zval*
void field_cache_dtor( zval* data_z )
{
field_cache* cache = reinterpret_cast<field_cache*>(Z_PTR_P(data_z));
field_cache* cache = static_cast<field_cache*>( Z_PTR_P( data_z ));
if( cache->value )
{
sqlsrv_free( cache->value );
}
sqlsrv_free( cache );
}
@ -1968,6 +1977,7 @@ void finalize_output_parameters( sqlsrv_stmt* stmt TSRMLS_DC )
char* str = Z_STRVAL_P( value_z );
SQLLEN str_len = stmt->param_ind_ptrs[ output_param->param_num ];
if( str_len == SQL_NULL_DATA ) {
zend_string_release( Z_STR_P( value_z ));
ZVAL_NULL( value_z );
continue;
}
@ -2044,7 +2054,7 @@ 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 )
_Out_ void*& field_value, _Out_ SQLLEN* field_len TSRMLS_DC )
{
SQLRETURN r;
SQLSMALLINT c_type;
@ -2433,6 +2443,7 @@ void sqlsrv_output_param_dtor( 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
sqlsrv_free( output_param );
}
// called by Zend for each stream in the sqlsrv_stmt::param_streams hash table when it is cleaned/destroyed
@ -2440,6 +2451,7 @@ void sqlsrv_stream_dtor( 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
sqlsrv_free( stream_encoding );
}
}

View file

@ -45,7 +45,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_bcount(count) char* buf, size_t count TSRMLS_DC )
size_t sqlsrv_stream_read( php_stream* stream, _Out_writes_bytes_(count) char* buf, size_t count TSRMLS_DC )
{
SQLLEN read = 0;
SQLSMALLINT c_type = SQL_C_CHAR;
@ -203,8 +203,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( php_stream_wrapper* wrapper, _In_ const char*, _In_ const char* mode,
int options, _In_ zend_string **, php_stream_context* STREAMS_DC TSRMLS_DC )
{
#if ZEND_DEBUG

View file

@ -33,9 +33,9 @@ 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_bcount(mbcs_len) char const* mbcs_in_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,
__out_ecount(utf16_len) __transfer( mbcs_in_string ) wchar_t* utf16_out_string,
_Out_writes_(utf16_len) __transfer( mbcs_in_string ) wchar_t* utf16_out_string,
unsigned int utf16_len );
}
@ -370,8 +370,8 @@ 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_bcount(mbcs_len) char const* mbcs_in_string,
unsigned int mbcs_len, __out_ecount(utf16_len) __transfer( mbcs_in_string ) wchar_t* utf16_out_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, _Out_writes_(utf16_len) __transfer( mbcs_in_string ) wchar_t* utf16_out_string,
unsigned int utf16_len )
{
unsigned int win_encoding = CP_ACP;

View file

@ -888,7 +888,7 @@ RETCODE SQL_API bcp_moretext (HDBC, DBINT, LPCBYTE);
RETCODE SQL_API bcp_readfmtA (HDBC, LPCSTR);
RETCODE SQL_API bcp_readfmtW (HDBC, LPCWSTR);
RETCODE SQL_API bcp_sendrow (HDBC);
RETCODE SQL_API bcp_setbulkmode (HDBC, INT, __in_bcount(cbField) void*, INT cbField, __in_bcount(cbRow) void *, INT cbRow);
RETCODE SQL_API bcp_setbulkmode (HDBC, INT, _In_reads_bytes_(cbField) void*, INT cbField, _In_reads_bytes_(cbRow) void *, INT cbRow);
RETCODE SQL_API bcp_setcolfmt (HDBC, INT, INT, void *, INT);
RETCODE SQL_API bcp_writefmtA (HDBC, LPCSTR);
RETCODE SQL_API bcp_writefmtW (HDBC, LPCWSTR);
@ -958,7 +958,7 @@ HANDLE __stdcall OpenSqlFilestream (
LPCWSTR FilestreamPath,
SQL_FILESTREAM_DESIRED_ACCESS DesiredAccess,
ULONG OpenOptions,
__in_bcount(FilestreamTransactionContextLength)
_In_reads_bytes_(FilestreamTransactionContextLength)
LPBYTE FilestreamTransactionContext,
SSIZE_T FilestreamTransactionContextLength,
PLARGE_INTEGER AllocationSize);
@ -995,11 +995,11 @@ extern "C" {
// type definition for LocalDBCreateInstance function
typedef HRESULT __cdecl FnLocalDBCreateInstance (
// I the LocalDB version (e.g. 11.0 or 11.0.1094.2)
__in_z PCWSTR wszVersion,
_In_z_ PCWSTR wszVersion,
// I the instance name
__in_z PCWSTR pInstanceName,
_In_z_ PCWSTR pInstanceName,
// I reserved for the future use. Currently should be set to 0.
__in DWORD dwFlags
_In_ DWORD dwFlags
);
// type definition for pointer to LocalDBCreateInstance function
@ -1008,14 +1008,14 @@ typedef FnLocalDBCreateInstance* PFnLocalDBCreateInstance;
// type definition for LocalDBStartInstance function
typedef HRESULT __cdecl FnLocalDBStartInstance (
// I the LocalDB instance name
__in_z PCWSTR pInstanceName,
_In_z_ PCWSTR pInstanceName,
// I reserved for the future use. Currently should be set to 0.
__in DWORD dwFlags,
_In_ DWORD dwFlags,
// O the buffer to store the connection string to the LocalDB instance
__out_ecount_z_opt(*lpcchSqlConnection) LPWSTR wszSqlConnection,
_Out_writes_opt_z_(*lpcchSqlConnection) LPWSTR wszSqlConnection,
// I/O on input has the size of the wszSqlConnection buffer in characters. On output, if the given buffer size is
// too small, has the buffer size required, in characters, including trailing null.
__inout_opt LPDWORD lpcchSqlConnection
_Inout_opt_ LPDWORD lpcchSqlConnection
);
// type definition for pointer to LocalDBStartInstance function
@ -1027,19 +1027,19 @@ typedef FnLocalDBStartInstance* PFnLocalDBStartInstance;
// type definition for LocalDBFormatMessage function
typedef HRESULT __cdecl FnLocalDBFormatMessage(
// I the LocalDB error code
__in HRESULT hrLocalDB,
_In_ HRESULT hrLocalDB,
// I Available flags:
// LOCALDB_TRUNCATE_ERR_MESSAGE - if the input buffer is too short,
// the error message will be truncated to fit into the buffer
__in DWORD dwFlags,
_In_ DWORD dwFlags,
// I Language desired (LCID) or 0 (in which case Win32 FormatMessage order is used)
__in DWORD dwLanguageId,
_In_ DWORD dwLanguageId,
// O the buffer to store the LocalDB error message
__out_ecount_z(*lpcchMessage) LPWSTR wszMessage,
_Out_writes_z_(*lpcchMessage) LPWSTR wszMessage,
// I/O on input has the size of the wszMessage buffer in characters. On output, if the given buffer size is
// too small, has the buffer size required, in characters, including trailing null. If the function succeeds
// contains the number of characters in the message, excluding the trailing null
__inout LPDWORD lpcchMessage
_Inout_ LPDWORD lpcchMessage
);
// type definition for function pointer to LocalDBFormatMessage function
@ -1112,14 +1112,14 @@ FnLocalDBStartInstance LocalDBStartInstance;
// type definition for LocalDBStopInstance function
typedef HRESULT __cdecl FnLocalDBStopInstance (
// I the LocalDB instance name
__in_z PCWSTR pInstanceName,
_In_z_ PCWSTR pInstanceName,
// I Available flags:
// LOCALDB_SHUTDOWN_KILL_PROCESS - force the instance to stop immediately
// LOCALDB_SHUTDOWN_WITH_NOWAIT - shutdown the instance with NOWAIT option
__in DWORD dwFlags,
_In_ DWORD dwFlags,
// I the time in seconds to wait this operation to complete. If this value is 0, this function will return immediately
// without waiting for LocalDB instance to stop
__in ULONG ulTimeout
_In_ ULONG ulTimeout
);
// type definition for pointer to LocalDBStopInstance function
@ -1149,9 +1149,9 @@ FnLocalDBStopInstance LocalDBStopInstance;
// type definition for LocalDBDeleteInstance function
typedef HRESULT __cdecl FnLocalDBDeleteInstance (
// I the LocalDB instance name
__in_z PCWSTR pInstanceName,
_In_z_ PCWSTR pInstanceName,
// I reserved for the future use. Currently should be set to 0.
__in DWORD dwFlags
_In_ DWORD dwFlags
);
// type definition for pointer to LocalDBDeleteInstance function
@ -1202,10 +1202,10 @@ typedef TLocalDBInstanceName* PTLocalDBInstanceName;
// type definition for LocalDBGetInstances function
typedef HRESULT __cdecl FnLocalDBGetInstances(
// O buffer for a LocalDB instance names
__out PTLocalDBInstanceName pInstanceNames,
_Out_ PTLocalDBInstanceName pInstanceNames,
// I/O on input has the number slots for instance names in the pInstanceNames buffer. On output,
// has the number of existing LocalDB instances
__inout LPDWORD lpdwNumberOfInstances
_Inout_ LPDWORD lpdwNumberOfInstances
);
// type definition for pointer to LocalDBGetInstances function
@ -1267,11 +1267,11 @@ typedef LocalDBInstanceInfo* PLocalDBInstanceInfo;
// type definition for LocalDBGetInstanceInfo function
typedef HRESULT __cdecl FnLocalDBGetInstanceInfo(
// I the LocalDB instance name
__in_z PCWSTR wszInstanceName,
_In_z_ PCWSTR wszInstanceName,
// O instance information
__out PLocalDBInstanceInfo pInfo,
_Out_ PLocalDBInstanceInfo pInfo,
// I Size of LocalDBInstanceInfo structure in bytes
__in DWORD cbInfo);
_In_ DWORD cbInfo);
// type definition for pointer to LocalDBGetInstances function
typedef FnLocalDBGetInstanceInfo* PFnLocalDBGetInstanceInfo;
@ -1298,10 +1298,10 @@ typedef TLocalDBVersion* PTLocalDBVersion;
// type definition for LocalDBGetVersions function
typedef HRESULT __cdecl FnLocalDBGetVersions(
// O buffer for installed LocalDB versions
__out PTLocalDBVersion pVersions,
_Out_ PTLocalDBVersion pVersions,
// I/O on input has the number slots for versions in the pVersions buffer. On output,
// has the number of existing LocalDB versions
__inout LPDWORD lpdwNumberOfVersions
_Inout_ LPDWORD lpdwNumberOfVersions
);
// type definition for pointer to LocalDBGetVersions function
@ -1352,11 +1352,11 @@ typedef LocalDBVersionInfo* PLocalDBVersionInfo;
// type definition for LocalDBGetVersionInfo function
typedef HRESULT __cdecl FnLocalDBGetVersionInfo(
// I LocalDB version string
__in_z PCWSTR wszVersion,
_In_z_ PCWSTR wszVersion,
// O version information
__out PLocalDBVersionInfo pVersionInfo,
_Out_ PLocalDBVersionInfo pVersionInfo,
// I Size of LocalDBVersionInfo structure in bytes
__in DWORD cbVersionInfo
_In_ DWORD cbVersionInfo
);
// type definition for pointer to LocalDBGetVersionInfo function
@ -1402,13 +1402,13 @@ FnLocalDBStopTracing LocalDBStopTracing;
// type definition for LocalDBShareInstance function
typedef HRESULT __cdecl FnLocalDBShareInstance(
// I the SID of the LocalDB instance owner
__in_opt PSID pOwnerSID,
_In_opt_ PSID pOwnerSID,
// I the private name of LocalDB instance which should be shared
__in_z PCWSTR wszPrivateLocalDBInstanceName,
_In_z_ PCWSTR wszPrivateLocalDBInstanceName,
// I the public shared name
__in_z PCWSTR wszSharedName,
_In_z_ PCWSTR wszSharedName,
// I reserved for the future use. Currently should be set to 0.
__in DWORD dwFlags);
_In_ DWORD dwFlags);
// type definition for pointer to LocalDBShareInstance function
typedef FnLocalDBShareInstance* PFnLocalDBShareInstance;
@ -1426,9 +1426,9 @@ FnLocalDBShareInstance LocalDBShareInstance;
// type definition for LocalDBUnshareInstance function
typedef HRESULT __cdecl FnLocalDBUnshareInstance(
// I the LocalDB instance name
__in_z PCWSTR pInstanceName,
_In_z_ PCWSTR pInstanceName,
// I reserved for the future use. Currently should be set to 0.
__in DWORD dwFlags);
_In_ DWORD dwFlags);
// type definition for pointer to LocalDBUnshareInstance function
typedef FnLocalDBUnshareInstance* PFnLocalDBUnshareInstance;
@ -1653,11 +1653,11 @@ Cleanup:
HRESULT __cdecl
LocalDBCreateInstance (
// I the LocalDB version (e.g. 11.0 or 11.0.1094.2)
__in_z PCWSTR wszVersion,
_In_z_ PCWSTR wszVersion,
// I the instance name
__in_z PCWSTR pInstanceName,
_In_z_ PCWSTR pInstanceName,
// I reserved for the future use. Currently should be set to 0.
__in DWORD dwFlags
_In_ DWORD dwFlags
)
{
LOCALDB_PROXY(LocalDBCreateInstance)(wszVersion, pInstanceName, dwFlags);
@ -1666,14 +1666,14 @@ LocalDBCreateInstance (
HRESULT __cdecl
LocalDBStartInstance(
// I the instance name
__in_z PCWSTR pInstanceName,
_In_z_ PCWSTR pInstanceName,
// I reserved for the future use. Currently should be set to 0.
__in DWORD dwFlags,
_In_ DWORD dwFlags,
// O the buffer to store the connection string to the LocalDB instance
__out_ecount_z_opt(*lpcchSqlConnection) LPWSTR wszSqlConnection,
_Out_writes_z__opt(*lpcchSqlConnection) LPWSTR wszSqlConnection,
// I/O on input has the size of the wszSqlConnection buffer in characters. On output, if the given buffer size is
// too small, has the buffer size required, in characters, including trailing null.
__inout_opt LPDWORD lpcchSqlConnection
_Inout_opt_ LPDWORD lpcchSqlConnection
)
{
LOCALDB_PROXY(LocalDBStartInstance)(pInstanceName, dwFlags, wszSqlConnection, lpcchSqlConnection);
@ -1682,14 +1682,14 @@ LocalDBStartInstance(
HRESULT __cdecl
LocalDBStopInstance (
// I the instance name
__in_z PCWSTR pInstanceName,
_In_z_ PCWSTR pInstanceName,
// I Available flags:
// LOCALDB_SHUTDOWN_KILL_PROCESS - force the instance to stop immediately
// LOCALDB_SHUTDOWN_WITH_NOWAIT - shutdown the instance with NOWAIT option
__in DWORD dwFlags,
_In_ DWORD dwFlags,
// I the time in seconds to wait this operation to complete. If this value is 0, this function will return immediately
// without waiting for LocalDB instance to stop
__in ULONG ulTimeout
_In_ ULONG ulTimeout
)
{
LOCALDB_PROXY(LocalDBStopInstance)(pInstanceName, dwFlags, ulTimeout);
@ -1698,9 +1698,9 @@ LocalDBStopInstance (
HRESULT __cdecl
LocalDBDeleteInstance (
// I the instance name
__in_z PCWSTR pInstanceName,
_In_z_ PCWSTR pInstanceName,
// reserved for the future use. Currently should be set to 0.
__in DWORD dwFlags
_In_ DWORD dwFlags
)
{
LOCALDB_PROXY(LocalDBDeleteInstance)(pInstanceName, dwFlags);
@ -1709,19 +1709,19 @@ LocalDBDeleteInstance (
HRESULT __cdecl
LocalDBFormatMessage(
// I the LocalDB error code
__in HRESULT hrLocalDB,
_In_ HRESULT hrLocalDB,
// I Available flags:
// LOCALDB_TRUNCATE_ERR_MESSAGE - if the input buffer is too short,
// the error message will be truncated to fit into the buffer
__in DWORD dwFlags,
_In_ DWORD dwFlags,
// I Language desired (LCID) or 0 (in which case Win32 FormatMessage order is used)
__in DWORD dwLanguageId,
_In_ DWORD dwLanguageId,
// O the buffer to store the LocalDB error message
__out_ecount_z(*lpcchMessage) LPWSTR wszMessage,
_Out_writes_z_(*lpcchMessage) LPWSTR wszMessage,
// I/O on input has the size of the wszMessage buffer in characters. On output, if the given buffer size is
// too small, has the buffer size required, in characters, including trailing null. If the function succeeds
// contains the number of characters in the message, excluding the trailing null
__inout LPDWORD lpcchMessage
_Inout_ LPDWORD lpcchMessage
)
{
LOCALDB_PROXY(LocalDBFormatMessage)(hrLocalDB, dwFlags, dwLanguageId, wszMessage, lpcchMessage);
@ -1730,10 +1730,10 @@ LocalDBFormatMessage(
HRESULT __cdecl
LocalDBGetInstances(
// O buffer with instance names
__out PTLocalDBInstanceName pInstanceNames,
_Out_ PTLocalDBInstanceName pInstanceNames,
// I/O on input has the number slots for instance names in the pInstanceNames buffer. On output,
// has the number of existing LocalDB instances
__inout LPDWORD lpdwNumberOfInstances
_Inout_ LPDWORD lpdwNumberOfInstances
)
{
LOCALDB_PROXY(LocalDBGetInstances)(pInstanceNames, lpdwNumberOfInstances);
@ -1742,11 +1742,11 @@ LocalDBGetInstances(
HRESULT __cdecl
LocalDBGetInstanceInfo(
// I the instance name
__in_z PCWSTR wszInstanceName,
_In_z_ PCWSTR wszInstanceName,
// O instance information
__out PLocalDBInstanceInfo pInfo,
_Out_ PLocalDBInstanceInfo pInfo,
// I Size of LocalDBInstanceInfo structure in bytes
__in DWORD cbInfo
_In_ DWORD cbInfo
)
{
LOCALDB_PROXY(LocalDBGetInstanceInfo)(wszInstanceName, pInfo, cbInfo);
@ -1767,13 +1767,13 @@ LocalDBStopTracing()
HRESULT __cdecl
LocalDBShareInstance(
// I the SID of the LocalDB instance owner
__in_opt PSID pOwnerSID,
_In_opt_ PSID pOwnerSID,
// I the private name of LocalDB instance which should be shared
__in_z PCWSTR wszLocalDBInstancePrivateName,
_In_z_ PCWSTR wszLocalDBInstancePrivateName,
// I the public shared name
__in_z PCWSTR wszSharedName,
_In_z_ PCWSTR wszSharedName,
// I reserved for the future use. Currently should be set to 0.
__in DWORD dwFlags)
_In_ DWORD dwFlags)
{
LOCALDB_PROXY(LocalDBShareInstance)(pOwnerSID, wszLocalDBInstancePrivateName, wszSharedName, dwFlags);
}
@ -1781,10 +1781,10 @@ LocalDBShareInstance(
HRESULT __cdecl
LocalDBGetVersions(
// O buffer for installed LocalDB versions
__out PTLocalDBVersion pVersions,
_Out_ PTLocalDBVersion pVersions,
// I/O on input has the number slots for versions in the pVersions buffer. On output,
// has the number of existing LocalDB versions
__inout LPDWORD lpdwNumberOfVersions
_Inout_ LPDWORD lpdwNumberOfVersions
)
{
LOCALDB_PROXY(LocalDBGetVersions)(pVersions, lpdwNumberOfVersions);
@ -1793,9 +1793,9 @@ LocalDBGetVersions(
HRESULT __cdecl
LocalDBUnshareInstance(
// I the LocalDB instance name
__in_z PCWSTR pInstanceName,
_In_z_ PCWSTR pInstanceName,
// I reserved for the future use. Currently should be set to 0.
__in DWORD dwFlags)
_In_ DWORD dwFlags)
{
LOCALDB_PROXY(LocalDBUnshareInstance)(pInstanceName, dwFlags);
}
@ -1803,11 +1803,11 @@ LocalDBUnshareInstance(
HRESULT __cdecl
LocalDBGetVersionInfo(
// I LocalDB version string
__in_z PCWSTR wszVersion,
_In_z_ PCWSTR wszVersion,
// O version information
__out PLocalDBVersionInfo pVersionInfo,
_Out_ PLocalDBVersionInfo pVersionInfo,
// I Size of LocalDBVersionInfo structure in bytes
__in DWORD cbVersionInfo)
_In_ DWORD cbVersionInfo)
{
LOCALDB_PROXY(LocalDBGetVersionInfo)(wszVersion, pVersionInfo, cbVersionInfo);
}

View file

@ -137,7 +137,7 @@ 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 validate_stmt_options( sqlsrv_context& ctx, zval* stmt_options, _Inout_ HashTable* pdo_stmt_options_ht TSRMLS_DC );
} // namespace
@ -404,6 +404,7 @@ int pdo_sqlsrv_db_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC)
zval* temp_server_z = NULL;
sqlsrv_malloc_auto_ptr<conn_string_parser> dsn_parser;
zval server_z;
ZVAL_UNDEF( &server_z );
try {
@ -443,12 +444,12 @@ int pdo_sqlsrv_db_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC)
zval_add_ref( &server_z );
zend_hash_index_del( pdo_conn_options_ht, PDO_CONN_OPTION_SERVER );
sqlsrv_conn* conn = core_sqlsrv_connect( *g_henv_cp, *g_henv_ncp, core::allocate_conn<pdo_sqlsrv_dbh>, Z_STRVAL(server_z ),
sqlsrv_conn* conn = core_sqlsrv_connect( *g_henv_cp, *g_henv_ncp, core::allocate_conn<pdo_sqlsrv_dbh>, Z_STRVAL( server_z ),
dbh->username, dbh->password, pdo_conn_options_ht, pdo_sqlsrv_handle_dbh_error,
PDO_CONN_OPTS, dbh, "pdo_sqlsrv_db_handle_factory" TSRMLS_CC );
// Free the string in server_z after being used
zend_string_release(Z_STR(server_z));
zend_string_release( Z_STR( server_z ));
SQLSRV_ASSERT( conn != NULL, "Invalid connection returned. Exception should have been thrown." );
@ -460,18 +461,18 @@ int pdo_sqlsrv_db_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC)
}
catch( core::CoreException& ) {
if ( Z_TYPE( server_z ) == IS_STRING ) {
zend_string_release( Z_STR( server_z ));
}
dbh->error_mode = prev_err_mode; // reset the error mode
g_henv_cp->invalidate();
return 0;
}
catch( ... ) {
DIE( "pdo_sqlsrv_db_handle_factory: Unknown exception caught" );
}
return 1;
}
@ -1095,7 +1096,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( pdo_dbh_t *dbh, const char *name, _Out_ size_t* len TSRMLS_DC )
{
PDO_RESET_DBH_ERROR;
PDO_VALIDATE_CONN;
@ -1305,7 +1306,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( sqlsrv_context& ctx, zval* stmt_options, _Inout_ HashTable* pdo_stmt_options_ht TSRMLS_DC )
{
try {

View file

@ -22,7 +22,7 @@
#include "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( sqlsrv_context& ctx, const char* dsn, int len, _Inout_ HashTable* conn_options_ht )
{
this->conn_str = dsn;
this->len = len;
@ -142,7 +142,7 @@ void conn_string_parser::validate_key(const char *key, int key_len TSRMLS_DC )
// encountered an invalid key, throw error.
sqlsrv_malloc_auto_ptr<char> key_name;
key_name = static_cast<char*>( sqlsrv_malloc( new_len + 1 ));
memcpy( key_name, key, new_len );
memcpy_s( key_name, new_len + 1 ,key, new_len );
key_name[ new_len ] = '\0';
THROW_PDO_ERROR( this->ctx, PDO_SQLSRV_ERROR_INVALID_DSN_KEY, key_name );

View file

@ -158,7 +158,7 @@ class conn_string_parser
void add_key_value_pair( const char* value, int len TSRMLS_DC );
public:
conn_string_parser( sqlsrv_context& ctx, const char* dsn, int len, __inout HashTable* conn_options_ht );
conn_string_parser( sqlsrv_context& ctx, const char* dsn, int len, _Inout_ HashTable* conn_options_ht );
void parse_conn_string( TSRMLS_D );
};

View file

@ -202,6 +202,9 @@ 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 )
{
if( meta->field_name ) {
meta->field_name.reset();
}
sqlsrv_free( meta );
}
@ -431,7 +434,7 @@ int pdo_sqlsrv_stmt_describe_col(pdo_stmt_t *stmt, int colno TSRMLS_DC)
// Set the name
column_data->name = zend_string_init( (const char*)core_meta_data->field_name.get(), core_meta_data->field_name_len, 0 );
core_meta_data->field_name.transferred();
core_meta_data->field_name.reset();
// Set the maxlen
column_data->maxlen = ( core_meta_data->field_precision > 0 ) ? core_meta_data->field_precision : core_meta_data->field_size;

View file

@ -599,11 +599,16 @@ void pdo_sqlsrv_throw_exception( sqlsrv_error_const* error TSRMLS_DC )
add_next_index_string( &ex_error_info, reinterpret_cast<char*>( error->sqlstate ));
add_next_index_long( &ex_error_info, error->native_code );
add_next_index_string( &ex_error_info, reinterpret_cast<char*>( error->native_message ));
//zend_update_property makes an entry in the properties_table in ex_obj point to the Z_ARRVAL( ex_error_info )
//and the refcount of the zend_array is incremented by 1
zend_update_property( ex_class, &ex_obj, EXCEPTION_PROPERTY_ERRORINFO, sizeof( EXCEPTION_PROPERTY_ERRORINFO ) - 1,
&ex_error_info TSRMLS_CC );
//DELREF ex_error_info here to decrement the refcount of the zend_array is 1
//the global hashtable EG(exception) then points to the zend_object in ex_obj in zend_throw_exception_object;
//this ensure when EG(exception) cleans itself at php shutdown, the zend_array allocated is properly destroyed
Z_DELREF( ex_error_info );
zend_throw_exception_object( &ex_obj TSRMLS_CC );
ex_msg.transferred();
}
}

View file

@ -1 +1 @@
Microsoft Drivers 4.0.0 for PHP for SQL Server (SQLSRV driver)
Microsoft Drivers 4.0.0 for PHP for SQL Server (PDO driver)

View file

@ -133,9 +133,9 @@ 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,
__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 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_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 );
@ -1218,7 +1218,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( sqlsrv_context& ctx, zval* stmt_options, _Inout_ HashTable* ss_stmt_options_ht TSRMLS_DC )
{
try {
@ -1258,7 +1258,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( sqlsrv_context& ctx, zval* user_options_z, _Out_ char** uid, _Out_ char** pwd, _Inout_ HashTable* ss_conn_options_ht TSRMLS_DC )
{
try {

View file

@ -57,7 +57,7 @@ const char CONNECTION_OPTION_MARS_ON[] = "MARS_Connection={Yes};";
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* driver,__inout std::string& connection_string TSRMLS_DC );
void* driver,_Inout_ std::string& connection_string TSRMLS_DC );
void determine_server_version( 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 );
@ -377,7 +377,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( sqlsrv_conn* conn, _Out_ zval *server_version TSRMLS_DC )
{
try {
@ -404,7 +404,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( sqlsrv_conn* conn, _Out_ zval *server_info TSRMLS_DC )
{
try {
@ -443,7 +443,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( sqlsrv_conn* conn, _Out_ zval *client_info TSRMLS_DC )
{
try {
@ -534,7 +534,7 @@ connection_option const* get_connection_option( sqlsrv_conn* conn, SQLULEN key,
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* driver,_Inout_ std::string& connection_string TSRMLS_DC )
{
bool credentials_mentioned = false;
bool mars_mentioned = false;
@ -689,7 +689,7 @@ void determine_server_version( sqlsrv_conn* conn TSRMLS_DC )
errno = 0;
char version_major_str[ 3 ];
SERVER_VERSION version_major;
memcpy( version_major_str, p, 2 );
memcpy_s( version_major_str, sizeof( version_major_str ), p, 2 );
version_major_str[ 2 ] = '\0';
version_major = static_cast<SERVER_VERSION>( atoi( version_major_str ));

View file

@ -145,14 +145,14 @@ void core_sqlsrv_mshutdown( sqlsrv_context& henv_cp, sqlsrv_context& henv_ncp )
if( henv_ncp != SQL_NULL_HANDLE ) {
henv_ncp.invalidate();
delete &henv_ncp;
}
delete &henv_ncp;
if( henv_cp != SQL_NULL_HANDLE ) {
henv_cp.invalidate();
delete &henv_cp;
}
delete &henv_cp;
return;
}

View file

@ -85,7 +85,7 @@ void cache_row_dtor(zval* data);
// 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,
SQLRETURN number_to_string( Number* number_data, _Out_ void* buffer, SQLLEN buffer_length, _Out_ SQLLEN* out_buffer_length,
sqlsrv_error_auto_ptr& last_error )
{
std::basic_ostringstream<Char> os;
@ -107,14 +107,14 @@ SQLRETURN number_to_string( Number* number_data, __out void* buffer, SQLLEN buff
}
*out_buffer_length = str_num.size() * sizeof(Char) + sizeof(Char); // include NULL terminator
memcpy( buffer, str_num.c_str(), *out_buffer_length );
memcpy_s( buffer, buffer_length, str_num.c_str(), *out_buffer_length );
return SQL_SUCCESS;
}
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( Char* string_data, SQLLEN str_len, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ SQLLEN* out_buffer_length, sqlsrv_error_auto_ptr& last_error )
{
Number* number_data = reinterpret_cast<Number*>( buffer );
std::locale loc; // default locale should match system
@ -214,7 +214,7 @@ SQLRETURN sqlsrv_odbc_result_set::fetch( SQLSMALLINT orientation, SQLLEN offset
}
SQLRETURN sqlsrv_odbc_result_set::get_data( SQLUSMALLINT field_index, SQLSMALLINT target_type,
__out SQLPOINTER buffer, SQLLEN buffer_length, __out SQLLEN* out_buffer_length,
_Out_ SQLPOINTER buffer, SQLLEN buffer_length, _Out_ SQLLEN* out_buffer_length,
bool handle_warning TSRMLS_DC )
{
SQLSRV_ASSERT( odbc != NULL, "Invalid statement handle" );
@ -222,8 +222,8 @@ SQLRETURN sqlsrv_odbc_result_set::get_data( SQLUSMALLINT field_index, SQLSMALLIN
}
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 )
_Out_ SQLPOINTER diag_info_buffer, SQLSMALLINT buffer_length,
_Out_ 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,
@ -596,7 +596,7 @@ SQLRETURN sqlsrv_buffered_result_set::fetch( SQLSMALLINT orientation, SQLLEN off
}
SQLRETURN sqlsrv_buffered_result_set::get_data( SQLUSMALLINT field_index, SQLSMALLINT target_type,
__out SQLPOINTER buffer, SQLLEN buffer_length, __out SQLLEN* out_buffer_length,
_Out_ SQLPOINTER buffer, SQLLEN buffer_length, _Out_ SQLLEN* out_buffer_length,
bool handle_warning TSRMLS_DC )
{
last_error = NULL;
@ -632,8 +632,8 @@ SQLRETURN sqlsrv_buffered_result_set::get_data( SQLUSMALLINT field_index, SQLSMA
}
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 )
_Out_ SQLPOINTER diag_info_buffer, SQLSMALLINT buffer_length,
_Out_ 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,
@ -648,7 +648,7 @@ SQLRETURN sqlsrv_buffered_result_set::get_diag_field( SQLSMALLINT record_number,
SQLSRV_ASSERT( last_error->sqlstate != NULL,
"Must have a SQLSTATE in a valid last_error in sqlsrv_buffered_result_set::get_diag_field" );
memcpy( diag_info_buffer, last_error->sqlstate, min( buffer_length, SQL_SQLSTATE_BUFSIZE ));
memcpy_s( diag_info_buffer, buffer_length, last_error->sqlstate, min( buffer_length, SQL_SQLSTATE_BUFSIZE ));
return SQL_SUCCESS;
}
@ -684,8 +684,8 @@ 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,
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 )
{
// hex characters for the conversion loop below
@ -745,8 +745,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( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ SQLLEN* out_buffer_length )
{
SQLCHAR* row = get_row();
SQLCHAR* field_data = NULL;
@ -763,8 +763,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( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ SQLLEN* out_buffer_length )
{
SQLCHAR* row = get_row();
SQLCHAR* field_data = NULL;
@ -782,8 +782,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( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ 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 "
@ -811,8 +811,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( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ 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" );
@ -823,8 +823,8 @@ SQLRETURN sqlsrv_buffered_result_set::double_to_system_string( SQLSMALLINT field
return number_to_string<char>( double_data, buffer, buffer_length, out_buffer_length, last_error );
}
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( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ 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" );
@ -835,8 +835,8 @@ SQLRETURN sqlsrv_buffered_result_set::double_to_wide_string( SQLSMALLINT field_i
return number_to_string<WCHAR>( double_data, buffer, buffer_length, out_buffer_length, last_error );
}
SQLRETURN sqlsrv_buffered_result_set::long_to_double( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length )
SQLRETURN sqlsrv_buffered_result_set::long_to_double( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( meta[ field_index ].c_type == SQL_C_LONG, "Invalid conversion to long" );
SQLSRV_ASSERT( buffer_length >= sizeof(double), "Buffer length must be able to find a long in sqlsrv_buffered_result_set::double_to_long" );
@ -850,8 +850,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( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ 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" );
@ -862,8 +862,8 @@ SQLRETURN sqlsrv_buffered_result_set::long_to_system_string( SQLSMALLINT field_i
return number_to_string<char>( long_data, buffer, buffer_length, out_buffer_length, last_error );
}
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( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ 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" );
@ -874,8 +874,8 @@ SQLRETURN sqlsrv_buffered_result_set::long_to_wide_string( SQLSMALLINT field_ind
return number_to_string<WCHAR>( long_data, buffer, buffer_length, out_buffer_length, last_error );
}
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( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ 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" );
@ -886,8 +886,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( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ 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" );
@ -898,8 +898,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( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ 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" );
@ -910,8 +910,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( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ 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" );
@ -922,8 +922,8 @@ 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,
__out SQLLEN* out_buffer_length )
SQLRETURN sqlsrv_buffered_result_set::system_to_wide_string( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( last_error == NULL, "Pending error for sqlsrv_buffered_results_set::system_to_wide_string" );
SQLSRV_ASSERT( buffer_length % 2 == 0, "Odd buffer length passed to sqlsrv_buffered_result_set::system_to_wide_string" );
@ -1015,8 +1015,8 @@ 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,
__out SQLLEN* out_buffer_length )
SQLRETURN sqlsrv_buffered_result_set::to_same_string( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( last_error == NULL, "Pending error for sqlsrv_buffered_results_set::to_same_string" );
@ -1074,19 +1074,19 @@ SQLRETURN sqlsrv_buffered_result_set::to_same_string( SQLSMALLINT field_index, _
SQLSRV_ASSERT( to_copy >= 0, "Negative field length calculated in buffered result set" );
if( to_copy > 0 ) {
memcpy( buffer, field_data + read_so_far, to_copy );
memcpy_s( buffer, buffer_length, field_data + read_so_far, to_copy );
read_so_far += to_copy;
}
if( extra ) {
OACR_WARNING_SUPPRESS( 26001, "Buffer length verified above" );
memcpy( reinterpret_cast<SQLCHAR*>( buffer ) + to_copy, L"\0", extra );
memcpy_s( reinterpret_cast<SQLCHAR*>( buffer ) + to_copy, buffer_length, L"\0", extra );
}
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( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( last_error == NULL, "Pending error for sqlsrv_buffered_results_set::wide_to_system_string" );
@ -1159,7 +1159,7 @@ SQLRETURN sqlsrv_buffered_result_set::wide_to_system_string( SQLSMALLINT field_i
if( to_copy > 0 ) {
memcpy( buffer, temp_string.get() + read_so_far, to_copy );
memcpy_s( buffer, buffer_length, temp_string.get() + read_so_far, to_copy );
}
SQLSRV_ASSERT( to_copy >= 0, "Invalid field copy length" );
OACR_WARNING_SUPPRESS( BUFFER_UNDERFLOW, "Buffer length verified above" );
@ -1170,14 +1170,14 @@ 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,
__out SQLLEN* out_buffer_length )
SQLRETURN sqlsrv_buffered_result_set::to_binary_string( SQLSMALLINT field_index, _Out_ void* buffer, 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,
__out SQLLEN* out_buffer_length )
SQLRETURN sqlsrv_buffered_result_set::to_long( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( meta[ field_index ].c_type == SQL_C_LONG, "Invlid conversion to long" );
SQLSRV_ASSERT( buffer_length >= sizeof( LONG ), "Buffer too small for SQL_C_LONG" ); // technically should ignore this
@ -1185,14 +1185,14 @@ SQLRETURN sqlsrv_buffered_result_set::to_long( SQLSMALLINT field_index, __out vo
unsigned char* row = get_row();
LONG* long_data = reinterpret_cast<LONG*>( &row[ meta[ field_index ].offset ] );
memcpy( buffer, long_data, sizeof( LONG ));
memcpy_s( buffer, buffer_length, long_data, sizeof( LONG ));
*out_buffer_length = sizeof( LONG );
return SQL_SUCCESS;
}
SQLRETURN sqlsrv_buffered_result_set::to_double( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length )
SQLRETURN sqlsrv_buffered_result_set::to_double( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( meta[ field_index ].c_type == SQL_C_DOUBLE, "Invlid conversion to double" );
SQLSRV_ASSERT( buffer_length >= sizeof( double ), "Buffer too small for SQL_C_DOUBLE" ); // technically should ignore this
@ -1200,7 +1200,7 @@ SQLRETURN sqlsrv_buffered_result_set::to_double( SQLSMALLINT field_index, __out
unsigned char* row = get_row();
double* double_data = reinterpret_cast<double*>( &row[ meta[ field_index ].offset ] );
memcpy( buffer, double_data, sizeof( double ));
memcpy_s( buffer, buffer_length, double_data, sizeof( double ));
*out_buffer_length = sizeof( double );
return SQL_SUCCESS;
@ -1211,7 +1211,7 @@ namespace {
// called for each row in the cache when the cache is destroyed in the destructor
void cache_row_dtor( zval* data )
{
row_dtor_closure* cl = reinterpret_cast<row_dtor_closure*>( Z_PTR_P(data) );
row_dtor_closure* cl = reinterpret_cast<row_dtor_closure*>( Z_PTR_P( data ) );
BYTE* row = cl->row_data;
// don't release this here, since this is called from the destructor of the result_set
sqlsrv_buffered_result_set* result_set = cl->results;
@ -1226,6 +1226,7 @@ void cache_row_dtor( zval* data )
}
sqlsrv_free( row );
sqlsrv_free( cl );
}
SQLPOINTER read_lob_field( sqlsrv_stmt* stmt, SQLUSMALLINT field_index, sqlsrv_buffered_result_set::meta_data& meta,

View file

@ -889,6 +889,8 @@ class sqlsrv_context {
{
if( handle_ != SQL_NULL_HANDLE ) {
::SQLFreeHandle( handle_type_, handle_ );
last_error_.reset();
}
handle_ = SQL_NULL_HANDLE;
}
@ -1136,9 +1138,9 @@ void core_sqlsrv_prepare( sqlsrv_stmt* stmt, const char* sql, SQLLEN sql_len TSR
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 );
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 );
@ -1197,7 +1199,7 @@ struct sqlsrv_stream {
};
// close any active stream
void close_active_stream( __inout sqlsrv_stmt* stmt TSRMLS_DC );
void close_active_stream( _Inout_ sqlsrv_stmt* stmt TSRMLS_DC );
extern php_stream_wrapper g_sqlsrv_stream_wrapper;
@ -1323,8 +1325,8 @@ void core_sqlsrv_execute( sqlsrv_stmt* stmt TSRMLS_DC, const char* sql = NULL, i
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,
__out SQLSRV_PHPTYPE *sqlsrv_php_type_out TSRMLS_DC);
_Out_ void*& field_value, _Out_ SQLLEN* field_length, 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 );
@ -1359,11 +1361,11 @@ struct sqlsrv_result_set {
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,
_Out_ void* buffer, SQLLEN buffer_length, _Out_ 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;
_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 SQLLEN row_count( TSRMLS_D ) = 0;
};
@ -1376,11 +1378,11 @@ struct sqlsrv_odbc_result_set : public sqlsrv_result_set {
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,
_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 );
_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 SQLLEN row_count( TSRMLS_D );
@ -1414,11 +1416,11 @@ struct sqlsrv_buffered_result_set : public sqlsrv_result_set {
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,
_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 );
_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 SQLLEN row_count( TSRMLS_D );
@ -1449,55 +1451,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)( SQLSMALLINT field_index, _Out_ void* buffer, SQLLEN buffer_length,
_Out_ 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,
__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,
__out SQLLEN* out_buffer_length );
SQLRETURN to_same_string( SQLSMALLINT field_index, __out void* buffer, 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 binary_to_wide_string( SQLSMALLINT field_index, _Out_ void* buffer, 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,
_Out_ SQLLEN* out_buffer_length );
SQLRETURN to_same_string( SQLSMALLINT field_index, _Out_ void* buffer, 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 );
// 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,
__out SQLLEN* out_buffer_length );
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,
_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( 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 );
// 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( 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 );
// utility functions for conversions
unsigned char* get_row( void );
@ -1520,7 +1522,7 @@ bool convert_zval_string_from_utf16(SQLSRV_ENCODING encoding, zval* value_z, SQL
bool validate_string(char* string, SQLLEN& len);
bool convert_string_from_utf16( SQLSRV_ENCODING encoding, const wchar_t* inString, SQLINTEGER cchInLen, char** outString, SQLLEN& cchOutLen );
wchar_t* utf16_string_from_mbcs_string( SQLSRV_ENCODING php_encoding, const char* mbcs_string,
unsigned int mbcs_len, __out unsigned int* utf16_len );
unsigned int mbcs_len, _Out_ unsigned int* utf16_len );
//*********************************************************************************************************************************
// Error handling routines and Predefined Errors
@ -1598,7 +1600,7 @@ 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,
bool core_sqlsrv_get_odbc_error( sqlsrv_context& ctx, int record_number, _Out_ sqlsrv_error_auto_ptr& error,
logging_severity severity TSRMLS_DC );
// format and return a driver specfic error
@ -1754,8 +1756,7 @@ namespace core {
throw CoreException();
}
std::size_t driver_version = stmt->conn->driver_version;
if(( len == sizeof( CONNECTION_BUSY_ODBC_ERROR[driver_version] ) - 1 ) &&
!strcmp( reinterpret_cast<const char*>( err_msg ), CONNECTION_BUSY_ODBC_ERROR[driver_version] )) {
if( !strcmp( reinterpret_cast<const char*>( err_msg ), CONNECTION_BUSY_ODBC_ERROR[driver_version] )) {
THROW_CORE_ERROR( stmt, SQLSRV_ERROR_MARS_OFF );
}
@ -1771,8 +1772,8 @@ namespace core {
// 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 )
_Out_ SQLPOINTER diag_info_buffer, SQLSMALLINT buffer_length,
_Out_ 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 );
@ -1785,7 +1786,7 @@ namespace core {
}
inline void SQLAllocHandle( SQLSMALLINT HandleType, sqlsrv_context& InputHandle,
__out_ecount(1) SQLHANDLE* OutputHandlePtr TSRMLS_DC )
_Out_writes_(1) SQLHANDLE* OutputHandlePtr TSRMLS_DC )
{
SQLRETURN r;
r = ::SQLAllocHandle( HandleType, InputHandle.handle(), OutputHandlePtr );
@ -1801,9 +1802,9 @@ namespace core {
SQLSMALLINT ParameterType,
SQLULEN ColumnSize,
SQLSMALLINT DecimalDigits,
__inout SQLPOINTER ParameterValuePtr,
_Inout_ SQLPOINTER ParameterValuePtr,
SQLLEN BufferLength,
__inout SQLLEN * StrLen_Or_IndPtr
_Inout_ SQLLEN * StrLen_Or_IndPtr
TSRMLS_DC )
{
SQLRETURN r;
@ -1817,8 +1818,8 @@ 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 )
_Out_ SQLPOINTER field_type_char, SQLSMALLINT buffer_length,
_Out_ SQLSMALLINT* out_buffer_length, _Out_ 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 );
@ -1829,9 +1830,9 @@ namespace core {
}
inline void SQLDescribeCol( sqlsrv_stmt* stmt, SQLSMALLINT colno, __out_z 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( 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 )
{
SQLRETURN r;
r = ::SQLDescribeCol( stmt->handle(), colno, col_name, col_name_length, col_name_length_out,
@ -1914,7 +1915,7 @@ namespace core {
}
inline SQLRETURN SQLGetData( sqlsrv_stmt* stmt, SQLUSMALLINT field_index, SQLSMALLINT target_type,
__out void* buffer, SQLLEN buffer_length, __out SQLLEN* out_buffer_length,
_Out_ void* buffer, SQLLEN buffer_length, _Out_ SQLLEN* out_buffer_length,
bool handle_warning TSRMLS_DC )
{
SQLRETURN r = ::SQLGetData( stmt->handle(), field_index, target_type, buffer, buffer_length, out_buffer_length );
@ -1936,8 +1937,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( sqlsrv_conn* conn, SQLUSMALLINT info_type, _Out_ SQLPOINTER info_value, SQLSMALLINT buffer_len,
_Out_ SQLSMALLINT* str_len TSRMLS_DC )
{
SQLRETURN r;
r = ::SQLGetInfo( conn->handle(), info_type, info_value, buffer_len, str_len );
@ -1986,7 +1987,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( sqlsrv_stmt* stmt, _Out_ SQLPOINTER* value_ptr_ptr TSRMLS_DC )
{
SQLRETURN r;
r = ::SQLParamData( stmt->handle(), value_ptr_ptr );
@ -2141,7 +2142,7 @@ namespace core {
}
}
inline void sqlsrv_array_init( sqlsrv_context& ctx, __out zval* new_array TSRMLS_DC)
inline void sqlsrv_array_init( sqlsrv_context& ctx, _Out_ zval* new_array TSRMLS_DC)
{
int zr = ::array_init(new_array);
CHECK_ZEND_ERROR( zr, ctx, SQLSRV_ERROR_ZEND_HASH ) {
@ -2158,7 +2159,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(sqlsrv_context& ctx, HashTable* ht, _Out_ 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 ) {
@ -2166,7 +2167,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(sqlsrv_context& ctx, HashTable* ht, _Out_ 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) {

View file

@ -35,7 +35,7 @@ struct field_cache {
// if the value is NULL, then just record a NULL pointer
if( field_value != NULL ) {
value = sqlsrv_malloc( field_len );
memcpy( value, field_value, field_len );
memcpy_s( value, field_len, field_value, field_len );
len = field_len;
}
else {
@ -76,23 +76,23 @@ 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 );
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 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);
// 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,
__out SQLULEN& column_size, __out SQLSMALLINT& decimal_digits TSRMLS_DC );
_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,
__out SQLSMALLINT& sql_type TSRMLS_DC );
_Out_ SQLSMALLINT& sql_type TSRMLS_DC );
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 );
_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 );
// assure there is enough space for the output parameter string
@ -312,7 +312,7 @@ 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,
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 )
{
@ -342,7 +342,7 @@ void core_sqlsrv_bind_param(sqlsrv_stmt* stmt, SQLUSMALLINT param_num, SQLSMALLI
if ( Z_ISREF_P( param_z ) ) {
ZVAL_DEREF( param_z );
}
bool zval_was_null = ( Z_TYPE_P( param_z ) == IS_NULL);
bool zval_was_null = ( Z_TYPE_P( param_z ) == IS_NULL );
bool zval_was_bool = ( Z_TYPE_P( param_z ) == IS_TRUE || Z_TYPE_P( param_z ) == IS_FALSE );
// if the user asks for for a specific type for input and output, make sure the data type we send matches the data we
// type we expect back, since we can only send and receive the same type. Anything can be converted to a string, so
@ -411,7 +411,7 @@ void core_sqlsrv_bind_param(sqlsrv_stmt* stmt, SQLUSMALLINT param_num, SQLSMALLI
// if the sql type is unknown, then set the default based on the PHP type passed in
if( sql_type == SQL_UNKNOWN_TYPE ) {
default_sql_type(stmt, param_num, param_z, encoding, sql_type TSRMLS_CC);
default_sql_type( stmt, param_num, param_z, encoding, sql_type TSRMLS_CC );
}
// if the size is unknown, then set the default based on the PHP type passed in
@ -456,7 +456,7 @@ void core_sqlsrv_bind_param(sqlsrv_stmt* stmt, SQLUSMALLINT param_num, SQLSMALLI
ind_ptr = buffer_len;
if( direction != SQL_PARAM_INPUT ) {
// save the parameter so that 1) the buffer doesn't go away, and 2) we can set it to NULL if returned
sqlsrv_output_param output_param(param_ref, static_cast<int>( param_num ), false );
sqlsrv_output_param output_param( param_ref, static_cast<int>( param_num ), false );
save_output_param_for_later( stmt, output_param TSRMLS_CC );
}
}
@ -493,11 +493,11 @@ void core_sqlsrv_bind_param(sqlsrv_stmt* stmt, SQLUSMALLINT param_num, SQLSMALLI
// or if the PHP type is a binary encoded string with a N(VAR)CHAR/NTEXTSQL type,
// convert it to wchar first
if( direction == SQL_PARAM_INPUT_OUTPUT &&
(c_type == SQL_C_WCHAR ||
(c_type == SQL_C_BINARY &&
(sql_type == SQL_WCHAR ||
sql_type == SQL_WVARCHAR ||
sql_type == SQL_WLONGVARCHAR )))) {
( c_type == SQL_C_WCHAR ||
( c_type == SQL_C_BINARY &&
( sql_type == SQL_WCHAR ||
sql_type == SQL_WVARCHAR ||
sql_type == SQL_WLONGVARCHAR )))) {
bool converted = convert_input_param_to_utf16( param_z, param_z );
CHECK_CUSTOM_ERROR( !converted, stmt, SQLSRV_ERROR_INPUT_PARAM_ENCODING_TRANSLATE,
@ -546,7 +546,7 @@ void core_sqlsrv_bind_param(sqlsrv_stmt* stmt, SQLUSMALLINT param_num, SQLSMALLI
SQLSRV_ASSERT( direction == SQL_PARAM_INPUT, "Invalid output param type. The driver layer should catch this." );
sqlsrv_stream stream_encoding( param_z, encoding );
HashTable* streams_ht = Z_ARRVAL( stmt->param_streams );
core::sqlsrv_zend_hash_index_update_mem(*stmt, streams_ht, param_num, &stream_encoding, sizeof(stream_encoding) TSRMLS_CC);
core::sqlsrv_zend_hash_index_update_mem( *stmt, streams_ht, param_num, &stream_encoding, sizeof(stream_encoding) TSRMLS_CC );
buffer = reinterpret_cast<SQLPOINTER>( param_num );
Z_TRY_ADDREF_P( param_z ); // so that it doesn't go away while we're using it
buffer_len = 0;
@ -567,7 +567,7 @@ void core_sqlsrv_bind_param(sqlsrv_stmt* stmt, SQLUSMALLINT param_num, SQLSMALLI
bool valid_class_name_found = false;
zend_class_entry *class_entry = Z_OBJCE_P(param_z TSRMLS_CC);
zend_class_entry *class_entry = Z_OBJCE_P( param_z TSRMLS_CC );
while( class_entry != NULL ) {
@ -593,7 +593,7 @@ void core_sqlsrv_bind_param(sqlsrv_stmt* stmt, SQLUSMALLINT param_num, SQLSMALLI
// sql type, it lacks the timezone.
if( sql_type == SQL_SS_TIMESTAMPOFFSET ) {
core::sqlsrv_zval_stringl( &format_z, const_cast<char*>( DateTime::DATETIMEOFFSET_FORMAT ),
DateTime::DATETIMEOFFSET_FORMAT_LEN);
DateTime::DATETIMEOFFSET_FORMAT_LEN );
}
else if( sql_type == SQL_TYPE_DATE ) {
core::sqlsrv_zval_stringl( &format_z, const_cast<char*>( DateTime::DATE_FORMAT ), DateTime::DATE_FORMAT_LEN );
@ -607,11 +607,13 @@ void core_sqlsrv_bind_param(sqlsrv_stmt* stmt, SQLUSMALLINT param_num, SQLSMALLI
// This is equivalent to the PHP code: $param_z->format( $format_z ); where param_z is the
// DateTime object and $format_z is the format string.
int zr = call_user_function( EG( function_table ), param_z, &function_z, &buffer_z, 1, params TSRMLS_CC );
zend_string_release( Z_STR( format_z ));
zend_string_release( Z_STR( function_z ));
CHECK_CUSTOM_ERROR( zr == FAILURE, stmt, SQLSRV_ERROR_INVALID_PARAMETER_PHPTYPE, param_num + 1 ) {
throw core::CoreException();
}
buffer = Z_STRVAL( buffer_z );
zr = add_next_index_zval( &(stmt->param_datetime_buffers), &buffer_z );
zr = add_next_index_zval( &( stmt->param_datetime_buffers ), &buffer_z );
CHECK_CUSTOM_ERROR( zr == FAILURE, stmt, SQLSRV_ERROR_INVALID_PARAMETER_PHPTYPE, param_num + 1 ) {
throw core::CoreException();
}
@ -694,7 +696,7 @@ void core_sqlsrv_execute( sqlsrv_stmt* stmt TSRMLS_DC, const char* sql, int sql_
stmt->executed = true;
// if all the data has been sent and no data was returned then finalize the output parameters
if( stmt->send_streams_at_exec && (r == SQL_NO_DATA || !core_sqlsrv_has_any_result( stmt TSRMLS_CC ))) {
if( stmt->send_streams_at_exec && ( r == SQL_NO_DATA || !core_sqlsrv_has_any_result( stmt TSRMLS_CC ))) {
finalize_output_parameters( stmt TSRMLS_CC );
}
@ -706,8 +708,12 @@ void core_sqlsrv_execute( sqlsrv_stmt* stmt TSRMLS_DC, const char* sql, int sql_
catch( core::CoreException& e ) {
// if the statement executed but failed in a subsequent operation before returning,
// we need to cancel the statement
if( stmt->executed ) {
// we need to cancel the statement and deref the output and stream parameters
if ( stmt->send_streams_at_exec ) {
zend_hash_clean( Z_ARRVAL( stmt->output_params ));
zend_hash_clean( Z_ARRVAL( stmt->param_streams ));
}
if( stmt->executed ) {
SQLCancel( stmt->handle() );
// stmt->executed = false; should this be reset if something fails?
}
@ -864,8 +870,8 @@ field_meta_data* core_sqlsrv_field_metadata( sqlsrv_stmt* stmt, SQLSMALLINT coln
// 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,
__out SQLSRV_PHPTYPE *sqlsrv_php_type_out TSRMLS_DC)
_Out_ void*& field_value, _Out_ SQLLEN* field_len, bool cache_field,
_Out_ SQLSRV_PHPTYPE *sqlsrv_php_type_out TSRMLS_DC)
{
try {
@ -884,7 +890,7 @@ void core_sqlsrv_get_field( sqlsrv_stmt* stmt, SQLUSMALLINT field_index, sqlsrv_
else {
field_value = sqlsrv_malloc( cached->len, sizeof( char ), 1 );
memcpy( field_value, cached->value, cached->len );
memcpy_s( field_value, ( cached->len * sizeof( char )), cached->value, cached->len );
if( cached->type.typeinfo.type == SQLSRV_PHPTYPE_STRING) {
// prevent the 'string not null terminated' warning
reinterpret_cast<char*>( field_value )[ cached->len ] = '\0';
@ -1329,7 +1335,7 @@ void stmt_option_buffered_query_limit:: operator()( sqlsrv_stmt* stmt, stmt_opti
// internal function to release the active stream. Called by each main API function
// that will alter the statement and cancel any retrieval of data from a stream.
void close_active_stream( __inout sqlsrv_stmt* stmt TSRMLS_DC )
void close_active_stream( _Inout_ sqlsrv_stmt* stmt TSRMLS_DC )
{
// if there is no active stream, return
if( Z_TYPE( stmt->active_stream ) == IS_UNDEF ) {
@ -1372,7 +1378,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( sqlsrv_stmt* stmt, SQLUSMALLINT field_index, SQLLEN sql_type, _Out_ SQLLEN& size TSRMLS_DC )
{
try {
@ -1468,8 +1474,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, SQLUSMALLINT field_index, sqlsrv_phptype
sqlsrv_php_type, _Out_ void*& field_value, _Out_ SQLLEN* field_len TSRMLS_DC )
{
try {
@ -1554,13 +1560,10 @@ void core_get_field_common( __inout sqlsrv_stmt* stmt, SQLUSMALLINT field_index,
zval params[1];
zval field_value_temp_z;
zval function_z;
zval_auto_ptr return_value_z;
ZVAL_UNDEF( &field_value_temp_z );
ZVAL_UNDEF( &function_z );
ZVAL_UNDEF( params );
return_value_z = (zval *)sqlsrv_malloc( sizeof( zval ));
ZVAL_UNDEF( return_value_z );
SQLRETURN r = stmt->current_results->get_data( field_index + 1, SQL_C_CHAR, field_value_temp,
MAX_DATETIME_STRING_LEN, field_len, true TSRMLS_CC );
@ -1569,6 +1572,10 @@ void core_get_field_common( __inout sqlsrv_stmt* stmt, SQLUSMALLINT field_index,
throw core::CoreException();
}
zval_auto_ptr return_value_z;
return_value_z = ( zval * )sqlsrv_malloc( sizeof( zval ));
ZVAL_UNDEF( return_value_z );
if( *field_len == SQL_NULL_DATA ) {
ZVAL_NULL( return_value_z );
field_value = reinterpret_cast<void*>( return_value_z.get());
@ -1599,9 +1606,6 @@ void core_get_field_common( __inout sqlsrv_stmt* stmt, SQLUSMALLINT field_index,
case SQLSRV_PHPTYPE_STREAM:
{
zval_auto_ptr return_value_z;
return_value_z = (zval *)sqlsrv_malloc(sizeof(zval));
ZVAL_UNDEF(return_value_z);
php_stream* stream = NULL;
sqlsrv_stream* ss = NULL;
SQLLEN sql_type;
@ -1627,6 +1631,10 @@ void core_get_field_common( __inout sqlsrv_stmt* stmt, SQLUSMALLINT field_index,
ss->sql_type = static_cast<SQLUSMALLINT>( sql_type );
ss->encoding = static_cast<SQLSRV_ENCODING>( sqlsrv_php_type.typeinfo.encoding );
zval_auto_ptr return_value_z;
return_value_z = ( zval * )sqlsrv_malloc( sizeof( zval ));
ZVAL_UNDEF( return_value_z );
// turn our stream into a zval to be returned
php_stream_to_zval( stream, return_value_z );
@ -1659,7 +1667,7 @@ void core_get_field_common( __inout sqlsrv_stmt* stmt, SQLUSMALLINT field_index,
// check_for_next_stream_parameter
// see if there is another stream to be sent. Returns true and sets the stream as current in the statement structure, otherwise
// returns false
bool check_for_next_stream_parameter( __inout sqlsrv_stmt* stmt TSRMLS_DC )
bool check_for_next_stream_parameter( _Inout_ sqlsrv_stmt* stmt TSRMLS_DC )
{
int stream_index = 0;
SQLRETURN r = SQL_SUCCESS;
@ -1810,7 +1818,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,
__out SQLSMALLINT& sql_type TSRMLS_DC )
_Out_ SQLSMALLINT& sql_type TSRMLS_DC )
{
sql_type = SQL_UNKNOWN_TYPE;
int php_type = Z_TYPE_P(param_z);
@ -1880,7 +1888,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,
__out SQLULEN& column_size, __out SQLSMALLINT& decimal_digits TSRMLS_DC )
_Out_ SQLULEN& column_size, _Out_ SQLSMALLINT& decimal_digits TSRMLS_DC )
{
int php_type = Z_TYPE_P( param_z );
column_size = 0;
@ -1933,11 +1941,12 @@ void default_sql_size_and_scale( sqlsrv_stmt* stmt, unsigned int paramno, zval*
void field_cache_dtor( zval* data_z )
{
field_cache* cache = reinterpret_cast<field_cache*>(Z_PTR_P(data_z));
field_cache* cache = static_cast<field_cache*>( Z_PTR_P( data_z ));
if( cache->value )
{
sqlsrv_free( cache->value );
}
sqlsrv_free( cache );
}
@ -1968,6 +1977,7 @@ void finalize_output_parameters( sqlsrv_stmt* stmt TSRMLS_DC )
char* str = Z_STRVAL_P( value_z );
SQLLEN str_len = stmt->param_ind_ptrs[ output_param->param_num ];
if( str_len == SQL_NULL_DATA ) {
zend_string_release( Z_STR_P( value_z ));
ZVAL_NULL( value_z );
continue;
}
@ -2044,7 +2054,7 @@ 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 )
_Out_ void*& field_value, _Out_ SQLLEN* field_len TSRMLS_DC )
{
SQLRETURN r;
SQLSMALLINT c_type;
@ -2433,6 +2443,7 @@ void sqlsrv_output_param_dtor( 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
sqlsrv_free( output_param );
}
// called by Zend for each stream in the sqlsrv_stmt::param_streams hash table when it is cleaned/destroyed
@ -2440,6 +2451,7 @@ void sqlsrv_stream_dtor( 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
sqlsrv_free( stream_encoding );
}
}

View file

@ -45,7 +45,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_bcount(count) char* buf, size_t count TSRMLS_DC )
size_t sqlsrv_stream_read( php_stream* stream, _Out_writes_bytes_(count) char* buf, size_t count TSRMLS_DC )
{
SQLLEN read = 0;
SQLSMALLINT c_type = SQL_C_CHAR;
@ -203,8 +203,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( php_stream_wrapper* wrapper, _In_ const char*, _In_ const char* mode,
int options, _In_ zend_string **, php_stream_context* STREAMS_DC TSRMLS_DC )
{
#if ZEND_DEBUG

View file

@ -33,9 +33,9 @@ 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_bcount(mbcs_len) char const* mbcs_in_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,
__out_ecount(utf16_len) __transfer( mbcs_in_string ) wchar_t* utf16_out_string,
_Out_writes_(utf16_len) __transfer( mbcs_in_string ) wchar_t* utf16_out_string,
unsigned int utf16_len );
}
@ -370,8 +370,8 @@ 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_bcount(mbcs_len) char const* mbcs_in_string,
unsigned int mbcs_len, __out_ecount(utf16_len) __transfer( mbcs_in_string ) wchar_t* utf16_out_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, _Out_writes_(utf16_len) __transfer( mbcs_in_string ) wchar_t* utf16_out_string,
unsigned int utf16_len )
{
unsigned int win_encoding = CP_ACP;

View file

@ -10,30 +10,28 @@
#define __msodbcsql_h__
#if !defined(SQLODBC_VER)
#define SQLODBC_VER 1300
#define SQLODBC_VER 1100
#endif
#if SQLODBC_VER >= 1300
#if SQLODBC_VER >= 1100
#define SQLODBC_PRODUCT_NAME_FULL_VER_ANSI "Microsoft ODBC Driver 13 for SQL Server"
#define SQLODBC_PRODUCT_NAME_FULL_VER_ANSI "Microsoft ODBC Driver 11 for SQL Server"
#define SQLODBC_PRODUCT_NAME_FULL_ANSI "Microsoft ODBC Driver for SQL Server"
#define SQLODBC_PRODUCT_NAME_SHORT_VER_ANSI "ODBC Driver 13 for SQL Server"
#define SQLODBC_PRODUCT_NAME_SHORT_VER_ANSI "ODBC Driver 11 for SQL Server"
#define SQLODBC_PRODUCT_NAME_SHORT_ANSI "ODBC Driver for SQL Server"
#define SQLODBC_FILE_NAME_ANSI "msodbcsql"
#define SQLODBC_FILE_NAME_VER_ANSI "msodbcsql13"
#define SQLODBC_FILE_NAME_FULL_ANSI "msodbcsql13.dll"
#define SQLODBC_FILE_NAME_VER_ANSI "msodbcsql11"
#define SQLODBC_FILE_NAME_FULL_ANSI "msodbcsql11.dll"
#define SQLODBC_PRODUCT_NAME_FULL_VER_UNICODE L"Microsoft ODBC Driver 13 for SQL Server"
#define SQLODBC_PRODUCT_NAME_FULL_VER_UNICODE L"Microsoft ODBC Driver 11 for SQL Server"
#define SQLODBC_PRODUCT_NAME_FULL_UNICODE L"Microsoft ODBC Driver for SQL Server"
#define SQLODBC_PRODUCT_NAME_SHORT_VER_UNICODE L"ODBC Driver 13 for SQL Server"
#define SQLODBC_PRODUCT_NAME_SHORT_VER_UNICODE L"ODBC Driver 11 for SQL Server"
#define SQLODBC_PRODUCT_NAME_SHORT_UNICODE L"ODBC Driver for SQL Server"
#define SQLODBC_FILE_NAME_UNICODE L"msodbcsql"
#define SQLODBC_FILE_NAME_VER_UNICODE L"msodbcsql13"
#define SQLODBC_FILE_NAME_FULL_UNICODE L"msodbcsql13.dll"
#define SQLODBC_FILE_NAME_VER_UNICODE L"msodbcsql11"
#define SQLODBC_FILE_NAME_FULL_UNICODE L"msodbcsql11.dll"
// define the character type agnostic constants
#if defined(_UNICODE) || defined(UNICODE)
@ -167,12 +165,12 @@
extern "C" {
#endif
// max SQL Server identifier length
// max SQL Server identifier length
#define SQL_MAX_SQLSERVERNAME 128
// SQLSetConnectAttr driver specific defines.
// Microsoft has 1200 thru 1249 reserved for Microsoft SQL Server Native Client driver usage.
// Connection attributes
// SQLSetConnectAttr driver specific defines.
// Microsoft has 1200 thru 1249 reserved for Microsoft SQL Server Native Client driver usage.
// Connection attributes
#define SQL_COPT_SS_BASE 1200
#define SQL_COPT_SS_REMOTE_PWD (SQL_COPT_SS_BASE+1) // dbrpwset SQLSetConnectOption only
#define SQL_COPT_SS_USE_PROC_FOR_PREP (SQL_COPT_SS_BASE+2) // Use create proc for SQLPrepare
@ -205,18 +203,14 @@ extern "C" {
#define SQL_COPT_SS_INTEGRATED_AUTHENTICATION_METHOD (SQL_COPT_SS_BASE+31) // The integrated authentication method used for the connection
#define SQL_COPT_SS_MUTUALLY_AUTHENTICATED (SQL_COPT_SS_BASE+32) // Used to decide if the connection is mutually authenticated
#define SQL_COPT_SS_CLIENT_CONNECTION_ID (SQL_COPT_SS_BASE+33) // Post connection attribute used to get the ConnectionID
#define SQL_COPT_SS_CLIENT_CERTIFICATE (SQL_COPT_SS_BASE+36) // Client certificate
#define SQL_COPT_SS_CLIENT_CERTIFICATE_FALLBACK (SQL_COPT_SS_BASE+37) // Client certificate fallback
// Define old names
// Define old names
#define SQL_REMOTE_PWD SQL_COPT_SS_REMOTE_PWD
#define SQL_USE_PROCEDURE_FOR_PREPARE SQL_COPT_SS_USE_PROC_FOR_PREP
#define SQL_INTEGRATED_SECURITY SQL_COPT_SS_INTEGRATED_SECURITY
#define SQL_PRESERVE_CURSORS SQL_COPT_SS_PRESERVE_CURSORS
// SQLSetStmtAttr SQL Server Native Client driver specific defines.
// Statement attributes
// SQLSetStmtAttr SQL Server Native Client driver specific defines.
// Statement attributes
#define SQL_SOPT_SS_BASE 1225
#define SQL_SOPT_SS_TEXTPTR_LOGGING (SQL_SOPT_SS_BASE+0) // Text pointer logging
#define SQL_SOPT_SS_CURRENT_COMMAND (SQL_SOPT_SS_BASE+1) // dbcurcmd SQLGetStmtOption only
@ -231,9 +225,8 @@ extern "C" {
#define SQL_SOPT_SS_QUERYNOTIFICATION_OPTIONS (SQL_SOPT_SS_BASE+10)// SQL service broker name
#define SQL_SOPT_SS_PARAM_FOCUS (SQL_SOPT_SS_BASE+11)// Direct subsequent calls to parameter related methods to set properties on constituent columns/parameters of container types
#define SQL_SOPT_SS_NAME_SCOPE (SQL_SOPT_SS_BASE+12)// Sets name scope for subsequent catalog function calls
#define SQL_SOPT_SS_COLUMN_ENCRYPTION (SQL_SOPT_SS_BASE+13)// Sets the column encryption mode
#define SQL_SOPT_SS_MAX_USED SQL_SOPT_SS_COLUMN_ENCRYPTION
// Define old names
#define SQL_SOPT_SS_MAX_USED SQL_SOPT_SS_NAME_SCOPE
// Define old names
#define SQL_TEXTPTR_LOGGING SQL_SOPT_SS_TEXTPTR_LOGGING
#define SQL_COPT_SS_BASE_EX 1240
#define SQL_COPT_SS_BROWSE_CONNECT (SQL_COPT_SS_BASE_EX+1) // Browse connect mode of operation
@ -244,17 +237,11 @@ extern "C" {
#define SQL_COPT_SS_RESET_CONNECTION (SQL_COPT_SS_BASE_EX+6) // When this option is set, we will perform connection reset on next packet
#define SQL_COPT_SS_APPLICATION_INTENT (SQL_COPT_SS_BASE_EX+7) // Application Intent
#define SQL_COPT_SS_MULTISUBNET_FAILOVER (SQL_COPT_SS_BASE_EX+8) // Multi-subnet Failover
#define SQL_COPT_SS_TNIR (SQL_COPT_SS_BASE_EX+9) // Transparent Network IP Resolution
#define SQL_COPT_SS_COLUMN_ENCRYPTION (SQL_COPT_SS_BASE_EX+10) // Always Encrypted Enabled or Disabled
#define SQL_COPT_SS_AEKEYSTOREPROVIDER (SQL_COPT_SS_BASE_EX+11) // Used to load a keystore provider DLL
#define SQL_COPT_SS_AEKEYSTOREDATA (SQL_COPT_SS_BASE_EX+12) // Used to communicate with keystore providers
#define SQL_COPT_SS_AETRUSTEDCMKPATHS (SQL_COPT_SS_BASE_EX+13) // List of trusted CMK paths
#define SQL_COPT_SS_AECEKCACHETTL (SQL_COPT_SS_BASE_EX+14)// Symmetric Key Cache TTL
#define SQL_COPT_SS_EX_MAX_USED SQL_COPT_SS_AECEKCACHETTL
#define SQL_COPT_SS_EX_MAX_USED SQL_COPT_SS_MULTISUBNET_FAILOVER
// SQLColAttributes driver specific defines.
// SQLSetDescField/SQLGetDescField driver specific defines.
// Microsoft has 1200 thru 1249 reserved for Microsoft SQL Server Native Client driver usage.
// SQLColAttributes driver specific defines.
// SQLSetDescField/SQLGetDescField driver specific defines.
// Microsoft has 1200 thru 1249 reserved for Microsoft SQL Server Native Client driver usage.
#define SQL_CA_SS_BASE 1200
#define SQL_CA_SS_COLUMN_SSTYPE (SQL_CA_SS_BASE+0) // dbcoltype/dbalttype
#define SQL_CA_SS_COLUMN_UTYPE (SQL_CA_SS_BASE+1) // dbcolutype/dbaltutype
@ -269,13 +256,13 @@ extern "C" {
#define SQL_CA_SS_COLUMN_SIZE (SQL_CA_SS_BASE+10) // dbcollen
#define SQL_CA_SS_COLUMN_HIDDEN (SQL_CA_SS_BASE+11) // Column is hidden (FOR BROWSE)
#define SQL_CA_SS_COLUMN_KEY (SQL_CA_SS_BASE+12) // Column is key column (FOR BROWSE)
//#define SQL_DESC_BASE_COLUMN_NAME_OLD (SQL_CA_SS_BASE+13) // This is defined at another location.
//#define SQL_DESC_BASE_COLUMN_NAME_OLD (SQL_CA_SS_BASE+13) // This is defined at another location.
#define SQL_CA_SS_COLUMN_COLLATION (SQL_CA_SS_BASE+14) // Column collation (only for chars)
#define SQL_CA_SS_VARIANT_TYPE (SQL_CA_SS_BASE+15)
#define SQL_CA_SS_VARIANT_SQL_TYPE (SQL_CA_SS_BASE+16)
#define SQL_CA_SS_VARIANT_SERVER_TYPE (SQL_CA_SS_BASE+17)
// XML, CLR UDT, and table valued parameter related metadata
// XML, CLR UDT, and table valued parameter related metadata
#define SQL_CA_SS_UDT_CATALOG_NAME (SQL_CA_SS_BASE+18) // UDT catalog name
#define SQL_CA_SS_UDT_SCHEMA_NAME (SQL_CA_SS_BASE+19) // UDT schema name
#define SQL_CA_SS_UDT_TYPE_NAME (SQL_CA_SS_BASE+20) // UDT type name
@ -287,143 +274,128 @@ extern "C" {
#define SQL_CA_SS_SCHEMA_NAME (SQL_CA_SS_BASE+26) // Schema name
#define SQL_CA_SS_TYPE_NAME (SQL_CA_SS_BASE+27) // Type name
// table valued parameter related metadata
// table valued parameter related metadata
#define SQL_CA_SS_COLUMN_COMPUTED (SQL_CA_SS_BASE+29) // column is computed
#define SQL_CA_SS_COLUMN_IN_UNIQUE_KEY (SQL_CA_SS_BASE+30) // column is part of a unique key
#define SQL_CA_SS_COLUMN_SORT_ORDER (SQL_CA_SS_BASE+31) // column sort order
#define SQL_CA_SS_COLUMN_SORT_ORDINAL (SQL_CA_SS_BASE+32) // column sort ordinal
#define SQL_CA_SS_COLUMN_HAS_DEFAULT_VALUE (SQL_CA_SS_BASE+33) // column has default value for all rows of the table valued parameter
// sparse column related metadata
// sparse column related metadata
#define SQL_CA_SS_IS_COLUMN_SET (SQL_CA_SS_BASE+34) // column is a column-set column for sparse columns
// Legacy datetime related metadata
// Legacy datetime related metadata
#define SQL_CA_SS_SERVER_TYPE (SQL_CA_SS_BASE+35) // column type to send on the wire for datetime types
// force column encryption
#define SQL_CA_SS_FORCE_ENCRYPT (SQL_CA_SS_BASE+36) // indicate mandatory encryption for this parameter
#define SQL_CA_SS_MAX_USED (SQL_CA_SS_BASE+36)
#define SQL_CA_SS_MAX_USED (SQL_CA_SS_BASE+37)
// Defines returned by SQL_ATTR_CURSOR_TYPE/SQL_CURSOR_TYPE
// Defines returned by SQL_ATTR_CURSOR_TYPE/SQL_CURSOR_TYPE
#define SQL_CURSOR_FAST_FORWARD_ONLY 8 // Only returned by SQLGetStmtAttr/Option
// Defines for use with SQL_COPT_SS_USE_PROC_FOR_PREP
// Defines for use with SQL_COPT_SS_USE_PROC_FOR_PREP
#define SQL_UP_OFF 0L // Procedures won't be used for prepare
#define SQL_UP_ON 1L // Procedures will be used for prepare
#define SQL_UP_ON_DROP 2L // Temp procedures will be explicitly dropped
#define SQL_UP_DEFAULT SQL_UP_ON
// Defines for use with SQL_COPT_SS_INTEGRATED_SECURITY - Pre-Connect Option only
// Defines for use with SQL_COPT_SS_INTEGRATED_SECURITY - Pre-Connect Option only
#define SQL_IS_OFF 0L // Integrated security isn't used
#define SQL_IS_ON 1L // Integrated security is used
#define SQL_IS_AD_OFF 2L // Active Directory integrated security isn't used
#define SQL_IS_AD_ON 3L // Active Directory integrated security is used
#define SQL_IS_DEFAULT SQL_IS_OFF
// Defines for use with SQL_COPT_SS_PRESERVE_CURSORS
// Defines for use with SQL_COPT_SS_PRESERVE_CURSORS
#define SQL_PC_OFF 0L // Cursors are closed on SQLTransact
#define SQL_PC_ON 1L // Cursors remain open on SQLTransact
#define SQL_PC_DEFAULT SQL_PC_OFF
// Defines for use with SQL_COPT_SS_USER_DATA
// Defines for use with SQL_COPT_SS_USER_DATA
#define SQL_UD_NOTSET NULL // No user data pointer set
// Defines for use with SQL_COPT_SS_TRANSLATE
// Defines for use with SQL_COPT_SS_TRANSLATE
#define SQL_XL_OFF 0L // Code page translation is not performed
#define SQL_XL_ON 1L // Code page translation is performed
#define SQL_XL_DEFAULT SQL_XL_ON
// Defines for use with SQL_COPT_SS_FALLBACK_CONNECT - Pre-Connect Option only
// Defines for use with SQL_COPT_SS_FALLBACK_CONNECT - Pre-Connect Option only
#define SQL_FB_OFF 0L // FallBack connections are disabled
#define SQL_FB_ON 1L // FallBack connections are enabled
#define SQL_FB_DEFAULT SQL_FB_OFF
// Defines for use with SQL_COPT_SS_BCP - Pre-Connect Option only
// Defines for use with SQL_COPT_SS_BCP - Pre-Connect Option only
#define SQL_BCP_OFF 0L // BCP is not allowed on connection
#define SQL_BCP_ON 1L // BCP is allowed on connection
#define SQL_BCP_DEFAULT SQL_BCP_OFF
// Defines for use with SQL_COPT_SS_QUOTED_IDENT
// Defines for use with SQL_COPT_SS_QUOTED_IDENT
#define SQL_QI_OFF 0L // Quoted identifiers are enable
#define SQL_QI_ON 1L // Quoted identifiers are disabled
#define SQL_QI_DEFAULT SQL_QI_ON
// Defines for use with SQL_COPT_SS_ANSI_NPW - Pre-Connect Option only
// Defines for use with SQL_COPT_SS_ANSI_NPW - Pre-Connect Option only
#define SQL_AD_OFF 0L // ANSI NULLs, Padding and Warnings are enabled
#define SQL_AD_ON 1L // ANSI NULLs, Padding and Warnings are disabled
#define SQL_AD_DEFAULT SQL_AD_ON
// Defines for use with SQL_COPT_SS_CONCAT_NULL - Pre-Connect Option only
// Defines for use with SQL_COPT_SS_CONCAT_NULL - Pre-Connect Option only
#define SQL_CN_OFF 0L // CONCAT_NULL_YIELDS_NULL is off
#define SQL_CN_ON 1L // CONCAT_NULL_YIELDS_NULL is on
#define SQL_CN_DEFAULT SQL_CN_ON
// Defines for use with SQL_SOPT_SS_TEXTPTR_LOGGING
// Defines for use with SQL_SOPT_SS_TEXTPTR_LOGGING
#define SQL_TL_OFF 0L // No logging on text pointer ops
#define SQL_TL_ON 1L // Logging occurs on text pointer ops
#define SQL_TL_DEFAULT SQL_TL_ON
// Defines for use with SQL_SOPT_SS_HIDDEN_COLUMNS
// Defines for use with SQL_SOPT_SS_HIDDEN_COLUMNS
#define SQL_HC_OFF 0L // FOR BROWSE columns are hidden
#define SQL_HC_ON 1L // FOR BROWSE columns are exposed
#define SQL_HC_DEFAULT SQL_HC_OFF
// Defines for use with SQL_SOPT_SS_NOBROWSETABLE
// Defines for use with SQL_SOPT_SS_NOBROWSETABLE
#define SQL_NB_OFF 0L // NO_BROWSETABLE is off
#define SQL_NB_ON 1L // NO_BROWSETABLE is on
#define SQL_NB_DEFAULT SQL_NB_OFF
// Defines for use with SQL_SOPT_SS_REGIONALIZE
// Defines for use with SQL_SOPT_SS_REGIONALIZE
#define SQL_RE_OFF 0L // No regionalization occurs on output character conversions
#define SQL_RE_ON 1L // Regionalization occurs on output character conversions
#define SQL_RE_DEFAULT SQL_RE_OFF
// Defines for use with SQL_SOPT_SS_CURSOR_OPTIONS
// Defines for use with SQL_SOPT_SS_CURSOR_OPTIONS
#define SQL_CO_OFF 0L // Clear all cursor options
#define SQL_CO_FFO 1L // Fast-forward cursor will be used
#define SQL_CO_AF 2L // Autofetch on cursor open
#define SQL_CO_FFO_AF (SQL_CO_FFO|SQL_CO_AF) // Fast-forward cursor with autofetch
#define SQL_CO_FIREHOSE_AF 4L // Auto fetch on fire-hose cursors
#define SQL_CO_DEFAULT SQL_CO_OFF
// Defines for use with SQL_SOPT_SS_COLUMN_ENCRYPTION
#define SQL_CE_DISABLED 0L // Disabled
#define SQL_CE_RESULTSETONLY 1L // Decryption Only (resultsets and return values)
#define SQL_CE_ENABLED 3L // Enabled (both encryption and decryption)
// Defines for use with SQL_COPT_SS_COLUMN_ENCRYPTION
#define SQL_COLUMN_ENCRYPTION_DISABLE 0L
#define SQL_COLUMN_ENCRYPTION_ENABLE 1L
#define SQL_COLUMN_ENCRYPTION_DEFAULT SQL_COLUMN_ENCRYPTION_DISABLE
// Defines for use with SQL_COPT_SS_AECEKCACHETTL
#define SQL_AECEKCACHETTL_DEFAULT 7200L // TTL value in seconds (2 hours)
//SQL_SOPT_SS_NOCOUNT_STATUS
//SQL_SOPT_SS_NOCOUNT_STATUS
#define SQL_NC_OFF 0L
#define SQL_NC_ON 1L
//SQL_SOPT_SS_DEFER_PREPARE
//SQL_SOPT_SS_DEFER_PREPARE
#define SQL_DP_OFF 0L
#define SQL_DP_ON 1L
//SQL_SOPT_SS_NAME_SCOPE
//SQL_SOPT_SS_NAME_SCOPE
#define SQL_SS_NAME_SCOPE_TABLE 0L
#define SQL_SS_NAME_SCOPE_TABLE_TYPE 1L
#define SQL_SS_NAME_SCOPE_EXTENDED 2L
#define SQL_SS_NAME_SCOPE_SPARSE_COLUMN_SET 3L
#define SQL_SS_NAME_SCOPE_DEFAULT SQL_SS_NAME_SCOPE_TABLE
//SQL_COPT_SS_ENCRYPT
//SQL_COPT_SS_ENCRYPT
#define SQL_EN_OFF 0L
#define SQL_EN_ON 1L
//SQL_COPT_SS_TRUST_SERVER_CERTIFICATE
//SQL_COPT_SS_TRUST_SERVER_CERTIFICATE
#define SQL_TRUST_SERVER_CERTIFICATE_NO 0L
#define SQL_TRUST_SERVER_CERTIFICATE_YES 1L
//SQL_COPT_SS_BROWSE_CONNECT
//SQL_COPT_SS_BROWSE_CONNECT
#define SQL_MORE_INFO_NO 0L
#define SQL_MORE_INFO_YES 1L
//SQL_COPT_SS_BROWSE_CACHE_DATA
//SQL_COPT_SS_BROWSE_CACHE_DATA
#define SQL_CACHE_DATA_NO 0L
#define SQL_CACHE_DATA_YES 1L
//SQL_COPT_SS_RESET_CONNECTION
//SQL_COPT_SS_RESET_CONNECTION
#define SQL_RESET_YES 1L
//SQL_COPT_SS_WARN_ON_CP_ERROR
//SQL_COPT_SS_WARN_ON_CP_ERROR
#define SQL_WARN_NO 0L
#define SQL_WARN_YES 1L
//SQL_COPT_SS_MARS_ENABLED
//SQL_COPT_SS_MARS_ENABLED
#define SQL_MARS_ENABLED_NO 0L
#define SQL_MARS_ENABLED_YES 1L
/* SQL_TXN_ISOLATION_OPTION bitmasks */
/* SQL_TXN_ISOLATION_OPTION bitmasks */
#define SQL_TXN_SS_SNAPSHOT 0x00000020L
// The following are defines for SQL_CA_SS_COLUMN_SORT_ORDER
// The following are defines for SQL_CA_SS_COLUMN_SORT_ORDER
#define SQL_SS_ORDER_UNSPECIFIED 0L
#define SQL_SS_DESCENDING_ORDER 1L
#define SQL_SS_ASCENDING_ORDER 2L
#define SQL_SS_ORDER_DEFAULT SQL_SS_ORDER_UNSPECIFIED
// Driver specific SQL data type defines.
// Microsoft has -150 thru -199 reserved for Microsoft SQL Server Native Client driver usage.
// Driver specific SQL data type defines.
// Microsoft has -150 thru -199 reserved for Microsoft SQL Server Native Client driver usage.
#define SQL_SS_VARIANT (-150)
#define SQL_SS_UDT (-151)
#define SQL_SS_XML (-152)
@ -431,22 +403,22 @@ extern "C" {
#define SQL_SS_TIME2 (-154)
#define SQL_SS_TIMESTAMPOFFSET (-155)
// Local types to be used with SQL_CA_SS_SERVER_TYPE
// Local types to be used with SQL_CA_SS_SERVER_TYPE
#define SQL_SS_TYPE_DEFAULT 0L
#define SQL_SS_TYPE_SMALLDATETIME 1L
#define SQL_SS_TYPE_DATETIME 2L
// Extended C Types range 4000 and above. Range of -100 thru 200 is reserved by Driver Manager.
// Extended C Types range 4000 and above. Range of -100 thru 200 is reserved by Driver Manager.
#define SQL_C_TYPES_EXTENDED 0x04000L
#define SQL_C_SS_TIME2 (SQL_C_TYPES_EXTENDED+0)
#define SQL_C_SS_TIMESTAMPOFFSET (SQL_C_TYPES_EXTENDED+1)
#ifndef SQLNCLI_NO_BCP
// Define the symbol SQLNCLI_NO_BCP if you are not using BCP in your application
// and you want to exclude the BCP-related definitions in this header file.
// Define the symbol SQLNCLI_NO_BCP if you are not using BCP in your application
// and you want to exclude the BCP-related definitions in this header file.
// SQL Server Data Type defines.
// New types for SQL 6.0 and later servers
// SQL Server Data Type defines.
// New types for SQL 6.0 and later servers
#define SQLTEXT 0x23
#define SQLVARBINARY 0x25
#define SQLINTN 0x26
@ -467,10 +439,10 @@ extern "C" {
#define SQLFLT4 0x3b
#define SQLMONEY4 0x7a
#define SQLDATETIM4 0x3a
// New types for SQL 6.0 and later servers
// New types for SQL 6.0 and later servers
#define SQLDECIMAL 0x6a
#define SQLNUMERIC 0x6c
// New types for SQL 7.0 and later servers
// New types for SQL 7.0 and later servers
#define SQLUNIQUEID 0x24
#define SQLBIGCHAR 0xaf
#define SQLBIGVARCHAR 0xa7
@ -480,29 +452,29 @@ extern "C" {
#define SQLNCHAR 0xef
#define SQLNVARCHAR 0xe7
#define SQLNTEXT 0x63
// New types for SQL 2000 and later servers
// New types for SQL 2000 and later servers
#define SQLINT8 0x7f
#define SQLVARIANT 0x62
// New types for SQL 2005 and later servers
// New types for SQL 2005 and later servers
#define SQLUDT 0xf0
#define SQLXML 0xf1
// New types for SQL 2008 and later servers
// New types for SQL 2008 and later servers
#define SQLTABLE 0xf3
#define SQLDATEN 0x28
#define SQLTIMEN 0x29
#define SQLDATETIME2N 0x2a
#define SQLDATETIMEOFFSETN 0x2b
// Define old names
// Define old names
#define SQLDECIMALN 0x6a
#define SQLNUMERICN 0x6c
#endif // SQLNCLI_NO_BCP
// SQL_SS_LENGTH_UNLIMITED is used to describe the max length of
// VARCHAR(max), VARBINARY(max), NVARCHAR(max), and XML columns
// SQL_SS_LENGTH_UNLIMITED is used to describe the max length of
// VARCHAR(max), VARBINARY(max), NVARCHAR(max), and XML columns
#define SQL_SS_LENGTH_UNLIMITED 0
// User Data Type definitions.
// Returned by SQLColAttributes/SQL_CA_SS_COLUMN_UTYPE.
// User Data Type definitions.
// Returned by SQLColAttributes/SQL_CA_SS_COLUMN_UTYPE.
#define SQLudtBINARY 3
#define SQLudtBIT 16
#define SQLudtBITN 0
@ -532,8 +504,8 @@ extern "C" {
#define SQLudtVARBINARY 4
#define SQLudtVARCHAR 2
#define MIN_USER_DATATYPE 256
// Aggregate operator types.
// Returned by SQLColAttributes/SQL_CA_SS_COLUMN_OP.
// Aggregate operator types.
// Returned by SQLColAttributes/SQL_CA_SS_COLUMN_OP.
#define SQLAOPSTDEV 0x30 // Standard deviation
#define SQLAOPSTDEVP 0x31 // Standard deviation population
#define SQLAOPVAR 0x32 // Variance
@ -545,8 +517,8 @@ extern "C" {
#define SQLAOPMAX 0x52 // Max
#define SQLAOPANY 0x53 // Any
#define SQLAOPNOOP 0x56 // None
// SQLGetInfo driver specific defines.
// Microsoft has 1151 thru 1200 reserved for Microsoft SQL Server Native Client driver usage.
// SQLGetInfo driver specific defines.
// Microsoft has 1151 thru 1200 reserved for Microsoft SQL Server Native Client driver usage.
#define SQL_INFO_SS_FIRST 1199
#define SQL_INFO_SS_NETLIB_NAMEW (SQL_INFO_SS_FIRST+0) // dbprocinfo
#define SQL_INFO_SS_NETLIB_NAMEA (SQL_INFO_SS_FIRST+1) // dbprocinfo
@ -557,16 +529,16 @@ extern "C" {
#define SQL_INFO_SS_NETLIB_NAME SQL_INFO_SS_NETLIB_NAMEA
#endif
// SQLGetDiagField driver specific defines.
// Microsoft has -1150 thru -1199 reserved for Microsoft SQL Server Native Client driver usage.
// SQLGetDiagField driver specific defines.
// Microsoft has -1150 thru -1199 reserved for Microsoft SQL Server Native Client driver usage.
#define SQL_DIAG_SS_BASE (-1150)
#define SQL_DIAG_SS_MSGSTATE (SQL_DIAG_SS_BASE)
#define SQL_DIAG_SS_SEVERITY (SQL_DIAG_SS_BASE-1)
#define SQL_DIAG_SS_SRVNAME (SQL_DIAG_SS_BASE-2)
#define SQL_DIAG_SS_PROCNAME (SQL_DIAG_SS_BASE-3)
#define SQL_DIAG_SS_LINE (SQL_DIAG_SS_BASE-4)
// SQLGetDiagField/SQL_DIAG_DYNAMIC_FUNCTION_CODE driver specific defines.
// Microsoft has -200 thru -299 reserved for Microsoft SQL Server Native Client driver usage.
// SQLGetDiagField/SQL_DIAG_DYNAMIC_FUNCTION_CODE driver specific defines.
// Microsoft has -200 thru -299 reserved for Microsoft SQL Server Native Client driver usage.
#define SQL_DIAG_DFC_SS_BASE (-200)
#define SQL_DIAG_DFC_SS_ALTER_DATABASE (SQL_DIAG_DFC_SS_BASE-0)
#define SQL_DIAG_DFC_SS_CHECKPOINT (SQL_DIAG_DFC_SS_BASE-1)
@ -631,7 +603,7 @@ extern "C" {
#define SQL_DIAG_DFC_SS_SET_XCTLVL (SQL_DIAG_DFC_SS_BASE-55)
#define SQL_DIAG_DFC_SS_MERGE (SQL_DIAG_DFC_SS_BASE-56)
// Severity codes for SQL_DIAG_SS_SEVERITY
// Severity codes for SQL_DIAG_SS_SEVERITY
#define EX_ANY 0
#define EX_INFO 10
#define EX_MAXISEVERITY EX_INFO
@ -652,75 +624,75 @@ extern "C" {
#define EX_DBCORRUPT 23
#define EX_HARDWARE 24
#define EX_CONTROL 25
// Internal server datatypes - used when binding to SQL_C_BINARY
// Internal server datatypes - used when binding to SQL_C_BINARY
#ifndef MAXNUMERICLEN // Resolve ODS/DBLib conflicts
// DB-Library datatypes
// DB-Library datatypes
#define DBMAXCHAR (8000+1) // Max length of DBVARBINARY and DBVARCHAR, etc. +1 for zero byte
#define MAXNAME (SQL_MAX_SQLSERVERNAME+1) // Max server identifier length including zero byte
#ifdef UNICODE
typedef wchar_t DBCHAR;
typedef wchar_t DBCHAR;
#else
typedef char DBCHAR;
typedef char DBCHAR;
#endif
typedef short SQLSMALLINT;
typedef short SQLSMALLINT;
typedef unsigned short SQLUSMALLINT;
typedef unsigned short SQLUSMALLINT;
typedef unsigned char DBBINARY;
typedef unsigned char DBBINARY;
typedef unsigned char DBTINYINT;
typedef unsigned char DBTINYINT;
typedef short DBSMALLINT;
typedef short DBSMALLINT;
typedef unsigned short DBUSMALLINT;
typedef unsigned short DBUSMALLINT;
typedef double DBFLT8;
typedef double DBFLT8;
typedef unsigned char DBBIT;
typedef unsigned char DBBIT;
typedef unsigned char DBBOOL;
typedef unsigned char DBBOOL;
typedef float DBFLT4;
typedef float DBFLT4;
typedef DBFLT4 DBREAL;
typedef DBFLT4 DBREAL;
typedef UINT DBUBOOL;
typedef UINT DBUBOOL;
typedef struct dbmoney
typedef struct dbmoney
{
LONG mnyhigh;
ULONG mnylow;
LONG mnyhigh;
ULONG mnylow;
} DBMONEY;
typedef struct dbdatetime
typedef struct dbdatetime
{
LONG dtdays;
ULONG dttime;
LONG dtdays;
ULONG dttime;
} DBDATETIME;
typedef struct dbdatetime4
typedef struct dbdatetime4
{
USHORT numdays;
USHORT nummins;
USHORT numdays;
USHORT nummins;
} DBDATETIM4;
typedef LONG DBMONEY4;
typedef LONG DBMONEY4;
#include <pshpack8.h> // 8-byte structure packing
// New Date Time Structures
// New Structure for TIME2
typedef struct tagSS_TIME2_STRUCT
{
// New Date Time Structures
// New Structure for TIME2
typedef struct tagSS_TIME2_STRUCT
{
SQLUSMALLINT hour;
SQLUSMALLINT minute;
SQLUSMALLINT second;
SQLUINTEGER fraction;
} SQL_SS_TIME2_STRUCT;
// New Structure for TIMESTAMPOFFSET
typedef struct tagSS_TIMESTAMPOFFSET_STRUCT
{
} SQL_SS_TIME2_STRUCT;
// New Structure for TIMESTAMPOFFSET
typedef struct tagSS_TIMESTAMPOFFSET_STRUCT
{
SQLSMALLINT year;
SQLUSMALLINT month;
SQLUSMALLINT day;
@ -730,130 +702,130 @@ extern "C" {
SQLUINTEGER fraction;
SQLSMALLINT timezone_hour;
SQLSMALLINT timezone_minute;
} SQL_SS_TIMESTAMPOFFSET_STRUCT;
} SQL_SS_TIMESTAMPOFFSET_STRUCT;
typedef struct tagDBTIME2
{
USHORT hour;
USHORT minute;
USHORT second;
ULONG fraction;
} DBTIME2;
typedef struct tagDBTIME2
{
USHORT hour;
USHORT minute;
USHORT second;
ULONG fraction;
} DBTIME2;
typedef struct tagDBTIMESTAMPOFFSET
{
SHORT year;
USHORT month;
USHORT day;
USHORT hour;
USHORT minute;
USHORT second;
ULONG fraction;
SHORT timezone_hour;
SHORT timezone_minute;
} DBTIMESTAMPOFFSET;
typedef struct tagDBTIMESTAMPOFFSET
{
SHORT year;
USHORT month;
USHORT day;
USHORT hour;
USHORT minute;
USHORT second;
ULONG fraction;
SHORT timezone_hour;
SHORT timezone_minute;
} DBTIMESTAMPOFFSET;
#include <poppack.h> // restore original structure packing
// Money value *10,000
// Money value *10,000
#define DBNUM_PREC_TYPE BYTE
#define DBNUM_SCALE_TYPE BYTE
#define DBNUM_VAL_TYPE BYTE
#if (ODBCVER < 0x0300)
#define MAXNUMERICLEN 16
typedef struct dbnumeric // Internal representation of NUMERIC data type
{
DBNUM_PREC_TYPE precision; // Precision
DBNUM_SCALE_TYPE scale; // Scale
BYTE sign; // Sign (1 if positive, 0 if negative)
DBNUM_VAL_TYPE val[MAXNUMERICLEN];// Value
} DBNUMERIC;
typedef DBNUMERIC DBDECIMAL;// Internal representation of DECIMAL data type
typedef struct dbnumeric // Internal representation of NUMERIC data type
{
DBNUM_PREC_TYPE precision; // Precision
DBNUM_SCALE_TYPE scale; // Scale
BYTE sign; // Sign (1 if positive, 0 if negative)
DBNUM_VAL_TYPE val[MAXNUMERICLEN];// Value
} DBNUMERIC;
typedef DBNUMERIC DBDECIMAL;// Internal representation of DECIMAL data type
#else // Use ODBC 3.0 definitions since same as DBLib
#define MAXNUMERICLEN SQL_MAX_NUMERIC_LEN
typedef SQL_NUMERIC_STRUCT DBNUMERIC;
typedef SQL_NUMERIC_STRUCT DBDECIMAL;
typedef SQL_NUMERIC_STRUCT DBNUMERIC;
typedef SQL_NUMERIC_STRUCT DBDECIMAL;
#endif // ODCBVER
#endif // MAXNUMERICLEN
#ifndef INT
typedef int INT;
typedef LONG DBINT;
typedef DBINT * LPDBINT;
typedef int INT;
typedef LONG DBINT;
typedef DBINT * LPDBINT;
#ifndef _LPCBYTE_DEFINED
#define _LPCBYTE_DEFINED
typedef BYTE const* LPCBYTE;
typedef BYTE const* LPCBYTE;
#endif //_LPCBYTE_DEFINED
#endif // INT
/**************************************************************************
This struct is a global used for gathering statistical data on the driver.
Access to this structure is controlled via the pStatCrit;
***************************************************************************/
typedef struct sqlperf
{
// Application Profile Statistics
DWORD TimerResolution;
DWORD SQLidu;
DWORD SQLiduRows;
DWORD SQLSelects;
DWORD SQLSelectRows;
DWORD Transactions;
DWORD SQLPrepares;
DWORD ExecDirects;
DWORD SQLExecutes;
DWORD CursorOpens;
DWORD CursorSize;
DWORD CursorUsed;
LDOUBLE PercentCursorUsed;
LDOUBLE AvgFetchTime;
LDOUBLE AvgCursorSize;
LDOUBLE AvgCursorUsed;
DWORD SQLFetchTime;
DWORD SQLFetchCount;
DWORD CurrentStmtCount;
DWORD MaxOpenStmt;
DWORD SumOpenStmt;
// Connection Statistics
DWORD CurrentConnectionCount;
DWORD MaxConnectionsOpened;
DWORD SumConnectionsOpened;
DWORD SumConnectiontime;
LDOUBLE AvgTimeOpened;
// Network Statistics
DWORD ServerRndTrips;
DWORD BuffersSent;
DWORD BuffersRec;
DWORD BytesSent;
DWORD BytesRec;
// Time Statistics;
DWORD msExecutionTime;
DWORD msNetWorkServerTime;
} SQLPERF;
// The following are options for SQL_COPT_SS_PERF_DATA and SQL_COPT_SS_PERF_QUERY
/**************************************************************************
This struct is a global used for gathering statistical data on the driver.
Access to this structure is controlled via the pStatCrit;
***************************************************************************/
typedef struct sqlperf
{
// Application Profile Statistics
DWORD TimerResolution;
DWORD SQLidu;
DWORD SQLiduRows;
DWORD SQLSelects;
DWORD SQLSelectRows;
DWORD Transactions;
DWORD SQLPrepares;
DWORD ExecDirects;
DWORD SQLExecutes;
DWORD CursorOpens;
DWORD CursorSize;
DWORD CursorUsed;
LDOUBLE PercentCursorUsed;
LDOUBLE AvgFetchTime;
LDOUBLE AvgCursorSize;
LDOUBLE AvgCursorUsed;
DWORD SQLFetchTime;
DWORD SQLFetchCount;
DWORD CurrentStmtCount;
DWORD MaxOpenStmt;
DWORD SumOpenStmt;
// Connection Statistics
DWORD CurrentConnectionCount;
DWORD MaxConnectionsOpened;
DWORD SumConnectionsOpened;
DWORD SumConnectiontime;
LDOUBLE AvgTimeOpened;
// Network Statistics
DWORD ServerRndTrips;
DWORD BuffersSent;
DWORD BuffersRec;
DWORD BytesSent;
DWORD BytesRec;
// Time Statistics;
DWORD msExecutionTime;
DWORD msNetWorkServerTime;
} SQLPERF;
// The following are options for SQL_COPT_SS_PERF_DATA and SQL_COPT_SS_PERF_QUERY
#define SQL_PERF_START 1 // Starts the driver sampling performance data.
#define SQL_PERF_STOP 2 // Stops the counters from sampling performance data.
// The following are defines for SQL_COPT_SS_PERF_DATA_LOG
// The following are defines for SQL_COPT_SS_PERF_DATA_LOG
#define SQL_SS_DL_DEFAULT TEXT("STATS.LOG")
// The following are defines for SQL_COPT_SS_PERF_QUERY_LOG
// The following are defines for SQL_COPT_SS_PERF_QUERY_LOG
#define SQL_SS_QL_DEFAULT TEXT("QUERY.LOG")
// The following are defines for SQL_COPT_SS_PERF_QUERY_INTERVAL
// The following are defines for SQL_COPT_SS_PERF_QUERY_INTERVAL
#define SQL_SS_QI_DEFAULT 30000 // 30,000 milliseconds
#ifndef SQLNCLI_NO_BCP
// Define the symbol SQLNCLI_NO_BCP if you are not using BCP in your application
// and you want to exclude the BCP-related definitions in this header file.
// Define the symbol SQLNCLI_NO_BCP if you are not using BCP in your application
// and you want to exclude the BCP-related definitions in this header file.
// ODBC BCP prototypes and defines
// Return codes
// ODBC BCP prototypes and defines
// Return codes
#define SUCCEED 1
#define FAIL 0
#define SUCCEED_ABORT 2
#define SUCCEED_ASYNC 3
// Transfer directions
// Transfer directions
#define DB_IN 1 // Transfer from client to server
#define DB_OUT 2 // Transfer from server to client
// bcp_control option
// bcp_control option
#define BCPMAXERRS 1 // Sets max errors allowed
#define BCPFIRST 2 // Sets first row to be copied out
#define BCPLAST 3 // Sets number of rows to be copied out
@ -876,14 +848,14 @@ extern "C" {
#define BCPLASTEX 18 // Ending Row for BCP operation (64 bit)
#define BCPROWCOUNT 19 // Total Number of Rows Copied (64 bit)
#define BCPDELAYREADFMT 20 // Delay reading format file unil bcp_exec
// BCPFILECP values
// Any valid code page that is installed on the client can be passed plus:
// BCPFILECP values
// Any valid code page that is installed on the client can be passed plus:
#define BCPFILECP_ACP 0 // Data in file is in Windows code page
#define BCPFILECP_OEMCP 1 // Data in file is in OEM code page (default)
#define BCPFILECP_RAW (-1)// Data in file is in Server code page (no conversion)
// bcp_collen definition
// bcp_collen definition
#define SQL_VARLEN_DATA (-10) // Use default length for column
// BCP column format properties
// BCP column format properties
#define BCP_FMT_TYPE 0x01
#define BCP_FMT_INDICATOR_LEN 0x02
#define BCP_FMT_DATA_LEN 0x03
@ -891,7 +863,7 @@ extern "C" {
#define BCP_FMT_SERVER_COL 0x05
#define BCP_FMT_COLLATION 0x06
#define BCP_FMT_COLLATION_ID 0x07
// bcp_setbulkmode properties
// bcp_setbulkmode properties
#define BCP_OUT_CHARACTER_MODE 0x01
#define BCP_OUT_WIDE_CHARACTER_MODE 0x02
#define BCP_OUT_NATIVE_TEXT_MODE 0x03
@ -899,31 +871,31 @@ extern "C" {
// BCP functions
DBINT SQL_API bcp_batch(HDBC);
RETCODE SQL_API bcp_bind(HDBC, LPCBYTE, INT, DBINT, LPCBYTE, INT, INT, INT);
RETCODE SQL_API bcp_colfmt(HDBC, INT, BYTE, INT, DBINT, LPCBYTE, INT, INT);
RETCODE SQL_API bcp_collen(HDBC, DBINT, INT);
RETCODE SQL_API bcp_colptr(HDBC, LPCBYTE, INT);
RETCODE SQL_API bcp_columns(HDBC, INT);
RETCODE SQL_API bcp_control(HDBC, INT, void *);
DBINT SQL_API bcp_done(HDBC);
RETCODE SQL_API bcp_exec(HDBC, LPDBINT);
RETCODE SQL_API bcp_getcolfmt(HDBC, INT, INT, void *, INT, INT *);
RETCODE SQL_API bcp_initA(HDBC, LPCSTR, LPCSTR, LPCSTR, INT);
RETCODE SQL_API bcp_initW(HDBC, LPCWSTR, LPCWSTR, LPCWSTR, INT);
RETCODE SQL_API bcp_moretext(HDBC, DBINT, LPCBYTE);
RETCODE SQL_API bcp_readfmtA(HDBC, LPCSTR);
RETCODE SQL_API bcp_readfmtW(HDBC, LPCWSTR);
RETCODE SQL_API bcp_sendrow(HDBC);
RETCODE SQL_API bcp_setbulkmode(HDBC, INT, __in_bcount(cbField) void*, INT cbField, __in_bcount(cbRow) void *, INT cbRow);
RETCODE SQL_API bcp_setcolfmt(HDBC, INT, INT, void *, INT);
RETCODE SQL_API bcp_writefmtA(HDBC, LPCSTR);
RETCODE SQL_API bcp_writefmtW(HDBC, LPCWSTR);
CHAR* SQL_API dbprtypeA(INT);
WCHAR* SQL_API dbprtypeW(INT);
CHAR* SQL_API bcp_gettypenameA(INT, DBBOOL);
WCHAR* SQL_API bcp_gettypenameW(INT, DBBOOL);
// BCP functions
DBINT SQL_API bcp_batch (HDBC);
RETCODE SQL_API bcp_bind (HDBC, LPCBYTE, INT, DBINT, LPCBYTE, INT, INT, INT);
RETCODE SQL_API bcp_colfmt (HDBC, INT, BYTE, INT, DBINT, LPCBYTE, INT, INT);
RETCODE SQL_API bcp_collen (HDBC, DBINT, INT);
RETCODE SQL_API bcp_colptr (HDBC, LPCBYTE, INT);
RETCODE SQL_API bcp_columns (HDBC, INT);
RETCODE SQL_API bcp_control (HDBC, INT, void *);
DBINT SQL_API bcp_done (HDBC);
RETCODE SQL_API bcp_exec (HDBC, LPDBINT);
RETCODE SQL_API bcp_getcolfmt (HDBC, INT, INT, void *, INT, INT *);
RETCODE SQL_API bcp_initA (HDBC, LPCSTR, LPCSTR, LPCSTR, INT);
RETCODE SQL_API bcp_initW (HDBC, LPCWSTR, LPCWSTR, LPCWSTR, INT);
RETCODE SQL_API bcp_moretext (HDBC, DBINT, LPCBYTE);
RETCODE SQL_API bcp_readfmtA (HDBC, LPCSTR);
RETCODE SQL_API bcp_readfmtW (HDBC, LPCWSTR);
RETCODE SQL_API bcp_sendrow (HDBC);
RETCODE SQL_API bcp_setbulkmode (HDBC, INT, _In_reads_bytes_(cbField) void*, INT cbField, _In_reads_bytes_(cbRow) void *, INT cbRow);
RETCODE SQL_API bcp_setcolfmt (HDBC, INT, INT, void *, INT);
RETCODE SQL_API bcp_writefmtA (HDBC, LPCSTR);
RETCODE SQL_API bcp_writefmtW (HDBC, LPCWSTR);
CHAR* SQL_API dbprtypeA (INT);
WCHAR* SQL_API dbprtypeW (INT);
CHAR* SQL_API bcp_gettypenameA (INT, DBBOOL);
WCHAR* SQL_API bcp_gettypenameW (INT, DBBOOL);
#ifdef UNICODE
#define bcp_init bcp_initW
@ -943,9 +915,9 @@ extern "C" {
#endif // SQLNCLI_NO_BCP
// The following options have been deprecated
// The following options have been deprecated
#define SQL_FAST_CONNECT (SQL_COPT_SS_BASE+0)
// Defines for use with SQL_FAST_CONNECT - only useable before connecting
// Defines for use with SQL_FAST_CONNECT - only useable before connecting
#define SQL_FC_OFF 0L // Fast connect is off
#define SQL_FC_ON 1L // Fast connect is on
#define SQL_FC_DEFAULT SQL_FC_OFF
@ -955,60 +927,6 @@ extern "C" {
#define SQL_AO_DEFAULT SQL_AO_OFF
#define SQL_CA_SS_BASE_COLUMN_NAME SQL_DESC_BASE_COLUMN_NAME
// Keystore Provider interface definition
typedef void errFunc(void *ctx, const wchar_t *msg, ...);
#define IDS_MSG(x) ((const wchar_t*)(x))
typedef struct AEKeystoreProvider
{
wchar_t *Name;
int (*Init)(void *ctx, errFunc *onError);
int (*Read)(void *ctx, errFunc *onError, void *data, unsigned int *len);
int (*Write)(void *ctx, errFunc *onError, void *data, unsigned int len);
int (*DecryptCEK)(
void *ctx,
errFunc *onError,
const wchar_t *keyPath,
const wchar_t *alg,
unsigned char *ecek,
unsigned short ecek_len,
unsigned char **cek_out,
unsigned short *cek_len);
void (*Free)();
} AEKEYSTOREPROVIDER;
/* Data is defined to be past the end of the structure header.
This is accepted by MSVC, GCC, and C99 standard but former emits
unnecessary warning, hence it has to be disabled.
*/
#pragma warning(push)
#pragma warning(disable:4200)
typedef struct AEKeystoreData
{
wchar_t *Name;
unsigned int dataSize;
char Data[];
} AEKEYSTOREPROVIDERDATA;
#pragma warning(pop)
// The following constants are for the Azure Key Vault configuration interface
#define AKV_CONFIG_FLAGS 0
#define AKVCFG_USECLIENTID 0x00000001
#define AKVCFG_AUTORENEW 0x00000002
#define AKV_CONFIG_CLIENTID 1
#define AKV_CONFIG_CLIENTKEY 2
#define AKV_CONFIG_ACCESSTOKEN 3
#define AKV_CONFIG_TOKENEXPIRY 4
#define AKV_CONFIG_MAXRETRIES 5
#define AKV_CONFIG_RETRYTIMEOUT 6
#define AKV_CONFIG_RETRYWAIT 7
#ifdef __cplusplus
} // extern "C"
@ -1023,12 +941,12 @@ extern "C" {
#endif
#include <windows.h>
//The following facilitates opening a handle to a SQL filestream
typedef enum _SQL_FILESTREAM_DESIRED_ACCESS {
SQL_FILESTREAM_READ = 0,
SQL_FILESTREAM_WRITE = 1,
SQL_FILESTREAM_READWRITE = 2
} SQL_FILESTREAM_DESIRED_ACCESS;
//The following facilitates opening a handle to a SQL filestream
typedef enum _SQL_FILESTREAM_DESIRED_ACCESS {
SQL_FILESTREAM_READ = 0,
SQL_FILESTREAM_WRITE = 1,
SQL_FILESTREAM_READWRITE = 2
} SQL_FILESTREAM_DESIRED_ACCESS;
#define SQL_FILESTREAM_OPEN_FLAG_ASYNC 0x00000001L
#define SQL_FILESTREAM_OPEN_FLAG_NO_BUFFERING 0x00000002L
#define SQL_FILESTREAM_OPEN_FLAG_NO_WRITE_THROUGH 0x00000004L
@ -1036,14 +954,14 @@ extern "C" {
#define SQL_FILESTREAM_OPEN_FLAG_RANDOM_ACCESS 0x00000010L
HANDLE __stdcall OpenSqlFilestream(
LPCWSTR FilestreamPath,
SQL_FILESTREAM_DESIRED_ACCESS DesiredAccess,
ULONG OpenOptions,
__in_bcount(FilestreamTransactionContextLength)
LPBYTE FilestreamTransactionContext,
SSIZE_T FilestreamTransactionContextLength,
PLARGE_INTEGER AllocationSize);
HANDLE __stdcall OpenSqlFilestream (
LPCWSTR FilestreamPath,
SQL_FILESTREAM_DESIRED_ACCESS DesiredAccess,
ULONG OpenOptions,
_In_reads_bytes_(FilestreamTransactionContextLength)
LPBYTE FilestreamTransactionContext,
SSIZE_T FilestreamTransactionContextLength,
PLARGE_INTEGER AllocationSize);
#define FSCTL_SQL_FILESTREAM_FETCH_OLD_CONTENT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 2392, METHOD_BUFFERED, FILE_ANY_ACCESS)
#ifdef __cplusplus
@ -1055,13 +973,10 @@ extern "C" {
#define SQL_COPT_SS_CONNECT_RETRY_COUNT (SQL_COPT_SS_BASE+34) // Post connection attribute used to get ConnectRetryCount
#define SQL_COPT_SS_CONNECT_RETRY_INTERVAL (SQL_COPT_SS_BASE+35) // Post connection attribute used to get ConnectRetryInterval
#define SQL_COPT_SS_CLIENT_CERTIFICATE (SQL_COPT_SS_BASE+36) // Client certificate
#define SQL_COPT_SS_CLIENT_CERTIFICATE_FALLBACK (SQL_COPT_SS_BASE+37) // Client certificate fallback
#ifdef SQL_COPT_SS_MAX_USED
#undef SQL_COPT_SS_MAX_USED
#endif // SQL_COPT_SS_MAX_USED
#define SQL_COPT_SS_MAX_USED SQL_COPT_SS_CLIENT_CERTIFICATE_FALLBACK
#define SQL_COPT_SS_MAX_USED SQL_COPT_SS_CONNECT_RETRY_INTERVAL
#ifndef _SQLUSERINSTANCE_H_
@ -1073,504 +988,491 @@ extern "C" {
extern "C" {
#endif
struct _CERT_CONTEXT;
typedef _CERT_CONTEXT CERT_CONTEXT;
typedef const CERT_CONTEXT *PCCERT_CONTEXT;
// type definition for client certificate fallback function
typedef DWORD(WINAPI *PFnClientCertificateFallback)(
__in BOOL fHash,
__in_z LPCWSTR pszCertificate,
__out PCCERT_CONTEXT *ppCertContext,
__out DWORD *pdwFlags,
__out ULONG cchKeyContainer,
__out_ecount(cchKeyContainer) WCHAR *pwchKeyContainer
);
// Recommended buffer size to store a LocalDB connection string
// Recommended buffer size to store a LocalDB connection string
#define LOCALDB_MAX_SQLCONNECTION_BUFFER_SIZE 260
// type definition for LocalDBCreateInstance function
typedef HRESULT __cdecl FnLocalDBCreateInstance(
// I the LocalDB version (e.g. 11.0 or 11.0.1094.2)
__in_z PCWSTR wszVersion,
// I the instance name
__in_z PCWSTR pInstanceName,
// I reserved for the future use. Currently should be set to 0.
__in DWORD dwFlags
);
// type definition for LocalDBCreateInstance function
typedef HRESULT __cdecl FnLocalDBCreateInstance (
// I the LocalDB version (e.g. 11.0 or 11.0.1094.2)
_In_z_ PCWSTR wszVersion,
// I the instance name
_In_z_ PCWSTR pInstanceName,
// I reserved for the future use. Currently should be set to 0.
_In_ DWORD dwFlags
);
// type definition for pointer to LocalDBCreateInstance function
typedef FnLocalDBCreateInstance* PFnLocalDBCreateInstance;
// type definition for pointer to LocalDBCreateInstance function
typedef FnLocalDBCreateInstance* PFnLocalDBCreateInstance;
// type definition for LocalDBStartInstance function
typedef HRESULT __cdecl FnLocalDBStartInstance(
// I the LocalDB instance name
__in_z PCWSTR pInstanceName,
// I reserved for the future use. Currently should be set to 0.
__in DWORD dwFlags,
// O the buffer to store the connection string to the LocalDB instance
__out_ecount_z_opt(*lpcchSqlConnection) LPWSTR wszSqlConnection,
// I/O on input has the size of the wszSqlConnection buffer in characters. On output, if the given buffer size is
// too small, has the buffer size required, in characters, including trailing null.
__inout_opt LPDWORD lpcchSqlConnection
);
// type definition for LocalDBStartInstance function
typedef HRESULT __cdecl FnLocalDBStartInstance (
// I the LocalDB instance name
_In_z_ PCWSTR pInstanceName,
// I reserved for the future use. Currently should be set to 0.
_In_ DWORD dwFlags,
// O the buffer to store the connection string to the LocalDB instance
_Out_writes_opt_z_(*lpcchSqlConnection) LPWSTR wszSqlConnection,
// I/O on input has the size of the wszSqlConnection buffer in characters. On output, if the given buffer size is
// too small, has the buffer size required, in characters, including trailing null.
_Inout_opt_ LPDWORD lpcchSqlConnection
);
// type definition for pointer to LocalDBStartInstance function
typedef FnLocalDBStartInstance* PFnLocalDBStartInstance;
// type definition for pointer to LocalDBStartInstance function
typedef FnLocalDBStartInstance* PFnLocalDBStartInstance;
// Flags for the LocalDBFormatMessage function
// Flags for the LocalDBFormatMessage function
#define LOCALDB_TRUNCATE_ERR_MESSAGE 0x0001L
// type definition for LocalDBFormatMessage function
typedef HRESULT __cdecl FnLocalDBFormatMessage(
// I the LocalDB error code
__in HRESULT hrLocalDB,
// I Available flags:
// LOCALDB_TRUNCATE_ERR_MESSAGE - if the input buffer is too short,
// the error message will be truncated to fit into the buffer
__in DWORD dwFlags,
// I Language desired (LCID) or 0 (in which case Win32 FormatMessage order is used)
__in DWORD dwLanguageId,
// O the buffer to store the LocalDB error message
__out_ecount_z(*lpcchMessage) LPWSTR wszMessage,
// I/O on input has the size of the wszMessage buffer in characters. On output, if the given buffer size is
// too small, has the buffer size required, in characters, including trailing null. If the function succeeds
// contains the number of characters in the message, excluding the trailing null
__inout LPDWORD lpcchMessage
);
// type definition for LocalDBFormatMessage function
typedef HRESULT __cdecl FnLocalDBFormatMessage(
// I the LocalDB error code
_In_ HRESULT hrLocalDB,
// I Available flags:
// LOCALDB_TRUNCATE_ERR_MESSAGE - if the input buffer is too short,
// the error message will be truncated to fit into the buffer
_In_ DWORD dwFlags,
// I Language desired (LCID) or 0 (in which case Win32 FormatMessage order is used)
_In_ DWORD dwLanguageId,
// O the buffer to store the LocalDB error message
_Out_writes_z_(*lpcchMessage) LPWSTR wszMessage,
// I/O on input has the size of the wszMessage buffer in characters. On output, if the given buffer size is
// too small, has the buffer size required, in characters, including trailing null. If the function succeeds
// contains the number of characters in the message, excluding the trailing null
_Inout_ LPDWORD lpcchMessage
);
// type definition for function pointer to LocalDBFormatMessage function
typedef FnLocalDBFormatMessage* PFnLocalDBFormatMessage;
// type definition for function pointer to LocalDBFormatMessage function
typedef FnLocalDBFormatMessage* PFnLocalDBFormatMessage;
// MessageId: LOCALDB_ERROR_NOT_INSTALLED
//
// MessageText:
//
// LocalDB is not installed.
//
// MessageId: LOCALDB_ERROR_NOT_INSTALLED
//
// MessageText:
//
// LocalDB is not installed.
//
#define LOCALDB_ERROR_NOT_INSTALLED ((HRESULT)0x89C50116L)
//---------------------------------------------------------------------
// Function: LocalDBCreateInstance
//
// Description: This function will create the new LocalDB instance.
//
// Available Flags:
// No flags available. Reserved for future use.
//
// Return Values:
// S_OK, if the function succeeds
// LOCALDB_ERROR_INVALID_PARAM_INSTANCE_NAME, if the instance name parameter is invalid
// LOCALDB_ERROR_INVALID_PARAM_VERSION, if the version parameter is invalid
// LOCALDB_ERROR_INVALID_PARAM_FLAGS, if the flags are invalid
// LOCALDB_ERROR_INVALID_OPERATION, if the user tries to create a default instance
// LOCALDB_ERROR_INSTANCE_FOLDER_PATH_TOO_LONG, if the path where instance should be stored is longer than MAX_PATH
// LOCALDB_ERROR_VERSION_REQUESTED_NOT_INSTALLED, if the specified service level is not installed
// LOCALDB_ERROR_INSTANCE_FOLDER_ALREADY_EXISTS, if the instance folder already exists and is not empty
// LOCALDB_ERROR_INSTANCE_EXISTS_WITH_LOWER_VERSION, if the specified instance already exists but with lower version
// LOCALDB_ERROR_CANNOT_CREATE_INSTANCE_FOLDER, if a folder cannot be created under %userprofile%
// LOCALDB_ERROR_CANNOT_GET_USER_PROFILE_FOLDER, if a user profile folder cannot be retrieved
// LOCALDB_ERROR_CANNOT_ACCESS_INSTANCE_FOLDER, if a instance folder cannot be accessed
// LOCALDB_ERROR_CANNOT_ACCESS_INSTANCE_REGISTRY, if a instance registry cannot be accessed
// LOCALDB_ERROR_INTERNAL_ERROR, if an unexpected error occurred. See event log for details
// LOCALDB_ERROR_CANNOT_MODIFY_INSTANCE_REGISTRY, if an instance registry cannot be modified
// LOCALDB_ERROR_CANNOT_CREATE_SQL_PROCESS, if a process for Sql Server cannot be created
// LOCALDB_ERROR_SQL_SERVER_STARTUP_FAILED, if a Sql Server process is started but Sql Server startup failed.
// LOCALDB_ERROR_INSTANCE_CONFIGURATION_CORRUPT, if a instance configuration is corrupted
//
FnLocalDBCreateInstance LocalDBCreateInstance;
//---------------------------------------------------------------------
// Function: LocalDBCreateInstance
//
// Description: This function will create the new LocalDB instance.
//
// Available Flags:
// No flags available. Reserved for future use.
//
// Return Values:
// S_OK, if the function succeeds
// LOCALDB_ERROR_INVALID_PARAM_INSTANCE_NAME, if the instance name parameter is invalid
// LOCALDB_ERROR_INVALID_PARAM_VERSION, if the version parameter is invalid
// LOCALDB_ERROR_INVALID_PARAM_FLAGS, if the flags are invalid
// LOCALDB_ERROR_INVALID_OPERATION, if the user tries to create a default instance
// LOCALDB_ERROR_INSTANCE_FOLDER_PATH_TOO_LONG, if the path where instance should be stored is longer than MAX_PATH
// LOCALDB_ERROR_VERSION_REQUESTED_NOT_INSTALLED, if the specified service level is not installed
// LOCALDB_ERROR_INSTANCE_FOLDER_ALREADY_EXISTS, if the instance folder already exists and is not empty
// LOCALDB_ERROR_INSTANCE_EXISTS_WITH_LOWER_VERSION, if the specified instance already exists but with lower version
// LOCALDB_ERROR_CANNOT_CREATE_INSTANCE_FOLDER, if a folder cannot be created under %userprofile%
// LOCALDB_ERROR_CANNOT_GET_USER_PROFILE_FOLDER, if a user profile folder cannot be retrieved
// LOCALDB_ERROR_CANNOT_ACCESS_INSTANCE_FOLDER, if a instance folder cannot be accessed
// LOCALDB_ERROR_CANNOT_ACCESS_INSTANCE_REGISTRY, if a instance registry cannot be accessed
// LOCALDB_ERROR_INTERNAL_ERROR, if an unexpected error occurred. See event log for details
// LOCALDB_ERROR_CANNOT_MODIFY_INSTANCE_REGISTRY, if an instance registry cannot be modified
// LOCALDB_ERROR_CANNOT_CREATE_SQL_PROCESS, if a process for Sql Server cannot be created
// LOCALDB_ERROR_SQL_SERVER_STARTUP_FAILED, if a Sql Server process is started but Sql Server startup failed.
// LOCALDB_ERROR_INSTANCE_CONFIGURATION_CORRUPT, if a instance configuration is corrupted
//
FnLocalDBCreateInstance LocalDBCreateInstance;
//---------------------------------------------------------------------
// Function: LocalDBStartInstance
//
// Description: This function will start the given LocalDB instance.
//
// Return Values:
// S_OK, if the function succeeds
// LOCALDB_ERROR_UNKNOWN_INSTANCE, if the specified instance doesn't exist
// LOCALDB_ERROR_INVALID_PARAM_INSTANCE_NAME, if the instance name parameter is invalid
// LOCALDB_ERROR_INVALID_PARAM_CONNECTION, if the wszSqlConnection parameter is NULL
// LOCALDB_ERROR_INVALID_PARAM_FLAGS, if the flags are invalid
// LOCALDB_ERROR_INSUFFICIENT_BUFFER, if the buffer wszSqlConnection is too small
// LOCALDB_ERROR_INSTANCE_FOLDER_PATH_TOO_LONG, if the path where instance should be stored is longer than MAX_PATH
//---------------------------------------------------------------------
// Function: LocalDBStartInstance
//
// Description: This function will start the given LocalDB instance.
//
// Return Values:
// S_OK, if the function succeeds
// LOCALDB_ERROR_UNKNOWN_INSTANCE, if the specified instance doesn't exist
// LOCALDB_ERROR_INVALID_PARAM_INSTANCE_NAME, if the instance name parameter is invalid
// LOCALDB_ERROR_INVALID_PARAM_CONNECTION, if the wszSqlConnection parameter is NULL
// LOCALDB_ERROR_INVALID_PARAM_FLAGS, if the flags are invalid
// LOCALDB_ERROR_INSUFFICIENT_BUFFER, if the buffer wszSqlConnection is too small
// LOCALDB_ERROR_INSTANCE_FOLDER_PATH_TOO_LONG, if the path where instance should be stored is longer than MAX_PATH
// LOCALDB_ERROR_CANNOT_GET_USER_PROFILE_FOLDER, if a user profile folder cannot be retrieved
// LOCALDB_ERROR_CANNOT_ACCESS_INSTANCE_FOLDER, if a instance folder cannot be accessed
// LOCALDB_ERROR_CANNOT_ACCESS_INSTANCE_REGISTRY, if a instance registry cannot be accessed
// LOCALDB_ERROR_INTERNAL_ERROR, if an unexpected error occurred. See event log for details
// LOCALDB_ERROR_CANNOT_MODIFY_INSTANCE_REGISTRY, if an instance registry cannot be modified
// LOCALDB_ERROR_CANNOT_CREATE_SQL_PROCESS, if a process for Sql Server cannot be created
// LOCALDB_ERROR_SQL_SERVER_STARTUP_FAILED, if a Sql Server process is started but Sql Server startup failed.
// LOCALDB_ERROR_INSTANCE_CONFIGURATION_CORRUPT, if a instance configuration is corrupted
//
FnLocalDBStartInstance LocalDBStartInstance;
// LOCALDB_ERROR_CANNOT_GET_USER_PROFILE_FOLDER, if a user profile folder cannot be retrieved
// LOCALDB_ERROR_CANNOT_ACCESS_INSTANCE_FOLDER, if a instance folder cannot be accessed
// LOCALDB_ERROR_CANNOT_ACCESS_INSTANCE_REGISTRY, if a instance registry cannot be accessed
// LOCALDB_ERROR_INTERNAL_ERROR, if an unexpected error occurred. See event log for details
// LOCALDB_ERROR_CANNOT_MODIFY_INSTANCE_REGISTRY, if an instance registry cannot be modified
// LOCALDB_ERROR_CANNOT_CREATE_SQL_PROCESS, if a process for Sql Server cannot be created
// LOCALDB_ERROR_SQL_SERVER_STARTUP_FAILED, if a Sql Server process is started but Sql Server startup failed.
// LOCALDB_ERROR_INSTANCE_CONFIGURATION_CORRUPT, if a instance configuration is corrupted
//
FnLocalDBStartInstance LocalDBStartInstance;
// type definition for LocalDBStopInstance function
typedef HRESULT __cdecl FnLocalDBStopInstance(
// I the LocalDB instance name
__in_z PCWSTR pInstanceName,
// I Available flags:
// LOCALDB_SHUTDOWN_KILL_PROCESS - force the instance to stop immediately
// LOCALDB_SHUTDOWN_WITH_NOWAIT - shutdown the instance with NOWAIT option
__in DWORD dwFlags,
// I the time in seconds to wait this operation to complete. If this value is 0, this function will return immediately
// without waiting for LocalDB instance to stop
__in ULONG ulTimeout
);
// type definition for LocalDBStopInstance function
typedef HRESULT __cdecl FnLocalDBStopInstance (
// I the LocalDB instance name
_In_z_ PCWSTR pInstanceName,
// I Available flags:
// LOCALDB_SHUTDOWN_KILL_PROCESS - force the instance to stop immediately
// LOCALDB_SHUTDOWN_WITH_NOWAIT - shutdown the instance with NOWAIT option
_In_ DWORD dwFlags,
// I the time in seconds to wait this operation to complete. If this value is 0, this function will return immediately
// without waiting for LocalDB instance to stop
_In_ ULONG ulTimeout
);
// type definition for pointer to LocalDBStopInstance function
typedef FnLocalDBStopInstance* PFnLocalDBStopInstance;
// type definition for pointer to LocalDBStopInstance function
typedef FnLocalDBStopInstance* PFnLocalDBStopInstance;
// Flags for the StopLocalDBInstance function
// Flags for the StopLocalDBInstance function
#define LOCALDB_SHUTDOWN_KILL_PROCESS 0x0001L
#define LOCALDB_SHUTDOWN_WITH_NOWAIT 0x0002L
//---------------------------------------------------------------------
// Function: LocalDBStopInstance
//
// Description: This function will shutdown the given LocalDB instance.
// If the flag LOCALDB_SHUTDOWN_KILL_PROCESS is set, the LocalDB instance will be killed immediately.
// IF the flag LOCALDB_SHUTDOWN_WITH_NOWAIT is set, the LocalDB instance will shutdown with NOWAIT option.
//
// Return Values:
// S_OK, if the function succeeds
// LOCALDB_ERROR_UNKNOWN_INSTANCE, if the specified instance doesn't exist
// LOCALDB_ERROR_INVALID_PARAM_INSTANCE_NAME, if the instance name parameter is invalid
// LOCALDB_ERROR_INVALID_PARAM_FLAGS, if the flags are invalid
// LOCALDB_ERROR_WAIT_TIMEOUT - if this function has not finished in given time
// LOCALDB_ERROR_INTERNAL_ERROR, if an unexpected error occurred. See event log for details
//
FnLocalDBStopInstance LocalDBStopInstance;
//---------------------------------------------------------------------
// Function: LocalDBStopInstance
//
// Description: This function will shutdown the given LocalDB instance.
// If the flag LOCALDB_SHUTDOWN_KILL_PROCESS is set, the LocalDB instance will be killed immediately.
// IF the flag LOCALDB_SHUTDOWN_WITH_NOWAIT is set, the LocalDB instance will shutdown with NOWAIT option.
//
// Return Values:
// S_OK, if the function succeeds
// LOCALDB_ERROR_UNKNOWN_INSTANCE, if the specified instance doesn't exist
// LOCALDB_ERROR_INVALID_PARAM_INSTANCE_NAME, if the instance name parameter is invalid
// LOCALDB_ERROR_INVALID_PARAM_FLAGS, if the flags are invalid
// LOCALDB_ERROR_WAIT_TIMEOUT - if this function has not finished in given time
// LOCALDB_ERROR_INTERNAL_ERROR, if an unexpected error occurred. See event log for details
//
FnLocalDBStopInstance LocalDBStopInstance;
// type definition for LocalDBDeleteInstance function
typedef HRESULT __cdecl FnLocalDBDeleteInstance(
// I the LocalDB instance name
__in_z PCWSTR pInstanceName,
// I reserved for the future use. Currently should be set to 0.
__in DWORD dwFlags
);
// type definition for LocalDBDeleteInstance function
typedef HRESULT __cdecl FnLocalDBDeleteInstance (
// I the LocalDB instance name
_In_z_ PCWSTR pInstanceName,
// I reserved for the future use. Currently should be set to 0.
_In_ DWORD dwFlags
);
// type definition for pointer to LocalDBDeleteInstance function
typedef FnLocalDBDeleteInstance* PFnLocalDBDeleteInstance;
// type definition for pointer to LocalDBDeleteInstance function
typedef FnLocalDBDeleteInstance* PFnLocalDBDeleteInstance;
//---------------------------------------------------------------------
// Function: LocalDBDeleteInstance
//
// Description: This function will remove the given LocalDB instance. If the given instance is running this function will
// fail with the error code LOCALDB_ERROR_INSTANCE_BUSY.
//
// Return Values:
// S_OK, if the function succeeds
// LOCALDB_ERROR_INVALID_PARAM_INSTANCE_NAME, if the instance name parameter is invalid
// LOCALDB_ERROR_INVALID_PARAM_FLAGS, if the flags are invalid
// LOCALDB_ERROR_UNKNOWN_INSTANCE, if the specified instance doesn't exist
// LOCALDB_ERROR_INSTANCE_BUSY, if the given instance is running
// LOCALDB_ERROR_INTERNAL_ERROR, if an unexpected error occurred. See event log for details
//
FnLocalDBDeleteInstance LocalDBDeleteInstance;
//---------------------------------------------------------------------
// Function: LocalDBDeleteInstance
//
// Description: This function will remove the given LocalDB instance. If the given instance is running this function will
// fail with the error code LOCALDB_ERROR_INSTANCE_BUSY.
//
// Return Values:
// S_OK, if the function succeeds
// LOCALDB_ERROR_INVALID_PARAM_INSTANCE_NAME, if the instance name parameter is invalid
// LOCALDB_ERROR_INVALID_PARAM_FLAGS, if the flags are invalid
// LOCALDB_ERROR_UNKNOWN_INSTANCE, if the specified instance doesn't exist
// LOCALDB_ERROR_INSTANCE_BUSY, if the given instance is running
// LOCALDB_ERROR_INTERNAL_ERROR, if an unexpected error occurred. See event log for details
//
FnLocalDBDeleteInstance LocalDBDeleteInstance;
// Function: LocalDBFormatMessage
//
// Description: This function will return the localized textual description for the given LocalDB error
//
// Available Flags:
// LOCALDB_TRUNCATE_ERR_MESSAGE - the error message should be truncated to fit into the provided buffer
//
// Return Value:
// S_OK, if the function succeeds
//
// LOCALDB_ERROR_UNKNOWN_HRESULT, if the given HRESULT is unknown
// LOCALDB_ERROR_UNKNOWN_LANGUAGE_ID, if the given language id is unknown (0 is recommended for the // default language)
// LOCALDB_ERROR_UNKNOWN_ERROR_CODE, if the LocalDB error code is unknown
// LOCALDB_ERROR_INVALID_PARAM_FLAGS, if the flags are invalid
// LOCALDB_ERROR_INSUFFICIENT_BUFFER, if the input buffer is too short and LOCALDB_TRUNCATE_ERR_MESSAGE flag
// is not set
// LOCALDB_ERROR_INTERNAL_ERROR, if an unexpected error occurred. See event log for details
//
FnLocalDBFormatMessage LocalDBFormatMessage;
// Function: LocalDBFormatMessage
//
// Description: This function will return the localized textual description for the given LocalDB error
//
// Available Flags:
// LOCALDB_TRUNCATE_ERR_MESSAGE - the error message should be truncated to fit into the provided buffer
//
// Return Value:
// S_OK, if the function succeeds
//
// LOCALDB_ERROR_UNKNOWN_HRESULT, if the given HRESULT is unknown
// LOCALDB_ERROR_UNKNOWN_LANGUAGE_ID, if the given language id is unknown (0 is recommended for the // default language)
// LOCALDB_ERROR_UNKNOWN_ERROR_CODE, if the LocalDB error code is unknown
// LOCALDB_ERROR_INVALID_PARAM_FLAGS, if the flags are invalid
// LOCALDB_ERROR_INSUFFICIENT_BUFFER, if the input buffer is too short and LOCALDB_TRUNCATE_ERR_MESSAGE flag
// is not set
// LOCALDB_ERROR_INTERNAL_ERROR, if an unexpected error occurred. See event log for details
//
FnLocalDBFormatMessage LocalDBFormatMessage;
#define MAX_LOCALDB_INSTANCE_NAME_LENGTH 128
#define MAX_LOCALDB_PARENT_INSTANCE_LENGTH MAX_INSTANCE_NAME
typedef WCHAR TLocalDBInstanceName[MAX_LOCALDB_INSTANCE_NAME_LENGTH + 1];
typedef TLocalDBInstanceName* PTLocalDBInstanceName;
typedef WCHAR TLocalDBInstanceName[MAX_LOCALDB_INSTANCE_NAME_LENGTH + 1];
typedef TLocalDBInstanceName* PTLocalDBInstanceName;
// type definition for LocalDBGetInstances function
typedef HRESULT __cdecl FnLocalDBGetInstances(
// O buffer for a LocalDB instance names
__out PTLocalDBInstanceName pInstanceNames,
// I/O on input has the number slots for instance names in the pInstanceNames buffer. On output,
// has the number of existing LocalDB instances
__inout LPDWORD lpdwNumberOfInstances
);
// type definition for LocalDBGetInstances function
typedef HRESULT __cdecl FnLocalDBGetInstances(
// O buffer for a LocalDB instance names
_Out_ PTLocalDBInstanceName pInstanceNames,
// I/O on input has the number slots for instance names in the pInstanceNames buffer. On output,
// has the number of existing LocalDB instances
_Inout_ LPDWORD lpdwNumberOfInstances
);
// type definition for pointer to LocalDBGetInstances function
typedef FnLocalDBGetInstances* PFnLocalDBGetInstances;
// type definition for pointer to LocalDBGetInstances function
typedef FnLocalDBGetInstances* PFnLocalDBGetInstances;
// Function: LocalDBGetInstances
//
// Description: This function returns names for all existing Local DB instances
//
// Usage Example:
// DWORD dwN = 0;
// LocalDBGetInstances(NULL, &dwN);
// Function: LocalDBGetInstances
//
// Description: This function returns names for all existing Local DB instances
//
// Usage Example:
// DWORD dwN = 0;
// LocalDBGetInstances(NULL, &dwN);
// PTLocalDBInstanceName insts = (PTLocalDBInstanceName) malloc(dwN * sizeof(TLocalDBInstanceName));
// LocalDBGetInstances(insts, &dwN);
// PTLocalDBInstanceName insts = (PTLocalDBInstanceName) malloc(dwN * sizeof(TLocalDBInstanceName));
// LocalDBGetInstances(insts, &dwN);
// for (int i = 0; i < dwN; i++)
// wprintf(L"%s\n", insts[i]);
//
// Return values:
// S_OK, if the function succeeds
//
// LOCALDB_ERROR_INSUFFICIENT_BUFFER, the given buffer is to small
// LOCALDB_ERROR_INTERNAL_ERROR, if an unexpected error occurred. See event log for details
//
FnLocalDBGetInstances LocalDBGetInstances;
// for (int i = 0; i < dwN; i++)
// wprintf(L"%s\n", insts[i]);
//
// Return values:
// S_OK, if the function succeeds
//
// LOCALDB_ERROR_INSUFFICIENT_BUFFER, the given buffer is to small
// LOCALDB_ERROR_INTERNAL_ERROR, if an unexpected error occurred. See event log for details
//
FnLocalDBGetInstances LocalDBGetInstances;
// SID string format: S - Revision(1B) - Authority ID (6B) {- Sub authority ID (4B)} * max 15 sub-authorities = 1 + 1 + 3 + 1 + 15 + (1 + 10) * 15
// SID string format: S - Revision(1B) - Authority ID (6B) {- Sub authority ID (4B)} * max 15 sub-authorities = 1 + 1 + 3 + 1 + 15 + (1 + 10) * 15
#define MAX_STRING_SID_LENGTH 186
#pragma pack(push)
#pragma pack(8)
// DEVNOTE: If you want to modify this structure please read DEVNOTEs on top of function LocalDBGetInstanceInfo in sqluserinstance.cpp file.
//
typedef struct _LocalDBInstanceInfo
{
DWORD cbLocalDBInstanceInfoSize;
TLocalDBInstanceName wszInstanceName;
BOOL bExists;
BOOL bConfigurationCorrupted;
BOOL bIsRunning;
DWORD dwMajor;
DWORD dwMinor;
DWORD dwBuild;
DWORD dwRevision;
FILETIME ftLastStartDateUTC;
WCHAR wszConnection[LOCALDB_MAX_SQLCONNECTION_BUFFER_SIZE];
BOOL bIsShared;
TLocalDBInstanceName wszSharedInstanceName;
WCHAR wszOwnerSID[MAX_STRING_SID_LENGTH + 1];
BOOL bIsAutomatic;
} LocalDBInstanceInfo;
// DEVNOTE: If you want to modify this structure please read DEVNOTEs on top of function LocalDBGetInstanceInfo in sqluserinstance.cpp file.
//
typedef struct _LocalDBInstanceInfo
{
DWORD cbLocalDBInstanceInfoSize;
TLocalDBInstanceName wszInstanceName;
BOOL bExists;
BOOL bConfigurationCorrupted;
BOOL bIsRunning;
DWORD dwMajor;
DWORD dwMinor;
DWORD dwBuild;
DWORD dwRevision;
FILETIME ftLastStartDateUTC;
WCHAR wszConnection[LOCALDB_MAX_SQLCONNECTION_BUFFER_SIZE];
BOOL bIsShared;
TLocalDBInstanceName wszSharedInstanceName;
WCHAR wszOwnerSID[MAX_STRING_SID_LENGTH + 1];
BOOL bIsAutomatic;
} LocalDBInstanceInfo;
#pragma pack(pop)
typedef LocalDBInstanceInfo* PLocalDBInstanceInfo;
typedef LocalDBInstanceInfo* PLocalDBInstanceInfo;
// type definition for LocalDBGetInstanceInfo function
typedef HRESULT __cdecl FnLocalDBGetInstanceInfo(
// I the LocalDB instance name
__in_z PCWSTR wszInstanceName,
// O instance information
__out PLocalDBInstanceInfo pInfo,
// I Size of LocalDBInstanceInfo structure in bytes
__in DWORD cbInfo);
// type definition for LocalDBGetInstanceInfo function
typedef HRESULT __cdecl FnLocalDBGetInstanceInfo(
// I the LocalDB instance name
_In_z_ PCWSTR wszInstanceName,
// O instance information
_Out_ PLocalDBInstanceInfo pInfo,
// I Size of LocalDBInstanceInfo structure in bytes
_In_ DWORD cbInfo);
// type definition for pointer to LocalDBGetInstances function
typedef FnLocalDBGetInstanceInfo* PFnLocalDBGetInstanceInfo;
// type definition for pointer to LocalDBGetInstances function
typedef FnLocalDBGetInstanceInfo* PFnLocalDBGetInstanceInfo;
// Function: LocalDBGetInstanceInfo
//
// Description: This function returns information about the given instance.
//
// Return values:
// S_OK, if the function succeeds
//
// ERROR_INVALID_PARAMETER, if some of the parameters is invalid
// LOCALDB_ERROR_INTERNAL_ERROR, if an unexpected error occurred. See event log for details
//
FnLocalDBGetInstanceInfo LocalDBGetInstanceInfo;
// Function: LocalDBGetInstanceInfo
//
// Description: This function returns information about the given instance.
//
// Return values:
// S_OK, if the function succeeds
//
// ERROR_INVALID_PARAMETER, if some of the parameters is invalid
// LOCALDB_ERROR_INTERNAL_ERROR, if an unexpected error occurred. See event log for details
//
FnLocalDBGetInstanceInfo LocalDBGetInstanceInfo;
// Version has format: Major.Minor[.Build[.Revision]]. Each of components is 32bit integer which is at most 40 digits and 3 dots
//
// Version has format: Major.Minor[.Build[.Revision]]. Each of components is 32bit integer which is at most 40 digits and 3 dots
//
#define MAX_LOCALDB_VERSION_LENGTH 43
typedef WCHAR TLocalDBVersion[MAX_LOCALDB_VERSION_LENGTH + 1];
typedef TLocalDBVersion* PTLocalDBVersion;
typedef WCHAR TLocalDBVersion[MAX_LOCALDB_VERSION_LENGTH + 1];
typedef TLocalDBVersion* PTLocalDBVersion;
// type definition for LocalDBGetVersions function
typedef HRESULT __cdecl FnLocalDBGetVersions(
// O buffer for installed LocalDB versions
__out PTLocalDBVersion pVersions,
// I/O on input has the number slots for versions in the pVersions buffer. On output,
// has the number of existing LocalDB versions
__inout LPDWORD lpdwNumberOfVersions
);
// type definition for LocalDBGetVersions function
typedef HRESULT __cdecl FnLocalDBGetVersions(
// O buffer for installed LocalDB versions
_Out_ PTLocalDBVersion pVersions,
// I/O on input has the number slots for versions in the pVersions buffer. On output,
// has the number of existing LocalDB versions
_Inout_ LPDWORD lpdwNumberOfVersions
);
// type definition for pointer to LocalDBGetVersions function
typedef FnLocalDBGetVersions* PFnLocalDBGetVersions;
// type definition for pointer to LocalDBGetVersions function
typedef FnLocalDBGetVersions* PFnLocalDBGetVersions;
// Function: LocalDBGetVersions
//
// Description: This function returns all installed LocalDB versions. Returned versions will be in format Major.Minor
//
// Usage Example:
// DWORD dwN = 0;
// LocalDBGetVersions(NULL, &dwN);
// Function: LocalDBGetVersions
//
// Description: This function returns all installed LocalDB versions. Returned versions will be in format Major.Minor
//
// Usage Example:
// DWORD dwN = 0;
// LocalDBGetVersions(NULL, &dwN);
// PTLocalDBVersion versions = (PTLocalDBVersion) malloc(dwN * sizeof(TLocalDBVersion));
// LocalDBGetVersions(insts, &dwN);
// PTLocalDBVersion versions = (PTLocalDBVersion) malloc(dwN * sizeof(TLocalDBVersion));
// LocalDBGetVersions(insts, &dwN);
// for (int i = 0; i < dwN; i++)
// wprintf(L"%s\n", insts[i]);
//
// Return values:
// S_OK, if the function succeeds
//
// LOCALDB_ERROR_INSUFFICIENT_BUFFER, the given buffer is to small
// LOCALDB_ERROR_INTERNAL_ERROR, if an unexpected error occurs.
//
FnLocalDBGetVersions LocalDBGetVersions;
// for (int i = 0; i < dwN; i++)
// wprintf(L"%s\n", insts[i]);
//
// Return values:
// S_OK, if the function succeeds
//
// LOCALDB_ERROR_INSUFFICIENT_BUFFER, the given buffer is to small
// LOCALDB_ERROR_INTERNAL_ERROR, if an unexpected error occurs.
//
FnLocalDBGetVersions LocalDBGetVersions;
#pragma pack(push)
#pragma pack(8)
// DEVNOTE: If you want to modify this structure please read DEVNOTEs on top of function LocalDBGetVersionInfo in sqluserinstance.cpp file.
//
typedef struct _LocalDBVersionInfo
{
DWORD cbLocalDBVersionInfoSize;
TLocalDBVersion wszVersion;
BOOL bExists;
DWORD dwMajor;
DWORD dwMinor;
DWORD dwBuild;
DWORD dwRevision;
} LocalDBVersionInfo;
// DEVNOTE: If you want to modify this structure please read DEVNOTEs on top of function LocalDBGetVersionInfo in sqluserinstance.cpp file.
//
typedef struct _LocalDBVersionInfo
{
DWORD cbLocalDBVersionInfoSize;
TLocalDBVersion wszVersion;
BOOL bExists;
DWORD dwMajor;
DWORD dwMinor;
DWORD dwBuild;
DWORD dwRevision;
} LocalDBVersionInfo;
#pragma pack(pop)
typedef LocalDBVersionInfo* PLocalDBVersionInfo;
typedef LocalDBVersionInfo* PLocalDBVersionInfo;
// type definition for LocalDBGetVersionInfo function
typedef HRESULT __cdecl FnLocalDBGetVersionInfo(
// I LocalDB version string
__in_z PCWSTR wszVersion,
// O version information
__out PLocalDBVersionInfo pVersionInfo,
// I Size of LocalDBVersionInfo structure in bytes
__in DWORD cbVersionInfo
);
// type definition for LocalDBGetVersionInfo function
typedef HRESULT __cdecl FnLocalDBGetVersionInfo(
// I LocalDB version string
_In_z_ PCWSTR wszVersion,
// O version information
_Out_ PLocalDBVersionInfo pVersionInfo,
// I Size of LocalDBVersionInfo structure in bytes
_In_ DWORD cbVersionInfo
);
// type definition for pointer to LocalDBGetVersionInfo function
typedef FnLocalDBGetVersionInfo* PFnLocalDBGetVersionInfo;
// type definition for pointer to LocalDBGetVersionInfo function
typedef FnLocalDBGetVersionInfo* PFnLocalDBGetVersionInfo;
// Function: LocalDBGetVersionInfo
//
// Description: This function returns information about the given LocalDB version
//
// Return values:
// S_OK, if the function succeeds
// LOCALDB_ERROR_INTERNAL_ERROR, if some internal error occurred
// LOCALDB_ERROR_INVALID_PARAMETER, if a input parameter is invalid
//
FnLocalDBGetVersionInfo LocalDBGetVersionInfo;
// Function: LocalDBGetVersionInfo
//
// Description: This function returns information about the given LocalDB version
//
// Return values:
// S_OK, if the function succeeds
// LOCALDB_ERROR_INTERNAL_ERROR, if some internal error occurred
// LOCALDB_ERROR_INVALID_PARAMETER, if a input parameter is invalid
//
FnLocalDBGetVersionInfo LocalDBGetVersionInfo;
typedef HRESULT __cdecl FnLocalDBStartTracing();
typedef FnLocalDBStartTracing* PFnLocalDBStartTracing;
typedef HRESULT __cdecl FnLocalDBStartTracing();
typedef FnLocalDBStartTracing* PFnLocalDBStartTracing;
// Function: LocalDBStartTracing
//
// Description: This function will write in registry that Tracing sessions should be started for the current user.
//
// Return values:
// S_OK - on success
// Propper HRESULT in case of failure
//
FnLocalDBStartTracing LocalDBStartTracing;
// Function: LocalDBStartTracing
//
// Description: This function will write in registry that Tracing sessions should be started for the current user.
//
// Return values:
// S_OK - on success
// Propper HRESULT in case of failure
//
FnLocalDBStartTracing LocalDBStartTracing;
typedef HRESULT __cdecl FnLocalDBStopTracing();
typedef FnLocalDBStopTracing* PFnFnLocalDBStopTracing;
typedef HRESULT __cdecl FnLocalDBStopTracing();
typedef FnLocalDBStopTracing* PFnFnLocalDBStopTracing;
// Function: LocalDBStopTracing
//
// Description: This function will write in registry that Tracing sessions should be stopped for the current user.
//
// Return values:
// S_OK - on success
// Propper HRESULT in case of failure
//
FnLocalDBStopTracing LocalDBStopTracing;
// Function: LocalDBStopTracing
//
// Description: This function will write in registry that Tracing sessions should be stopped for the current user.
//
// Return values:
// S_OK - on success
// Propper HRESULT in case of failure
//
FnLocalDBStopTracing LocalDBStopTracing;
// type definition for LocalDBShareInstance function
typedef HRESULT __cdecl FnLocalDBShareInstance(
// I the SID of the LocalDB instance owner
__in_opt PSID pOwnerSID,
// I the private name of LocalDB instance which should be shared
__in_z PCWSTR wszPrivateLocalDBInstanceName,
// I the public shared name
__in_z PCWSTR wszSharedName,
// I reserved for the future use. Currently should be set to 0.
__in DWORD dwFlags);
// type definition for LocalDBShareInstance function
typedef HRESULT __cdecl FnLocalDBShareInstance(
// I the SID of the LocalDB instance owner
_In_opt_ PSID pOwnerSID,
// I the private name of LocalDB instance which should be shared
_In_z_ PCWSTR wszPrivateLocalDBInstanceName,
// I the public shared name
_In_z_ PCWSTR wszSharedName,
// I reserved for the future use. Currently should be set to 0.
_In_ DWORD dwFlags);
// type definition for pointer to LocalDBShareInstance function
typedef FnLocalDBShareInstance* PFnLocalDBShareInstance;
// type definition for pointer to LocalDBShareInstance function
typedef FnLocalDBShareInstance* PFnLocalDBShareInstance;
// Function: LocalDBShareInstance
//
// Description: This function will share the given private instance of the given user with the given shared name.
// This function has to be executed elevated.
//
// Return values:
// HRESULT
//
FnLocalDBShareInstance LocalDBShareInstance;
// Function: LocalDBShareInstance
//
// Description: This function will share the given private instance of the given user with the given shared name.
// This function has to be executed elevated.
//
// Return values:
// HRESULT
//
FnLocalDBShareInstance LocalDBShareInstance;
// type definition for LocalDBUnshareInstance function
typedef HRESULT __cdecl FnLocalDBUnshareInstance(
// I the LocalDB instance name
__in_z PCWSTR pInstanceName,
// I reserved for the future use. Currently should be set to 0.
__in DWORD dwFlags);
// type definition for LocalDBUnshareInstance function
typedef HRESULT __cdecl FnLocalDBUnshareInstance(
// I the LocalDB instance name
_In_z_ PCWSTR pInstanceName,
// I reserved for the future use. Currently should be set to 0.
_In_ DWORD dwFlags);
// type definition for pointer to LocalDBUnshareInstance function
typedef FnLocalDBUnshareInstance* PFnLocalDBUnshareInstance;
// type definition for pointer to LocalDBUnshareInstance function
typedef FnLocalDBUnshareInstance* PFnLocalDBUnshareInstance;
// Function: LocalDBUnshareInstance
//
// Description: This function unshares the given LocalDB instance.
// If a shared name is given then that shared instance will be unshared.
// If a private name is given then we will check if the caller
// shares a private instance with the given private name and unshare it.
//
// Return values:
// HRESULT
//
FnLocalDBUnshareInstance LocalDBUnshareInstance;
// Function: LocalDBUnshareInstance
//
// Description: This function unshares the given LocalDB instance.
// If a shared name is given then that shared instance will be unshared.
// If a private name is given then we will check if the caller
// shares a private instance with the given private name and unshare it.
//
// Return values:
// HRESULT
//
FnLocalDBUnshareInstance LocalDBUnshareInstance;
#ifdef __cplusplus
} // extern "C"
#endif
#if defined(LOCALDB_DEFINE_PROXY_FUNCTIONS)
//---------------------------------------------------------------------
// The following section is enabled only if the constant LOCALDB_DEFINE_PROXY_FUNCTIONS
// is defined. It provides an implementation of proxies for each of the LocalDB APIs.
// The proxy implementations use a common function to bind to entry points in the
// latest installed SqlUserInstance DLL, and then forward the requests.
//
// The current implementation loads the SqlUserInstance DLL on the first call into
// a proxy function. There is no provision for unloading the DLL. Note that if the
// process includes multiple binaries (EXE and one or more DLLs), each of them could
// load a separate instance of the SqlUserInstance DLL.
//
// For future consideration: allow the SqlUserInstance DLL to be unloaded dynamically.
//
// WARNING: these functions must not be called in DLL initialization, since a deadlock
// could result loading dependent DLLs.
//---------------------------------------------------------------------
//---------------------------------------------------------------------
// The following section is enabled only if the constant LOCALDB_DEFINE_PROXY_FUNCTIONS
// is defined. It provides an implementation of proxies for each of the LocalDB APIs.
// The proxy implementations use a common function to bind to entry points in the
// latest installed SqlUserInstance DLL, and then forward the requests.
//
// The current implementation loads the SqlUserInstance DLL on the first call into
// a proxy function. There is no provision for unloading the DLL. Note that if the
// process includes multiple binaries (EXE and one or more DLLs), each of them could
// load a separate instance of the SqlUserInstance DLL.
//
// For future consideration: allow the SqlUserInstance DLL to be unloaded dynamically.
//
// WARNING: these functions must not be called in DLL initialization, since a deadlock
// could result loading dependent DLLs.
//---------------------------------------------------------------------
// This macro provides the body for each proxy function.
//
// This macro provides the body for each proxy function.
//
#define LOCALDB_PROXY(LocalDBFn) static Fn##LocalDBFn* pfn##LocalDBFn = NULL; if (!pfn##LocalDBFn) {HRESULT hr = LocalDBGetPFn(#LocalDBFn, (FARPROC *)&pfn##LocalDBFn); if (FAILED(hr)) return hr;} return (*pfn##LocalDBFn)
// Structure and function to parse the "Installed Versions" registry subkeys
//
// Structure and function to parse the "Installed Versions" registry subkeys
//
typedef struct {
DWORD dwComponent[2];
WCHAR wszKeyName[256];
@ -1606,7 +1508,7 @@ static BOOL ParseVersion(Version * pVersion)
if (!fHaveDigit)
return FALSE;
pVersion->dwComponent[i] = (DWORD)llVal;
pVersion->dwComponent[i] = (DWORD) llVal;
if (*pwch == L'\0')
return TRUE;
@ -1636,11 +1538,11 @@ static HRESULT LocalDBGetPFn(LPCSTR szLocalDBFn, FARPROC *pfnLocalDBFn)
LONG ec;
HKEY hkeyVersions = NULL;
HKEY hkeyVersion = NULL;
Version verHigh = { 0 };
Version verHigh = {0};
Version verCurrent;
DWORD cchKeyName;
DWORD dwValueType;
WCHAR wszLocalDBDll[MAX_PATH + 1];
WCHAR wszLocalDBDll[MAX_PATH+1];
DWORD cbLocalDBDll = sizeof(wszLocalDBDll) - sizeof(WCHAR); // to deal with RegQueryValueEx null-termination quirk
HMODULE hLocalDBDllTemp = NULL;
@ -1690,7 +1592,7 @@ static HRESULT LocalDBGetPFn(LPCSTR szLocalDBFn, FARPROC *pfnLocalDBFn)
{
goto Cleanup;
}
if (ERROR_SUCCESS != (ec = RegQueryValueExW(hkeyVersion, L"InstanceAPIPath", NULL, &dwValueType, (PBYTE)wszLocalDBDll, &cbLocalDBDll)))
if (ERROR_SUCCESS != (ec = RegQueryValueExW(hkeyVersion, L"InstanceAPIPath", NULL, &dwValueType, (PBYTE) wszLocalDBDll, &cbLocalDBDll)))
{
goto Cleanup;
}
@ -1702,7 +1604,7 @@ static HRESULT LocalDBGetPFn(LPCSTR szLocalDBFn, FARPROC *pfnLocalDBFn)
// Ensure string value null-terminated
// Note that we left a spare character in the output buffer for RegQueryValueEx for this purpose
//
wszLocalDBDll[cbLocalDBDll / sizeof(WCHAR)] = L'\0';
wszLocalDBDll[cbLocalDBDll/sizeof(WCHAR)] = L'\0';
hLocalDBDllTemp = LoadLibraryW(wszLocalDBDll);
if (NULL == hLocalDBDllTemp)
@ -1717,7 +1619,7 @@ static HRESULT LocalDBGetPFn(LPCSTR szLocalDBFn, FARPROC *pfnLocalDBFn)
hLocalDBDllTemp = NULL;
}
ec = ERROR_SUCCESS;
Cleanup:
Cleanup:
if (hLocalDBDllTemp)
FreeLibrary(hLocalDBDllTemp);
if (hkeyVersion)
@ -1739,7 +1641,7 @@ static HRESULT LocalDBGetPFn(LPCSTR szLocalDBFn, FARPROC *pfnLocalDBFn)
if (!pfn)
{
return HRESULT_FROM_WIN32(GetLastError());
return HRESULT_FROM_WIN32(GetLastError());
}
*pfnLocalDBFn = pfn;
return S_OK;
@ -1749,165 +1651,165 @@ static HRESULT LocalDBGetPFn(LPCSTR szLocalDBFn, FARPROC *pfnLocalDBFn)
//
HRESULT __cdecl
LocalDBCreateInstance(
// I the LocalDB version (e.g. 11.0 or 11.0.1094.2)
__in_z PCWSTR wszVersion,
// I the instance name
__in_z PCWSTR pInstanceName,
// I reserved for the future use. Currently should be set to 0.
__in DWORD dwFlags
)
LocalDBCreateInstance (
// I the LocalDB version (e.g. 11.0 or 11.0.1094.2)
_In_z_ PCWSTR wszVersion,
// I the instance name
_In_z_ PCWSTR pInstanceName,
// I reserved for the future use. Currently should be set to 0.
_In_ DWORD dwFlags
)
{
LOCALDB_PROXY(LocalDBCreateInstance)(wszVersion, pInstanceName, dwFlags);
LOCALDB_PROXY(LocalDBCreateInstance)(wszVersion, pInstanceName, dwFlags);
}
HRESULT __cdecl
LocalDBStartInstance(
// I the instance name
__in_z PCWSTR pInstanceName,
// I reserved for the future use. Currently should be set to 0.
__in DWORD dwFlags,
// O the buffer to store the connection string to the LocalDB instance
__out_ecount_z_opt(*lpcchSqlConnection) LPWSTR wszSqlConnection,
// I/O on input has the size of the wszSqlConnection buffer in characters. On output, if the given buffer size is
// too small, has the buffer size required, in characters, including trailing null.
__inout_opt LPDWORD lpcchSqlConnection
)
// I the instance name
_In_z_ PCWSTR pInstanceName,
// I reserved for the future use. Currently should be set to 0.
_In_ DWORD dwFlags,
// O the buffer to store the connection string to the LocalDB instance
_Out_writes_z__opt(*lpcchSqlConnection) LPWSTR wszSqlConnection,
// I/O on input has the size of the wszSqlConnection buffer in characters. On output, if the given buffer size is
// too small, has the buffer size required, in characters, including trailing null.
_Inout_opt_ LPDWORD lpcchSqlConnection
)
{
LOCALDB_PROXY(LocalDBStartInstance)(pInstanceName, dwFlags, wszSqlConnection, lpcchSqlConnection);
LOCALDB_PROXY(LocalDBStartInstance)(pInstanceName, dwFlags, wszSqlConnection, lpcchSqlConnection);
}
HRESULT __cdecl
LocalDBStopInstance(
// I the instance name
__in_z PCWSTR pInstanceName,
// I Available flags:
// LOCALDB_SHUTDOWN_KILL_PROCESS - force the instance to stop immediately
// LOCALDB_SHUTDOWN_WITH_NOWAIT - shutdown the instance with NOWAIT option
__in DWORD dwFlags,
// I the time in seconds to wait this operation to complete. If this value is 0, this function will return immediately
// without waiting for LocalDB instance to stop
__in ULONG ulTimeout
)
LocalDBStopInstance (
// I the instance name
_In_z_ PCWSTR pInstanceName,
// I Available flags:
// LOCALDB_SHUTDOWN_KILL_PROCESS - force the instance to stop immediately
// LOCALDB_SHUTDOWN_WITH_NOWAIT - shutdown the instance with NOWAIT option
_In_ DWORD dwFlags,
// I the time in seconds to wait this operation to complete. If this value is 0, this function will return immediately
// without waiting for LocalDB instance to stop
_In_ ULONG ulTimeout
)
{
LOCALDB_PROXY(LocalDBStopInstance)(pInstanceName, dwFlags, ulTimeout);
LOCALDB_PROXY(LocalDBStopInstance)(pInstanceName, dwFlags, ulTimeout);
}
HRESULT __cdecl
LocalDBDeleteInstance(
// I the instance name
__in_z PCWSTR pInstanceName,
// reserved for the future use. Currently should be set to 0.
__in DWORD dwFlags
)
LocalDBDeleteInstance (
// I the instance name
_In_z_ PCWSTR pInstanceName,
// reserved for the future use. Currently should be set to 0.
_In_ DWORD dwFlags
)
{
LOCALDB_PROXY(LocalDBDeleteInstance)(pInstanceName, dwFlags);
LOCALDB_PROXY(LocalDBDeleteInstance)(pInstanceName, dwFlags);
}
HRESULT __cdecl
LocalDBFormatMessage(
// I the LocalDB error code
__in HRESULT hrLocalDB,
// I Available flags:
// LOCALDB_TRUNCATE_ERR_MESSAGE - if the input buffer is too short,
// the error message will be truncated to fit into the buffer
__in DWORD dwFlags,
// I Language desired (LCID) or 0 (in which case Win32 FormatMessage order is used)
__in DWORD dwLanguageId,
// O the buffer to store the LocalDB error message
__out_ecount_z(*lpcchMessage) LPWSTR wszMessage,
// I/O on input has the size of the wszMessage buffer in characters. On output, if the given buffer size is
// too small, has the buffer size required, in characters, including trailing null. If the function succeeds
// contains the number of characters in the message, excluding the trailing null
__inout LPDWORD lpcchMessage
)
// I the LocalDB error code
_In_ HRESULT hrLocalDB,
// I Available flags:
// LOCALDB_TRUNCATE_ERR_MESSAGE - if the input buffer is too short,
// the error message will be truncated to fit into the buffer
_In_ DWORD dwFlags,
// I Language desired (LCID) or 0 (in which case Win32 FormatMessage order is used)
_In_ DWORD dwLanguageId,
// O the buffer to store the LocalDB error message
_Out_writes_z_(*lpcchMessage) LPWSTR wszMessage,
// I/O on input has the size of the wszMessage buffer in characters. On output, if the given buffer size is
// too small, has the buffer size required, in characters, including trailing null. If the function succeeds
// contains the number of characters in the message, excluding the trailing null
_Inout_ LPDWORD lpcchMessage
)
{
LOCALDB_PROXY(LocalDBFormatMessage)(hrLocalDB, dwFlags, dwLanguageId, wszMessage, lpcchMessage);
LOCALDB_PROXY(LocalDBFormatMessage)(hrLocalDB, dwFlags, dwLanguageId, wszMessage, lpcchMessage);
}
HRESULT __cdecl
LocalDBGetInstances(
// O buffer with instance names
__out PTLocalDBInstanceName pInstanceNames,
// I/O on input has the number slots for instance names in the pInstanceNames buffer. On output,
// has the number of existing LocalDB instances
__inout LPDWORD lpdwNumberOfInstances
)
// O buffer with instance names
_Out_ PTLocalDBInstanceName pInstanceNames,
// I/O on input has the number slots for instance names in the pInstanceNames buffer. On output,
// has the number of existing LocalDB instances
_Inout_ LPDWORD lpdwNumberOfInstances
)
{
LOCALDB_PROXY(LocalDBGetInstances)(pInstanceNames, lpdwNumberOfInstances);
LOCALDB_PROXY(LocalDBGetInstances)(pInstanceNames, lpdwNumberOfInstances);
}
HRESULT __cdecl
LocalDBGetInstanceInfo(
// I the instance name
__in_z PCWSTR wszInstanceName,
// O instance information
__out PLocalDBInstanceInfo pInfo,
// I Size of LocalDBInstanceInfo structure in bytes
__in DWORD cbInfo
)
// I the instance name
_In_z_ PCWSTR wszInstanceName,
// O instance information
_Out_ PLocalDBInstanceInfo pInfo,
// I Size of LocalDBInstanceInfo structure in bytes
_In_ DWORD cbInfo
)
{
LOCALDB_PROXY(LocalDBGetInstanceInfo)(wszInstanceName, pInfo, cbInfo);
LOCALDB_PROXY(LocalDBGetInstanceInfo)(wszInstanceName, pInfo, cbInfo);
}
HRESULT __cdecl
LocalDBStartTracing()
{
LOCALDB_PROXY(LocalDBStartTracing)();
LOCALDB_PROXY(LocalDBStartTracing)();
}
HRESULT __cdecl
LocalDBStopTracing()
{
LOCALDB_PROXY(LocalDBStopTracing)();
LOCALDB_PROXY(LocalDBStopTracing)();
}
HRESULT __cdecl
HRESULT __cdecl
LocalDBShareInstance(
// I the SID of the LocalDB instance owner
__in_opt PSID pOwnerSID,
// I the private name of LocalDB instance which should be shared
__in_z PCWSTR wszLocalDBInstancePrivateName,
// I the public shared name
__in_z PCWSTR wszSharedName,
// I reserved for the future use. Currently should be set to 0.
__in DWORD dwFlags)
// I the SID of the LocalDB instance owner
_In_opt_ PSID pOwnerSID,
// I the private name of LocalDB instance which should be shared
_In_z_ PCWSTR wszLocalDBInstancePrivateName,
// I the public shared name
_In_z_ PCWSTR wszSharedName,
// I reserved for the future use. Currently should be set to 0.
_In_ DWORD dwFlags)
{
LOCALDB_PROXY(LocalDBShareInstance)(pOwnerSID, wszLocalDBInstancePrivateName, wszSharedName, dwFlags);
LOCALDB_PROXY(LocalDBShareInstance)(pOwnerSID, wszLocalDBInstancePrivateName, wszSharedName, dwFlags);
}
HRESULT __cdecl
LocalDBGetVersions(
// O buffer for installed LocalDB versions
__out PTLocalDBVersion pVersions,
// I/O on input has the number slots for versions in the pVersions buffer. On output,
// has the number of existing LocalDB versions
__inout LPDWORD lpdwNumberOfVersions
)
// O buffer for installed LocalDB versions
_Out_ PTLocalDBVersion pVersions,
// I/O on input has the number slots for versions in the pVersions buffer. On output,
// has the number of existing LocalDB versions
_Inout_ LPDWORD lpdwNumberOfVersions
)
{
LOCALDB_PROXY(LocalDBGetVersions)(pVersions, lpdwNumberOfVersions);
LOCALDB_PROXY(LocalDBGetVersions)(pVersions, lpdwNumberOfVersions);
}
HRESULT __cdecl
LocalDBUnshareInstance(
// I the LocalDB instance name
__in_z PCWSTR pInstanceName,
// I reserved for the future use. Currently should be set to 0.
__in DWORD dwFlags)
// I the LocalDB instance name
_In_z_ PCWSTR pInstanceName,
// I reserved for the future use. Currently should be set to 0.
_In_ DWORD dwFlags)
{
LOCALDB_PROXY(LocalDBUnshareInstance)(pInstanceName, dwFlags);
LOCALDB_PROXY(LocalDBUnshareInstance)(pInstanceName, dwFlags);
}
HRESULT __cdecl
HRESULT __cdecl
LocalDBGetVersionInfo(
// I LocalDB version string
__in_z PCWSTR wszVersion,
// O version information
__out PLocalDBVersionInfo pVersionInfo,
// I Size of LocalDBVersionInfo structure in bytes
__in DWORD cbVersionInfo)
// I LocalDB version string
_In_z_ PCWSTR wszVersion,
// O version information
_Out_ PLocalDBVersionInfo pVersionInfo,
// I Size of LocalDBVersionInfo structure in bytes
_In_ DWORD cbVersionInfo)
{
LOCALDB_PROXY(LocalDBGetVersionInfo)(wszVersion, pVersionInfo, cbVersionInfo);
LOCALDB_PROXY(LocalDBGetVersionInfo)(wszVersion, pVersionInfo, cbVersionInfo);
}
#endif
@ -2271,7 +2173,7 @@ LocalDBGetVersionInfo(
//
#define LOCALDB_ERROR_CANNOT_LOAD_RESOURCES ((HRESULT)0x89C50121L)
// Detailed error descriptions
// Detailed error descriptions
//
// MessageId: LOCALDB_EDETAIL_DATADIRECTORY_IS_MISSING
//

View file

@ -368,13 +368,13 @@ PHP_FUNCTION(sqlsrv_errors);
// 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 mbcs_len, _Out_ wchar_t* utf16_out_string,
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.
wchar_t* utf16_string_from_mbcs_string( unsigned int php_encoding, const char* mbcs_string,
unsigned int mbcs_len, __out unsigned int* utf16_len );
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,
@ -604,7 +604,7 @@ namespace ss {
}
};
inline void zend_register_resource(__out zval& rsrc_result, void* rsrc_pointer, int rsrc_type, char* rsrc_name TSRMLS_DC)
inline void zend_register_resource(_Out_ zval& rsrc_result, void* rsrc_pointer, int rsrc_type, 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,

View file

@ -90,21 +90,21 @@ const char SS_SQLSRV_WARNING_PARAM_VAR_NOT_REF[] = "Variable parameter %d not pa
void convert_to_zval( sqlsrv_stmt* stmt, SQLSRV_PHPTYPE sqlsrv_php_type, void* in_val, SQLLEN field_len, 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, zend_long fetch_type, _Out_ zval& fields, 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,
__out SQLSMALLINT* decimal_digits );
bool determine_column_size_or_precision( sqlsrv_stmt const* stmt, sqlsrv_sqltype sqlsrv_type, _Out_ 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,
__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 parse_param_array( 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 );
bool verify_and_set_encoding( const char* encoding_string, _Out_ sqlsrv_phptype& phptype_encoding TSRMLS_DC );
}
@ -812,8 +812,9 @@ PHP_FUNCTION( sqlsrv_fetch_object )
// find the zend_class_entry of the class the user requested (stdClass by default) for use below
zend_class_entry* class_entry = NULL;
zend_string* class_name_str_z = zend_string_init(class_name, class_name_len, 0);
int zr = (NULL != (class_entry = zend_lookup_class(class_name_str_z TSRMLS_CC))) ? SUCCESS : FAILURE;
zend_string* class_name_str_z = zend_string_init( class_name, class_name_len, 0 );
int zr = ( NULL != ( class_entry = zend_lookup_class( class_name_str_z TSRMLS_CC ))) ? SUCCESS : FAILURE;
zend_string_release( class_name_str_z );
CHECK_ZEND_ERROR( zr, stmt, SS_SQLSRV_ERROR_ZEND_BAD_CLASS, class_name ) {
throw ss::SSException();
}
@ -831,6 +832,8 @@ PHP_FUNCTION( sqlsrv_fetch_object )
// default parameters directly in the object, meaning the default property value is changed when
// the object's property is changed.
zend_merge_properties( &retval_z, properties_ht TSRMLS_CC );
zend_hash_destroy( properties_ht );
FREE_HASHTABLE( properties_ht );
// find and call the object's constructor
@ -876,8 +879,8 @@ PHP_FUNCTION( sqlsrv_fetch_object )
memset( &fci, 0, sizeof( fci ));
fci.size = sizeof( fci );
fci.function_table = &(class_entry)->function_table;
ZVAL_UNDEF( &(fci.function_name) );
fci.function_table = &( class_entry )->function_table;
ZVAL_UNDEF( &( fci.function_name ) );
fci.retval = &ctor_retval_z;
fci.param_count = num_params;
fci.params = params_m; // purposefully not transferred since ownership isn't actually transferred.
@ -907,6 +910,10 @@ PHP_FUNCTION( sqlsrv_fetch_object )
zend_hash_destroy( properties_ht );
FREE_HASHTABLE( properties_ht );
}
else if ( Z_TYPE( retval_z ) == IS_ARRAY ) {
zend_hash_destroy( Z_ARRVAL( retval_z ));
FREE_HASHTABLE( Z_ARRVAL( retval_z ));
}
RETURN_FALSE;
}
@ -1277,6 +1284,7 @@ void bind_params( ss_sqlsrv_stmt* stmt TSRMLS_DC )
catch( core::CoreException& ) {
SQLFreeStmt( stmt->handle(), SQL_RESET_PARAMS );
zval_ptr_dtor( stmt->params_z );
sqlsrv_free( stmt->params_z );
stmt->params_z = NULL;
throw;
}
@ -1536,8 +1544,8 @@ 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
bool determine_column_size_or_precision( sqlsrv_stmt const* stmt, sqlsrv_sqltype sqlsrv_type, __out SQLULEN* column_size,
__out SQLSMALLINT* decimal_digits )
bool determine_column_size_or_precision( sqlsrv_stmt const* stmt, sqlsrv_sqltype sqlsrv_type, _Out_ SQLULEN* column_size,
_Out_ SQLSMALLINT* decimal_digits )
{
*decimal_digits = 0;
@ -1785,7 +1793,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, zend_long fetch_type, _Out_ zval& fields, bool allow_empty_field_names
TSRMLS_DC )
{
void* field_value = NULL;
@ -1815,7 +1823,7 @@ void fetch_fields_common( __inout ss_sqlsrv_stmt* stmt, zend_long fetch_type, __
core::SQLColAttribute(stmt, i + 1, SQL_DESC_NAME, field_name_temp, SS_MAXCOLNAMELEN + 1, &field_name_len, NULL
TSRMLS_CC);
field_names[i].name = static_cast<char*>( sqlsrv_malloc( field_name_len, sizeof(char), 1 ));
memcpy(( void* )field_names[i].name, field_name_temp, field_name_len);
memcpy_s(( void* )field_names[i].name, ( field_name_len * sizeof( char )) ,field_name_temp, field_name_len);
field_names[i].name[field_name_len] = '\0'; // null terminate the field name since SQLColAttribute doesn't.
field_names[i].len = field_name_len + 1;
}
@ -1864,7 +1872,7 @@ void fetch_fields_common( __inout ss_sqlsrv_stmt* stmt, zend_long fetch_type, __
}
}
//only addref when the fetch_type is BOTH because this is the only case when fields(hashtable)
//has 2 elements pointing to field. Do not addref if the type is NUMBERIC or ASSOC because
//has 2 elements pointing to field. Do not addref if the type is NUMERIC or ASSOC because
//fields now only has 1 element pointing to field and we want the ref count to be only 1
if (fetch_type == SQLSRV_FETCH_BOTH) {
Z_TRY_ADDREF(field);
@ -1873,9 +1881,9 @@ void fetch_fields_common( __inout ss_sqlsrv_stmt* stmt, zend_long fetch_type, __
}
void parse_param_array( 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 parse_param_array( 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 )
{
zval* var_or_val = NULL;
@ -2109,7 +2117,7 @@ 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( const char* encoding_string, _Out_ sqlsrv_phptype& phptype_encoding TSRMLS_DC )
{
void* encoding_temp = NULL;
zend_ulong index = -1;

View file

@ -43,7 +43,7 @@ bool handle_errors_and_warnings( sqlsrv_context& ctx, zval* reported_chain, zval
unsigned int sqlsrv_error_code, bool warning, va_list* print_args TSRMLS_DC );
int sqlsrv_merge_zend_hash_dtor( zval* dest TSRMLS_DC );
bool sqlsrv_merge_zend_hash( __inout zval* dest_z, zval const* src_z TSRMLS_DC );
bool sqlsrv_merge_zend_hash( _Inout_ zval* dest_z, zval const* src_z TSRMLS_DC );
}
@ -300,8 +300,8 @@ ss_error SS_ERRORS[] = {
{
SQLSRV_ERROR_DRIVER_NOT_INSTALLED,
{ IMSSP, (SQLCHAR*) "This extension requires the Microsoft ODBC Driver 11 for SQL Server. "
"Access the following URL to download the ODBC Driver 11 for SQL Server for %1!s!: "
{ IMSSP, (SQLCHAR*) "This extension requires the Microsoft ODBC Driver 11 or 13 for SQL Server. "
"Access the following URL to download the ODBC Driver 11 or 13 for SQL Server for %1!s!: "
"http://go.microsoft.com/fwlink/?LinkId=163712", -49, true }
},
@ -478,18 +478,18 @@ PHP_FUNCTION( sqlsrv_errors )
}
if( flags == SQLSRV_ERR_ALL || flags == SQLSRV_ERR_ERRORS ) {
if( Z_TYPE( SQLSRV_G( errors )) == IS_ARRAY && !sqlsrv_merge_zend_hash( &err_z, &SQLSRV_G( errors ) TSRMLS_CC )) {
zval_ptr_dtor(&err_z);
RETURN_FALSE;
}
}
if( flags == SQLSRV_ERR_ALL || flags == SQLSRV_ERR_WARNINGS ) {
if( Z_TYPE( SQLSRV_G( warnings )) == IS_ARRAY && !sqlsrv_merge_zend_hash( &err_z, &SQLSRV_G( warnings ) TSRMLS_CC )) {
zval_ptr_dtor(&err_z);
RETURN_FALSE;
}
}
if( zend_hash_num_elements( Z_ARRVAL_P( &err_z )) == 0 ) {
zval_ptr_dtor(&err_z);
RETURN_NULL();
}
RETURN_ZVAL( &err_z, 1, 1 );
@ -888,7 +888,7 @@ int sqlsrv_merge_zend_hash_dtor( zval* dest TSRMLS_DC )
// sqlsrv_merge_zend_hash
// merge a source hash into a dest hash table and return any errors.
bool sqlsrv_merge_zend_hash( __inout zval* dest_z, zval const* src_z TSRMLS_DC )
bool sqlsrv_merge_zend_hash( _Inout_ zval* dest_z, zval const* src_z TSRMLS_DC )
{
if( Z_TYPE_P( dest_z ) != IS_ARRAY && Z_TYPE_P( dest_z ) != IS_NULL ) DIE( "dest_z must be an array or null" );
if( Z_TYPE_P( src_z ) != IS_ARRAY && Z_TYPE_P( src_z ) != IS_NULL ) DIE( "src_z must be an array or null" );