“ride.exe"有什么特别之处?反正? [英] What's so special about "ride.exe" anyway?

查看:32
本文介绍了“ride.exe"有什么特别之处?反正?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在使用 Direct2D/DirectWrite 为高性能文本呈现实现原生 Win32 UI 原型时遇到了一个晦涩的问题.事情进展顺利,看起来很有希望:调整应用程序窗口大小没有任何延迟,整个文本呈现如预期的那样稳定.

I just bumped into an obscure issue, while implementing a prototype for a native Win32 UI using Direct2D/DirectWrite for high performance text rendering. Things went fine and looked promising: Resizing the application window was devoid of any lag, and the entire text rendering was as solid as one could expect.

也就是说,直到我决定将二进制文件重命名为 ride.exe".那时,操作系统选择强制我的应用程序进入故障模式".调整大小突然引入了非常明显的滞后,再加上调整大小时的差距,最终只会再次填补.另外,文本输出变得很跳跃,感知的字体大小各不相同.考虑到我只在应用程序启动时创建字体资源,这很奇怪.

That is, until I decided to rename the binary to "ride.exe". At that point, the OS opted to force my application into "glitch mode". Resizing suddenly introduced a very noticeable lag, combined with gaps when sizing up, that would only eventually fill again. Plus, text output got all jumpy, with the perceived font size varying. Which is odd considering that I only ever create the font resource at application startup.

如果我将二进制文件重命名为其他任何东西,所有这些工件都会立即消失,并立即返回,当我选择再次调用它ride.exe".不涉及重新编译或链接,它实际上只是一个重命名操作.

All those artifacts instantly go away, if I rename the binary to anything else, and instantly return, when I choose to call it "ride.exe" again. No recompilation or linking involved, it's literally just a rename operation.

在这一点上我迷路了,尽管看起来操作系统正在使用一些涉及图像名称的启发式方法来决定如何执行代码.那么,这里发生了什么?

I'm lost at this point, though it looks a lot like the OS is using some heuristic that involves the image name to decide, how to execute the code. So, what's going on here?

这是一个完整的重现来说明问题:

This is a complete repro to illustrate the issue:

#include <Windows.h>
#include <d2d1.h>
#include <d2d1_1helper.h>
#include <dwrite.h>

#pragma comment(lib, "D2d1.lib")
#pragma comment(lib, "Dwrite.lib")


LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void create_graphics_resources(HWND const hwnd) noexcept;
void discard_graphics_resources() noexcept;
void resize_render_target(HWND const hwnd) noexcept;
void create_dw_resources() noexcept;
void discard_dw_resources() noexcept;


ID2D1Factory1* pd2d_factory { nullptr };
ID2D1HwndRenderTarget* prender_target { nullptr };
ID2D1SolidColorBrush* ptext_color_brush { nullptr };
IDWriteFactory* pdw_factory { nullptr };
IDWriteTextFormat* pdw_text_format { nullptr };


int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR, int nCmdShow)
{
    CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);

    WNDCLASSEXW wcex {};
    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.style = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc = WndProc;
    wcex.hInstance = hInstance;
    wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
    wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wcex.lpszClassName = L"d2d_mcve";
    RegisterClassExW(&wcex);

    auto const hWnd { CreateWindowExW(0, L"d2d_mcve", L"D2D MCVE", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT,
                                      0, nullptr, nullptr, hInstance, nullptr) };
    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);

    MSG msg {};

    // Main message loop:
    while (GetMessage(&msg, nullptr, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    CoUninitialize();
    return (int)msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_CREATE: {
        D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, D2D1_FACTORY_OPTIONS {}, &pd2d_factory);
        DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(pdw_factory),
                            reinterpret_cast<IUnknown**>(&pdw_factory));
    }
    break;

    case WM_DESTROY:
        discard_dw_resources();
        discard_graphics_resources();
        pdw_factory->Release();
        pd2d_factory->Release();
        PostQuitMessage(0);
        break;

    case WM_SIZE:
        resize_render_target(hWnd);
        InvalidateRect(hWnd, nullptr, FALSE);
        break;

    case WM_PAINT: {
        PAINTSTRUCT ps {};
        BeginPaint(hWnd, &ps);

        create_graphics_resources(hWnd);
        prender_target->BeginDraw();

        prender_target->Clear(D2D1::ColorF(D2D1::ColorF::Black));
        create_dw_resources();
        auto const target_size { prender_target->GetSize() };
        prender_target->SetTransform(D2D1::Matrix3x2F::Identity());

        auto const& placeholder_text { L"Lorem ipsum dolor sit amet, consectetur adipiscing elit." };
        prender_target->DrawTextW(placeholder_text, ARRAYSIZE(placeholder_text) - 1, pdw_text_format,
                                 D2D1::RectF(0.0f, 0.0f, target_size.width, target_size.height),
                                 ptext_color_brush);

        auto const hr { prender_target->EndDraw() };
        if (hr == D2DERR_RECREATE_TARGET)
        {
            discard_graphics_resources();
            InvalidateRect(hWnd, nullptr, FALSE);
        }

        EndPaint(hWnd, &ps);
    }
    break;

    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }

    return 0;
}


void create_graphics_resources(HWND const hwnd) noexcept
{
    if (prender_target == nullptr)
    {
        RECT rc {};
        GetClientRect(hwnd, &rc);

        auto const size { D2D1::SizeU(static_cast<UINT32>(rc.right), static_cast<UINT32>(rc.bottom)) };
        pd2d_factory->CreateHwndRenderTarget(D2D1::RenderTargetProperties(),
                                             D2D1::HwndRenderTargetProperties(hwnd, size), &prender_target);

        prender_target->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::White, 1.0f), &ptext_color_brush);
    }
}

void discard_graphics_resources() noexcept
{
    if (ptext_color_brush != nullptr)
    {
        ptext_color_brush->Release();
        ptext_color_brush = nullptr;
    }
    if (prender_target != nullptr)
    {
        prender_target->Release();
        prender_target = nullptr;
    }
}

void resize_render_target(HWND const hwnd) noexcept
{
    if (prender_target != nullptr)
    {
        RECT rc {};
        GetClientRect(hwnd, &rc);

        auto const size { D2D1::SizeU(static_cast<UINT32>(rc.right), static_cast<UINT32>(rc.bottom)) };
        prender_target->Resize(size);
    }
}

void create_dw_resources() noexcept
{
    if (pdw_text_format == nullptr)
    {
        pdw_factory->CreateTextFormat(L"Courier New", nullptr, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL,
                                      DWRITE_FONT_STRETCH_NORMAL, 48.0f, L"en-US", &pdw_text_format);
    }
}

void discard_dw_resources() noexcept
{
    if (pdw_text_format != nullptr)
    {
        pdw_text_format->Release();
        pdw_text_format = nullptr;
    }
}

  1. 将源代码另存为main.cpp".
  2. 使用以下命令行编译代码:
    cl.exe/O2/EHsc/D "NDEBUG";/D UNICODE"/MD main.cpp user32.lib ole32.lib
  3. 在文件系统的任意位置创建一个名为 choosing_a_trident_for_a_buttplug_is_not_prudent" 的目录,然后将 main.exe" 复制到该目录中.
  4. 启动 main.exe" 并观察应用程序在调整主窗口大小时的行为.
  5. choosing_a_trident_for_a_buttplug_is_not_prudent"下的main.exe"副本重命名为ride.exe",启动ride.exe" 并观察调整主窗口大小时的行为.
  1. Save the source code as "main.cpp".
  2. Compile the code using the following command line:
    cl.exe /O2 /EHsc /D "NDEBUG" /D "UNICODE" /MD main.cpp user32.lib ole32.lib
  3. Create a directory named "choosing_a_trident_for_a_buttplug_is_not_prudent" anywhere in the filesystem and copy "main.exe" into that directory.
  4. Launch "main.exe" and observe the behavior of the application when resizing the main window.
  5. Rename the copy of "main.exe" under "choosing_a_trident_for_a_buttplug_is_not_prudent" to "ride.exe", launch "ride.exe" and observe the behavior when resizing the main window.

最后一步在我的系统 (Windows 10 19041.330) 上显示出各种视觉故障.当将可执行映像重命名为除 ride.exe" 之外的任何内容,或将每个父目录重命名为不再包含短语 ride" 时,应用程序会立即恢复正常操作em>.外壳没有区别.

The last step exhibits all sorts of visual glitches on my system (Windows 10 19041.330). The application instantly returns to normal operation when either renaming the executable image to anything but "ride.exe", or renaming every parent directory to no longer contain the phrase "ride". Casing doesn't make a difference.

推荐答案

我还没有对究竟发生的事情进行彻底的分析,但似乎系统正在使用 - 我敢说 - 有点(?)粗略的策略来修复损坏的应用程序.像往常一样,可以在注册表中找到耻辱堂:

I haven't done a thorough analysis on what exactly is happening, yet it appears that the system is using a - dare I say - somewhat (?) crude strategy to fix broken applications. As usual, the Hall of Shame is to be found in the registry:

在我的系统上,HKU\\System\GameConfigStore\Children 下有一个名为 8e89aac5-6105-47bd-bfb3-6ed01bda07b0 的密钥.暂时将明显的 WTF 放在一边,GameConfigStore 似乎是我的用户帐户的 System 关键键,该键具有名为 ExeParentDirectory 的值和 Flags,以及相关数据 RIDE (REG_SZ) 和 0x11 (REG_DWORD), 分别.

On my system there's a key named 8e89aac5-6105-47bd-bfb3-6ed01bda07b0 under HKU\<sid>\System\GameConfigStore\Children. Leaving the obvious WTF aside for a minute, that GameConfigStore is seemingly a System-vital key for my user account, that key has values named ExeParentDirectory and Flags, with associated data RIDE (REG_SZ) and 0x11 (REG_DWORD), respectively.

我的理解是:如果由 <sid> 识别的用户尝试启动一个名为 ride.exe(硬编码,某处)的二进制文件,该二进制文件驻留在在名称包含 RIDE 的目录下,首先将标志 0x11 应用于 something,对于运动,只是为了引起他们的注意,然后才允许主要线程来执行.这是为了确保损坏的应用程序 X 继续显示未损坏,当 决定更改可能会出现损坏的环境时.

The way I read this is: If a user identified by <sid> attempts to launch a binary called ride.exe (hardcoded, somewhere), that resides under a directory whose name contains RIDE, first apply the flags 0x11 to something, for sports, just to get their attention, before allowing the primary thread to execute. This is to ensure that broken app X continues to appear not broken, when <user> decides to change the environment that would otherwise exhibit the brokenness.

即使这会破坏其他正确编写的应用程序.

Even if this were to break other, properly written applications.

现在这听起来可能很糟糕,但您必须在应得的地方给予 Microsoft地球,事实上,专业,并使用 GUID.

Now this may sound bad, but you have to give Microsoft credit where credit is due: Out of all possible combinations of characters that form a valid registry key name to communicate with us, devs, they have opted to keep this down to earth, matter of fact, professional, and use GUIDs.

我的意思是...

他们也可以选择跟随:

  • 质量不重要,投资回报率才重要
  • 什么意思,你做过 RTFM?!
  • 老兄,什么合同保证?大声笑,n00b
  • 这只是一个友好的FU.但是不,我们不在乎那些实际上尝试不吸吮的开发者

但他们没有!那谢谢啦?我猜.

But they didn't! So... thanks? I guess.

这篇关于“ride.exe"有什么特别之处?反正?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆