Files

138 lines
2.4 KiB
C

#include <windows.h>
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "hook/args.h"
/* This does not handle escaped double quotes inside args correctly yet */
static HRESULT args_push(
int *argc,
char ***argv,
const char *begin,
const char *end)
{
int tmp_argc;
char **tmp_argv;
size_t nchars;
char *str;
nchars = end - begin;
str = malloc(nchars + 1);
if (str == NULL) {
goto fail;
}
memcpy(str, begin, nchars);
str[nchars] = '\0';
tmp_argc = *argc + 1;
tmp_argv = realloc(*argv, tmp_argc * sizeof(char **));
if (tmp_argv == NULL) {
goto fail;
}
tmp_argv[tmp_argc - 1] = str;
*argv = tmp_argv;
*argc = tmp_argc;
return S_OK;
fail:
free(str);
return E_OUTOFMEMORY;
}
HRESULT args_recover(int *argc_out, char ***argv_out)
{
int argc;
char **argv;
const char *begin;
const char *pos;
bool quote;
HRESULT hr;
assert(argc_out != NULL);
assert(argv_out != NULL);
*argc_out = 0;
*argv_out = NULL;
argc = 0;
argv = NULL;
quote = false;
for (begin = pos = GetCommandLine() ; *pos ; pos++) {
switch (*pos) {
case '"':
if (!quote) {
quote = true;
begin = pos + 1;
} else {
hr = args_push(&argc, &argv, begin, pos);
if (FAILED(hr)) {
goto fail;
}
quote = false;
begin = NULL;
}
break;
case ' ':
if (!quote && begin != NULL) {
args_push(&argc, &argv, begin, pos);
begin = NULL;
}
break;
default:
if (begin == NULL) {
begin = pos;
}
break;
}
}
if (begin != NULL && !quote) {
hr = args_push(&argc, &argv, begin, pos);
if (FAILED(hr)) {
goto fail;
}
}
*argc_out = argc;
*argv_out = argv;
return S_OK;
fail:
args_free(argc, argv);
return hr;
}
void args_free(int argc, char **argv)
{
int i;
for (i = 0 ; i < argc ; i++) {
free(argv[i]);
}
free(argv);
}