void sqlsrv_param_inout::process_string_param()

in source/shared/core_stmt.cpp [2701:2770]


void sqlsrv_param_inout::process_string_param(_Inout_ sqlsrv_stmt* stmt, _Inout_ zval* param_z)
{
    bool is_numeric_type = derive_string_types_sizes(param_z);

    buffer = Z_STRVAL_P(param_z);
    buffer_length = Z_STRLEN_P(param_z);

    if (ZSTR_IS_INTERNED(Z_STR_P(param_z))) {
        // PHP 5.4 added interned strings, and since we obviously want to change that string here in some fashion,
        // we reallocate the string if it's interned
        core::sqlsrv_zval_stringl(param_z, static_cast<const char*>(buffer), buffer_length);

        // reset buffer and its length
        buffer = Z_STRVAL_P(param_z);
        buffer_length = Z_STRLEN_P(param_z);
    }

    // If it's a UTF-8 input output parameter (signified by the C type being SQL_C_WCHAR)
    // or if the PHP type is a binary encoded string with a N(VAR)CHAR/NTEXT SQL type,
    // convert it to wchar first
    if (direction == SQL_PARAM_INPUT_OUTPUT &&
        (c_data_type == SQL_C_WCHAR ||
            (c_data_type == SQL_C_BINARY &&
                (sql_data_type == SQL_WCHAR || sql_data_type == SQL_WVARCHAR || sql_data_type == SQL_WLONGVARCHAR)))) {

        if (buffer_length > 0) {
            sqlsrv_malloc_auto_ptr<SQLWCHAR> wide_buffer;
            unsigned int wchar_size = 0;

            wide_buffer = utf16_string_from_mbcs_string(SQLSRV_ENCODING_UTF8, reinterpret_cast<const char*>(buffer), static_cast<int>(buffer_length), &wchar_size);
            CHECK_CUSTOM_ERROR(wide_buffer == 0, stmt, SQLSRV_ERROR_INPUT_PARAM_ENCODING_TRANSLATE, param_pos + 1, get_last_error_message()) {
                throw core::CoreException();
            }
            wide_buffer[wchar_size] = L'\0';
            core::sqlsrv_zval_stringl(param_z, reinterpret_cast<char*>(wide_buffer.get()), wchar_size * sizeof(SQLWCHAR));
            buffer = Z_STRVAL_P(param_z);
            buffer_length = Z_STRLEN_P(param_z);
        }
    } 

    strlen_or_indptr = buffer_length;

    // Since this is an output string, assure there is enough space to hold the requested size and
    // update all the variables accordingly (param_z, buffer, buffer_length, and strlen_or_indptr)
    resize_output_string_buffer(param_z, is_numeric_type);
    if (is_numeric_type) {
        encoding = SQLSRV_ENCODING_CHAR;
    }

    // For output parameters, if we set the column_size to be same as the buffer_len,
    // then if there is a truncation due to the data coming from the server being
    // greater than the column_size, we don't get any truncation error. In order to
    // avoid this silent truncation, we set the column_size to be "MAX" size for
    // string types. This will guarantee that there is no silent truncation for
    // output parameters.
    // if column encryption is enabled, at this point the correct column size has been set by SQLDescribeParam
    if (direction == SQL_PARAM_OUTPUT && !stmt->conn->ce_option.enabled) {

        switch (sql_data_type) {
        case SQL_VARBINARY:
        case SQL_VARCHAR:
        case SQL_WVARCHAR:
            column_size = SQL_SS_LENGTH_UNLIMITED;
            break;

        default:
            break;
        }
    }
}