Exemplo n.º 1
0
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;
}
Exemplo n.º 2
0
// 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 );
}
Exemplo n.º 3
0
// format and return a driver specfic error
void core_sqlsrv_format_driver_error( sqlsrv_context& ctx, sqlsrv_error_const const* custom_error, 
                                      sqlsrv_error_auto_ptr& formatted_error, logging_severity severity TSRMLS_DC, va_list* args )
{
    // allocate space for the formatted message
    formatted_error = new (sqlsrv_malloc( sizeof( sqlsrv_error ))) sqlsrv_error();
    formatted_error->sqlstate = reinterpret_cast<SQLCHAR*>( sqlsrv_malloc( SQL_SQLSTATE_BUFSIZE ));
    formatted_error->native_message = reinterpret_cast<SQLCHAR*>( sqlsrv_malloc( SQL_MAX_MESSAGE_LENGTH + 1 ));

    DWORD rc = FormatMessage( FORMAT_MESSAGE_FROM_STRING, reinterpret_cast<LPSTR>( custom_error->native_message ), 0, 0, 
                              reinterpret_cast<LPSTR>( formatted_error->native_message ), SQL_MAX_MESSAGE_LENGTH, args );
    if( rc == 0 ) {
        strcpy_s( reinterpret_cast<char*>( formatted_error->native_message ), SQL_MAX_MESSAGE_LENGTH,
                  reinterpret_cast<char*>( INTERNAL_FORMAT_ERROR ));
    }
    
    strcpy_s( reinterpret_cast<char*>( formatted_error->sqlstate ), SQL_SQLSTATE_BUFSIZE,
              reinterpret_cast<char*>( custom_error->sqlstate ));
    formatted_error->native_code = custom_error->native_code;

    // log the error
    LOG( severity, "%1!s!: SQLSTATE = %2!s!", ctx.func(), formatted_error->sqlstate );
    LOG( severity, "%1!s!: error code = %2!d!", ctx.func(), formatted_error->native_code );
    LOG( severity, "%1!s!: message = %2!s!", ctx.func(), formatted_error->native_message );
}
Exemplo n.º 4
0
// 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;
}
Exemplo n.º 5
0
// Validate a given DSN keyword.
void conn_string_parser::validate_key(const char *key, int key_len TSRMLS_DC )
{
    int new_len = discard_trailing_white_spaces( key, key_len );

    for( int i=0; PDO_CONN_OPTS[ i ].conn_option_key != SQLSRV_CONN_OPTION_INVALID; ++i )
    {
        // discard the null terminator.
        if( new_len == ( PDO_CONN_OPTS[ i ].sqlsrv_len - 1 ) && !_strnicmp( key, PDO_CONN_OPTS[ i ].sqlsrv_name, new_len )) {

            this->current_key = PDO_CONN_OPTS[ i ].conn_option_key;
            this->current_key_name = PDO_CONN_OPTS[ i ].sqlsrv_name;
            return;
        }
    }

    // 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 );
    key_name[ new_len ] = '\0';  

    THROW_PDO_ERROR( this->ctx, PDO_SQLSRV_ERROR_INVALID_DSN_KEY, key_name ); 
}
Exemplo n.º 6
0
bool core_sqlsrv_get_odbc_error( sqlsrv_context& ctx, int record_number, sqlsrv_error_auto_ptr& error, logging_severity severity 
                                 TSRMLS_DC )
{
    SQLHANDLE h = ctx.handle();
    SQLSMALLINT h_type = ctx.handle_type();

    if( h == NULL ) {
        return false;
    }

    zval* ssphp_z = NULL;
    int zr = SUCCESS;
    zval* temp = NULL;
    SQLRETURN r = SQL_SUCCESS;
    SQLSMALLINT wmessage_len = 0;
    SQLWCHAR wsqlstate[ SQL_SQLSTATE_BUFSIZE ];
    SQLWCHAR wnative_message[ SQL_MAX_MESSAGE_LENGTH + 1 ];
    SQLSRV_ENCODING enc = ctx.encoding();

    switch( h_type ) {

        case SQL_HANDLE_STMT:
            {
                sqlsrv_stmt* stmt = static_cast<sqlsrv_stmt*>( &ctx );
                if( stmt->current_results != NULL ) {

                    error = stmt->current_results->get_diag_rec( record_number );
                    // don't use the CHECK* macros here since it will trigger reentry into the error handling system
                    if( error == NULL ) {
                        return false;
                    }
                    break;
                }

                // convert the error into the encoding of the context
                if( enc == SQLSRV_ENCODING_DEFAULT ) {
                    enc = stmt->conn->encoding();
                }
            }


        default:

            error = new ( sqlsrv_malloc( sizeof( sqlsrv_error ))) sqlsrv_error();
            r = SQLGetDiagRecW( h_type, h, record_number, wsqlstate, &error->native_code, wnative_message,
                                SQL_MAX_MESSAGE_LENGTH + 1, &wmessage_len );
            // don't use the CHECK* macros here since it will trigger reentry into the error handling system
            if( !SQL_SUCCEEDED( r ) || r == SQL_NO_DATA ) {
                return false;
            }

            SQLINTEGER sqlstate_len = 0;
            convert_string_from_utf16(enc, wsqlstate, sizeof(wsqlstate), (char**)&error->sqlstate, sqlstate_len);

            SQLINTEGER message_len = 0;
            convert_string_from_utf16(enc, wnative_message, wmessage_len, (char**)&error->native_message, message_len);
            break;
    }


    // log the error first
    LOG( severity, "%1!s!: SQLSTATE = %2!s!", ctx.func(), error->sqlstate );
    LOG( severity, "%1!s!: error code = %2!d!", ctx.func(), error->native_code );
    LOG( severity, "%1!s!: message = %2!s!", ctx.func(), error->native_message );

    error->format = false;

    return true;
}