Last active
February 17, 2024 07:13
-
-
Save xWTF/3c07aec941bbe13a9b78a37cebd9ae9b to your computer and use it in GitHub Desktop.
Yet Another Windows Shim Wrapper Solution. Chocolatey's shimgen https://github.com/chocolatey/shimgen is not FOSS, so I made one.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Get updates from [this gist](https://gist.github.com/xWTF/3c07aec941bbe13a9b78a37cebd9ae9b) | |
Copyright © 2023 xWTF | |
This work is free. You can redistribute it and/or modify it under the | |
terms of the Do What The Fuck You Want To Public License, Version 2, | |
as published by Sam Hocevar. See the COPYING file or http://www.wtfpl.net/ | |
for more details. | |
""" | |
import os | |
import sys | |
import shutil | |
SHIM_CFG_FILE = "../.shim.cfg" | |
if len(sys.argv) < 2: | |
print("Usage: python generate_shim.py <target dir>") | |
exit(1) | |
os.chdir(os.path.dirname(os.path.realpath(__file__))) | |
known_shims = set() | |
shim_cfg = open(SHIM_CFG_FILE, "r").read() | |
for line in shim_cfg.split("\n"): | |
known_shims.add(line.split("=")[0]) | |
target_dir = sys.argv[1].replace("/", "\\") | |
if target_dir.endswith("\\"): | |
target_dir = target_dir[:-1] | |
for file in os.listdir(target_dir): | |
if not file.endswith(".exe"): | |
continue | |
if file in known_shims: | |
print("Skipping " + file) | |
continue | |
print("Generating shim for " + file) | |
shutil.copyfile("shim.exe", "../" + file) | |
shim_cfg += "\n" + file + "=" + target_dir | |
shim_cfg += "\n" | |
open(SHIM_CFG_FILE, "w").write(shim_cfg) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Get updates from [this gist](https://gist.github.com/xWTF/3c07aec941bbe13a9b78a37cebd9ae9b) | |
* | |
* Copyright © 2023 xWTF | |
* This work is free. You can redistribute it and/or modify it under the | |
* terms of the Do What The Fuck You Want To Public License, Version 2, | |
* as published by Sam Hocevar. See the COPYING file or http://www.wtfpl.net/ | |
* for more details. | |
*/ | |
#define _CRT_SECURE_NO_WARNINGS | |
#include <fstream> | |
#include <iostream> | |
#include <string> | |
#include <vector> | |
#include <windows.h> | |
#define SHIM_CFG_FILE L".shim.cfg" | |
#define MAX_ENV 32767 | |
int wmain(int argc, wchar_t* argv[]) | |
{ | |
wchar_t module_file[MAX_PATH]; | |
if (GetModuleFileNameW(NULL, module_file, MAX_PATH) == 0) { | |
std::cerr << "GetModuleFileName failed (" << GetLastError() << ").\n"; | |
return -1; | |
} | |
std::wstring cfg_path(module_file), exe_name; | |
size_t pos = cfg_path.find_last_of('\\'); | |
if (pos == std::string::npos) { | |
std::cerr << "Failed to locate config file (" << GetLastError() << ").\n"; | |
return -1; | |
} | |
exe_name = cfg_path.substr(pos + 1); | |
cfg_path = cfg_path.substr(0, pos + 1); | |
cfg_path += SHIM_CFG_FILE; | |
//// Read Config ///////////////////////////////////////////// | |
bool found = false; | |
std::wstring line, expected_path; | |
std::wifstream cfg(cfg_path.data()); | |
while (std::getline(cfg, line)) { | |
if (line.empty() || line[0] == '#') { | |
continue; | |
} | |
auto pos = line.find('='); | |
if (pos == std::string::npos) { | |
continue; | |
} | |
auto key = line.substr(0, pos); | |
if (key == exe_name) { | |
expected_path = line.substr(pos + 1); | |
found = true; | |
break; | |
} | |
} | |
cfg.close(); | |
if (!found) { | |
std::wcerr << "No entry for " << exe_name << " in " << cfg_path << "\n"; | |
return -1; | |
} | |
//// Prepend PATH ///////////////////////////////////////////////// | |
wchar_t PATH[MAX_ENV]; | |
DWORD lPATH = GetEnvironmentVariableW(L"PATH", PATH, MAX_ENV); | |
if (lPATH == 0) { | |
std::cerr << "GetEnvironmentVariable failed (" << GetLastError() << ").\n"; | |
return -1; | |
} | |
wchar_t* PATH_new = new wchar_t[lPATH + expected_path.size() + 2]; | |
wcscpy(PATH_new, expected_path.c_str()); | |
PATH_new[expected_path.size()] = L';'; | |
wcsncpy(PATH_new + expected_path.size() + 1, PATH, lPATH); | |
PATH_new[lPATH + expected_path.size() + 1] = L'\0'; | |
if (!SetEnvironmentVariableW(L"PATH", PATH_new)) { | |
std::cerr << "SetEnvironmentVariable failed (" << GetLastError() << ").\n"; | |
return -1; | |
} | |
delete[] PATH_new; | |
//// Prepare Command Line ///////////////////////////////////////////////// | |
auto lpCmdLineW = GetCommandLineW(); | |
if (*lpCmdLineW == '"') { | |
++lpCmdLineW; | |
while (*lpCmdLineW++ != '"'); | |
} else { | |
while (*lpCmdLineW && *lpCmdLineW != ' ' && *lpCmdLineW != '\t') { | |
++lpCmdLineW; | |
} | |
} | |
while (*lpCmdLineW == ' ' || *lpCmdLineW == '\t') { | |
lpCmdLineW++; | |
} | |
// Append executable name | |
expected_path += L'\\'; | |
expected_path += exe_name; | |
//// Create process ////////////////////////////////////////////// | |
STARTUPINFOW si {}; | |
si.cb = sizeof(si); | |
PROCESS_INFORMATION pi {}; | |
if (!CreateProcessW(expected_path.data(), const_cast<wchar_t*>((exe_name + L' ' + lpCmdLineW).c_str()), | |
NULL, NULL, // Process, thread attributes | |
TRUE, // Handle inheritance | |
0, // No creation flags | |
NULL, // Use parent's environment block | |
NULL, // Use parent's starting directory | |
&si, &pi) // Pointers | |
) { | |
std::cerr << "CreateProcess failed (" << GetLastError() << ").\n"; | |
return -1; | |
} | |
WaitForSingleObject(pi.hProcess, INFINITE); | |
DWORD exitCode; | |
if (!GetExitCodeProcess(pi.hProcess, &exitCode)) { | |
std::cerr << "GetExitCodeProcess failed (" << GetLastError() << ").\n"; | |
return -1; | |
} | |
CloseHandle(pi.hProcess); | |
CloseHandle(pi.hThread); | |
return exitCode; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Get updates from [this gist](https://gist.github.com/xWTF/3c07aec941bbe13a9b78a37cebd9ae9b) | |
Copyright © 2023 xWTF | |
This work is free. You can redistribute it and/or modify it under the | |
terms of the Do What The Fuck You Want To Public License, Version 2, | |
as published by Sam Hocevar. See the COPYING file or http://www.wtfpl.net/ | |
for more details. | |
""" | |
import os | |
import shutil | |
for file in os.listdir("../"): | |
if not file.endswith(".exe"): | |
continue | |
print("Updating shim for " + file) | |
shutil.copyfile("shim.exe", "../" + file) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment