mirror of
https://gitea.tendokyu.moe/TeamTofuShop/capnhook.git
synced 2026-09-27 01:00:42 +03:00
hook/args.c: Add command line recovery helper
This commit is contained in:
+137
@@ -0,0 +1,137 @@
|
||||
#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);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
HRESULT args_recover(int *argc, char ***argv);
|
||||
void args_free(int argc, char **argv);
|
||||
@@ -3,6 +3,8 @@ hook_lib = static_library(
|
||||
include_directories : inc,
|
||||
c_pch : '../precompiled.h',
|
||||
sources : [
|
||||
'args.c',
|
||||
'args.h',
|
||||
'com-proxy.c',
|
||||
'com-proxy.h',
|
||||
'hr.c',
|
||||
|
||||
Reference in New Issue
Block a user