I have a few quick questions about the Microsoft Detours Library. I have used it before (successfully), but I just had a thought about this function:
LONG DetourUpdateThread(HANDLE hThread);
I read elsewhere that this function will actually suspend the thread until the transaction completes. This seems odd since most sample code calls:
DetourUpdateThread(GetCurrentThread());
Anyway, apparently this function "enlists" threads so that, when the transaction commits (and the detours are made), their instruction pointers are modified if they lie "within the rewritten code in either the target function or the trampoline function."
My questions are:
When the transaction commits, is the current thread's instruction pointer going to be within the DetourTransactionCommit function? If so, why should we bother enlisting it to be updated?
Also, if the enlisted threads are suspended, how can the current thread continue executing (given that most sample code calls DetourUpdateThread(GetCurrentThread());)?
Finally, could you suspend all threads for the current process, avoiding race conditions (considering that threads could be getting created and destroyed at any time)? Perhaps this is done when the transaction begins? This would allow us to enumerate threads more safely (as it seems less likely that new threads could be created), although what about CreateRemoteThread()?
Thanks,
Paul
For reference, here is an extract from the simple sample:
// DllMain function attaches and detaches the TimedSleep detour to the
// Sleep target function. The Sleep target function is referred to
// through the TrueSleep target pointer.
BOOL WINAPI DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID reserved)
{
if (dwReason == DLL_PROCESS_ATTACH) {
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)TrueSleep, TimedSleep);
DetourTransactionCommit();
}
else if (dwReason == DLL_PROCESS_DETACH) {
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourDetach(&(PVOID&)TrueSleep, TimedSleep);
DetourTransactionCommit();
}
return TRUE;
}