// pdo error handler for the dbh context. bool pdo_sqlsrv_handle_dbh_error( sqlsrv_context& ctx, unsigned int sqlsrv_error_code, bool warning TSRMLS_DC, va_list* print_args ) { pdo_dbh_t* dbh = reinterpret_cast<pdo_dbh_t*>( ctx.driver()); SQLSRV_ASSERT( dbh != NULL, "pdo_sqlsrv_handle_dbh_error: Null dbh passed" ); sqlsrv_error_auto_ptr error; if( sqlsrv_error_code != SQLSRV_ERROR_ODBC ) { core_sqlsrv_format_driver_error( ctx, get_error_message( sqlsrv_error_code ), error, SEV_ERROR TSRMLS_CC, print_args ); } else { bool err = core_sqlsrv_get_odbc_error( ctx, 1, error, SEV_ERROR TSRMLS_CC ); SQLSRV_ASSERT( err == true, "No ODBC error was found" ); } SQLSRV_STATIC_ASSERT( sizeof( error->sqlstate ) <= sizeof( dbh->error_code )); strcpy_s( dbh->error_code, sizeof( dbh->error_code ), reinterpret_cast<const char*>( error->sqlstate )); switch( dbh->error_mode ) { case PDO_ERRMODE_EXCEPTION: if( !warning ) { pdo_sqlsrv_throw_exception( error TSRMLS_CC ); } ctx.set_last_error( error ); break; case PDO_ERRMODE_WARNING: if( !warning ) { unsigned int msg_len = strlen( reinterpret_cast<const char*>( error->native_message )) + SQL_SQLSTATE_BUFSIZE + MAX_DIGITS + 1; sqlsrv_malloc_auto_ptr<char> msg; msg = static_cast<char*>( sqlsrv_malloc( msg_len )); core_sqlsrv_format_message( msg, msg_len, WARNING_TEMPLATE, error->sqlstate, error->native_code, error->native_message ); php_error( E_WARNING, msg ); sqlsrv_free( msg ); } ctx.set_last_error( error ); break; case PDO_ERRMODE_SILENT: ctx.set_last_error( error ); break; default: DIE( "Unknown error mode. %1!d!", dbh->error_mode ); break; } // return error ignored = true for warnings. return ( warning ? true : false ); }
// thin wrapper around convert_string_from_default_encoding that handles // allocation of the destination string. An empty string passed in returns // failure since it's a failure case for convert_string_from_default_encoding. wchar_t* utf16_string_from_mbcs_string( SQLSRV_ENCODING php_encoding, const char* mbcs_string, unsigned int mbcs_len, unsigned int* utf16_len ) { *utf16_len = (mbcs_len + 1); wchar_t* utf16_string = reinterpret_cast<wchar_t*>( sqlsrv_malloc( *utf16_len * sizeof( wchar_t ))); *utf16_len = convert_string_from_default_encoding( php_encoding, mbcs_string, mbcs_len, utf16_string, *utf16_len ); if( *utf16_len == 0 ) { // we preserve the error and reset it because sqlsrv_free resets the last error DWORD last_error = GetLastError(); sqlsrv_free( utf16_string ); SetLastError( last_error ); return NULL; } return utf16_string; }
bool convert_string_from_utf16( SQLSRV_ENCODING encoding, const wchar_t* inString, SQLINTEGER cchInLen, char** outString, SQLINTEGER& cchOutLen ) { SQLSRV_ASSERT( inString != NULL, "Input string must be specified" ); SQLSRV_ASSERT( outString != NULL, "Output buffer pointer must be specified" ); SQLSRV_ASSERT( *outString == NULL, "Output buffer pointer must not be set" ); if (cchInLen == 0 && inString[0] == L'\0') { *outString = reinterpret_cast<char*>( sqlsrv_malloc ( 1 ) ); *outString[0] = '\0'; cchOutLen = 0; return true; } // flags set to 0 by default, which means that any invalid characters are dropped rather than causing // an error. This happens only on XP. DWORD flags = 0; if( encoding == CP_UTF8 && g_osversion.dwMajorVersion >= SQLSRV_OS_VISTA_OR_LATER ) { // Vista (and later) will detect invalid UTF-16 characters and raise an error. flags = WC_ERR_INVALID_CHARS; } // calculate the number of characters needed cchOutLen = WideCharToMultiByte( encoding, flags, inString, cchInLen, NULL, 0, NULL, NULL ); if( cchOutLen == 0 ) { return false; } // Create a buffer to fit the encoded string char* newString = reinterpret_cast<char*>( sqlsrv_malloc( cchOutLen + 1 /* NULL char*/ )); int rc = WideCharToMultiByte( encoding, flags, inString, cchInLen, newString, cchOutLen, NULL, NULL ); if( rc == 0 ) { cchOutLen = 0; sqlsrv_free( newString ); return false; } *outString = newString; newString[cchOutLen] = '\0'; // null terminate the encoded string return true; }
bool convert_string_from_utf16_inplace( SQLSRV_ENCODING encoding, char** string, SQLLEN& len) { SQLSRV_ASSERT( string != NULL && *string != NULL, "String must be specified" ); // for the empty string, we simply returned we converted it if( len == 0 && *string[0] == '\0' ) { return true; } char* outString = NULL; SQLINTEGER outLen = 0; bool result = convert_string_from_utf16( encoding, reinterpret_cast<const wchar_t*>(*string), len / sizeof(wchar_t), &outString, outLen); if (result) { sqlsrv_free( *string ); *string = outString; len = outLen; } return result; }