CreateWaitableTimerEx and SetWaitableTimerEx with high resolution flag, name and callback. Bug or feature?

Viewed 57

I try to use Windows high resolution waitable timer and completion routine.

  1. If create a waitable timer (call CreateWaitableTimerExW) with a name and CREATE_WAITABLE_TIMER_HIGH_RESOLUTION flag, it returns NULL and error code 0x57 (87) "wrong parameter".
  2. If create a waitable timer with the flag CREATE_WAITABLE_TIMER_HIGH_RESOLUTION and without name, it returns valid handle, then call SetWaitableTimerEx (or SetWaitableTimer) with completion routing it returns FALSE and error code 0x57 (87).
  3. It works if call CreateWaitableTimerExW without CREATE_WAITABLE_TIMER_HIGH_RESOLUTION flag.

Here is an example to reproduce problems. In the following example, just uncomment your desired CreateWaitableTimerExW call to see the results.

The question: is it a bug or known feature? I didn't find anything in MS documents regarding high resolution timers, names and callbacks.

#include <iostream>
#include <windows.h>
#include <tchar.h>

void TimerRoutine(LPVOID lpArgToCompletionRoutine, DWORD dwTimerLowValue, DWORD dwTimerHighValue)
{
    HANDLE* hEvent = static_cast<HANDLE*>(lpArgToCompletionRoutine);
    if (hEvent != nullptr)
    {
        std::cout << "Test succeeded!\n";
        SetEvent(*hEvent);
    }
}

int main()
{
    constexpr int64_t COEFF{ -10'000 };
    constexpr int64_t TIMEOUT{ 5'000 };

    HANDLE hEvent = CreateEvent(nullptr, TRUE, FALSE, _T("AnEvent"));
    if (hEvent == nullptr)
    {
        DWORD err = GetLastError();
        std::cerr << "Failed to create an event object, error code = " << err << std::endl;
        return -1;
    }

    // Create high resolution waitable timer. Uncomment one of them and compare behavior.
    HANDLE hTimer = CreateWaitableTimerExW(nullptr, L"ATimer", CREATE_WAITABLE_TIMER_HIGH_RESOLUTION, TIMER_ALL_ACCESS);
    // HANDLE hTimer = CreateWaitableTimerExW(nullptr, nullptr, CREATE_WAITABLE_TIMER_HIGH_RESOLUTION, TIMER_ALL_ACCESS);
    // HANDLE hTimer = CreateWaitableTimerExW(nullptr, L"ATimer", 0, TIMER_ALL_ACCESS);
    if (hTimer == nullptr)
    {
        DWORD err = GetLastError();
        std::cerr << "Failed to create a high resolution waitable timer with a name, error code = " << err << std::endl;
        CloseHandle(hEvent);
        return -1;
    }

    // Set timer with callback, relative timeout.
    LARGE_INTEGER dueTime;
    dueTime.QuadPart = TIMEOUT * COEFF;
    if (SetWaitableTimerEx(hTimer, &dueTime, 0, &TimerRoutine, &hEvent, nullptr, 0) == FALSE)
    {
        DWORD err = GetLastError();
        std::cerr << "Failed to set timer, error code = " << err << std::endl;
        CloseHandle(hTimer);
        CloseHandle(hEvent);
        return -1;
    }

    // Wait until event object is signaled from the timer callback.
    WaitForSingleObjectEx(hEvent, INFINITE, TRUE);

    CloseHandle(hTimer);
    CloseHandle(hEvent);

    return 0;
}
0 Answers
Related