Compare two date log handles for underlying collection equality
CompareDateLogHandle determines whether two date log handles refer to equal underlying date log collections. It locks both
handles (in a consistent pointer-value order to avoid deadlocks), compares their holidays handles (if applicable), compares file info,
and compares the underlying DATE_LOG_CORE content.
Lets callers verify that two handles (for example, one loaded from a file and one generated or merged in memory) describe the same date collection before deciding whether to rewrite, replace, or synchronize a backing store.
BOOL, not an HRESULT — failures to lock or validate are reported as FALSE
BOOL _Check_return_ CompareDateLogHandle(
_In_ DATE_LOG_HANDLE hDateLogHandle1,
_In_ DATE_LOG_HANDLE hDateLogHandle2
);
[In] DATE_LOG_HANDLE
The first handle to compare.
FALSE[In] DATE_LOG_HANDLE
The second handle to compare.
FALSEThe function returns a BOOL. Because the function is marked _Check_return_, always use the result.
Both handles refer to equal date log collections (same magic, same holidays, same file info, same core).
The collections are not equal, an argument is NULL, the handles have different magic numbers, or a lock could not be acquired.
A FALSE result does not distinguish “not equal” from a lock or validation failure. If you need to know whether a handle is usable, validate it first with IsValidDateLogHandle.
Both handles are locked for the duration of the comparison. Locks are always acquired in ascending pointer-value order of the two handles to prevent deadlocks when the function is called concurrently with swapped arguments (for example, CompareDateLogHandle(a, b) on one thread and CompareDateLogHandle(b, a) on another).
The function does not change reference counts. Handles created with DuplicateDateLogHandle share a single context with their source; each must still be released with CloseDateLogHandle.
The result is a BOOL (TRUE/FALSE), not an ordering. Unlike CompareDateItem and CompareFiletime, there is no negative/positive result, and the function cannot be used to sort date logs.
The example builds two date logs over the same range with a small helper, duplicates one of them, compares the combinations, and closes every handle it created.
#include <stdio.h>
#include "datelog.h"
/* BuildSampleDateLog is shown below; it creates a date log covering
2024-01-02 through 2024-01-31. */
static HRESULT BuildSampleDateLog(HOLIDAYS_HANDLE hHolidays, DATE_LOG_HANDLE *phDateLog)
{
DATE_LOG_HANDLE hDateLog = 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;
*phDateLog = NULL;
/* Tuesday 2 January 2024 through Wednesday 31 January 2024 (both market days). */
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)) {
return HRESULT_FROM_WIN32(GetLastError());
}
hr = InitializeDateLogHandle(NULL, DATE_LOG_MAX, hHolidays, &hDateLog, HandleIsForDatelog);
if (FAILED(hr)) {
return hr;
}
hr = InitializeDateItem(hDateLog, &ftStart, NULL, &hStart);
if (SUCCEEDED(hr)) {
hr = InitializeDateItem(hDateLog, &ftEnd, NULL, &hEnd);
}
if (SUCCEEDED(hr)) {
/* No file context: generate the contiguous range between hStart and hEnd. */
hr = LoadDateLogHandle(NULL, hStart, hEnd, hDateLog, NULL, 0);
}
FreeDateItem(hEnd);
FreeDateItem(hStart);
if (FAILED(hr)) {
CloseDateLogHandle(hDateLog);
return hr;
}
*phDateLog = hDateLog;
return S_OK;
}
int main(void)
{
HOLIDAYS_HANDLE hHolidays = NULL;
DATE_LOG_HANDLE hLogA = NULL;
DATE_LOG_HANDLE hLogB = NULL;
DATE_LOG_HANDLE hLogDup = NULL;
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;
}
hr = BuildSampleDateLog(hHolidays, &hLogA);
if (FAILED(hr)) {
printf("BuildSampleDateLog failed for A: 0x%08lX\n", (unsigned long)hr);
goto cleanup;
}
hr = BuildSampleDateLog(hHolidays, &hLogB);
if (FAILED(hr)) {
printf("BuildSampleDateLog failed for B: 0x%08lX\n", (unsigned long)hr);
goto cleanup;
}
hr = DuplicateDateLogHandle(hLogA, &hLogDup);
if (FAILED(hr)) {
printf("DuplicateDateLogHandle failed: 0x%08lX\n", (unsigned long)hr);
goto cleanup;
}
/* Two logs built independently from the same range. The result also reflects
the other compared properties (file info, core content). */
if (CompareDateLogHandle(hLogA, hLogB)) {
printf("A and B hold equal date log collections.\n");
}
else {
printf("A and B are not equal (or could not be locked).\n");
}
/* A duplicate shares the same context as its source. */
if (CompareDateLogHandle(hLogA, hLogDup)) {
printf("A and its duplicate are equal.\n");
}
else {
printf("A and its duplicate are not equal (or could not be locked).\n");
}
/* NULL arguments are not an error: the function simply returns FALSE. */
if (!CompareDateLogHandle(hLogA, NULL)) {
printf("Comparison with NULL returned FALSE as documented.\n");
}
rc = 0;
cleanup:
if (hLogDup != NULL && FAILED(CloseDateLogHandle(hLogDup))) {
rc = 1;
}
if (hLogB != NULL && FAILED(CloseDateLogHandle(hLogB))) {
rc = 1;
}
if (hLogA != NULL && FAILED(CloseDateLogHandle(hLogA))) {
rc = 1;
}
if (FAILED(CloseDateLogHandle(hHolidays))) {
rc = 1;
}
return rc;
}