Release an ODBC_CONNECT_PARAMS instance and its internal parameter list
FreeOdbcConnectParams releases a PODBC_CONNECT_PARAMS instance previously
returned by InitializeOdbcConnectParams(). It clears the public bPromptIfIncomplete,
AddParam, and ClearParams fields, then frees the underlying allocation (recovered by
up-casting the public view back to its internal superset struct, which is valid because the public struct is
always the first member).
ODBC_CONNECT_PARAMS is the end-user-facing parameter bag used to build a connection string before
connecting. Because the public structure is only the first member of a larger private structure, it cannot be
released with free(); this function is the only supported way to tear it down, including its
internal SLIST-backed parameter storage.
ERROR_INVALID_PARAMETER
HRESULT _Success_(SUCCEEDED(return)) FreeOdbcConnectParams(
_In_ _Post_invalid_ PODBC_CONNECT_PARAMS pParams
);
[In, Post-invalid] PODBC_CONNECT_PARAMS
The instance to free, obtained from InitializeOdbcConnectParams().
PODBC_CONNECT_PARAMS), not the address of a pointer.HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER).InitializeOdbcConnectParams(). Do not pass a stack-declared or malloced ODBC_CONNECT_PARAMS._Post_invalid_) and must not be used or freed again; set your variable to NULL afterwards.Check the result with FAILED/SUCCEEDED.
| Return value | Meaning |
|---|---|
S_OK | Instance released successfully. |
HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER) | pParams is NULL. |
The function clears bPromptIfIncomplete, AddParam, and ClearParams, then frees the allocation obtained from InitializeOdbcConnectParams() after recovering the internal superset structure from the public view.
ODBC_CONNECT_PARAMS object itself (the end-user-facing parameter bag used to build a connection string before connecting). It is distinct from the connection's own internal parameter list, which is released as part of FreeOdbcConnectionContext().InitializeOdbcConnectParams() with exactly one call to FreeOdbcConnectParams() to avoid leaking the internal SLIST-backed parameter storage.ConnectDateLogHandleToOdbcDatabase() consumes the parameters without retaining pParams, so the object can be freed as soon as that call returns (and the caller remains responsible for freeing it, whether or not the connection succeeded). Closing the date log handle does not free it.AddParam).DATE_LOG_HANDLE.InitializeOdbcConnectParams() → add parameters → use (ConnectDateLogHandleToOdbcDatabase()) → FreeOdbcConnectParams().&pParams. The overview above
mentions a public bPromptIfIncomplete field, which the structure page does not list among the public members.
#include <Windows.h>
#include <stdio.h>
#include "datelog.h"
static BOOL MakeFiletime(WORD wYear, WORD wMonth, WORD wDay, PFILETIME pFiletime)
{
SYSTEMTIME st = { 0 };
st.wYear = wYear;
st.wMonth = wMonth;
st.wDay = wDay;
return SystemTimeToFileTime(&st, pFiletime);
}
int main(void)
{
HOLIDAYS_HANDLE hHolidays = NULL;
DATE_LOG_HANDLE hDateLog = NULL;
DATE_ITEM_HANDLE hStart = NULL;
DATE_ITEM_HANDLE hEnd = NULL;
FILETIME ftStart = { 0 };
FILETIME ftEnd = { 0 };
HRESULT hr = E_FAIL;
int exitCode = 1;
PODBC_CONNECT_PARAMS pParams = NULL;
hr = InitializeDateLogHandle(NULL, DATE_LOG_MAX, NULL, &hHolidays, HandleIsForHolidays);
if (FAILED(hr)) {
printf("InitializeDateLogHandle [holidays] failed: 0x%08lX\n", (unsigned long)hr);
goto cleanup;
}
hr = InitializeDateLogHandle(NULL, DATE_LOG_MAX, hHolidays, &hDateLog, HandleIsForDatelog);
if (FAILED(hr)) {
printf("InitializeDateLogHandle [date log] failed: 0x%08lX\n", (unsigned long)hr);
goto cleanup;
}
if (!MakeFiletime(2026, 1, 5, &ftStart) || !MakeFiletime(2026, 3, 31, &ftEnd)) {
printf("SystemTimeToFileTime failed: %lu\n", GetLastError());
goto cleanup;
}
/* Standalone date items; the caller owns them and frees them with FreeDateItem. */
hr = InitializeDateItem(hHolidays, &ftStart, NULL, &hStart);
if (FAILED(hr)) {
printf("InitializeDateItem [start] failed: 0x%08lX\n", (unsigned long)hr);
goto cleanup;
}
hr = InitializeDateItem(hHolidays, &ftEnd, NULL, &hEnd);
if (FAILED(hr)) {
printf("InitializeDateItem [end] failed: 0x%08lX\n", (unsigned long)hr);
goto cleanup;
}
/* The date log needs a reserved connection slot before it can be connected. */
hr = InitializeDateLogHandleOdbc(hDateLog, DATE_LOG_ODBC_1);
if (FAILED(hr)) {
printf("InitializeDateLogHandleOdbc failed: 0x%08lX\n", (unsigned long)hr);
goto cleanup;
}
hr = InitializeOdbcConnectParams(&pParams);
if (FAILED(hr)) {
printf("InitializeOdbcConnectParams failed: 0x%08lX\n", (unsigned long)hr);
goto cleanup;
}
/* Parameters are added through the AddParam function pointer on the instance. */
hr = pParams->AddParam(pParams, "Driver", "{ODBC Driver 17 for SQL Server}");
if (FAILED(hr)) {
printf("AddParam [Driver] failed: 0x%08lX\n", (unsigned long)hr);
goto cleanup;
}
hr = pParams->AddParam(pParams, "Server", "localhost\\SQLEXPRESS");
if (FAILED(hr)) {
printf("AddParam [Server] failed: 0x%08lX\n", (unsigned long)hr);
goto cleanup;
}
hr = pParams->AddParam(pParams, "Database", "DateDatabase");
if (FAILED(hr)) {
printf("AddParam [Database] failed: 0x%08lX\n", (unsigned long)hr);
goto cleanup;
}
hr = pParams->AddParam(pParams, "Trusted_Connection", "yes");
if (FAILED(hr)) {
printf("AddParam [Trusted_Connection] failed: 0x%08lX\n", (unsigned long)hr);
goto cleanup;
}
printf("Connection string holds %lu parameter(s).\n", (unsigned long)pParams->ParamCount);
/* The handle consumes the parameters without retaining pParams itself. */
hr = ConnectDateLogHandleToOdbcDatabase(hDateLog, pParams, DATE_LOG_ODBC_1);
if (FAILED(hr)) {
printf("ConnectDateLogHandleToOdbcDatabase failed: 0x%08lX\n", (unsigned long)hr);
goto cleanup;
}
/* Exactly one FreeOdbcConnectParams per successful InitializeOdbcConnectParams. */
hr = FreeOdbcConnectParams(pParams);
pParams = NULL;
if (FAILED(hr)) {
printf("FreeOdbcConnectParams failed: 0x%08lX\n", (unsigned long)hr);
goto cleanup;
}
printf("Connected; the parameter object has been released.\n");
exitCode = 0;
cleanup:
if (pParams != NULL) {
/* Failure paths that never reached the free above release the object here. */
hr = FreeOdbcConnectParams(pParams);
if (FAILED(hr)) {
printf("FreeOdbcConnectParams failed: 0x%08lX\n", (unsigned long)hr);
}
pParams = NULL;
}
FreeDateItem(hEnd);
FreeDateItem(hStart);
if (hDateLog != NULL) {
hr = CloseDateLogHandle(hDateLog);
if (FAILED(hr)) {
printf("CloseDateLogHandle [date log] failed: 0x%08lX\n", (unsigned long)hr);
}
}
if (hHolidays != NULL) {
hr = CloseDateLogHandle(hHolidays);
if (FAILED(hr)) {
printf("CloseDateLogHandle [holidays] failed: 0x%08lX\n", (unsigned long)hr);
}
}
return exitCode;
}