IsValidDateLogHandle

Universal validation function for DATE_LOG, DATE_RANGE, and HOLIDAYS handles with caching and error detection

Overview

IsValidDateLogHandle is the primary validation function for date collection handles. It validates DATE_LOG_HANDLE, DATE_RANGE_HANDLE, and HOLIDAYS_HANDLE instances by checking structural integrity, magic numbers, resource availability, and handle state. The function implements a multi-level validation strategy with result caching for performance optimization.

Purpose

This function serves as the gatekeeper for all handle operations:

Key Features

Function Signature

BOOL _Check_return_ IsValidDateLogHandle(
    _In_  DATE_COLLECTION_HANDLE hDateLogHandle
);

Calling Convention

Standard C calling convention. The _Check_return_ SAL annotation marks this as a function whose return value must be checked—ignoring the return value generates compiler warnings.

Parameters Summary

Parameter Type Direction Description
hDateLogHandle DATE_COLLECTION_HANDLE In Handle to validate (DATE_LOG, DATE_RANGE, or HOLIDAYS)

Parameters

hDateLogHandle

[In] DATE_COLLECTION_HANDLE

Opaque handle to a date collection (DATE_LOG, DATE_RANGE, or HOLIDAYS).

  • Can be NULL (returns FALSE)
  • Can be any of three handle types (validation dispatches accordingly)
  • Must have been created by InitializeDateLogHandle()
  • Can be in valid, invalid, or cached-valid state
  • Not modified by this function

Return Values

Valid Handle

TRUE (non-zero)

Handle is valid and can be used safely in handle operations.

Invalid Handle Scenarios

FALSE (0)

Returned in any of these cases:

Validation Process

Five-Stage Validation Strategy

The function implements a hierarchical validation approach:

CHECK 1: NULL Pointer Guard
Verifies hDateLogHandle != NULL
if (hDateLogHandle == NULL) return FALSE;
CHECK 2: Invalid Marker Detection
Rejects handles marked with __IS_INVALID_MAGIC__
Used to permanently invalidate corrupted handles
if (pDateLog->dwCheckedMagic == __IS_INVALID_MAGIC__) return FALSE;
CHECK 3: Cached Validation Optimization
Returns cached result if already validated
Avoids redundant type-specific validation
if (pDateLog->dwCheckedMagic == __CHECKED_MAGIC__) return TRUE;
CHECK 4: Context Pointer Validation
Ensures context structure exists before dereferencing
Prevents NULL pointer access violations
if (pDateLog->pContext == NULL) return FALSE;
CHECK 5: Type-Specific Dispatch
Routes to appropriate validator based on magic number
Each validator performs detailed structural checks
switch (pDateLog->pContext->dwMagic) { ... }

Type-Specific Validators

After dispatching by magic number, the function delegates to:

Magic Number Handle Type Validator Function Validations Performed
__DATE_LOG_MAGIC__ DATE_LOG_HANDLE IsValidDateLogHandleInternal() Core integrity, holidays linkage, max length, file info
__RANGE_LOG_MAGIC__ DATE_RANGE_HANDLE IsValidDateRangeHandle() Core integrity, max length, both DateLog and Range magic
__HOLIDAY_MAGIC__ HOLIDAYS_HANDLE IsValidHolidaysHandle() Core integrity, magic number, max holidays count
Any Other Unknown/Corrupted N/A Returns FALSE immediately

Detailed Validation Steps in Type Validators

Each type-specific validator checks:

Caching Behavior

After successful validation, the function caches the result:

pDateLog->dwCheckedMagic = __CHECKED_MAGIC__;

On subsequent calls, the cached __CHECKED_MAGIC__ value allows immediate return without re-validation, unless:

Usage Examples

Example 1: Basic Validation Check

DATE_LOG_HANDLE hDateLog = /* create handle */;

if (IsValidDateLogHandle(hDateLog)) {
    // Handle is valid - safe to use
    DWORD count = GetDateCollectionLength(hDateLog);
    DATE_ITEM_HANDLE hFirst = GetDateLogFirstDate(hDateLog);
} else {
    // Handle is invalid - cleanup and report error
    printf("Error: invalid date log handle\n");
    return E_INVALIDARG;
}
            
Example 2: Protecting Against Corruption

// Function that must validate before use
HRESULT ProcessDateLog(DATE_LOG_HANDLE hLog) {
    // First check: is the handle still valid?
    if (!IsValidDateLogHandle(hLog)) {
        printf("Error: date log has been invalidated or corrupted\n");
        return E_HANDLE;
    }

    // Now safe to proceed
    DATE_ITEM_HANDLE hFirst = GetDateLogFirstDate(hLog);
    if (hFirst == NULL) {
        return E_NO_DATA;
    }

    // ... process dates ...
    return S_OK;
}
            
Example 3: Multi-Handle Validation

// Validate all three handle types
BOOL ValidateAllHandles(
    DATE_LOG_HANDLE hDateLog,
    DATE_RANGE_HANDLE hRange,
    HOLIDAYS_HANDLE hHolidays
) {
    if (!IsValidDateLogHandle(hDateLog)) {
        printf("Invalid date log\n");
        return FALSE;
    }

    if (!IsValidDateLogHandle((DATE_LOG_HANDLE)hRange)) {
        printf("Invalid date range\n");
        return FALSE;
    }

    if (!IsValidDateLogHandle((DATE_LOG_HANDLE)hHolidays)) {
        printf("Invalid holidays handle\n");
        return FALSE;
    }

    return TRUE;  // All handles valid
}
            
Example 4: Caching Demonstration

DATE_LOG_HANDLE hDateLog = /* create and validate once */;

// First call: full validation (all 5 checks performed)
BOOL valid1 = IsValidDateLogHandle(hDateLog);

// Second call: cached validation (only checks 1, 2, and 3 performed)
// Skips context dereferencing and type-specific validation
BOOL valid2 = IsValidDateLogHandle(hDateLog);

// Both return same result but second is faster due to caching
assert(valid1 == valid2);
            

Thread Safety

Validation Function Behavior

IsValidDateLogHandle() is read-only and thread-safe for concurrent validation calls. Multiple threads can simultaneously validate the same handle without synchronization issues.

When Validation Succeeds Across Threads

When Validation is Used in Handle Operations

Validation alone does NOT provide synchronization. If the handle is used after validation:

Pattern: Validate → Acquire Mutex → Use Handle → Release Mutex

Invalidation is Single-Direction

Once marked with __IS_INVALID_MAGIC__, a handle is permanently invalid. This state cannot be cleared, ensuring failed handles are never mistakenly reused.

Important Notes

Caching is Conservative: The function only caches positive results. Handles are marked valid once and trusted thereafter. If a handle becomes corrupted after validation, the caller must detect this separately.
Must Check Return Value: The _Check_return_ attribute means compiler will warn if you ignore the return value. Always write: if (!IsValidDateLogHandle(hLog)) { /* handle error */ }
NULL Check is First: Passing NULL is safe—it returns FALSE, not an exception. This enables optional handle patterns.
Type Agnostic: The function accepts any DATE_COLLECTION_HANDLE and routes to appropriate type validator. Callers can use this as a universal validation point for all handle types.

Performance Characteristics

Related Functions

Error Handling Pattern

Recommended pattern for all functions receiving handles:


HRESULT SomeFunction(DATE_LOG_HANDLE hLog) {
    // Validate immediately
    if (!IsValidDateLogHandle(hLog)) {
        return HRESULT_FROM_WIN32(ERROR_INVALID_HANDLE);
    }

    // Proceed with operation
    // ...
    return S_OK;
}