I try to use Windows high resolution waitable timer and completion routine.
- If create a waitable timer (call
CreateWaitableTimerExW) with a name andCREATE_WAITABLE_TIMER_HIGH_RESOLUTIONflag, it returnsNULLand error code 0x57 (87) "wrong parameter". - If create a waitable timer with the flag
CREATE_WAITABLE_TIMER_HIGH_RESOLUTIONand without name, it returns valid handle, then callSetWaitableTimerEx(orSetWaitableTimer) with completion routing it returnsFALSEand error code 0x57 (87). - It works if call
CreateWaitableTimerExWwithoutCREATE_WAITABLE_TIMER_HIGH_RESOLUTIONflag.
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;
}