DateLogHandleHasChanged

Determine whether new dates were added/merged into a date log since load

Overview

DateLogHandleHasChanged returns the internal bHasChanged flag of a date log’s shared context, indicating whether dates have been added or merged since the date log was loaded/created.

Purpose

Used by callers to decide whether the underlying physical file needs to be rewritten/re-encrypted, so that unchanged logs are not written unnecessarily.

Key Features

Function Signature


BOOL _Check_return_ DateLogHandleHasChanged(
    _In_ DATE_COLLECTION_HANDLE hDateLogHandle
);
Header note: datelog.h declares the corresponding export as BOOL DateLogHasChanged(_In_ _Pre_valid_ DATE_LOG_HANDLE hDateLogHandle). The name and handle typedef differ from this page; both typedefs are void*. The signature above is the one documented for this page.

Parameters

hDateLogHandle

[In] DATE_COLLECTION_HANDLE

Handle to query.

  • NULL: allowed; the function returns FALSE
  • Type: a valid date log (or other collection) handle; an invalid handle also yields FALSE
  • Ownership: not retained or closed; the caller keeps ownership
  • Lifetime: must remain valid for the duration of the call

Return Values

TRUE

Dates have been added/merged since the context was created/loaded.

FALSE

No changes, or hDateLogHandle is NULL, or validation/locking failed.

A FALSE result cannot distinguish “unchanged” from “could not be queried”. Validate the handle with IsValidDateLogHandle if that distinction matters.

Remarks

Thread Safety

Reads the flag under the context’s critical section (EnterCriticalSection/LeaveCriticalSection) guarded by an interlocked “inside count”, ensuring consistent reads even while another thread is mutating the core.

The returned value is only a snapshot: another thread may add or merge dates immediately after the call returns, so a later write should itself be performed with the appropriate locking.

Handle Lifetime and Reference Counting

The function does not change the reference count. The flag belongs to the shared context, not to an individual handle, so querying any duplicate created with DuplicateDateLogHandle returns the same answer.

Typical Sources of Changes

Dates are added or merged by LoadDateLogHandle (for example when auto-extending a log to the current market date) and MergeDateLogHandle. To check whether a log already contains the most recent market date, see IsDateLogHandleUpToDate.

Sample Code

The example builds a date log over a fixed range, validates it, queries the changed flag, and closes every handle it created.


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


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 hDateLog  = 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, &hDateLog);
    if (FAILED(hr)) {
        printf("BuildSampleDateLog failed: 0x%08lX\n", (unsigned long)hr);
        goto cleanup;
    }

    if (!IsValidDateLogHandle(hDateLog)) {
        printf("The handle is not a valid date log handle.\n");
        goto cleanup;
    }

    /* The flag is set when dates have been added or merged since the log was loaded/created. */
    if (DateLogHandleHasChanged(hDateLog)) {
        printf("The date log has changed (%lu dates); its backing store needs to be rewritten.\n",
               (unsigned long)GetDateCollectionLength(hDateLog));
        /* Rewrite or re-encrypt the physical file here. */
    }
    else {
        printf("No changes since load; nothing to write. (FALSE is also returned if validation or locking failed.)\n");
    }

    rc = 0;

cleanup:
    if (hDateLog != NULL && FAILED(CloseDateLogHandle(hDateLog))) {
        rc = 1;
    }
    if (FAILED(CloseDateLogHandle(hHolidays))) {
        rc = 1;
    }
    return rc;
}

See Also