Reclassify a DATE_RANGE_HANDLE context into a DATE_LOG_HANDLE context
ConvertDateLogHandle verifies that the handle’s underlying file size is a valid multiple of
DATE_RECORD_LENGTH and that it matches the date collection’s length exactly, then reclassifies the
shared context’s magic number from __RANGE_LOG_MAGIC__ to __DATE_LOG_MAGIC__. All
duplicate handles sharing this context are silently reclassified as well, since the magic number lives on the
shared context, not on any individual handle.
Used after a successful merge (for example by LoadDateLogHandle) to promote a provisional/merged range context into a verified, fully-fledged date log once its file contents have been confirmed consistent.
DATE_RECORD_LENGTH) and that it corresponds exactly to the collection length
HRESULT _Must_inspect_result_ _Success_(SUCCEEDED(return)) ConvertDateLogHandle(
_Inout_ DATE_RANGE_HANDLE hDateRangeHandle,
_In_ DWORD dwFlags
);
ConvertToDateLogHandle(hDateRangeHandle, hLastDate) that takes an optional DATE_ITEM_HANDLE hLastDate rather than a flags value. The signature above is the one documented for this page; the existing documentation does not explain the relationship between the two.[In, Out] DATE_RANGE_HANDLE
Handle whose shared context is reclassified on success.
__RANGE_LOG_MAGIC__) that holds a populated collection; other states fail validation as listed under Return Values[In] DWORD
Behavior flags.
DATE_CONVERT_INTERNAL (same value as DATE_RANGE_MERGE_INTERNAL) only when calling from within an already-locked internal context, to skip redundant locking0File size and collection length are consistent; the context was reclassified to __DATE_LOG_MAGIC__.
File size is zero or not a multiple of DATE_RECORD_LENGTH.
Date collection length is zero or exceeds DATE_LOG_MAX (0x591C8, 370,120 items).
File size does not correspond exactly to the reported collection length.
ERR_INVALID_DATELOG_HANDLE and ERR_MERGE_NO_COMPLETE are documented in date_error.h. ERR_FILE_IS_CORRUPTED is also listed on LoadDateLogHandle but does not appear in the date_error.h reference page. When a check fails, the context is not reclassified.
Resets dwCheckedMagic to 0 on the handle so subsequent lock operations re-verify the newly-set magic number rather than relying on a stale cached check.
Unless DATE_CONVERT_INTERNAL is passed, the function locks the handle for the duration of the call. Because the magic number is stored on the shared context, other threads holding duplicate handles observe the new classification once the call completes; they should not assume the type of a handle across a concurrent conversion.
Populate the range first (for example with LoadDateLogHandle, optionally followed by MergeDateLogHandle), then convert. Functions that require a date log handle, such as InitializeDateLogHandleOdbc, only accept the handle after it has been reclassified.
The function does not allocate or free anything visible to the caller.
The example creates a range handle, populates it with a generated range of market dates, promotes it with ConvertDateLogHandle, and reports each documented failure. Conversion checks the underlying file size, so it is intended for ranges backed by file content; a range with no file content is expected to report ERR_FILE_IS_CORRUPTED when the file size is zero. The sample frees every date item and closes both handles.
#include <stdio.h>
#include "datelog.h"
int main(void)
{
HOLIDAYS_HANDLE hHolidays = NULL;
DATE_RANGE_HANDLE hRange = NULL;
DATE_ITEM_HANDLE hStart = NULL;
DATE_ITEM_HANDLE hEnd = NULL;
SYSTEMTIME stStart = { 0 };
SYSTEMTIME stEnd = { 0 };
FILETIME ftStart = { 0 };
FILETIME ftEnd = { 0 };
HRESULT hr = E_FAIL;
int rc = 1;
/* Holidays handle. Populate it with your market holiday data (see
LoadDateLogHandle) before building date logs; that step is application specific. */
hr = InitializeDateLogHandle(NULL, DATE_LOG_MAX, NULL, &hHolidays, HandleIsForHolidays);
if (FAILED(hr)) {
printf("InitializeDateLogHandle failed for holidays: 0x%08lX\n", (unsigned long)hr);
return 1;
}
stStart.wYear = 2024; stStart.wMonth = 1; stStart.wDay = 2;
stEnd.wYear = 2024; stEnd.wMonth = 1; stEnd.wDay = 31;
if (!SystemTimeToFileTime(&stStart, &ftStart) || !SystemTimeToFileTime(&stEnd, &ftEnd)) {
printf("SystemTimeToFileTime failed: %lu\n", GetLastError());
goto cleanup;
}
/* A date range is a provisional collection: create one and populate it. */
hr = InitializeDateLogHandle(NULL, DATE_LOG_MAX, hHolidays, &hRange, HandleIsForRange);
if (FAILED(hr)) {
printf("InitializeDateLogHandle failed: 0x%08lX\n", (unsigned long)hr);
goto cleanup;
}
hr = InitializeDateItem(hRange, &ftStart, NULL, &hStart);
if (SUCCEEDED(hr)) {
hr = InitializeDateItem(hRange, &ftEnd, NULL, &hEnd);
}
if (SUCCEEDED(hr)) {
hr = LoadDateLogHandle(NULL, hStart, hEnd, hRange, NULL, 0);
}
if (FAILED(hr)) {
printf("Populating the range failed: 0x%08lX\n", (unsigned long)hr);
goto cleanup;
}
/* Promote the range to a verified date log; pass 0 for an ordinary (unlocked) call. */
hr = ConvertDateLogHandle(hRange, 0);
if (SUCCEEDED(hr)) {
printf("The range context is now a date log; collection length = %lu\n",
(unsigned long)GetDateCollectionLength(hRange));
rc = 0;
}
else if (hr == ERR_FILE_IS_CORRUPTED) {
printf("File size is zero or not a multiple of DATE_RECORD_LENGTH.\n");
}
else if (hr == ERR_INVALID_DATELOG_HANDLE) {
printf("The collection length is zero or exceeds DATE_LOG_MAX.\n");
}
else if (hr == ERR_MERGE_NO_COMPLETE) {
printf("The file size does not match the collection length.\n");
}
else {
printf("ConvertDateLogHandle failed: 0x%08lX\n", (unsigned long)hr);
}
cleanup:
FreeDateItem(hEnd);
FreeDateItem(hStart);
if (hRange != NULL && FAILED(CloseDateLogHandle(hRange))) {
rc = 1;
}
if (FAILED(CloseDateLogHandle(hHolidays))) {
rc = 1;
}
return rc;
}