in Detours/detours.cpp [2140:2277]
LONG WINAPI DetourDetach(_Inout_ PVOID *ppPointer,
_In_ PVOID pDetour)
{
LONG error = NO_ERROR;
if (s_nPendingThreadId != (LONG)GetCurrentThreadId()) {
return ERROR_INVALID_OPERATION;
}
// If any of the pending operations failed, then we don't need to do this.
if (s_nPendingError != NO_ERROR) {
return s_nPendingError;
}
if (pDetour == NULL) {
return ERROR_INVALID_PARAMETER;
}
if (ppPointer == NULL) {
return ERROR_INVALID_HANDLE;
}
if (*ppPointer == NULL) {
error = ERROR_INVALID_HANDLE;
s_nPendingError = error;
s_ppPendingError = ppPointer;
DETOUR_BREAK();
return error;
}
DetourOperation *o = new NOTHROW DetourOperation;
if (o == NULL) {
error = ERROR_NOT_ENOUGH_MEMORY;
fail:
s_nPendingError = error;
DETOUR_BREAK();
stop:
if (o != NULL) {
delete o;
o = NULL;
}
s_ppPendingError = ppPointer;
return error;
}
#ifdef DETOURS_IA64
PPLABEL_DESCRIPTOR ppldTrampo = (PPLABEL_DESCRIPTOR)*ppPointer;
PPLABEL_DESCRIPTOR ppldDetour = (PPLABEL_DESCRIPTOR)pDetour;
PVOID pDetourGlobals = NULL;
PVOID pTrampoGlobals = NULL;
pDetour = (PBYTE)DetourCodeFromPointer(ppldDetour, &pDetourGlobals);
PDETOUR_TRAMPOLINE pTrampoline = (PDETOUR_TRAMPOLINE)
DetourCodeFromPointer(ppldTrampo, &pTrampoGlobals);
DETOUR_TRACE((" ppldDetour=%p, code=%p [gp=%p]\n",
ppldDetour, pDetour, pDetourGlobals));
DETOUR_TRACE((" ppldTrampo=%p, code=%p [gp=%p]\n",
ppldTrampo, pTrampoline, pTrampoGlobals));
DETOUR_TRACE(("\n"));
DETOUR_TRACE(("detours: &pldTrampoline =%p\n",
&pTrampoline->pldTrampoline));
DETOUR_TRACE(("detours: &bMovlTargetGp =%p [%p]\n",
&pTrampoline->bMovlTargetGp,
pTrampoline->bMovlTargetGp.GetMovlGp()));
DETOUR_TRACE(("detours: &rbCode =%p [%p]\n",
&pTrampoline->rbCode,
((DETOUR_IA64_BUNDLE&)pTrampoline->rbCode).GetBrlTarget()));
DETOUR_TRACE(("detours: &bBrlRemainEip =%p [%p]\n",
&pTrampoline->bBrlRemainEip,
pTrampoline->bBrlRemainEip.GetBrlTarget()));
DETOUR_TRACE(("detours: &bMovlDetourGp =%p [%p]\n",
&pTrampoline->bMovlDetourGp,
pTrampoline->bMovlDetourGp.GetMovlGp()));
DETOUR_TRACE(("detours: &bBrlDetourEip =%p [%p]\n",
&pTrampoline->bCallDetour,
pTrampoline->bCallDetour.GetBrlTarget()));
DETOUR_TRACE(("detours: pldDetour =%p [%p]\n",
pTrampoline->ppldDetour->EntryPoint,
pTrampoline->ppldDetour->GlobalPointer));
DETOUR_TRACE(("detours: pldTarget =%p [%p]\n",
pTrampoline->ppldTarget->EntryPoint,
pTrampoline->ppldTarget->GlobalPointer));
DETOUR_TRACE(("detours: pbRemain =%p\n",
pTrampoline->pbRemain));
DETOUR_TRACE(("detours: pbDetour =%p\n",
pTrampoline->pbDetour));
DETOUR_TRACE(("\n"));
#else // !DETOURS_IA64
PDETOUR_TRAMPOLINE pTrampoline =
(PDETOUR_TRAMPOLINE)DetourCodeFromPointer(*ppPointer, NULL);
pDetour = DetourCodeFromPointer(pDetour, NULL);
#endif // !DETOURS_IA64
////////////////////////////////////// Verify that Trampoline is in place.
//
LONG cbTarget = pTrampoline->cbRestore;
PBYTE pbTarget = pTrampoline->pbRemain - cbTarget;
if (cbTarget == 0 || cbTarget > sizeof(pTrampoline->rbCode)) {
error = ERROR_INVALID_BLOCK;
if (s_fIgnoreTooSmall) {
goto stop;
}
else {
DETOUR_BREAK();
goto fail;
}
}
if (pTrampoline->pbDetour != pDetour) {
error = ERROR_INVALID_BLOCK;
if (s_fIgnoreTooSmall) {
goto stop;
}
else {
DETOUR_BREAK();
goto fail;
}
}
DWORD dwOld = 0;
if (!VirtualProtect(pbTarget, cbTarget,
PAGE_EXECUTE_READWRITE, &dwOld)) {
error = GetLastError();
DETOUR_BREAK();
goto fail;
}
o->fIsRemove = TRUE;
o->ppbPointer = (PBYTE*)ppPointer;
o->pTrampoline = pTrampoline;
o->pbTarget = pbTarget;
o->dwPerm = dwOld;
o->pNext = s_pPendingOperations;
s_pPendingOperations = o;
return NO_ERROR;
}