Initialize the ODBC connection internals / reserve a connection slot for a DATE_LOG_HANDLE
InitializeDateLogHandleOdbc lazily allocates the handle's ODBC connection internals (on the first call, OdbcLevel must be DATE_LOG_ODBC_1), then allocates a new connection node wrapping a freshly initialized connection context for the requested OdbcLevel and pushes it onto the handle's internal connection list. No database connection is opened yet.
Reserves one of up to four ODBC connection slots on a date log handle. It must be called once per OdbcLevel, in strictly increasing order (1, then 2, then 3, then 4), before ConnectDateLogHandleToOdbcDatabase can target that level. The slot can then be configured with AddOdbcParamter and SetDateLogOdbcConnectAttr.
HRESULT _Must_inspect_result_ _Success_(SUCCEEDED(return)) InitializeDateLogHandleOdbc(
_In_ DATE_LOG_HANDLE hDateLogHandle,
_In_ DATE_LOG_ODBC_LEVEL OdbcLevel
);
[In] DATE_LOG_HANDLE
Must be a DATE_LOG_HANDLE (dwMagic == __DATE_LOG_MAGIC__); other handle types are rejected. Create it with InitializeDateLogHandle using HandleIsForDatelog.
Must not be NULL. The handle is not closed by this function; the new connection slot is owned by the handle's shared context.
[In] DATE_LOG_ODBC_LEVEL
Must equal the current connection count + 1, i.e. sequential starting at DATE_LOG_ODBC_1. Valid values are DATE_LOG_ODBC_1 through DATE_LOG_ODBC_4 (the per-handle limit is 4 connections).
| Value | Meaning |
|---|---|
S_OK | The connection slot was reserved and initialized successfully. |
ERR_BAD_HANDLE_TYPE | hDateLogHandle is not a DATE_LOG_MAGIC handle. |
HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER) | OdbcLevel is out of range or is not the next sequential slot. |
HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY) | Allocation of the node or connection context failed. |
Slot reservation changes the shared context of the handle. Complete all InitializeDateLogHandleOdbc calls before other threads begin using the ODBC connections of the same context (including through handles created with DuplicateDateLogHandle).
ODBC connections belong to the shared context, not to an individual handle. They are released, together with their statements, when the last handle referencing the context is closed with CloseDateLogHandle. There is no separate function to release a reserved slot.
Calling a later level before the earlier ones, or the same level twice, fails with ERROR_INVALID_PARAMETER.
DATE_LOG_ODBC_LEVEL_READ_ONLY, which is not among the levels listed on the ODBC pages (DATE_LOG_ODBC_1..DATE_LOG_ODBC_4).
#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;
}
/* Reserve connection slots strictly in order: 1, then 2. */
hr = InitializeDateLogHandleOdbc(hDateLog, DATE_LOG_ODBC_1);
if (FAILED(hr)) {
printf("Reserving ODBC level 1 failed: 0x%08lX\n", (unsigned long)hr);
goto cleanup;
}
hr = InitializeDateLogHandleOdbc(hDateLog, DATE_LOG_ODBC_2);
if (FAILED(hr)) {
printf("Reserving ODBC level 2 failed: 0x%08lX\n", (unsigned long)hr);
goto cleanup;
}
/* Reserving level 2 again is not the next sequential slot and must fail. */
hr = InitializeDateLogHandleOdbc(hDateLog, DATE_LOG_ODBC_2);
if (FAILED(hr)) {
printf("Second reservation of level 2 rejected: 0x%08lX\n", (unsigned long)hr);
}
hr = InitializeOdbcConnectParams(&pParams);
if (FAILED(hr)) {
printf("Creating ODBC parameters failed: 0x%08lX\n", (unsigned long)hr);
goto cleanup;
}
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;
/* Connect the first slot; level 2 stays reserved but unconnected. */
hr = ConnectDateLogHandleToOdbcDatabase(hDateLog, pParams, DATE_LOG_ODBC_1);
if (FAILED(hr)) {
printf("Connecting level 1 failed: 0x%08lX\n", (unsigned long)hr);
goto cleanup;
}
printf("ODBC level 1 connected.\n");
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;
}