GenerateDateCollection

    HRESULT _Must_inspect_result_ _Success_(SUCCEEDED(return)) GenerateDateCollection(
        _In_opt_  PFILE_INFO pFileInfo,
        _In_opt_  _When_(pFileInfo == NULL, _Notnull_) DATE_ITEM_HANDLE hStartDate,
        _In_opt_  _When_(pFileInfo == NULL, _Notnull_) DATE_ITEM_HANDLE hEndDate,
        _In_	 DATE_LOG_HANDLE hDateLogHandle,
        _In_opt_ PDATE_COLLECTION_PROGRESS pProgData,
        _In_ DWORD dwFlags
    );

Date Collection Generation and Parsing

Generates or extends a date collection for a DATE_LOG_HANDLE, DATE_RANGE_HANDLE, or HOLIDAYS_HANDLE.

This function supports four primary workflows based on the handle type:

1. File-based DateLog (HandleIsForDatelog with pFileInfo)

  • Parses an existing date log file and populates the handle.
  • Optionally extends the parsed dates to hEndDate if provided and after the last parsed date.
  • Supports GUID replacement when DATE_RANGE_MERGE_FAVOR_SOURCE flag is set.
  • File is retained on handle for potential future updates.

2. Range-based DateLog (HandleIsForDatelog without pFileInfo)

  • Generates a new temporary file for the handle.
  • Populates dates from hStartDate to hEndDate (inclusive, market days only).
  • Useful for generating date ranges on-demand without file input.

3. Simple Range (HandleIsForRange)

  • Populates a date range handle with market dates from hStartDate to hEndDate.
  • No file association required; operates on in-memory date collection.

4. Holiday Stream Parsing (HandleIsForHolidays)

  • Parses holiday definitions from a file stream.
  • File input (pFileInfo) is required; programmatic holiday generation not supported.

Thread Safety

  • Handle's context mutex protects shared reference-counted state.
  • Each handle maintains its own mutex for file operations.
  • Critical section used for atomic counter updates during handle duplication.
  • Caller must not modify handle while this function executes.

Memory Management

  • pLastDate: Pointer to item within existing array; NOT separately allocated; caller not responsible for freeing.
  • hDateRange: Internally allocated; always freed before function return.
  • pFileInfo: Assigned to handle on success; freed by FreeDateCollectionHandle when handle is destroyed.
  • All intermediate allocations cleaned up on error paths.

Date Validation

  • All dates must be covered by the holidays handle (within date range, not themselves holidays).
  • End dates must not be future dates (validation against system clock).
  • Start and end dates must represent market days (non-weekend, non-holiday).
  • Market days gap validation ensures no gaps exceed capacity.

Error Recovery

  • On failure, all allocated resources are cleaned up.
  • File info attached to handle is freed if operation fails.
  • Handle remains in valid state even if operation fails.
  • Caller should not use handle if this function returns failure.

Merge Flags (dwFlags)

  • DATE_RANGE_MERGE_FAVOR_SOURCE (0x08): Replace destination GUIDs with source in overlapping range.
  • DATE_RANGE_MERGE_FAVOR_DEST (0x04): Keep destination GUIDs in overlapping range.
  • When neither flag set for DateLog case: extends log only if end date is after last parsed date.

Handle Type Detection

  • Determined automatically.
  • Invalid handle values cause ERROR_INVALID_HANDLE return.

Preconditions

  • hDateLogHandle must be valid and initialized via InitializeDateLogHandle.
  • If pFileInfo provided: must be valid file info with readable handle.
  • If pFileInfo is NULL and HandleIsForDatelog: both hStartDate and hEndDate must be non-NULL and valid.
  • If HandleIsForRange: both hStartDate and hEndDate must be non-NULL and valid.
  • If HandleIsForHolidays: pFileInfo must be non-NULL (no random generation supported).
  • Holiday handle must be valid and properly initialized.

Postconditions on Success (S_OK)

  • Handle populated with date items from source (file or generated).
  • bHasChanged flag set to TRUE if dates were modified.
  • hDateRange (if allocated internally) is freed before return.

Parameters

pFileInfo

[In, Optional] File info pointer for file-based parsing.

  • When provided: file is parsed and dates extracted; extended to hEndDate if set and applicable.
  • When NULL: dates generated from hStartDate to hEndDate based on handle type.
  • Must pass IsValidFileInfo validation if provided.

hStartDate

[In, Optional] Start date handle for range generation or merge operation.

  • Required when: pFileInfo is NULL AND handle type is HandleIsForRange.
  • Optional when: pFileInfo is provided (used for extension boundaries).
  • Required to be valid DATE_ITEM_HANDLE: covered by holidays, not a future date.
  • Must be non-NULL when pFileInfo is NULL for DateLog handles.

hEndDate

[In, Optional] End date handle (inclusive ceiling) for range generation or extension.

  • Required when: pFileInfo is NULL AND handle type is HandleIsForRange.
  • Optional when: pFileInfo is provided (used for extension to this date).
  • Required to be valid DATE_ITEM_HANDLE: covered by holidays, not a future date.
  • Must be non-NULL when pFileInfo is NULL for DateLog handles.

hDateLogHandle

[In] Handle to populate with dates.

  • Must be valid DATE_LOG_HANDLE, DATE_RANGE_HANDLE, or HOLIDAYS_HANDLE.
  • Must have been initialized via InitializeDateLogHandle.
  • Must have valid associated holidays handle for DateLog and Range types.

pProgData

[In, Optional] Progress data structure for reporting during file parsing.

  • When provided: periodically updated with dwCount (current parsed dates) and dwMaxCount (maximum).
  • When NULL: no progress reporting occurs.
  • Must have valid hMutex if provided.
  • Updated under mutex protection for thread safety.

dwFlags

[In] Merge flags controlling date range merge behavior.

  • DATE_RANGE_MERGE_FAVOR_SOURCE (0x08): Replace destination GUIDs with source in overlap.
  • DATE_RANGE_MERGE_FAVOR_DEST (0x04): Keep destination GUIDs in overlap.
  • When neither flag: extends log only if new dates don't overlap.
  • Used only for DateLog handle type with file info and merge scenarios.

Return Value

HRESULT indicating operation success or failure:

Success

  • S_OK: Date collection generated/parsed and merged successfully.

Validation Errors (ERROR_INVALID_PARAMETER)

  • pFileInfo provided but IsValidFileInfo fails.
  • Both pFileInfo NULL and (hStartDate NULL or hEndDate NULL).
  • hDateLogHandle invalid or NULL.

Handle/State Errors (ERR_INVALID_DATELOG_HANDLE, ERR_INVALID_HOLIDAY_HANDLE)

  • hDateLogHandle magic value invalid.
  • Associated holidays handle invalid or missing.
  • Wrong handle type for operation (e.g., DateLog handle where Range expected).

Date/Range Errors

  • ERR_DATE_NO_COVERED: Date not covered by holidays (outside date range or is holiday).
  • ERR_DATE_IS_FUTURE_DATE: End date is in the future (after today).
  • ERR_DATELOG_ZERO_GAP: Gap between dates is zero or negative.
  • ERR_MAX_DATELOG_REACHED: Market days between dates exceeds DATE_LOG_MAX capacity.
  • ERR_DATELOG_LENGTH_MAX: Collection length exceeds maximum allowed.

File/IO Errors

  • HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY): Memory allocation failed.
  • HRESULT_FROM_WIN32(ERROR_FILE_*): File operation failed.
  • HRESULT_FROM_WIN32(GetLastError()): System error from file or mutex operations.

Merge/Conversion Errors

  • ERR_DATEITEM_NOT_FOUND: Required date item not found during merge.
  • ERR_DATEITEM_END_NO_MATCH: End date mismatch in contained merge.
  • ERR_DATEITEM_FINAL_NO_MATCH: Final date count mismatch after merge.
  • ERR_MERGE_NO_COMPLETE: Merge count doesn't match expected count.
  • Various errors from ConvertToDateLogHandle, MergeDateRangeIntoDateLog.

Invalid Flags/Type Errors

  • ERROR_INVALID_FLAGS: dwFlags missing required source/dest favor flag.
  • ERR_BAD_HANDLE_TYPE: Handle magic indicates unsupported type.

Remarks

Handle Type Auto-Detection

  • Unlike older versions, this function deduces handle type
  • Invalid magic returns ERROR_INVALID_HANDLE immediately.

pLastDate Ownership

When obtained via GetDateLogLastDate, pLastDate is a pointer to an item within the existing array, NOT a separately allocated copy. Caller is NOT responsible for freeing pLastDate; it remains valid as long as the handle's context is valid.

hDateRange Lifecycle

Internally allocated when merging; ALWAYS freed before function return, even in success paths. This ensures no resource leak.

File Persistence

When pFileInfo is successfully processed, it is assigned to pDateLog->pFileInfo and retained. File is freed only when handle is destroyed via FreeDateCollectionHandle. On error, file is cleaned up immediately.

Sentinel Values

GetMarketDaysGap returns DATE_LOG_SENTINEL (-1) on validation errors. This is checked BEFORE checking dwGap <= 0 to distinguish error from zero gap. Order matters: ERR_MAX_DATELOG_REACHED checked before ERR_DATELOG_ZERO_GAP.

Locale Handling

Date parsing (via ParseDateLogFiles) uses system locale internally. ParseHolidayStream (for holidays) also uses system locale; no explicit locale parameter. Callers requiring specific locale must ensure system locale is set appropriately.

Thread Safety Guarantees

  • Caller must ensure exclusive access to hDateLogHandle during execution.
  • Internal mutex protections do NOT prevent concurrent calls with same handle.
  • Safe for multiple threads with DIFFERENT handles referencing same context.
  • Unsafe for concurrent calls with same handle from different threads.

See Also

  • InitializeDateLogHandle
  • FreeDateCollectionHandle
  • GenerateDateItemRange
  • ParseDateLogFiles
  • MergeDateRangeIntoDateLog
  • ConvertToDateLogHandle


InitializeDateLogHandle

    HRESULT _Must_inspect_result_ _Success_(SUCCEEDED(return)) InitializeDateLogHandle(
        _In_opt_  PSECURITY_ATTRIBUTES pSecAttr,
        _In_opt_ _Pre_satisfies_(dwMaximumLength <= DATE_LOG_MAX) const DWORD dwMaximumLength,
        _In_opt_ _When_(HandleType == HandleIsForDatelog, _Notnull_ _Valid_)
                 _When_(HandleType == HandleIsForRange, _Notnull_ _Valid_) HOLIDAYS_HANDLE hHolidays,
        _Out_ DATE_LOG_HANDLE *hDateLogHandle,
        _In_ DateHandleType HandleType
    )	;

Initializes a new DATE_LOG_HANDLE for date collection management. This function creates and initializes a handle that supports DateLog, DateRange, and Holidays, with thread-safe access and a shared reference-counted context.

Handle Types

  • HandleIsForDatelog full date log with holiday awareness
  • HandleIsForRange temporary date range
  • HandleIsForHolidays holiday definitions

Thread Safety

  • Each handle has a dedicated mutex for file operations.
  • The shared context includes a critical section.
  • Multiple handles may reference the same context.
  • The context is freed only when the reference count reaches zero.

Memory Management

  • dwMaximumLength defines capacity; defaults depend on the handle type.
  • DATE_LOG_MAX applies to DateLog and Range handles.
  • MAX_HOLIDAYS applies to holiday handles.
  • Allocation failures return ERROR_OUTOFMEMORY.

Synchronization Resources Created

  • Primary mutex for file operations.
  • Shared context mutex for reference counting.
  • Shared critical section for atomic counter updates.

Notes

  • Initialize hDateLogHandle to NULL before calling.
  • Parameters are validated early.
  • All resources are cleaned up automatically on failure.
  • Reference count begins at 1.

Parameters

pSecAttr

Optional security attributes for mutex creation.

dwMaximumLength

Maximum number of date items; must not exceed DATE_LOG_MAX.

hHolidays

Valid HOLIDAYS_HANDLE for DateLog and Range types.

hDateLogHandle

Receives the newly created DATE_LOG_HANDLE.

HandleType

Specifies the type of handle to create.

Returns

  • S_OK on success
  • ERROR_INVALID_PARAMETER for invalid inputs
  • ERROR_OUTOFMEMORY for allocation failures
  • GetLastError() for mutex failures


DuplicateDateLogHandle

    HRESULT  _Must_inspect_result_ _Success_(SUCCEEDED(return)) DuplicateDateLogHandle(
        _In_  DATE_LOG_HANDLE hSourceHandle,
        _Out_ DATE_LOG_HANDLE *lpTargetHandle
    );

Duplicates a DATE_LOG_HANDLE for concurrent thread access. This function creates a new DATE_LOG handle that references the same shared context as the source handle, allowing multiple threads to independently query and cache the last accessed date item without mutex contention for different date searches.

Reference Counting

  • uiHandles is incremented in DATE_CONTEXT to track active handles.
  • Context is freed only when uiHandles reaches 0.
  • Function prevents duplication during context teardown (bIsFreeing check).

Thread Safety

  • SOURCE context mutex protects file info access.
  • Critical section protects handle counter increment.
  • Duplicated handle mutex is independently created for file operations.

Error Conditions

  • ERROR_INVALID_HANDLE: Source is invalid or context is being freed.
  • ERROR_INVALID_PARAMETER: lpTargetHandle is NULL.
  • ERROR_OUTOFMEMORY: Allocation failure.

Note

Returned handle must be freed via FreeDateCollectionHandle() to properly decrement the reference count and potentially free the shared context.

Parameters

hSourceHandle

Valid DATE_LOG_HANDLE, DATE_RANGE_HANDLE, or HOLIDAYS_HANDLE to duplicate.

lpTargetHandle

Out parameter receiving the new DATE_LOG_HANDLE; caller must call FreeDateCollectionHandle() when finished.

Returns

  • S_OK: Successfully duplicated handle.
  • ERROR_INVALID_HANDLE: Source handle invalid or context is being freed.
  • ERROR_INVALID_PARAMETER: lpTargetHandle is NULL.
  • ERROR_OUTOFMEMORY: Memory allocation failed.


LockFileRegions

LockFileRegions Function Overview

    HRESULT _Must_inspect_result_ _Success_(SUCCEEDED(return)) LockFileRegions(
        _In_ PFILE_INFO pFileInfo,
        _Inout_ PLOCK_FILE_INFO pLockInfo
    )
    ;

The LockFileRegions function attempts to lock one or more byte ranges within a file using the Windows LockFile API. It implements a best-effort, per-region locking strategy rather than an atomic all-or-nothing model. Each region is locked independently, and partial success is allowed.

What It Does

The function receives:

  • A FILE_INFO structure containing a valid file handle
  • A LOCK_FILE_INFO structure specifying one or more byte ranges to lock

It then attempts to lock each region individually using LockFile.

Key Behavior

No Rollback on Partial Failure

If some regions lock successfully but others fail, the function does not roll back the successful locks. This “fail-open” behavior allows callers to:

  • Use any regions that did lock successfully
  • Retry failed regions later
  • Continue processing with partially locked regions

Successfully locked regions remain locked until explicitly released via UnLockFileRegions.

Operation Flow

1. Input Validation

  • pLockInfo must not be NULL
  • pFileInfo must be valid
  • nLockRegions must not exceed MAX_LOCK_REGIONS

2. Parameter Pre-Check

Before locking begins, the function iterates through all regions:

  • Ensures each region has a non-zero lock size
  • Initializes bLocked, bLockResult, and bUnlockResult to FALSE

3. Locking Loop

For each region, LockFile is called with the region’s offset and length:

  • If lock fails:
    • bLocked = FALSE
    • bLockResult = FALSE
    • Increment uFailedCount
    • Record first error HRESULT
  • If lock succeeds:
    • bLocked = TRUE
    • bLockResult = TRUE
    • Increment uLockedCount

4. Return Value

The function returns:

  • S_OK — only if all regions locked successfully
  • Otherwise — an HRESULT corresponding to the first failure

Callers must inspect bLocked for each region to determine which locks succeeded.

Important Notes

  • The function does not unlock failed regions
  • Successful locks remain active until UnLockFileRegions is called
  • The operation is synchronous and blocking (uses LockFile, not LockFileEx)

    1. Call LockFileRegions() with 3 regions (A, B, C)
    2. Suppose region B fails to lock (maybe it's already locked by another process)
           - Region A: bLocked = TRUE (usable)
           - Region B: bLocked = FALSE (not locked)
           - Region C: bLocked = TRUE (usable)
           - Return value: ERROR_LOCK_VIOLATION
    3. Caller can immediately use regions A and C for file operations
    4. In parallel or later, caller can retry locking region B
    5. When done with regions A and C, call UnLockFileRegions() to release them
    6. Region B remains unlocked (caller skipped its unlock since bLocked = FALSE)


UnlockFileRegions

UnLockFileRegions Function Overview

        HRESULT _Must_inspect_result_ _Success_(SUCCEEDED(return)) UnLockFileRegions(
            _In_ PFILE_INFO pFileInfo,
            _In_ PLOCK_FILE_INFO pLockInfo
        )	;

The UnLockFileRegions function releases file byte-range locks previously acquired via LockFileRegions, attempting to unlock all specified regions even if individual unlock operations fail. It implements best-effort semantics, ensuring reliable cleanup and per-region diagnostics.
“It implements best-effort semantics, ensuring that callers can reliably unlock multiple regions…”

Function Purpose and Design Philosophy

UnLockFileRegions complements LockFileRegions by providing symmetrical unlock functionality with defensive error handling. Rather than aborting on the first failed unlock, the function continues attempting all unlocks, recording success or failure for each region.
“This approach is critical for reliable resource management…”

The function uses synchronous UnlockFile, ensuring deterministic unlock behavior.

Parameter Descriptions

pFileInfo (PFILE_INFO, required)

Pointer to a valid FILE_INFO structure containing the file handle. Validated via IsValidFileInfo. A NULL or invalid pointer causes immediate ERROR_INVALID_PARAMETER.
“The file handle (hFile) is extracted from this structure and used for all UnlockFile calls.”

pLockInfo (PLOCK_FILE_INFO, required)

Structure defining the regions to unlock. Contains:

  • nLockRegions — number of regions
  • dwOffsetLow / dwOffsetHigh — 64-bit offset
  • dwLockLow / dwLockHigh — 64-bit size
  • bLocked — TRUE if region is currently locked
  • bUnlockResult — TRUE/FALSE per-region unlock result

A NULL pointer causes immediate ERROR_INVALID_PARAMETER.

Validation and Error Tracking

Before unlocking, the function validates:

  • pLockInfo is non-NULL
  • pFileInfo is valid
  • nLockRegions = MAX_LOCK_REGIONS

Two state variables track errors:

  • hrFirst — first error encountered (initially S_OK)
  • bAnyFailed — TRUE if any unlock fails

“This becomes the function’s return value, ensuring the caller learns about at least one failure…”

Operational Sequence

The function iterates over all regions:

  • If bLocked == FALSE, skip region.
  • Call UnlockFile with region’s offset and size.
  • If unlock fails:
    • Capture error via GetLastError()
    • Store first error in hrFirst
    • Set bAnyFailed = TRUE
    • Set bUnlockResult = FALSE
  • If unlock succeeds:
    • Set bLocked = FALSE
    • Set bUnlockResult = TRUE

After all regions are processed, the function returns:
bAnyFailed ? hrFirst : S_OK
“If all unlocks succeed, S_OK is returned…”

Key Design Characteristics

  • Best-effort semantics — attempts all unlocks regardless of failures.
  • Per-region diagnostics — bUnlockResult records success/failure.
  • Persistent state tracking — bLocked remains TRUE for failed unlocks.
  • Symmetry with LockFileRegions — complements atomic locking with robust unlocking.

“This asymmetry is intentional… unlocking failures do not require rollback.”

Typical Usage Pattern

After a call to LockFileRegions(pFileInfo, pLockInfo) that succeeded, a caller would later invoke UnLockFileRegions(pFileInfo, pLockInfo) using the same structures to release the locks. If all unlocks succeed, S_OK is returned and all regions' bUnlockResult fields are TRUE. If some unlocks fail (e.g., due to concurrent access or file handle corruption), the function returns the first error code, but bUnlockResult fields indicate which specific regions failed, allowing the caller to log detailed diagnostic information or attempt targeted cleanup. For example:

    HRESULT hr = UnLockFileRegions(pFileInfo, pLockInfo);
    if (FAILED(hr)) {
            for (int i = 0; i < pLockInfo->nLockRegions; i++) {
                    if (!pLockInfo->LockRegions[i].bUnlockResult) {
                            // Region i failed to unlock
                            // Log or handle this specific failure
                    }
            }
    }


BuilKnownFolderPath

BuildKnownFolderPath Function Overview

     HRESULT _Must_inspect_result_ _Success_(SUCCEEDED(return)) BuildKnownFolderPath(
         _In_	REFKNOWNFOLDERID												* rfid,
         _In_	KNOWN_FOLDER_FLAG 												dwFolderFlags,
         _In_reads_opt_z_(dwPathBufferLength)	 LPWSTR 										pszPathBuffer,
         _In_opt_ _Pre_satisfies_(dwPathBufferLength == 0 || (dwPathBufferLength > 0 && dwPathBufferLength <= MAX_PATH))  DWORD 	dwPathBufferLength,
         _In_reads_opt_z_(dwFileNameLength) 	LPWSTR 										pszFileName,
         _In_opt_ _Pre_satisfies_(dwFileNameLength == 0 || (dwFileNameLength > 0 && dwFileNameLength <= MAX_PATH)) DWORD 	dwFileNameLength,
         _Outptr_ PUNICODE_STRING* pNewPath,
         _In_	DWORD dwFlags
     );	;

The BuildKnownFolderPath function is a path construction utility that assembles a complete file system path by combining a Windows known folder location, optional subdirectories, and an optional filename, returning the result as a newly allocated UNICODE_STRING.
“It serves as a centralized mechanism for generating standardized application file paths…”

Function Purpose and Design Philosophy

BuildKnownFolderPath abstracts the platform-dependent process of locating system folders and constructing paths to them. Instead of requiring callers to invoke SHGetKnownFolderPath and manually concatenate path components, this function encapsulates the entire workflow: retrieving the known folder, validating lengths, optionally generating a GUID-based filename, formatting the final path, and returning a fully validated UNICODE_STRING.
“The function validates all intermediate results and applies strict length constraints…”

Parameter Descriptions

rfid (REFKNOWNFOLDERID, required)

Pointer to a known folder identifier such as FOLDERID_AppData, FOLDERID_LocalAppData, FOLDERID_Temp, or FOLDERID_Documents. Passed directly to SHGetKnownFolderPath. A NULL pointer causes immediate failure.
“A NULL pointer causes immediate validation failure…”

dwFolderFlags (KNOWN_FOLDER_FLAG)

Flags controlling folder retrieval behavior, such as KF_FLAG_CREATE or KF_FLAG_DEFAULT. Passed directly to SHGetKnownFolderPath.

pszPathBuffer (LPWSTR, optional)

Optional subdirectory path to append after the known folder. Length is validated via dwPathBufferLength and must not exceed MAX_PATH.

dwPathBufferLength (DWORD)

Length of pszPathBuffer. Must be 0 if pszPathBuffer is NULL, otherwise non-zero and = MAX_PATH.
“Violations… cause ERROR_INVALID_PARAMETER return.”

pszFileName (LPWSTR, optional)

Optional filename to append. If PATH_ADD_RANDOM_FILE_NAME is set, this must be NULL.

dwFileNameLength (DWORD)

Length of pszFileName. Must follow the same rules as dwPathBufferLength.

pNewPath (PUNICODE_STRING*, required output)

Output pointer receiving the newly allocated UNICODE_STRING. Always initialized to NULL before any operations.

dwFlags (DWORD)

Optional behavior flags:

  • 0 — no special processing
  • PATH_ADD_TRAILING_BACKSLASH — append trailing backslash
  • PATH_ADD_RANDOM_FILE_NAME — generate GUID filename

These flags are mutually exclusive.
“Setting both… is invalid and causes ERROR_INVALID_FLAGS return.”

Operational Sequence

The function performs validation and construction in a strict order:

  • Validate pNewPath and rfid (must be non-NULL).
  • Validate dwFlags (must be one of the allowed values).
  • Validate pointer/length relationships for pszPathBuffer and pszFileName.
  • Retrieve known folder via SHGetKnownFolderPath.
  • Compute total path length and ensure it does not exceed MAX_PATH.
  • Allocate a UNICODE_STRING with MAX_PATH capacity.
  • If random filename requested, generate GUID via GenerateTempFileName.
  • Format the complete path using StringCbPrintfEx.
  • Set Length and MaximumLength fields.
  • Return S_OK and assign *pNewPath.

“The constructed path is validated… and MaximumLength is set to MAX_PATH.”

Error Handling and Resource Management

A centralized cleanup block frees all temporary resources, including the known folder path returned by SHGetKnownFolderPath, any generated filename, and any temporary UNICODE_STRING. Ownership is transferred to the caller only on success.
“This ensures that all allocated resources… are freed regardless of which step fails.”

Typical Usage Pattern

Example usage:

  • BuildKnownFolderPath(&FOLDERID_LocalAppData, KF_FLAG_CREATE, L"MyApp\\Logs", 12, L"debug.log", 9, &pPath, 0)

Produces:
C:\Users\User\AppData\Local\MyApp\Logs\debug.log

  • BuildKnownFolderPath(&FOLDERID_Temp, KF_FLAG_DEFAULT, NULL, 0, NULL, 0, &pPath, PATH_ADD_RANDOM_FILE_NAME)

Produces a GUID-based filename such as:
C:\Users\User\AppData\Local\Temp\12345678-1234-1234-1234-123456789012

When finished, callers must free the returned path via FreeUnicodeString(pPath).


NewFileInfo

NewFileInfo Function Overview

    HRESULT _Must_inspect_result_ _Success_(SUCCEEDED(return)) NewFileInfo(
        _In_	PUNICODE_STRING		  pFilePath,
        _In_	DWORD                 dwDesiredAccess,
        _In_	DWORD                 dwSharedMode,
        _In_opt_	LPSECURITY_ATTRIBUTES pSecAttr,
        _Inout_	PFILE_INFO* pNewFileInfo,
        _In_	DWORD                 dwCreationDisposition,
        _In_	DWORD                 dwFlagsAndAttributes,
        _In_opt_ PLOCK_FILE_INFO      pLockInfo
    )	;

The NewFileInfo function is a comprehensive factory constructor that allocates, initializes, and validates a FILE_INFO structure representing an opened file with full metadata, security context, optional byte-range locking, and path descriptor information. It serves as the primary gateway for creating properly configured file handles within the mdts_io DLL, encapsulating Win32 file operations and defensive validation into a single, fail-safe entry point.
“It serves as the primary gateway for creating properly configured file handles…”

Function Purpose and Design Philosophy

NewFileInfo abstracts away the complexity of file creation and initialization by bundling multiple Win32 API calls (CreateFile, GetFileInformationByHandle, LockFile operations, path parsing) into a single transaction-like operation. The function implements an all-or-nothing contract: if any step fails, all previously acquired resources are cleaned up and the caller receives a clear error code.
“This design eliminates the common error of partial initialization or leaked handles…”

This design is especially valuable when both file access and explicit byte-range locking are required, ensuring that failure recovery always releases locks before closing the file handle.

Parameter Descriptions

pFilePath (PUNICODE_STRING, required)

Pointer to a well-formed UNICODE_STRING containing the file path. The buffer must be non-NULL, Length must be = MaximumLength, and MaximumLength must be = MAX_PATH. A malformed path causes immediate failure.
“The path must be well-formed (non-NULL buffer, logical Length = MaximumLength = MAX_PATH).”

dwDesiredAccess (DWORD)

Access rights passed directly to CreateFile. Common values include GENERIC_READ, GENERIC_WRITE, or both. Validation occurs implicitly during file opening.

dwSharedMode (DWORD)

File sharing constraints passed to CreateFile. Determines whether other processes may open the same file concurrently.

pSecAttr (PSECURITY_ATTRIBUTES, optional)

Optional security attributes validated via IsValidSecurityAttributes. Must contain absolute-format security descriptors. Copied into FILE_INFO on success.
“Invalid security attributes abort initialization with ERROR_INVALID_SECURITY_DESCR.”

pNewFileInfo (PFILE_INFO*, required output)

Output pointer receiving the newly allocated FILE_INFO structure. Always initialized to NULL before any operations to guarantee unambiguous failure semantics.

dwCreationDisposition (DWORD)

Creation behavior flags passed to CreateFile. Used to infer whether the file is newly created or existing for the bNewFile flag in PROG_FILE_PATH_DESC.

dwFlagsAndAttributes (DWORD)

File attributes and behavioral flags passed to CreateFile. FILE_FLAG_OVERLAPPED is propagated into the FILE_INFO attributes mask.

pLockInfo (PLOCK_FILE_INFO, optional)

Optional byte-range locking descriptor. If provided, all regions must be valid and within FILE_INFO_MAX_FILE_SIZE. Locking failures trigger rollback and cleanup.
“If any region fails to lock, all previously locked regions are unlocked via rollback…”

Operational Sequence

The function performs initialization in a strict, fail-fast order:

  • Validate pFilePath and pNewFileInfo (must be non-NULL).
  • Validate the UNICODE_STRING path (buffer, Length, MaximumLength, MAX_PATH).
  • Validate pLockInfo if provided (region count, offsets, sizes).
  • Validate security attributes if provided.
  • Parse and validate filename via PathFindFileNameW.
  • Allocate FILE_INFO via calloc.
  • Open the file via CreateFile.
  • Extract file metadata via GetFileInformationByHandle.
  • Copy security attributes if provided.
  • Lock byte-range regions if pLockInfo is provided.
  • Duplicate the path via NewUnicodeString.
  • Re-extract filename from duplicated buffer and validate.
  • Store access rights, share mode, and flags.
  • Validate the complete structure via IsValidFileInfo.
  • Return S_OK and assign *pNewFileInfo.

“Finally, if all validations pass, the FILE_INFO pointer is assigned… and S_OK is returned.”

Cleanup and Error Handling

The function uses a centralized cleanup block that closes the file handle, unlocks regions, frees allocated UNICODE_STRING buffers, clears the path descriptor, frees temporary data, and finally frees the FILE_INFO structure.

“This ensures no resource leak occurs regardless of which validation step fails.”

Typical Usage Pattern

A caller may invoke:

  • NewFileInfo(pPath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, &pFileInfo, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, pLockInfo)

On success, pFileInfo points to a fully initialized, validated, and optionally locked file structure. On failure, pFileInfo remains NULL and the caller checks the returned error code.

When finished, the caller must invoke FreeFileInfo(pFileInfo) to release all resources.


NewUnicodeString

NewUnicodeString Function Overview

    PUNICODE_STRING _Must_inspect_result_ _Success_(SUCCEEDED(return)) NewUnicodeString(
        _Pre_satisfies_(Length >= 1 && Length <= MAX_STRING_LENGTH) USHORT const Length,
        _Pre_satisfies_(MaximumLength >= 1 && MaximumLength <= MAX_STRING_LENGTH) USHORT const MaximumLength,
        _In_opt_z_ LPCWSTR Buffer
    );

The NewUnicodeString function is a memory-safe factory constructor that dynamically allocates and initializes a UNICODE_STRING structure with a wide-character (UTF-16) buffer. It serves as the primary mechanism for creating properly formatted Unicode string objects throughout the mdts_io DLL, ensuring consistent initialization and defensive validation of input parameters.

Function Purpose and Design Philosophy

NewUnicodeString encapsulates the creation logic for UNICODE_STRING structures, which are fundamental Win32 types used throughout the Windows API for representing variable-length Unicode text. Rather than requiring callers to manually allocate memory, initialize fields, and validate constraints, this function provides a single, controlled entry point that guarantees well-formed output or unambiguous failure (NULL return).

This design reduces the likelihood of buffer overruns, uninitialized fields, and off-by-one errors that commonly plague manual string management in C.

The function implements a two-phase initialization strategy: it first validates all input parameters defensively, then allocates and initializes memory only after confirming that the input contract will be satisfiable. This fail-fast approach prevents partial allocations or corrupted state when invalid inputs are detected.

Parameter Descriptions

Length (USHORT const)

Logical length of the string in wide characters. Valid range is 1 to 65535. Represents the number of meaningful characters to be stored. The function validates defensively even though SAL contracts guarantee the range. A value of zero is rejected and results in NULL.

MaximumLength (USHORT const)

Total capacity of the string buffer in wide characters. Must be ≥ Length. Valid range is 1 to 65535. This value determines the heap allocation size. If MaximumLength < Length, the function aborts and returns NULL.

Buffer (LPCWSTR, optional)

Optional source wide-character string to copy into the newly allocated buffer. If NULL, the function creates an empty UNICODE_STRING with pre-allocated capacity. If non-NULL, exactly Length characters are copied using wcsncpy_s. NUL termination in the source is not required; the Length parameter governs the copy.

Operational Sequence

The function executes in the following order:

  • Validate Length and MaximumLength (non-zero, within bounds, and Length = MaximumLength).
  • Allocate the UNICODE_STRING structure; initialize fields to safe defaults.
  • Re-validate MaximumLength defensively.
  • Allocate the buffer with (MaximumLength + 1) * sizeof(wchar_t).
  • Initialize the buffer with a NUL terminator at index 0.
  • If a source buffer is provided, copy exactly Length characters using wcsncpy_s.
  • On copy success, set Length; on failure, free all memory and return NULL.
  • If no source buffer is provided, leave Length = 0 and keep the allocated capacity.
  • Return the fully initialized UNICODE_STRING or NULL on failure.

Typical Usage Pattern

A caller may invoke:

  • NewUnicodeString(256, 256, L"C:\\Users\\Example\\File.txt") — creates a populated string with 256-character capacity.
  • NewUnicodeString(512, 512, NULL) — creates an empty string with 512-character capacity.

The returned pointer is valid only on success. NULL indicates failure and requires no cleanup. When the string is no longer needed, the caller must invoke FreeUnicodeString to release both the buffer and the structure.

Error Handling and Contract Guarantees

On any failure (validation, allocation, or copy), the function returns NULL. No partial structure is returned, and no exception is raised. This simplifies error handling: NULL is unambiguous.

On success, all fields are fully initialized, the buffer is NUL-terminated, and the caller has exclusive ownership of the structure and must free it later using FreeUnicodeString.


Duplicate FILE_INFO

Creates a new independent FILE_INFO by reopening the same file path with identical access rights.

Parameters

pFileInfo

[In] Pointer to an existing, valid FILE_INFO structure to be duplicated.

  • Must be a non-NULL, previously allocated FILE_INFO created by NewFileInfo().
  • The file must still exist and be accessible with the original access rights.
  • The FILE_INFO structure itself is not modified.

ppNewFileInfo

[Out] Pointer to a FILE_INFO pointer that will receive the newly allocated structure.

  • On success: points to a new, independent FILE_INFO with a fresh file handle to the same path.
  • On failure: set to NULL.
  • The new FILE_INFO has the same path, access rights, share mode, and attributes as the source.
  • The new FILE_INFO is independent: closing one does not affect the other.
  • Caller is responsible for freeing via FreeFileInfo().

Returns

S_OK on success; appropriate HRESULT error codes on failure:

  • ERROR_INVALID_PARAMETER: pFileInfo or ppNewFileInfo is NULL.
  • ERROR_FILE_NOT_FOUND: File no longer exists or is inaccessible.
  • ERROR_ACCESS_DENIED: Insufficient permissions to reopen the file.
  • ERROR_SHARING_VIOLATION: File is locked or being used by another process.
  • ERROR_OUTOFMEMORY: Memory allocation for new FILE_INFO structure failed.
  • ERROR_INVALID_DATA: Reopened FILE_INFO failed validation checks.

Remarks

Operation Details

This function reopens the file referenced by the source FILE_INFO, creating a completely independent FILE_INFO structure with a new file handle. The two structures can be used concurrently without interference. The operation preserves the original access rights, sharing mode, security attributes, and file attributes. No file locking is applied to the new FILE_INFO (lock parameters are all zero).

Use Cases

  • Create multiple independent handles to the same file for concurrent operations.
  • Ensure the file is still accessible (validates file still exists and can be reopened).
  • Transfer file access to a different context while maintaining original access parameters.

Important Constraints

  • The source file must still exist when this function is called.
  • The file must be accessible with the original access rights.
  • Both FILE_INFO structures must be freed independently via FreeFileInfo().


FileInfo

FILE_INFO Structure Overview

Encapsulates a file handle with comprehensive metadata, security context, and path information.

Structure Overview

This structure maintains a complete record of an open file, including the file handle, system metadata, custom timestamps, security attributes, and path information. It serves as the primary container for file operations throughout the mdts_io library.

Field Descriptions

dwCategory

  • Generic classification number for the file (can be 0).
  • Used for categorizing files by type or source without strict type constraints.

SecAttr

  • Security attributes applied when the file was opened.
  • Includes the security descriptor, inheritance flag, and structure length.
  • Preserves the original security context.

hFile

  • Windows file handle obtained from CreateFile().
  • Must be valid and open; used for all file operations (read, write, lock, close).
  • Validated as INVALID_HANDLE_VALUE when deallocated.

Fileinfo

  • BY_HANDLE_FILE_INFORMATION structure populated by GetFileInformationByHandle().
  • Contains file attributes, timestamps (creation, access, write), file size (high/low 32-bit components), and volume serial number.
  • Queried once at file creation and not updated.

pPathDesc

  • PROG_FILE_PATH_DESC pointer holding the file path as a UNICODE_STRING.
  • Includes file type, encoding flags, and optional decryption tag.
  • Always maintained as a separate allocation.
  • Freed via FreeFileInfo().

pszFileName

  • Direct pointer to the filename within the path buffer.
  • Extracted via PathFindFileNameW() for quick access.
  • Deprecated: Use usFileNameOffset and GET_FILEINFO_FILENAME() instead.

pFiletime

  • Optional FILETIME pointer for a custom timestamp associated with the file.
  • May be NULL if no custom time is set.
  • If allocated, must be freed via FreeFileInfo().

Resource Management

  • Allocated via NewFileInfo().
  • Must be freed via FreeFileInfo() to release hFile, pPathDesc.pFilePath, and pFiletime.
  • Closing hFile does not affect pPathDesc or pFiletime; they are independent allocations.
  • Validation performed by IsValidFileInfo() checks handle validity, path consistency, and file existence.

Important Notes

  • All pointer fields (pPathDesc, pszFileName, pFiletime) are owned by FILE_INFO and must not be freed independently.
  • Use FreeFileInfo() to release the entire structure.
  • pszFileName is transitional and deprecated — use GET_FILEINFO_FILENAME() or usFileNameOffset.
  • The BY_HANDLE_FILE_INFORMATION snapshot is static; file size or attributes may change on disk after creation without affecting the structure.


FilePathDesc

PROG_FILE_PATH_DESC Structure

        typedef struct PROG_FILE_PATH_DESC {
        DWORD			dwType;
        BOOL				bNewFile;
        DWORD			dwEncodingFlags;
        PUNICODE_STRING		pFilePath;
        PCRYPT_DATA_BLOB                 pTag;
       } FILE_PATH_DESC, *PFILE_PATH_DESC;
} PROG_FILE_PATH_DESC;

The PROG_FILE_PATH_DESC structure is a descriptor container that encapsulates all essential metadata required to identify, classify, and process a file within the mdts_io DLL framework. This structure serves as a bridge between high-level file operations and the underlying file system, carrying contextual information that determines how a file should be accessed, encrypted, or decrypted.

Structure Purpose and Usage

The primary purpose of PROG_FILE_PATH_DESC is to provide a unified representation of a file's identity and operational context. Rather than passing individual parameters (path, type, encoding state) across function boundaries, callers can bundle this information into a single structure, improving code clarity and maintainability.

This is particularly valuable in scenarios involving file cryptography, where encoding/decoding decisions depend on both the file's type and its current processing state.

Member Descriptions

dwType (DWORD)

A generic type identifier that categorizes the file. Values range from 0 to 63 (a 6-bit constraint), allowing the application to define up to 64 distinct file classifications. This may distinguish between log files, configuration files, encrypted payloads, temporary files, or other application-specific categories. The specific values are determined by the application's file type enumeration.

bNewFile (BOOL)

Indicates whether the file represents a newly created entity (TRUE) or an existing file being opened (FALSE). This distinction is critical for initialization logic: new files may require default metadata, while existing files must be validated and have their metadata read from storage.

dwEncodingFlags (DWORD)

A bitmask containing encoding/cryptographic operation flags derived from Win32 encoding functions. Common values include:

  • CRYPT_STRING_BASE64 (1) — File requires encryption
  • CRYPT_STRING_HEX (2) — File requires decryption
  • Flags from Win32 API

This field drives the cryptographic workflow, determining whether the file should be encrypted, decrypted, or left untouched.

pFilePath (PUNICODE_STRING)

Pointer to a dynamically allocated UNICODE_STRING structure containing the full file path in wide-character format. The caller must allocate this structure (typically via NewUnicodeString()) and ensure the path remains valid throughout the descriptor's lifetime.

The path must be properly null-terminated and reference a file accessible via Win32 APIs. A NULL pointer indicates an invalid or uninitialized descriptor.

pTag (PCRYPT_DATA_BLOB)

Pointer to a CRYPT_DATA_BLOB containing cryptographic metadata such as a decryption tag or initialization vector. This field is optional and may be NULL if no cryptographic context is required.

The tag is typically used during decryption operations to validate authenticity or reconstruct cryptographic context. This member is marked for future removal, indicating that cryptographic handling may be refactored in upcoming versions.

Typical Usage Pattern

A function receiving a PROG_FILE_PATH_DESC would:

  • Extract the file path from pFilePath
  • Examine dwType to determine type-specific handling
  • Check bNewFile to decide initialization behavior
  • Consult dwEncodingFlags to determine cryptographic operations
  • Use pTag if encryption/decryption is required

For example, a file-processing function might open the file referenced by pFilePath, validate its type, and then conditionally encrypt or decrypt its contents based on dwEncodingFlags. If bNewFile is TRUE, the function may initialize default metadata; otherwise, it reads and validates existing metadata.