驅動程式 - Windows Driver Model (WDM) - 解決StampInf.exe無法修改"Z:\"底下的INF檔案問題



main.cpp

#include <windows.h>
#include <filesystem>
#include <iostream>
#include <string>
#include <vector>

namespace fs = std::filesystem;

static const wchar_t* TEMP_DIR = L"c:\\stampinf_temp";

int wmain(int argc, wchar_t* argv[])
{
    if (argc < 2) {
        std::wcerr << L"Usage: stampinf.exe [arguments]\n";
        return 1;
    }

    fs::path wrapperPath = fs::absolute(argv[0]);
    fs::path realStampinf = wrapperPath.parent_path() / L"_stampinf.exe";

    if (!fs::exists(realStampinf)) {
        std::wcerr << L"ERROR: Real stampinf.exe not found:\n" << L"  " << realStampinf << L"\n";
        return 1;
    }

    int fIndex = -1;
    fs::path originalFile;

    for (int i = 1; i < argc; ++i) {
        if (_wcsicmp(argv[i], L"-f") == 0) {
            if (i + 1 >= argc) {
                std::wcerr << L"ERROR: -f requires a filename.\n";
                return 1;
            }

            fIndex = i;
            originalFile = argv[i + 1];
            break;
        }
    }

    if (fIndex == -1) {
        std::wcerr << L"ERROR: -f parameter not found.\n";
        return 1;
    }

    if (!fs::exists(originalFile)) {
        std::wcerr << L"ERROR: File does not exist:\n" << L"  " << originalFile << L"\n";
        return 1;
    }

    fs::path tempDir = TEMP_DIR;
    std::error_code ec;
    fs::create_directories(tempDir, ec);

    if (ec) {
        std::wcerr << L"ERROR: Cannot create temporary directory:\n" << L"  " << tempDir << L"\n";
        return 1;
    }

    fs::path tempFile = tempDir / originalFile.filename();
    std::wcout << L"Copying:\n" << L"  " << originalFile << L"\n" << L"to:\n" << L"  " << tempFile << L"\n";
    fs::copy_file(originalFile, tempFile, fs::copy_options::overwrite_existing, ec);

    if (ec) {
        std::wcerr << L"ERROR: Failed to copy file: " << ec.message().c_str() << L"\n";
        return 1;
    }

    std::wstring commandLine;

    auto appendArg = [&](const std::wstring& arg)
    {
        if (!commandLine.empty()) {
            commandLine += L" ";
        }
        commandLine += L"\"";

        size_t backslashes = 0;

        for (wchar_t c : arg) {
            if (c == L'\\') {
                ++backslashes;
            }
            else if (c == L'"') {
                commandLine.append(backslashes * 2 + 1, L'\\');
                commandLine += L'"';
                backslashes = 0;
            }
            else {
                if (backslashes) {
                    commandLine.append(backslashes, L'\\');
                }

                backslashes = 0;
                commandLine += c;
            }
        }

        if (backslashes) {
            commandLine.append(backslashes * 2, L'\\');
        }

        commandLine += L"\"";
    };

    for (int i = 1; i < argc; ++i) {
        appendArg(argv[i]);

        if (i == fIndex) {
            ++i;
            appendArg(tempFile.wstring());
        }
    }

    std::wcout << L"\nExecuting:\n";
    std::wcout << L"\"" << realStampinf << L"\" " << commandLine << L"\n\n";
    std::wstring fullCommand = L"\"" + std::wstring(realStampinf) + L"\" " + commandLine;

    STARTUPINFOW si = {};
    PROCESS_INFORMATION pi = {};

    si.cb = sizeof(si);

    std::vector<wchar_t> cmdBuffer(
        fullCommand.begin(),
        fullCommand.end()
    );

    cmdBuffer.push_back(L'\0');
    BOOL result = CreateProcessW(
        nullptr,
        cmdBuffer.data(),
        nullptr,
        nullptr,
        FALSE,
        0,
        nullptr,
        nullptr,
        &si,
        &pi
    );

    if (!result) {
        DWORD error = GetLastError();

        std::wcerr << L"ERROR: CreateProcess failed. Error = " << error << L"\n";
        fs::copy_file(tempFile, originalFile, fs::copy_options::overwrite_existing, ec);
        fs::remove(tempFile, ec);

        return 1;
    }

    WaitForSingleObject(pi.hProcess, INFINITE);

    DWORD exitCode = 1;
    GetExitCodeProcess(pi.hProcess, &exitCode);
    CloseHandle(pi.hThread);
    CloseHandle(pi.hProcess);
    std::wcout << L"\nCopying modified file back:\n" << L"  " << tempFile << L"\n" << L"to:\n" << L"  " << originalFile << L"\n";
    fs::copy_file(tempFile, originalFile, fs::copy_options::overwrite_existing, ec);

    if (ec) {
        std::wcerr << L"ERROR: Failed to copy file back: " << ec.message().c_str() << L"\n";
        fs::remove(tempFile, ec);

        return 1;
    }

    fs::remove(tempFile, ec);
    std::wcout << L"\nstampinf.exe exit code: " << exitCode << L"\n";

    return static_cast<int>(exitCode);
}

編譯

$ x86_64-w64-mingw32-g++ -std=c++17 -O2 -s -municode -static -o stampinf.exe main.cpp

P.S. 將原本stampinf.exe改成_stampinf.exe後, 再把編譯後的stampinf.exe複製進去即可