diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 44e7bbd8..091438a9 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -7,12 +7,17 @@ env: # Compile in parallel where possible. CL: /MP -# Triggers the workflow on push or pull request events for the master branch. +# Triggers the workflow on push or pull request events for the main branch. on: push: - branches: [ master ] + branches: [ main ] pull_request: - branches: [ master ] + branches: [ main ] + +permissions: + actions: read + contents: read + security-events: write jobs: build: @@ -21,12 +26,12 @@ jobs: fail-fast: false matrix: os: [windows-2019, windows-2022] - arch: [x86, x64, x64_arm, x64_arm64] + arch: [x86, x64, x64_arm64] conf: [Release, Debug] steps: - name: Clone Repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 # Setup build environment variables using vcvarsall.bat. - name: Configure MSCV Compiler for ${{ matrix.arch }} @@ -35,7 +40,7 @@ jobs: arch: ${{ matrix.arch }} - name: Initialize CodeQL for C++ - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 if: ${{ matrix.os == 'windows-2019' && matrix.conf == 'Debug' }} with: languages: cpp @@ -56,14 +61,14 @@ jobs: if: ${{ matrix.arch == 'x86' || matrix.arch == 'x64' }} - name: Upload artifacts for ${{ matrix.arch }} on ${{ matrix.os }} - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: - name: artifacts-${{ matrix.os }} + name: artifacts-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.conf }} path: | lib.*/ bin.*/ include/ - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@v3 if: ${{ matrix.os == 'windows-2019' && matrix.conf == 'Debug' }} diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..b2f52a2b --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +Copyright (c) Microsoft Corporation. + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 84a4d14f..8fe4043e 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ and allows the community to support Detours using open source tools and processe Detours is compatible with the Windows NT family of operating systems: Windows NT, Windows XP, Windows Server 2003, Windows 7, -Windows 8, and Windows 10. It cannot be used by Windows Store apps +Windows 8, Windows 10, and Windows 11. It cannot be used by Windows Store apps because Detours requires APIs not available to those applications. This repo contains the source code for version 4.0.1 of Detours. diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 00000000..e138ec5d --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,41 @@ + + +## Security + +Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). + +If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below. + +## Reporting Security Issues + +**Please do not report security vulnerabilities through public GitHub issues.** + +Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report). + +If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey). + +You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc). + +Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: + + * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) + * Full paths of source file(s) related to the manifestation of the issue + * The location of the affected source code (tag/branch/commit or direct URL) + * Any special configuration required to reproduce the issue + * Step-by-step instructions to reproduce the issue + * Proof-of-concept or exploit code (if possible) + * Impact of the issue, including how an attacker might exploit the issue + +This information will help us triage your report more quickly. + +If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs. + +## Preferred Languages + +We prefer all communications to be in English. + +## Policy + +Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd). + + diff --git a/samples/commem/commem.cpp b/samples/commem/commem.cpp index 67798438..b713fb6e 100644 --- a/samples/commem/commem.cpp +++ b/samples/commem/commem.cpp @@ -86,7 +86,10 @@ int main(int argc, char **argv) DetourTransactionBegin(); DetourUpdateThread(GetCurrentThread()); - DetourAttach(&(PVOID&)RealIStreamWrite, MineIStreamWrite); + if (DetourAttach(&(PVOID&)RealIStreamWrite, MineIStreamWrite) != NO_ERROR) { + printf("commem: DetourAttach failed.\n"); + return 1; + } DetourTransactionCommit(); printf("commem: Calling Write w/o after attach.\n"); diff --git a/samples/common.mak b/samples/common.mak index 9a909f25..5612f3de 100644 --- a/samples/common.mak +++ b/samples/common.mak @@ -61,6 +61,17 @@ CFLAGS=$(CFLAGS) /D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE CFLAGS=$(CFLAGS) /D_$(DETOURS_TARGET_PROCESSOR:X64=AMD64)_ # redundant with windows.h except for midl proxies +!ELSEIF "$(DETOURS_TARGET_PROCESSOR)" == "ARM64" + +ASM=armasm64 + +!ELSEIF "$(DETOURS_TARGET_PROCESSOR)" == "ARM64EC" + +ASM=ml64 +CFLAGS=/arm64EC $(CFLAGS) +LIBFLAGS=$(LIBFLAGS) /machine:arm64x +LINKFLAGS=$(LINKFLAGS) /machine:arm64ec softintrin.lib + !ENDIF DEPS = $(LIBD)\syelog.lib $(LIBD)\detours.lib diff --git a/samples/cping/Makefile b/samples/cping/Makefile index b750a2a2..a4ada9bc 100644 --- a/samples/cping/Makefile +++ b/samples/cping/Makefile @@ -70,6 +70,8 @@ MIDLFLAGS=$(MIDLFLAGS) /x64 MIDLFLAGS=$(MIDLFLAGS) /arm32 !ELSEIF "$(DETOURS_TARGET_PROCESSOR)" == "ARM64" MIDLFLAGS=$(MIDLFLAGS) /arm64 +!ELSEIF "$(DETOURS_TARGET_PROCESSOR)" == "ARM64EC" +MIDLFLAGS=$(MIDLFLAGS) /x64 !ENDIF OBJS = \ diff --git a/samples/cping/cping.cpp b/samples/cping/cping.cpp index 43123417..003d9784 100644 --- a/samples/cping/cping.cpp +++ b/samples/cping/cping.cpp @@ -30,7 +30,7 @@ #include #include "iping.h" -// ARM64 ReadTimeStampCounter is a function. +// ARM64/ARM64EC ReadTimeStampCounter is a function. // ARM ReadTimeStampCounter is a declared function but not implemented. // old IA64: ReadTimeStampCounter nonexisant. // new IA64: ReadTimeStampCounter is a macro. @@ -38,7 +38,7 @@ // new x86: ReadTimeStampCounter is a macro. // AMD64: ReadTimeStampCounter is a macro. -#if defined(_ARM64_) || defined(ReadTimeStampCounter) +#if defined(_ARM64_) || defined(_ARM64EC_) || defined(ReadTimeStampCounter) #define GetTimeStamp() ReadTimeStampCounter() #elif defined(_X86_) || defined(_AMD64_) extern "C" diff --git a/samples/disas/Makefile b/samples/disas/Makefile index ecf0f66b..88195cf2 100644 --- a/samples/disas/Makefile +++ b/samples/disas/Makefile @@ -36,7 +36,7 @@ dirs: $(OBJD)\disasm.obj : x86.cpp cl $(CFLAGS) /Fe$@ /FAcs /Fa$(OBJD)\x86.lst \ /Fd$(@R).pdb /Fo$(OBJD)\disasm.obj /c x86.cpp -!ELSEIF "$(DETOURS_TARGET_PROCESSOR)" == "X64" +!ELSEIF "$(DETOURS_TARGET_PROCESSOR)" == "X64" || "$(DETOURS_TARGET_PROCESSOR)" == "ARM64EC" $(OBJD)\disasm.obj : x64.asm $(ASM) $(AFLAGS) /Fo$(OBJD)\disasm.obj /Fl$(OBJD)\x64.lst x64.asm !ELSEIF "$(DETOURS_TARGET_PROCESSOR)" == "IA64" diff --git a/samples/dtest/dtarge.cpp b/samples/dtest/dtarge.cpp index 2cd45343..42049954 100644 --- a/samples/dtest/dtarge.cpp +++ b/samples/dtest/dtarge.cpp @@ -8,6 +8,7 @@ // #include #include +#include #include "dtarge.h" DWORD_PTR WINAPI Target0() diff --git a/samples/dtest/dtarge.h b/samples/dtest/dtarge.h index 7aa5cd6c..f60317b9 100644 --- a/samples/dtest/dtarge.h +++ b/samples/dtest/dtarge.h @@ -12,49 +12,49 @@ typedef DWORD DWORD_PTR; #endif -DWORD_PTR WINAPI Target0(); -DWORD_PTR WINAPI Target1(DWORD_PTR v1); -DWORD_PTR WINAPI Target2(DWORD_PTR v1, DWORD_PTR v2); -DWORD_PTR WINAPI Target3(DWORD_PTR v1, DWORD_PTR v2, DWORD_PTR v3); -DWORD_PTR WINAPI Target4(DWORD_PTR v1, DWORD_PTR v2, DWORD_PTR v3, DWORD_PTR v4); -DWORD_PTR WINAPI Target5(DWORD_PTR v1, DWORD_PTR v2, DWORD_PTR v3, DWORD_PTR v4, +DECLSPEC_HYBRID_PATCHABLE DWORD_PTR WINAPI Target0(); +DECLSPEC_HYBRID_PATCHABLE DWORD_PTR WINAPI Target1(DWORD_PTR v1); +DECLSPEC_HYBRID_PATCHABLE DWORD_PTR WINAPI Target2(DWORD_PTR v1, DWORD_PTR v2); +DECLSPEC_HYBRID_PATCHABLE DWORD_PTR WINAPI Target3(DWORD_PTR v1, DWORD_PTR v2, DWORD_PTR v3); +DECLSPEC_HYBRID_PATCHABLE DWORD_PTR WINAPI Target4(DWORD_PTR v1, DWORD_PTR v2, DWORD_PTR v3, DWORD_PTR v4); +DECLSPEC_HYBRID_PATCHABLE DWORD_PTR WINAPI Target5(DWORD_PTR v1, DWORD_PTR v2, DWORD_PTR v3, DWORD_PTR v4, DWORD_PTR v5); -DWORD_PTR WINAPI Target6(DWORD_PTR v1, DWORD_PTR v2, DWORD_PTR v3, DWORD_PTR v4, +DECLSPEC_HYBRID_PATCHABLE DWORD_PTR WINAPI Target6(DWORD_PTR v1, DWORD_PTR v2, DWORD_PTR v3, DWORD_PTR v4, DWORD_PTR v5, DWORD_PTR v6); -DWORD_PTR WINAPI Target7(DWORD_PTR v1, DWORD_PTR v2, DWORD_PTR v3, DWORD_PTR v4, +DECLSPEC_HYBRID_PATCHABLE DWORD_PTR WINAPI Target7(DWORD_PTR v1, DWORD_PTR v2, DWORD_PTR v3, DWORD_PTR v4, DWORD_PTR v5, DWORD_PTR v6, DWORD_PTR v7); -DWORD_PTR WINAPI Target8(DWORD_PTR v1, DWORD_PTR v2, DWORD_PTR v3, DWORD_PTR v4, +DECLSPEC_HYBRID_PATCHABLE DWORD_PTR WINAPI Target8(DWORD_PTR v1, DWORD_PTR v2, DWORD_PTR v3, DWORD_PTR v4, DWORD_PTR v5, DWORD_PTR v6, DWORD_PTR v7, DWORD_PTR v8); -DWORD_PTR WINAPI Target9(DWORD_PTR v1, DWORD_PTR v2, DWORD_PTR v3, DWORD_PTR v4, +DECLSPEC_HYBRID_PATCHABLE DWORD_PTR WINAPI Target9(DWORD_PTR v1, DWORD_PTR v2, DWORD_PTR v3, DWORD_PTR v4, DWORD_PTR v5, DWORD_PTR v6, DWORD_PTR v7, DWORD_PTR v8, DWORD_PTR v9); -DWORD_PTR WINAPI Target10(DWORD_PTR v1, DWORD_PTR v2, DWORD_PTR v3, DWORD_PTR v4, +DECLSPEC_HYBRID_PATCHABLE DWORD_PTR WINAPI Target10(DWORD_PTR v1, DWORD_PTR v2, DWORD_PTR v3, DWORD_PTR v4, DWORD_PTR v5, DWORD_PTR v6, DWORD_PTR v7, DWORD_PTR v8, DWORD_PTR v9, DWORD_PTR v10); -DWORD_PTR WINAPI Target11(DWORD_PTR v1, DWORD_PTR v2, DWORD_PTR v3, DWORD_PTR v4, +DECLSPEC_HYBRID_PATCHABLE DWORD_PTR WINAPI Target11(DWORD_PTR v1, DWORD_PTR v2, DWORD_PTR v3, DWORD_PTR v4, DWORD_PTR v5, DWORD_PTR v6, DWORD_PTR v7, DWORD_PTR v8, DWORD_PTR v9, DWORD_PTR v10, DWORD_PTR v11); -DWORD_PTR WINAPI Target12(DWORD_PTR v1, DWORD_PTR v2, DWORD_PTR v3, DWORD_PTR v4, +DECLSPEC_HYBRID_PATCHABLE DWORD_PTR WINAPI Target12(DWORD_PTR v1, DWORD_PTR v2, DWORD_PTR v3, DWORD_PTR v4, DWORD_PTR v5, DWORD_PTR v6, DWORD_PTR v7, DWORD_PTR v8, DWORD_PTR v9, DWORD_PTR v10, DWORD_PTR v11, DWORD_PTR v12); -DWORD_PTR WINAPI Target13(DWORD_PTR v1, DWORD_PTR v2, DWORD_PTR v3, DWORD_PTR v4, +DECLSPEC_HYBRID_PATCHABLE DWORD_PTR WINAPI Target13(DWORD_PTR v1, DWORD_PTR v2, DWORD_PTR v3, DWORD_PTR v4, DWORD_PTR v5, DWORD_PTR v6, DWORD_PTR v7, DWORD_PTR v8, DWORD_PTR v9, DWORD_PTR v10, DWORD_PTR v11, DWORD_PTR v12, DWORD_PTR v13); -DWORD_PTR WINAPI Target14(DWORD_PTR v1, DWORD_PTR v2, DWORD_PTR v3, DWORD_PTR v4, +DECLSPEC_HYBRID_PATCHABLE DWORD_PTR WINAPI Target14(DWORD_PTR v1, DWORD_PTR v2, DWORD_PTR v3, DWORD_PTR v4, DWORD_PTR v5, DWORD_PTR v6, DWORD_PTR v7, DWORD_PTR v8, DWORD_PTR v9, DWORD_PTR v10, DWORD_PTR v11, DWORD_PTR v12, DWORD_PTR v13, DWORD_PTR v14); -DWORD_PTR WINAPI Target15(DWORD_PTR v1, DWORD_PTR v2, DWORD_PTR v3, DWORD_PTR v4, +DECLSPEC_HYBRID_PATCHABLE DWORD_PTR WINAPI Target15(DWORD_PTR v1, DWORD_PTR v2, DWORD_PTR v3, DWORD_PTR v4, DWORD_PTR v5, DWORD_PTR v6, DWORD_PTR v7, DWORD_PTR v8, DWORD_PTR v9, DWORD_PTR v10, DWORD_PTR v11, DWORD_PTR v12, DWORD_PTR v13, DWORD_PTR v14, DWORD_PTR v15); -DWORD_PTR WINAPI Target16(DWORD_PTR v1, DWORD_PTR v2, DWORD_PTR v3, DWORD_PTR v4, +DECLSPEC_HYBRID_PATCHABLE DWORD_PTR WINAPI Target16(DWORD_PTR v1, DWORD_PTR v2, DWORD_PTR v3, DWORD_PTR v4, DWORD_PTR v5, DWORD_PTR v6, DWORD_PTR v7, DWORD_PTR v8, DWORD_PTR v9, DWORD_PTR v10, DWORD_PTR v11, DWORD_PTR v12, DWORD_PTR v13, DWORD_PTR v14, DWORD_PTR v15, DWORD_PTR v16); -DWORD_PTR WINAPI TargetV(DWORD_PTR v1, ...); -DWORD_PTR WINAPI TargetR(DWORD_PTR v1, ...); +DECLSPEC_HYBRID_PATCHABLE DWORD_PTR WINAPI TargetV(DWORD_PTR v1, ...); +DECLSPEC_HYBRID_PATCHABLE DWORD_PTR WINAPI TargetR(DWORD_PTR v1, ...); // ///////////////////////////////////////////////////////////////// End of File. diff --git a/samples/dtest/dtest.cpp b/samples/dtest/dtest.cpp index f7de56d1..698120fa 100644 --- a/samples/dtest/dtest.cpp +++ b/samples/dtest/dtest.cpp @@ -18,7 +18,7 @@ #include #include "dtarge.h" -DWORD_PTR WINAPI LocalTarget1(DWORD_PTR v1); +DECLSPEC_HYBRID_PATCHABLE DWORD_PTR WINAPI LocalTarget1(DWORD_PTR v1); ////////////////////////////////////////////////////// Multi-Argument Detours. // diff --git a/samples/einst/Makefile b/samples/einst/Makefile index 2821fb7d..24faacc2 100644 --- a/samples/einst/Makefile +++ b/samples/einst/Makefile @@ -12,7 +12,7 @@ # ARM64 does not like base addresses below 4GB. # Append two extra zeros for it. # -!if "$(DETOURS_TARGET_PROCESSOR)" == "ARM64" +!if "$(DETOURS_TARGET_PROCESSOR)" == "ARM64" || "$(DETOURS_TARGET_PROCESSOR)" == "ARM64EC" EDLL1X_BASE=0x710000000 EDLL2X_BASE=0x720000000 EDLL3X_BASE=0x730000000 diff --git a/samples/findfunc/Makefile b/samples/findfunc/Makefile index 2ea19dc6..ba6befb4 100644 --- a/samples/findfunc/Makefile +++ b/samples/findfunc/Makefile @@ -10,15 +10,15 @@ !include ..\common.mak # ARM64 does not like base addresses below 4GB. -# Append two extra zeros for it. -# -!if "$(DETOURS_TARGET_PROCESSOR)" == "ARM64" -TARGET_BASE=0x190000000 -EXTEND_BASE=0x1a0000000 -!else -TARGET_BASE=0x1900000 -EXTEND_BASE=0x1a00000 -!endif +# Append two extra zeros for it. +# +!if "$(DETOURS_TARGET_PROCESSOR)" == "ARM64" || "$(DETOURS_TARGET_PROCESSOR)" == "ARM64EC" +TARGET_BASE=0x190000000 +EXTEND_BASE=0x1a0000000 +!else +TARGET_BASE=0x1900000 +EXTEND_BASE=0x1a00000 +!endif LIBS=$(LIBS) kernel32.lib diff --git a/samples/member/member.cpp b/samples/member/member.cpp index 585ef98a..a2a3f78a 100644 --- a/samples/member/member.cpp +++ b/samples/member/member.cpp @@ -40,7 +40,7 @@ class CMember { public: - void Target(void); + DECLSPEC_HYBRID_PATCHABLE void Target(void); }; void CMember::Target(void) diff --git a/samples/syelog/syelog.cpp b/samples/syelog/syelog.cpp index 72e02e55..b7e5f09c 100644 --- a/samples/syelog/syelog.cpp +++ b/samples/syelog/syelog.cpp @@ -159,7 +159,7 @@ static PCHAR do_estr(PCHAR pszOut, PCHAR pszEnd, PCSTR pszIn) *pszOut++ = '0' + (c % 10); *pszOut++ = ';'; } - else if (c < 1000 && pszOut + 6 <= pszEnd) { + else if (pszOut + 6 <= pszEnd) { *pszOut++ = '&'; *pszOut++ = '#'; *pszOut++ = '0' + ((c / 100) % 10); diff --git a/samples/traceapi/trcapi.cpp b/samples/traceapi/trcapi.cpp index 76c908b1..ff95c73f 100644 --- a/samples/traceapi/trcapi.cpp +++ b/samples/traceapi/trcapi.cpp @@ -352,7 +352,7 @@ BOOL ProcessEnumerate() Syelog(SYELOG_SEVERITY_INFORMATION, "###\n"); LPVOID lpvEnv = Real_GetEnvironmentStrings(); - Syelog(SYELOG_SEVERITY_INFORMATION, "### Env= %08x [%08x %08x]\n", + Syelog(SYELOG_SEVERITY_INFORMATION, "### Env= %p [%p %p]\n", lpvEnv, ((PVOID*)lpvEnv)[0], ((PVOID*)lpvEnv)[1]); return TRUE; diff --git a/samples/tracebld/trcbld.cpp b/samples/tracebld/trcbld.cpp index b246da36..270e17b5 100644 --- a/samples/tracebld/trcbld.cpp +++ b/samples/tracebld/trcbld.cpp @@ -1752,7 +1752,7 @@ static PCHAR do_estr(PCHAR pszOut, PCHAR pszEnd, PCSTR pszIn) *pszOut++ = '0' + (c % 10); *pszOut++ = ';'; } - else if (c < 1000 && pszOut + 6 <= pszEnd) { + else if (pszOut + 6 <= pszEnd) { *pszOut++ = '&'; *pszOut++ = '#'; *pszOut++ = '0' + ((c / 100) % 10); diff --git a/samples/tryman/tstman.cpp b/samples/tryman/tstman.cpp index 0ae169b0..0e7a1851 100644 --- a/samples/tryman/tstman.cpp +++ b/samples/tryman/tstman.cpp @@ -164,16 +164,16 @@ void DumpModuleInfo(HMODULE hModule) } if (pinh->FileHeader.Machine == 0x8664) { - StringCchPrintfA(szMachine, ARRAYSIZE(szMachine), "x64", pinh->FileHeader.Machine); + StringCchPrintfA(szMachine, ARRAYSIZE(szMachine), "x64"); } else if (pinh->FileHeader.Machine == 0x014c) { - StringCchPrintfA(szMachine, ARRAYSIZE(szMachine), "x86", pinh->FileHeader.Machine); + StringCchPrintfA(szMachine, ARRAYSIZE(szMachine), "x86"); } else if (pinh->FileHeader.Machine == 0x0200) { - StringCchPrintfA(szMachine, ARRAYSIZE(szMachine), "i64", pinh->FileHeader.Machine); + StringCchPrintfA(szMachine, ARRAYSIZE(szMachine), "i64"); } else if (pinh->FileHeader.Machine == 0x01c0) { - StringCchPrintfA(szMachine, ARRAYSIZE(szMachine), "arm", pinh->FileHeader.Machine); + StringCchPrintfA(szMachine, ARRAYSIZE(szMachine), "arm"); } else { StringCchPrintfA(szMachine, ARRAYSIZE(szMachine), "%04x", pinh->FileHeader.Machine); diff --git a/src/Makefile b/src/Makefile index 75606c8b..413b30b0 100644 --- a/src/Makefile +++ b/src/Makefile @@ -28,12 +28,22 @@ CFLAGS=$(CFLAGS) /DWIN32_LEAN_AND_MEAN /D_WIN32_WINNT=0x501 CFLAGS=$(CFLAGS) /wd4163 # intrinsic rdtebex not available; using newer Windows headers with older compiler !ENDIF +!IF "$(DETOURS_TARGET_PROCESSOR)" == "ARM64EC" +CFLAGS=/arm64EC $(CFLAGS) +!ENDIF + !if defined(DETOURS_WIN_7) && defined(DETOURS_CL_17_OR_NEWER) CFLAGS=$(CFLAGS) /D_USING_V110_SDK71_ !elseif defined(DETOURS_ANALYZE) CFLAGS=$(CFLAGS) /analyze !endif +LIBFLAGS=/nologo + +!IF "$(DETOURS_TARGET_PROCESSOR)" == "ARM64EC" +LIBFLAGS=$(LIBFLAGS) /machine:arm64x +!ENDIF + OBJS = \ $(OBJD)\detours.obj \ $(OBJD)\modules.obj \ @@ -90,7 +100,7 @@ $(OBJD)\detours.bsc : $(OBJS) bscmake /v /n /o $@ $(OBJS:.obj=.sbr) $(LIBD)\detours.lib : $(OBJS) - link /lib /out:$@ /nologo $(OBJS) + link /lib $(LIBFLAGS) /out:$@ $(OBJS) $(INCD)\detours.h : detours.h copy detours.h $@ diff --git a/src/detours.cpp b/src/detours.cpp index c1138dca..09b1d379 100644 --- a/src/detours.cpp +++ b/src/detours.cpp @@ -156,6 +156,8 @@ inline PBYTE detour_gen_brk(PBYTE pbCode, PBYTE pbLimit) inline PBYTE detour_skip_jmp(PBYTE pbCode, PVOID *ppGlobals) { + PBYTE pbCodeOriginal; + if (pbCode == NULL) { return NULL; } @@ -179,6 +181,7 @@ inline PBYTE detour_skip_jmp(PBYTE pbCode, PVOID *ppGlobals) PBYTE pbNew = pbCode + 2 + *(CHAR *)&pbCode[1]; DETOUR_TRACE(("%p->%p: skipped over short jump.\n", pbCode, pbNew)); pbCode = pbNew; + pbCodeOriginal = pbCode; // First, skip over the import vector if there is one. if (pbCode[0] == 0xff && pbCode[1] == 0x25) { // jmp [imm32] @@ -195,6 +198,23 @@ inline PBYTE detour_skip_jmp(PBYTE pbCode, PVOID *ppGlobals) pbNew = pbCode + 5 + *(UNALIGNED INT32 *)&pbCode[1]; DETOUR_TRACE(("%p->%p: skipped over long jump.\n", pbCode, pbNew)); pbCode = pbNew; + + // Patches applied by the OS will jump through an HPAT page to get + // the target function in the patch image. The jump is always performed + // to the target function found at the current instruction pointer + + // PAGE_SIZE - 6 (size of jump). + // If this is an OS patch, we want to detour at the point of the target function + // padding in the base image. Ideally, we would detour at the target function, but + // since it's patched it begins with a short jump (to padding) which isn't long + // enough to hold the detour code bytes. + if (pbCode[0] == 0xff && + pbCode[1] == 0x25 && + *(UNALIGNED INT32 *)&pbCode[2] == (UNALIGNED INT32)(pbCode + 0x1000)) { // jmp [eip+PAGE_SIZE-6] + + DETOUR_TRACE(("%p->%p: OS patch encountered, reset back to long jump 5 bytes prior to target function.\n", pbCode, pbCodeOriginal)); + pbCode = pbCodeOriginal; + } + } } return pbCode; @@ -369,6 +389,8 @@ inline PBYTE detour_gen_brk(PBYTE pbCode, PBYTE pbLimit) inline PBYTE detour_skip_jmp(PBYTE pbCode, PVOID *ppGlobals) { + PBYTE pbCodeOriginal; + if (pbCode == NULL) { return NULL; } @@ -392,6 +414,7 @@ inline PBYTE detour_skip_jmp(PBYTE pbCode, PVOID *ppGlobals) PBYTE pbNew = pbCode + 2 + *(CHAR *)&pbCode[1]; DETOUR_TRACE(("%p->%p: skipped over short jump.\n", pbCode, pbNew)); pbCode = pbNew; + pbCodeOriginal = pbCode; // First, skip over the import vector if there is one. if (pbCode[0] == 0xff && pbCode[1] == 0x25) { // jmp [+imm32] @@ -408,6 +431,21 @@ inline PBYTE detour_skip_jmp(PBYTE pbCode, PVOID *ppGlobals) pbNew = pbCode + 5 + *(UNALIGNED INT32 *)&pbCode[1]; DETOUR_TRACE(("%p->%p: skipped over long jump.\n", pbCode, pbNew)); pbCode = pbNew; + + // Patches applied by the OS will jump through an HPAT page to get + // the target function in the patch image. The jump is always performed + // to the target function found at the current instruction pointer + + // PAGE_SIZE - 6 (size of jump). + // If this is an OS patch, we want to detour at the point of the target function + // in the base image. Since we need 5 bytes to perform the jump, detour at the + // point of the long jump instead of the short jump at the start of the target. + if (pbCode[0] == 0xff && + pbCode[1] == 0x25 && + *(UNALIGNED INT32 *)&pbCode[2] == 0xFFA) { // jmp [rip+PAGE_SIZE-6] + + DETOUR_TRACE(("%p->%p: OS patch encountered, reset back to long jump 5 bytes prior to target function.\n", pbCode, pbCodeOriginal)); + pbCode = pbCodeOriginal; + } } } return pbCode; @@ -1151,9 +1189,45 @@ inline void detour_find_jmp_bounds(PBYTE pbCode, *ppUpper = (PDETOUR_TRAMPOLINE)hi; } +inline BOOL detour_is_code_os_patched(PBYTE pbCode) +{ + // Identify whether the provided code pointer is a OS patch jump. + // We can do this by checking if a branch (b ) is present, and if so, + // it must be jumping to an HPAT page containing ldr [PC+PAGE_SIZE-4], br . + ULONG Opcode = fetch_opcode(pbCode); + + if ((Opcode & 0xfc000000) != 0x14000000) { + return FALSE; + } + // The branch must be jumping forward if it's going into the HPAT. + // Check that the sign bit is cleared. + if ((Opcode & 0x2000000) != 0) { + return FALSE; + } + ULONG Delta = (ULONG)((Opcode & 0x1FFFFFF) * 4); + PBYTE BranchTarget = pbCode + Delta; + + // Now inspect the opcodes of the code we jumped to in order to determine if it's HPAT. + ULONG HpatOpcode1 = fetch_opcode(BranchTarget); + ULONG HpatOpcode2 = fetch_opcode(BranchTarget + 4); + + if (HpatOpcode1 != 0x58008010) { // ldr [PC+PAGE_SIZE] + return FALSE; + } + if (HpatOpcode2 != 0xd61f0200) { // br + return FALSE; + } + return TRUE; +} + inline BOOL detour_does_code_end_function(PBYTE pbCode) { ULONG Opcode = fetch_opcode(pbCode); + // When the OS has patched a function entry point, it will incorrectly + // appear as though the function is just a single branch instruction. + if (detour_is_code_os_patched(pbCode)) { + return FALSE; + } if ((Opcode & 0xfffffc1f) == 0xd65f0000 || // br (Opcode & 0xfc000000) == 0x14000000) { // b return TRUE; @@ -1837,41 +1911,46 @@ LONG WINAPI DetourTransactionCommitEx(_Out_opt_ PVOID **pppFailedPointer) } } - // Update any suspended threads. - for (t = s_pPendingThreads; t != NULL; t = t->pNext) { - CONTEXT cxt; - cxt.ContextFlags = CONTEXT_CONTROL; - #undef DETOURS_EIP +#undef DETOURS_CONTEXT_FLAGS #ifdef DETOURS_X86 #define DETOURS_EIP Eip +#define DETOURS_CONTEXT_FLAGS CONTEXT_CONTROL #endif // DETOURS_X86 #ifdef DETOURS_X64 #define DETOURS_EIP Rip +#define DETOURS_CONTEXT_FLAGS (CONTEXT_CONTROL | CONTEXT_INTEGER) #endif // DETOURS_X64 #ifdef DETOURS_IA64 #define DETOURS_EIP StIIP +#define DETOURS_CONTEXT_FLAGS CONTEXT_CONTROL #endif // DETOURS_IA64 #ifdef DETOURS_ARM #define DETOURS_EIP Pc +#define DETOURS_CONTEXT_FLAGS CONTEXT_CONTROL #endif // DETOURS_ARM #ifdef DETOURS_ARM64 #define DETOURS_EIP Pc +#define DETOURS_CONTEXT_FLAGS (CONTEXT_CONTROL | CONTEXT_INTEGER) #endif // DETOURS_ARM64 typedef ULONG_PTR DETOURS_EIP_TYPE; + // Update any suspended threads. + for (t = s_pPendingThreads; t != NULL; t = t->pNext) { + CONTEXT cxt; + cxt.ContextFlags = DETOURS_CONTEXT_FLAGS; if (GetThreadContext(t->hThread, &cxt)) { for (o = s_pPendingOperations; o != NULL; o = o->pNext) { if (o->fIsRemove) { if (cxt.DETOURS_EIP >= (DETOURS_EIP_TYPE)(ULONG_PTR)o->pTrampoline && cxt.DETOURS_EIP < (DETOURS_EIP_TYPE)((ULONG_PTR)o->pTrampoline - + sizeof(o->pTrampoline)) + + sizeof(*o->pTrampoline)) ) { cxt.DETOURS_EIP = (DETOURS_EIP_TYPE) @@ -2064,6 +2143,15 @@ LONG WINAPI DetourAttachEx(_Inout_ PVOID *ppPointer, DETOUR_TRACE((" ppldTarget=%p, code=%p [gp=%p]\n", ppldTarget, pbTarget, pTargetGlobals)); #else // DETOURS_IA64 +#if defined(_M_ARM64EC) + if (RtlIsEcCode(reinterpret_cast(*ppPointer))) { + DETOUR_TRACE(("*ppPointer is an Arm64EC address (ppPointer=%p). " + "An Arm64EC address cannot be legitimately detoured with an x64 jmp. " + "Mark the target function with __declspec(hybrid_patchable) to make it detour-able. " + "We still allow an Arm64EC function to be detoured with an x64 jmp to make it easy (crash) to debug.\n", ppPointer)); + DETOUR_BREAK(); + } +#endif pbTarget = (PBYTE)DetourCodeFromPointer(pbTarget, NULL); pDetour = DetourCodeFromPointer(pDetour, NULL); #endif // !DETOURS_IA64 diff --git a/src/detours.h b/src/detours.h index f3738af0..8e987854 100644 --- a/src/detours.h +++ b/src/detours.h @@ -83,11 +83,15 @@ #undef DETOURS_32BIT #undef DETOURS_64BIT +#ifndef DECLSPEC_HYBRID_PATCHABLE +#define DECLSPEC_HYBRID_PATCHABLE DECLSPEC_CHPE_PATCHABLE +#endif + #if defined(_X86_) #define DETOURS_X86 #define DETOURS_OPTION_BITS 64 -#elif defined(_AMD64_) +#elif defined(_AMD64_) || defined(_ARM64EC_) #define DETOURS_X64 #define DETOURS_OPTION_BITS 32 @@ -102,7 +106,7 @@ #define DETOURS_ARM64 #else -#error Unknown architecture (x86, amd64, ia64, arm, arm64) +#error Unknown architecture (x86, amd64, ia64, arm, arm64, arm64ec) #endif #ifdef _WIN64 @@ -381,10 +385,10 @@ extern const GUID DETOUR_EXE_RESTORE_GUID; extern const GUID DETOUR_EXE_HELPER_GUID; #define DETOUR_TRAMPOLINE_SIGNATURE 0x21727444 // Dtr! -typedef struct _DETOUR_TRAMPOLINE DETOUR_TRAMPOLINE, *PDETOUR_TRAMPOLINE; - -#ifndef DETOUR_MAX_SUPPORTED_IMAGE_SECTION_HEADERS -#define DETOUR_MAX_SUPPORTED_IMAGE_SECTION_HEADERS 32 +typedef struct _DETOUR_TRAMPOLINE DETOUR_TRAMPOLINE, *PDETOUR_TRAMPOLINE; + +#ifndef DETOUR_MAX_SUPPORTED_IMAGE_SECTION_HEADERS +#define DETOUR_MAX_SUPPORTED_IMAGE_SECTION_HEADERS 32 #endif // !DETOUR_MAX_SUPPORTED_IMAGE_SECTION_HEADERS /////////////////////////////////////////////////////////// Binary Structures. @@ -594,8 +598,8 @@ PVOID WINAPI DetourCopyInstruction(_In_opt_ PVOID pDst, BOOL WINAPI DetourSetCodeModule(_In_ HMODULE hModule, _In_ BOOL fLimitReferencesToModule); PVOID WINAPI DetourAllocateRegionWithinJumpBounds(_In_ LPCVOID pbTarget, - _Out_ PDWORD pcbAllocatedSize); -BOOL WINAPI DetourIsFunctionImported(_In_ PBYTE pbCode, + _Out_ PDWORD pcbAllocatedSize); +BOOL WINAPI DetourIsFunctionImported(_In_ PBYTE pbCode, _In_ PBYTE pbAddress); ///////////////////////////////////////////////////// Loaded Binary Functions. diff --git a/system.mak b/system.mak index 388c0395..40404bc6 100644 --- a/system.mak +++ b/system.mak @@ -52,6 +52,10 @@ DETOURS_TARGET_PROCESSOR=$(DETOURS_TARGET_PROCESSOR:x=X) DETOURS_TARGET_PROCESSOR=$(DETOURS_TARGET_PROCESSOR:y=Y) DETOURS_TARGET_PROCESSOR=$(DETOURS_TARGET_PROCESSOR:z=Z) +!IF "$(DETOURS_TARGET_PROCESSOR)" == "WIN32" +DETOURS_TARGET_PROCESSOR = X86 +!ENDIF + !IF "$(DETOURS_TARGET_PROCESSOR)" == "AMD64" DETOURS_TARGET_PROCESSOR = X64 !ENDIF @@ -90,7 +94,9 @@ DETOURS_OPTION_BITS=64 !ELSEIF "$(DETOURS_TARGET_PROCESSOR)" == "ARM" #!MESSAGE Building for 32-bit ARM. !ELSEIF "$(DETOURS_TARGET_PROCESSOR)" == "ARM64" -#!MESSAGE Building for 64-bit ARM. +#!MESSAGE Building for 64-bit ARM64. +!ELSEIF "$(DETOURS_TARGET_PROCESSOR)" == "ARM64EC" +#!MESSAGE Building for 64-bit ARM64EC. !ELSE !MESSAGE Note: To select the target processor architecture set either !MESSAGE PROCESSOR_ARCHITECTURE or DETOURS_TARGET_PROCESSOR. diff --git a/tests/test_module_api.cpp b/tests/test_module_api.cpp index 3e2928cd..e3f0ca53 100644 --- a/tests/test_module_api.cpp +++ b/tests/test_module_api.cpp @@ -28,6 +28,103 @@ extern "C" int mainCRTStartup(); // void NoopFunction() { } +#include + +#if defined(_ARM64EC_) +inline bool +StdFFSMatch( + unsigned __int64 x64Address, + unsigned __int64 EcAddress + ) +{ + unsigned __int64 FFSpart1; + unsigned short FFSpart2; + unsigned __int64 EcAddr; + int JmpOffset; + + // + // A standard fast-forward sequence follows this pattern + // + // 488bc4 mov rax,rsp + // 48895820 mov qword ptr [rax+20h],rbx + // 55 push rbp + // 5d pop rbp + // e952df1600 jmp ntdll!_swprintf (00000001`80178760) + // + // See https://learn.microsoft.com/en-us/cpp/cpp/hybrid-patchable?view=msvc-170 for details. + // + + if (x64Address % 16 != 0) + { + // + // All standard FFS are 16-byte aligned guaranteed by compiler + // + + return false; + } + + if (RtlIsEcCode(x64Address)) + { + // + // Arm64EC code is never a standard FFS + // + + return false; + } + + __try + { + FFSpart1 = ReadULong64NoFence((ULONG64*)x64Address); + FFSpart2 = ReadUShortNoFence((USHORT*)(x64Address + 8)); + JmpOffset = ReadULongNoFence((ULONG*)(x64Address + 10)); + } + __except(EXCEPTION_EXECUTE_HANDLER) + { + return false; + } + + if (FFSpart1 == 0x5520588948c48b48 && FFSpart2 == 0xe95d) + { + + EcAddr = (ULONG_PTR)((LONG_PTR)x64Address + 14 + JmpOffset); + if (!RtlIsEcCode(EcAddr)) + { + return false; + } + + if (EcAddress != EcAddr) + { + return false; + } + + return true; + } + + return false; +} +#endif + +bool EquivalentFunctions(void* a, void* b) +{ + if (a == b) + { + return true; + } + + // TODO: Remove Arm64EC-specific FFS matching logic when address taken operator + // inconsistency in Arm64EC MSVC is fixed. + // See https://developercommunity.visualstudio.com/t/Functions-dllimported-from-arm64ec-dlls/10670642 +#if defined(_ARM64EC_) + if (StdFFSMatch(reinterpret_cast(a), reinterpret_cast(b)) || + StdFFSMatch(reinterpret_cast(b), reinterpret_cast(a))) + { + return true; + } +#endif + + return false; +} + TEST_CASE("DetourLoadImageHlp", "[module]") { SECTION("Passing own function, results in own HMODULE") @@ -131,7 +228,7 @@ TEST_CASE("DetourGetEntyPoint", "[module]") auto entry = DetourGetEntryPoint(nullptr); REQUIRE( GetLastError() == NO_ERROR ); - REQUIRE( entry == mainCRTStartup ); + REQUIRE( EquivalentFunctions( entry, mainCRTStartup ) ); } SECTION("Passing nullptr, equals executing image") @@ -147,7 +244,7 @@ TEST_CASE("DetourGetEntyPoint", "[module]") auto entry = DetourGetEntryPoint(reinterpret_cast(&__ImageBase)); REQUIRE( GetLastError() == NO_ERROR ); - REQUIRE( entry == mainCRTStartup ); + REQUIRE( EquivalentFunctions( entry, mainCRTStartup ) ); } SECTION("Corrupt image DOS header magic, results in bad exe format error") @@ -729,9 +826,14 @@ TEST_CASE("DetourRestoreAfterWithEx", "[module]") } // Define the import symbol so that we can get the address of the IAT entry for a static import -#ifdef _X86_ +#pragma warning(push) #pragma warning(disable:4483) // disable warning/error about __identifier() +#if defined(_X86_) #define __imp_SetLastError __identifier("_imp__SetLastError@4") +#elif defined(_ARM64EC_) +// In Arm64EC binaries, __imp_aux_foo points the primary IAT entry +// for foo, and __imp_foo points to the auxiliary IAT entry for foo. +#define __imp_SetLastError __identifier("__imp_aux_SetLastError") #endif extern "C" extern void *__imp_SetLastError; @@ -754,3 +856,4 @@ TEST_CASE("DetourIsFunctionImported", "[module]") } } +#pragma warning(pop) diff --git a/vc/Detours.sln b/vc/Detours.sln index 2bd53476..4bae9dae 100644 --- a/vc/Detours.sln +++ b/vc/Detours.sln @@ -1,7 +1,5 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.29519.181 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Detours", "Detours.vcxproj", "{37489709-8054-4903-9C49-A79846049FC9}" EndProject @@ -9,10 +7,12 @@ Global GlobalSection(SolutionConfigurationPlatforms) = preSolution DebugMDd|ARM = DebugMDd|ARM DebugMDd|ARM64 = DebugMDd|ARM64 + DebugMDd|ARM64EC = DebugMDd|ARM64EC DebugMDd|x64 = DebugMDd|x64 DebugMDd|x86 = DebugMDd|x86 ReleaseMD|ARM = ReleaseMD|ARM ReleaseMD|ARM64 = ReleaseMD|ARM64 + ReleaseMD|ARM64EC = ReleaseMD|ARM64EC ReleaseMD|x64 = ReleaseMD|x64 ReleaseMD|x86 = ReleaseMD|x86 EndGlobalSection @@ -21,6 +21,8 @@ Global {37489709-8054-4903-9C49-A79846049FC9}.DebugMDd|ARM.Build.0 = DebugMDd|ARM {37489709-8054-4903-9C49-A79846049FC9}.DebugMDd|ARM64.ActiveCfg = DebugMDd|ARM64 {37489709-8054-4903-9C49-A79846049FC9}.DebugMDd|ARM64.Build.0 = DebugMDd|ARM64 + {37489709-8054-4903-9C49-A79846049FC9}.DebugMDd|ARM64EC.ActiveCfg = DebugMDd|ARM64EC + {37489709-8054-4903-9C49-A79846049FC9}.DebugMDd|ARM64EC.Build.0 = DebugMDd|ARM64EC {37489709-8054-4903-9C49-A79846049FC9}.DebugMDd|x64.ActiveCfg = DebugMDd|x64 {37489709-8054-4903-9C49-A79846049FC9}.DebugMDd|x64.Build.0 = DebugMDd|x64 {37489709-8054-4903-9C49-A79846049FC9}.DebugMDd|x86.ActiveCfg = DebugMDd|Win32 @@ -29,6 +31,8 @@ Global {37489709-8054-4903-9C49-A79846049FC9}.ReleaseMD|ARM.Build.0 = ReleaseMD|ARM {37489709-8054-4903-9C49-A79846049FC9}.ReleaseMD|ARM64.ActiveCfg = ReleaseMD|ARM64 {37489709-8054-4903-9C49-A79846049FC9}.ReleaseMD|ARM64.Build.0 = ReleaseMD|ARM64 + {37489709-8054-4903-9C49-A79846049FC9}.ReleaseMD|ARM64EC.ActiveCfg = ReleaseMD|ARM64EC + {37489709-8054-4903-9C49-A79846049FC9}.ReleaseMD|ARM64EC.Build.0 = ReleaseMD|ARM64EC {37489709-8054-4903-9C49-A79846049FC9}.ReleaseMD|x64.ActiveCfg = ReleaseMD|x64 {37489709-8054-4903-9C49-A79846049FC9}.ReleaseMD|x64.Build.0 = ReleaseMD|x64 {37489709-8054-4903-9C49-A79846049FC9}.ReleaseMD|x86.ActiveCfg = ReleaseMD|Win32 diff --git a/vc/Detours.vcxproj b/vc/Detours.vcxproj index 9a3f966f..7cea8720 100644 --- a/vc/Detours.vcxproj +++ b/vc/Detours.vcxproj @@ -9,6 +9,10 @@ DebugMDd ARM64 + + DebugMDd + ARM64EC + DebugMDd Win32 @@ -21,6 +25,10 @@ ReleaseMD ARM64 + + ReleaseMD + ARM64EC + ReleaseMD Win32 @@ -45,49 +53,61 @@ Makefile true - v142 + v143 Unicode Makefile false - v142 + v143 Unicode Makefile true - v142 + v143 + Unicode + + + Makefile + true + v143 Unicode Makefile true - v142 + v143 Unicode Makefile true - v142 + v143 Unicode Makefile false - v142 + v143 + Unicode + + + Makefile + false + v143 Unicode Makefile false - v142 + v143 Unicode Makefile false - v142 + v143 Unicode @@ -104,6 +124,9 @@ + + + @@ -113,6 +136,9 @@ + + + @@ -120,98 +146,122 @@ - SET DETOURS_TARGET_PROCESSOR=$(PlatformTarget) + SET DETOURS_TARGET_PROCESSOR=$(Platform) cd .. nmake - SET DETOURS_TARGET_PROCESSOR=$(PlatformTarget) + SET DETOURS_TARGET_PROCESSOR=$(Platform) cd .. nmake clean nmake - SET DETOURS_TARGET_PROCESSOR=$(PlatformTarget) + SET DETOURS_TARGET_PROCESSOR=$(Platform) +cd .. +nmake clean + + + SET DETOURS_TARGET_PROCESSOR=$(Platform) +cd .. +nmake + SET DETOURS_TARGET_PROCESSOR=$(Platform) +cd .. +nmake clean +nmake + SET DETOURS_TARGET_PROCESSOR=$(Platform) cd .. nmake clean - SET DETOURS_TARGET_PROCESSOR=$(PlatformTarget) + SET DETOURS_TARGET_PROCESSOR=$(Platform) cd .. nmake - SET DETOURS_TARGET_PROCESSOR=$(PlatformTarget) + SET DETOURS_TARGET_PROCESSOR=$(Platform) cd .. nmake clean nmake - SET DETOURS_TARGET_PROCESSOR=$(PlatformTarget) + SET DETOURS_TARGET_PROCESSOR=$(Platform) cd .. nmake clean - SET DETOURS_TARGET_PROCESSOR=$(PlatformTarget) + SET DETOURS_TARGET_PROCESSOR=$(Platform) cd .. nmake - SET DETOURS_TARGET_PROCESSOR=$(PlatformTarget) + SET DETOURS_TARGET_PROCESSOR=$(Platform) cd .. nmake clean nmake - SET DETOURS_TARGET_PROCESSOR=$(PlatformTarget) + SET DETOURS_TARGET_PROCESSOR=$(Platform) cd .. nmake clean - SET DETOURS_TARGET_PROCESSOR=$(PlatformTarget) + SET DETOURS_TARGET_PROCESSOR=$(Platform) +cd .. +nmake + SET DETOURS_TARGET_PROCESSOR=$(Platform) +cd .. +nmake clean +nmake + SET DETOURS_TARGET_PROCESSOR=$(Platform) +cd .. +nmake clean + + + SET DETOURS_TARGET_PROCESSOR=$(Platform) cd .. nmake - SET DETOURS_TARGET_PROCESSOR=$(PlatformTarget) + SET DETOURS_TARGET_PROCESSOR=$(Platform) cd .. nmake clean nmake - SET DETOURS_TARGET_PROCESSOR=$(PlatformTarget) + SET DETOURS_TARGET_PROCESSOR=$(Platform) cd .. nmake clean - SET DETOURS_TARGET_PROCESSOR=$(PlatformTarget) + SET DETOURS_TARGET_PROCESSOR=$(Platform) cd .. nmake - SET DETOURS_TARGET_PROCESSOR=$(PlatformTarget) + SET DETOURS_TARGET_PROCESSOR=$(Platform) cd .. nmake clean nmake - SET DETOURS_TARGET_PROCESSOR=$(PlatformTarget) + SET DETOURS_TARGET_PROCESSOR=$(Platform) cd .. nmake clean - SET DETOURS_TARGET_PROCESSOR=$(PlatformTarget) + SET DETOURS_TARGET_PROCESSOR=$(Platform) cd .. nmake - SET DETOURS_TARGET_PROCESSOR=$(PlatformTarget) + SET DETOURS_TARGET_PROCESSOR=$(Platform) cd .. nmake clean nmake - SET DETOURS_TARGET_PROCESSOR=$(PlatformTarget) + SET DETOURS_TARGET_PROCESSOR=$(Platform) cd .. nmake clean - SET DETOURS_TARGET_PROCESSOR=$(PlatformTarget) + SET DETOURS_TARGET_PROCESSOR=$(Platform) cd .. nmake - SET DETOURS_TARGET_PROCESSOR=$(PlatformTarget) + SET DETOURS_TARGET_PROCESSOR=$(Platform) cd .. nmake clean nmake - SET DETOURS_TARGET_PROCESSOR=$(PlatformTarget) + SET DETOURS_TARGET_PROCESSOR=$(Platform) cd .. nmake clean - SET DETOURS_TARGET_PROCESSOR=$(PlatformTarget) + SET DETOURS_TARGET_PROCESSOR=$(Platform) cd .. nmake - SET DETOURS_TARGET_PROCESSOR=$(PlatformTarget) + SET DETOURS_TARGET_PROCESSOR=$(Platform) cd .. nmake clean nmake - SET DETOURS_TARGET_PROCESSOR=$(PlatformTarget) + SET DETOURS_TARGET_PROCESSOR=$(Platform) cd .. nmake clean @@ -231,7 +281,7 @@ nmake clean - SET DETOURS_TARGET_PROCESSOR=$(PlatformTarget) + SET DETOURS_TARGET_PROCESSOR=$(Platform) cd .. nmake @@ -255,7 +305,33 @@ nmake - SET DETOURS_TARGET_PROCESSOR=$(PlatformTarget) + SET DETOURS_TARGET_PROCESSOR=$(Platform) +cd .. +nmake + + + + + Level4 + Disabled + true + _DEBUG;_LIB;%(PreprocessorDefinitions) + true + true + ProgramDatabase + + + + + $(OutputPath)$(TargetName).pdb + + + Windows + true + + + + SET DETOURS_TARGET_PROCESSOR=$(Platform) cd .. nmake @@ -281,7 +357,7 @@ nmake - SET DETOURS_TARGET_PROCESSOR=$(PlatformTarget) + SET DETOURS_TARGET_PROCESSOR=$(Platform) cd .. nmake @@ -307,7 +383,7 @@ nmake - SET DETOURS_TARGET_PROCESSOR=$(PlatformTarget) + SET DETOURS_TARGET_PROCESSOR=$(Platform) cd .. nmake @@ -331,7 +407,7 @@ nmake - SET DETOURS_TARGET_PROCESSOR=$(PlatformTarget) + SET DETOURS_TARGET_PROCESSOR=$(Platform) cd .. nmake @@ -357,7 +433,35 @@ nmake - SET DETOURS_TARGET_PROCESSOR=$(PlatformTarget) + SET DETOURS_TARGET_PROCESSOR=$(Platform) +cd .. +nmake + + + + + Level4 + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + true + true + + + + + $(OutputPath)$(TargetName).pdb + + + Windows + true + true + true + + + + SET DETOURS_TARGET_PROCESSOR=$(Platform) cd .. nmake @@ -385,7 +489,7 @@ nmake - SET DETOURS_TARGET_PROCESSOR=$(PlatformTarget) + SET DETOURS_TARGET_PROCESSOR=$(Platform) cd .. nmake @@ -413,7 +517,7 @@ nmake - SET DETOURS_TARGET_PROCESSOR=$(PlatformTarget) + SET DETOURS_TARGET_PROCESSOR=$(Platform) cd .. nmake @@ -601,4 +705,4 @@ nmake - + \ No newline at end of file