# YY-Thunks makes a modern binary run on Windows XP by faking the missing APIs

> YY-Thunks is a C++ shim library that intercepts the Windows APIs a newer build expects and either calls the real one or supplies a fallback, so a program can run on Windows XP and other old systems without source changes. The cost is a linker-time dependency and a set of behaviours you have to trust.

**Chuyu-Team/YY-Thunks** — Fix DecodePointer, EncodePointer,RegDeleteKeyEx etc. APIs not found in Windows XP RTM.

- Repository: https://github.com/Chuyu-Team/YY-Thunks
- Stars: 1,036 · Forks: 155
- Language: C++
- License: MIT
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/chuyu-team-yy-thunks

## The problem is APIs that simply do not exist on old systems

Each new version of Windows adds APIs, and applications written against those APIs stop working on older systems. The README names open source projects that are no longer compatible with Windows XP or Windows 7 as the motivating case, and frames the question plainly: when the old system cannot find the API, is there a way to deal with it quickly? YY-Thunks is the answer it gives. The compatibility problem is resolved automatically by tweaking the linker, with no change to the application code, which is the property that makes it usable in projects you do not own. The APIs named in the project description, DecodePointer, EncodePointer and RegDeleteKeyEx among them, are the kind that modern toolchains emit calls to without the developer thinking about it.

## Each shim tries the real function, then falls back

The mechanism is `LoadLibrary` and `GetProcAddress` for dynamic loading, with a fallback implementation when the API turns out to be missing. The README's example is `GetTickCount64`, which Windows XP does not support:

```cpp
// Windows XP not support GetTickCount64.
ULONGLONG WINAPI GetTickCount64(VOID)
{
    if (auto const _pfnGetTickCount64 = try_get_GetTickCount64())
    {
        return _pfnGetTickCount64();
    }
    // Fallback
    return GetTickCount();
}
```

The shape is the same for every thunk in the library. The wrapper calls the real function when the running system has it, so on modern Windows the behaviour is exactly what the OS provides. On an old system the fallback runs, and for `GetTickCount64` the fallback is the 32-bit `GetTickCount` widened. That fallback is a real approximation, since the 32-bit millisecond counter wraps far sooner, and it is the clearest example of the general caveat: the library keeps your program running, but some behaviours on old systems are substitutes rather than the thing you asked for.

## Function pointers are cached and encrypted, not looked up each call

The performance claim in the README is specific rather than vague. The thunks ship with a built-in L2 cache and encrypt all function pointers to prevent brute-force memory searches, and the stated purpose is to minimise unwanted and unnecessary calls to `LoadLibrary` and `GetProcAddress`. Both halves of that matter for a shim that sits on every call to a shimmed API. A naive implementation would call `GetProcAddress` on every invocation, which on a hot path is a real cost. Encrypting the cached pointers is about something else: a predictable table of resolved addresses in the process image is the kind of thing an attacker scans for, so the library stores them in a form that does not read as pointers. The project is explicit that the code is fully open source and that pull requests are welcome, and the repository keeps a separate architecture document alongside a coding style guide written in Chinese, which tells you where the project's conventions come from.

## NuGet is the recommended install path

The README offers several routes and recommends NuGet first, on the grounds that NuGet is designed to be foolproof and easier to use. For a Visual Studio C++ project the steps are: right-click the project, choose `Manage NuGet Packages`, search for `YY-Thunks` and install a suitable version, then set the minimum compatible system version to 5.1.2600.0 under the package's properties for XP support, and rebuild the solution. The .NET Native AOT route is similar, with the addition that `TargetFramework` has to be set to `net8.0-windows` or `net9.0-windows`, and `SupportedOSPlatformVersion` set to 5.1:

```xml
<Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
        <!-- ... -->
        <TargetFramework>net8.0-windows</TargetFramework>
        <SupportedOSPlatformVersion>5.1</SupportedOSPlatformVersion>
        <!-- ... -->
    </PropertyGroup>
  <!--...-->
</Project>
```

The 5.1 value is what tells the toolchain to keep the old system in the supported set, and it is the single setting that turns the compatibility on.

## CMake builds need a Directory.Build.props and a NuGet restore

For a CMake project the README asks you to create a `Directory.Build.props` file in the source directory with a package reference and a `WindowsTargetPlatformMinVersion` of 5.1.2600, then build with the Visual Studio generator, because the README notes that the generator must be `Visual Studio` since Visual Studio is the one that supports NuGet. The sequence is configure, build with a restore, install:

```bash
# The Gen parameter must be use `Visual Studio`, as Visual Studio only supports nuget.
# Assuming that the output dir is `.build\x86-Release`, you can modify it as needed.
cmake -G "Visual Studio 17 2022" -A Win32 -DCMAKE_CONFIGURATION_TYPES:STRING=Release -DCMAKE_INSTALL_PREFIX:PATH=.\build\x86-Release .

# Note the `-- -r` at the end, which is the command to restore the nuget package.
cmake --build .\build\x86-Release --config Release -- -r

cmake --install .\build\x86-Release --config Release
```

The trailing `-- -r` is the part people miss, since it is what restores the NuGet package rather than building anything. The example also shows the 32-bit `Win32` architecture, and the runtime identifiers in the props file cover win, win-x86, win-x64, win-arm and win-arm64, so the same mechanism is intended to work across the current architecture set rather than only on the machines the author happened to test.

## The manual path links an object file, and DLLs need an extra step

If you would rather not use NuGet, the README describes linking the prebuilt object file directly. You download and unzip the YY-Thunks-Objs archive from the releases into the project directory, add `objs\$(PlatformShortName)\YY_Thunks_for_WinXP.obj` to the linker's additional dependencies, and set the minimum required version to 5.1 for 32-bit XP or 5.2 for XP x64 and Server 2003. The DLL case has a trap the README calls out explicitly: if the project is a dynamic link library and you skip the step, the XP system may crash on `thread_local`. The fix is to change the custom entry point to `DllMainCRTStartupForYY_Thunks` and add the corresponding alternate name option for 32-bit and 64-bit builds. A crash on a thread-local in a DLL on XP only is exactly the kind of failure that eats an afternoon, so treat that step as required rather than optional.

## What the library does not do for you

The scope is narrower than the marketing line suggests, and the file list is a good guide. The repository holds the source under `src/`, a `NuGet/` directory for packaging, an `ARCHITECTURE.md` describing the internals, `ThunksList.md` which is the inventory of covered APIs, a Chinese coding style document, and two readme files, the English one and a Simplified Chinese one under a different name. The listed thunks are the ones the project maintains, and the honest way to use the library is to check `ThunksList.md` for the APIs your binary actually calls. The project is under an MIT licence with the file in the repository root, releases are tagged on GitHub with v1.2.3 dated 2026-10-09, and the last push to the master branch was on 2026-10-13.

## Conclusion

Adopt YY-Thunks when you ship a native Windows application to a fleet that still includes Windows XP or Windows 7 and you cannot change the source, since the whole mechanism is a link-time shim that needs no code changes. Do not adopt it to make an app work on a system it was never meant to support, because the fallbacks are approximations, not the real kernel behaviour. Verify first that the APIs you rely on are in the project's ThunksList.md, that the minimum version setting in the package matches the oldest machine in your fleet, and that the DLL case in the manual configuration is handled, because the README warns the system may crash on thread_local if that step is skipped.

## FAQ

### What problem does YY-Thunks solve?

It lets an application built with a modern toolchain run on older Windows systems such as Windows XP and Windows 7, where APIs the binary calls simply do not exist. The compatibility is resolved at link time by tweaking the linker, without changing the application source.

### How do I install YY-Thunks in a Visual Studio C++ project?

Use Manage NuGet Packages on the project, search for `YY-Thunks` and install a version, then set the minimum compatible system version to 5.1.2600.0 for XP support and rebuild the solution. The README recommends NuGet over the manual route because it is designed to be foolproof.

### How does YY-Thunks handle an API that the old system does not have?

The thunk calls `GetProcAddress` to find the real function and uses it when it exists. If it does not exist, the thunk's own fallback runs instead, as in the `GetTickCount64` example, which falls back to the 32-bit `GetTickCount`.

### What do I need to watch out for when building a DLL with YY-Thunks?

The README warns that if the project is a dynamic link library and you ignore the entry point step, the XP system may crash on `thread_local`. The fix is to set the custom entry point to `DllMainCRTStartupForYY_Thunks` and add the matching alternate name linker option.

### Which APIs does YY-Thunks cover?

The repository holds a `ThunksList.md` file that records the covered APIs, and the project description names DecodePointer, EncodePointer and RegDeleteKeyEx among them. The README does not publish a compatibility matrix, so that list is the place to check before relying on a specific call.

## Sources

- [Chuyu-Team/YY-Thunks on GitHub](https://github.com/Chuyu-Team/YY-Thunks)
- [Issues](https://github.com/Chuyu-Team/YY-Thunks/issues)
- [License: MIT](https://github.com/Chuyu-Team/YY-Thunks/blob/master/LICENSE)
- [README](https://github.com/Chuyu-Team/YY-Thunks/blob/master/README.md)
- [Releases](https://github.com/Chuyu-Team/YY-Thunks/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/chuyu-team-yy-thunks
