InitializeOdbcConnectParams

Allocate and initialize a new ODBC_CONNECT_PARAMS instance

Overview

InitializeOdbcConnectParams allocates and initializes a new ODBC_CONNECT_PARAMS instance: it zeroes all public fields, wires up the AddParam (AddOdbcParamter) and ClearParams (OdbcClearParamsImpl) function pointers, and sets all tri-state fields (Trusted_Connection, Encrypt, MARS_Connection, ColumnEncryption) to ODBC_UNSPECIFIED.

Purpose

This is the only supported way to obtain an ODBC_CONNECT_PARAMS instance. The public struct is always the first member of a larger, private internal struct maintained exclusively inside odbc.c; allocating or declaring the public struct directly (e.g. via sizeof(ODBC_CONNECT_PARAMS)) undersizes the allocation and corrupts memory the moment AddParam() is called. See ODBC_CONNECT_PARAMS for the members.

Key Features

Function Signature


HRESULT _Must_inspect_result_ _Success_(SUCCEEDED(return)) InitializeOdbcConnectParams(
    _Outptr_ PODBC_CONNECT_PARAMS * ppParams
);

Parameters

ppParams

[Out] PODBC_CONNECT_PARAMS *

Address of a PODBC_CONNECT_PARAMS pointer that receives the newly allocated instance on success. Must not be NULL. *ppParams is set to NULL on entry and on failure.

Initialize the local pointer to NULL before calling. The caller owns the returned instance and must release it exactly once with FreeOdbcConnectParams; do not use free() or delete.

Return Values

ValueMeaning
S_OK*ppParams receives a valid, ready-to-use instance.
HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER)ppParams is NULL.
HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY)Allocation of the internal structure failed.

Notes

Release the returned instance exclusively with FreeOdbcConnectParams(). Never call free()/delete directly on it.
Never declare an ODBC_CONNECT_PARAMS on the stack or with malloc(sizeof(ODBC_CONNECT_PARAMS)) — this allocates storage for only the public-view fields, which is smaller than the real internal allocation the library expects, causing a heap buffer overrun the first time AddParam() is invoked.

Remarks

Thread Safety

The instance is a plain parameter bag with no internal locking described. Build and use one instance from a single thread at a time; use a separate instance per thread if needed.

Ownership and Lifetime

Each successful call must be paired with exactly one FreeOdbcConnectParams call. ConnectDateLogHandleToOdbcDatabase consumes the connection-string parameters without retaining the pParams pointer, so the instance can be freed right after connecting (the caller remains responsible for freeing it).

Ordering

InitializeOdbcConnectParams
→
AddParam / set tri-state fields
→
ConnectDateLogHandleToOdbcDatabase
→
FreeOdbcConnectParams
The ODBC_CONNECT_PARAMS page documents AddParam(pParams, LPCSTR key, LPCSTR value) and uses FreeOdbcConnectParams(&pParams), whereas AddOdbcParamter and FreeOdbcConnectParams document a handle-based eight-argument form and a PODBC_CONNECT_PARAMS (not pointer-to-pointer) argument. The sample below follows the function signature pages for Free and the structure page for AddParam.

See Also

Sample Code


#include <stdio.h>
#include <Windows.h>
#include "datelog.h"

int main(void)
{
    HRESULT hr = E_FAIL;
    HOLIDAYS_HANDLE hHolidays = NULL;
    DATE_LOG_HANDLE hDateLog = NULL;
    PODBC_CONNECT_PARAMS pParams = NULL;
    int exitCode = 1;

    /* A holidays handle is created with HandleIsForHolidays; hHolidays must be NULL for that type. */
    hr = InitializeDateLogHandle(NULL, DATE_LOG_MAX, NULL, &hHolidays, HandleIsForHolidays);
    if (FAILED(hr)) {
        printf("Holidays handle creation failed: 0x%08lX\n", (unsigned long)hr);
        goto cleanup;
    }

    /* The date log duplicates hHolidays internally; the caller still owns hHolidays. */
    hr = InitializeDateLogHandle(NULL, DATE_LOG_MAX, hHolidays, &hDateLog, HandleIsForDatelog);
    if (FAILED(hr)) {
        printf("Date log creation failed: 0x%08lX\n", (unsigned long)hr);
        goto cleanup;
    }

    hr = InitializeDateLogHandleOdbc(hDateLog, DATE_LOG_ODBC_1);
    if (FAILED(hr)) {
        printf("Reserving ODBC level 1 failed: 0x%08lX\n", (unsigned long)hr);
        goto cleanup;
    }

    /* pParams is NULL before the call; the library allocates the full internal structure. */
    hr = InitializeOdbcConnectParams(&pParams);
    if (FAILED(hr)) {
        printf("Creating ODBC parameters failed: 0x%08lX\n", (unsigned long)hr);
        goto cleanup;
    }

    printf("Initial state: ParamCount=%lu, Encrypt=%s\n",
           pParams->ParamCount, pParams->Encrypt == ODBC_UNSPECIFIED ? "unspecified" : "set");

    hr = pParams->AddParam(pParams, "Driver", "{ODBC Driver 17 for SQL Server}");
    if (SUCCEEDED(hr)) {
        hr = pParams->AddParam(pParams, "Server", "localhost\\SQLEXPRESS");
    }
    if (SUCCEEDED(hr)) {
        hr = pParams->AddParam(pParams, "Database", "MarketDates");
    }
    if (FAILED(hr)) {
        printf("Adding an ODBC parameter failed: 0x%08lX\n", (unsigned long)hr);
        goto cleanup;
    }

    pParams->Trusted_Connection = ODBC_TRUE;
    pParams->Encrypt = ODBC_TRUE;
    pParams->MARS_Connection = ODBC_FALSE;
    printf("ParamCount after adding: %lu\n", pParams->ParamCount);

    hr = ConnectDateLogHandleToOdbcDatabase(hDateLog, pParams, DATE_LOG_ODBC_1);
    if (FAILED(hr)) {
        printf("Connecting failed: 0x%08lX\n", (unsigned long)hr);
        goto cleanup;
    }

    /* The connection is owned by hDateLog; the parameter bag is freed by the caller. */
    FreeOdbcConnectParams(pParams);
    pParams = NULL;

    exitCode = 0;

cleanup:
    if (pParams != NULL) {
        FreeOdbcConnectParams(pParams);
    }
    /* Closing the date log also releases the ODBC connections it owns. */
    if (hDateLog != NULL) {
        CloseDateLogHandle(hDateLog);
    }
    if (hHolidays != NULL) {
        CloseDateLogHandle(hHolidays);
    }
    return exitCode;
}