Commit 54c94a6f authored by Amos Wenger's avatar Amos Wenger

Add --msiexec command

parent a8469541
Pipeline #466 passed with stage
......@@ -6,6 +6,16 @@
#define SEE_MASK_NOASYNC 0x00000100
#endif
#define SAFE_APPEND(fmt, arg) \
{ \
int written = snprintf(tmp, MAX_ARGUMENTS_LENGTH, (fmt), parameters, (arg)); \
if (written < 0 || written >= MAX_ARGUMENTS_LENGTH) { \
bail(1, "argument string too long"); \
} \
\
strncpy(parameters, tmp, MAX_ARGUMENTS_LENGTH); \
}
// cf. https://www.msigeek.com/442/windows-os-version-numbers - Vista is 6.0
#define VISTA_MAJOR_VERSION 6
......@@ -24,51 +34,18 @@ static int getMajorOSVersion() {
return ovi.dwMajorVersion;
}
/**
* Inspired by / with some code from the following MIT-licensed projects:
* - https://github.com/atom/node-runas
* - https://github.com/jpassing/elevate
*/
int main(int argc, char** argv) {
if (getMajorOSVersion() < VISTA_MAJOR_VERSION) {
bail(1, "elevate requires Windows Vista or above");
}
if (argc < 2) {
bail(1, "Usage: elevate PROGRAM ARGS");
}
if (strcmp("-V", argv[1]) == 0) {
printf("%s\n", ELEVATE_VERSION);
return 0;
}
const int MAX_ARGUMENTS_LENGTH = 65536;
char parameters[MAX_ARGUMENTS_LENGTH];
char tmp[MAX_ARGUMENTS_LENGTH];
parameters[0] = '\0';
for (int i = 2; i < argc; i++) {
int written = snprintf(tmp, MAX_ARGUMENTS_LENGTH, "%s%s ", parameters, argv[i]);
if (written < 0 || written >= MAX_ARGUMENTS_LENGTH) {
bail(1, "argument string too long");
}
strncpy(parameters, tmp, MAX_ARGUMENTS_LENGTH);
}
int exec(const char *verb, const char *file, const char *parameters) {
SHELLEXECUTEINFO sei;
fprintf(stderr, "[elevate] %s %s\n", argv[1], parameters);
fprintf(stderr, "[elevate] %s %s %s\n", verb, file, parameters);
fflush(stderr);
SHELLEXECUTEINFO sei;
ZeroMemory(&sei, sizeof(SHELLEXECUTEINFO));
sei.cbSize = sizeof(SHELLEXECUTEINFO);
// we want to wait until the program exits to exit with its code
sei.fMask = SEE_MASK_NOASYNC | SEE_MASK_NOCLOSEPROCESS;
// would be "open" if we didn't need privilege elevation
sei.lpVerb = "runas";
sei.lpFile = argv[1];
sei.lpVerb = verb;
sei.lpFile = file;
sei.lpParameters = parameters;
sei.nShow = SW_HIDE;
......@@ -87,3 +64,92 @@ int main(int argc, char** argv) {
return code;
}
int elevate(int argc, char** argv) {
const int MAX_ARGUMENTS_LENGTH = 65536;
char parameters[MAX_ARGUMENTS_LENGTH];
char tmp[MAX_ARGUMENTS_LENGTH];
parameters[0] = '\0';
for (int i = 2; i < argc; i++) {
SAFE_APPEND("%s%s ", argv[i])
}
fprintf(stderr, "[elevate] %s %s\n", argv[1], parameters);
fflush(stderr);
return exec("runas", argv[1], parameters);
}
void msibail() {
bail(1, "Usage: elevate --msiexec [--install/--uninstall] msiPath installPath logPath");
}
int msiexec(int argc, char** argv) {
const int MAX_ARGUMENTS_LENGTH = 65536;
char parameters[MAX_ARGUMENTS_LENGTH];
char tmp[MAX_ARGUMENTS_LENGTH];
parameters[0] = '\0';
if (argc < 6) {
fprintf(stderr, "Not enough arguments, expected 6, got %d\n", argc);
msibail();
}
const char* command = argv[2];
const char* msiPath = argv[3];
const char* installPath = argv[4];
const char* logPath = argv[5];
SAFE_APPEND("%s%s ", "ALLUSERS=2");
SAFE_APPEND("%s%s ", "MSIINSTALLPERUSER=1");
SAFE_APPEND("%sTARGETDIR=\"%s\" ", installPath);
SAFE_APPEND("%sINSTALLDIR=\"%s\" ", installPath);
SAFE_APPEND("%sAPPDIR=\"%s\" ", installPath);
SAFE_APPEND("%s%s ", "/norestart");
SAFE_APPEND("%s%s ", "/quiet");
SAFE_APPEND("%s%s ", "/l*v");
SAFE_APPEND("%s%s ", logPath);
if (strcmp(command, "--install") == 0) {
SAFE_APPEND("%s%s ", "/i");
} else if (strcmp(command, "--uninstall") == 0) {
SAFE_APPEND("%s%s ", "/x");
} else {
fprintf(stderr, "Command must be --install or --uninstall, got %s\n", command);
msibail();
}
SAFE_APPEND("%s%s ", msiPath);
return exec("open", "msiexec", parameters);
}
/**
* Inspired by / with some code from the following MIT-licensed projects:
* - https://github.com/atom/node-runas
* - https://github.com/jpassing/elevate
*/
int main(int argc, char** argv) {
if (getMajorOSVersion() < VISTA_MAJOR_VERSION) {
bail(1, "elevate requires Windows Vista or above");
}
if (argc < 2) {
bail(1, "Usage: elevate PROGRAM ARGS");
}
if (strcmp("-V", argv[1]) == 0) {
printf("%s\n", ELEVATE_VERSION);
return 0;
}
if (strcmp("--msiexec", argv[1]) == 0) {
return msiexec(argc, argv);
} else {
return elevate(argc, argv);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment