in Detours/creatwth.cpp [584:729]
BOOL WINAPI DetourUpdateProcessWithDllEx(_In_ HANDLE hProcess,
_In_ HMODULE hModule,
_In_ BOOL bIs32BitProcess,
_In_reads_(nDlls) LPCSTR *rlpDlls,
_In_ DWORD nDlls)
{
// Find the next memory region that contains a mapped PE image.
//
BOOL bIs32BitExe = FALSE;
DETOUR_TRACE(("DetourUpdateProcessWithDllEx(%p,%p,dlls=%d)\n", hProcess, hModule, nDlls));
IMAGE_NT_HEADERS32 inh;
if (hModule == NULL || LoadNtHeaderFromProcess(hProcess, hModule, &inh) == NULL) {
SetLastError(ERROR_INVALID_OPERATION);
return FALSE;
}
if (inh.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC
&& inh.FileHeader.Machine != 0) {
bIs32BitExe = TRUE;
}
DETOUR_TRACE((" 32BitExe=%d 32BitProcess\n", bIs32BitExe, bIs32BitProcess));
if (hModule == NULL) {
SetLastError(ERROR_INVALID_OPERATION);
return FALSE;
}
// Save the various headers for DetourRestoreAfterWith.
//
DETOUR_EXE_RESTORE der;
if (!RecordExeRestore(hProcess, hModule, der)) {
return FALSE;
}
#if defined(DETOURS_64BIT)
// Try to convert a neutral 32-bit managed binary to a 64-bit managed binary.
if (bIs32BitExe && !bIs32BitProcess) {
if (!der.pclr // Native binary
|| (der.clr.Flags & 1) == 0 // Or mixed-mode MSIL
|| (der.clr.Flags & 2) != 0) { // Or 32BIT Required MSIL
SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
if (!UpdateFrom32To64(hProcess, hModule,
#if defined(DETOURS_X64)
IMAGE_FILE_MACHINE_AMD64,
#elif defined(DETOURS_IA64)
IMAGE_FILE_MACHINE_IA64,
#elif defined(DETOURS_ARM64)
IMAGE_FILE_MACHINE_ARM64,
#else
#error Must define one of DETOURS_X64 or DETOURS_IA64 or DETOURS_ARM64 on 64-bit.
#endif
der)) {
return FALSE;
}
bIs32BitExe = FALSE;
}
#endif // DETOURS_64BIT
// Now decide if we can insert the detour.
#if defined(DETOURS_32BIT)
if (bIs32BitProcess) {
// 32-bit native or 32-bit managed process on any platform.
if (!UpdateImports32(hProcess, hModule, rlpDlls, nDlls)) {
return FALSE;
}
}
else {
// 64-bit native or 64-bit managed process.
//
// Can't detour a 64-bit process with 32-bit code.
// Note: This happens for 32-bit PE binaries containing only
// manage code that have been marked as 64-bit ready.
//
SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
#elif defined(DETOURS_64BIT)
if (bIs32BitProcess || bIs32BitExe) {
// Can't detour a 32-bit process with 64-bit code.
SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
else {
// 64-bit native or 64-bit managed process on any platform.
if (!UpdateImports64(hProcess, hModule, rlpDlls, nDlls)) {
return FALSE;
}
}
#else
#pragma Must define one of DETOURS_32BIT or DETOURS_64BIT.
#endif // DETOURS_64BIT
/////////////////////////////////////////////////// Update the CLR header.
//
if (der.pclr != NULL) {
DETOUR_CLR_HEADER clr;
CopyMemory(&clr, &der.clr, sizeof(clr));
clr.Flags &= 0xfffffffe; // Clear the IL_ONLY flag.
DWORD dwProtect;
if (!DetourVirtualProtectSameExecuteEx(hProcess, der.pclr, sizeof(clr), PAGE_READWRITE, &dwProtect)) {
DETOUR_TRACE(("VirtualProtectEx(clr) write failed: %d\n", GetLastError()));
return FALSE;
}
if (!WriteProcessMemory(hProcess, der.pclr, &clr, sizeof(clr), NULL)) {
DETOUR_TRACE(("WriteProcessMemory(clr) failed: %d\n", GetLastError()));
return FALSE;
}
if (!VirtualProtectEx(hProcess, der.pclr, sizeof(clr), dwProtect, &dwProtect)) {
DETOUR_TRACE(("VirtualProtectEx(clr) restore failed: %d\n", GetLastError()));
return FALSE;
}
DETOUR_TRACE(("CLR: %p..%p\n", der.pclr, der.pclr + der.cbclr));
#if DETOURS_64BIT
if (der.clr.Flags & 0x2) { // Is the 32BIT Required Flag set?
// X64 never gets here because the process appears as a WOW64 process.
// However, on IA64, it doesn't appear to be a WOW process.
DETOUR_TRACE(("CLR Requires 32-bit\n", der.pclr, der.pclr + der.cbclr));
SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
#endif // DETOURS_64BIT
}
//////////////////////////////// Save the undo data to the target process.
//
if (!DetourCopyPayloadToProcess(hProcess, DETOUR_EXE_RESTORE_GUID, &der, sizeof(der))) {
DETOUR_TRACE(("DetourCopyPayloadToProcess failed: %d\n", GetLastError()));
return FALSE;
}
return TRUE;
}