IInspectable
IInspectable

Reputation: 51506

How does WaitForDebugEvent[Ex] report a timeout?

The WaitForDebugEvent and WaitForDebugEventEx APIs allow a caller to specify a timeout. The functions return when a debug event occurred, or the timeout expired, whichever happened first. While the documentation describes how debug events are reported, there's no information at all on the APIs' behaviors in case of a timeout.

Questions

Upvotes: 2

Views: 362

Answers (1)

Neitsa
Neitsa

Reputation: 8176

How do the APIs report a timeout?

The function returns FALSE and sets the last error to ERROR_SEM_TIMEOUT(0x79).

Does this protocol hold for a value of 0 for dwMilliseconds as well?

Yes.


Since it's not documented we'll go with the implementation (I'm on Win 10).

enter image description here

Both kernelbase!WaitForDebugEvent and kernelbase!WaitForDebugEventEx APIs call the same piece of code (simply with a different arg).

In the shared piece of code the second call is made on ntdll!DbgUiWaitStateChange which itself is a simple wrapper around ntdll!NtWaitForDebugEvent.

On function return the code checks if the returned status is either STATUS_ALERTED (0x101) or STATUS_USER_APC (0xc0). If it is, it keeps calling the previous function (ntdll!DbgUiWaitStateChange), otherwise it checks if the status is an error (more precisely if the status is signed).

If it's not signed it checks that the status is STATUS_TIMEOUT (0x102). If it is, the NT Status is converted to a win32 error - from STATUS_TIMEOUT to ERROR_SEM_TIMEOUT (0x79) - and the function is exited.


Inside nt!NtWaitForDebugEvent (kernel level) we can have a good overview of what is happening with the ReactOS source code.

After a call to nt!KeWaitForSingleObject on the debug object the code checks (source) what is the status of the call. If it is STATUS_TIMEOUT (which, if I'm not mistaken should happen in case of a 0 timeout), the function bails out and return the current status, which is, as explained above, converted to ERROR_SEM_TIMEOUT in userland.

         Status = KeWaitForSingleObject(&DebugObject->EventsPresent,
                                        Executive,
                                        PreviousMode,
                                        Alertable,
                                        Timeout);
         if (!NT_SUCCESS(Status) ||
             (Status == STATUS_TIMEOUT) ||
             (Status == STATUS_ALERTED) ||
             (Status == STATUS_USER_APC))
         {
             /* Break out the wait */
             break;

Upvotes: 4

Related Questions