| #include <windows.h> |
| #include <nt.h> |
| #include <string.h> |
| #include <wchar.h> |
| |
| #define malloc(S) RtlAllocateHeap(Heap, 0, S) |
| #define realloc(P, S) RtlReAllocateHeap(Heap, 0, P, S) |
| #define free(P) RtlFreeHeap(Heap, 0, P) |
| |
| extern int main(int, char **, char **); |
| static void *Heap; |
| |
| void __main() {} |
| |
| static int _parse_tokens(char *string, char ***tokens, int length) { |
| /* Extract whitespace- and quotes- delimited tokens from the given string |
| and put them into the tokens array. Returns number of tokens |
| extracted. Length specifies the current size of tokens[]. |
| THIS METHOD MODIFIES string. */ |
| |
| const char *whitespace = " \t\r\n"; |
| char *tokenEnd; |
| const char *quoteCharacters = "\"\'"; |
| char *end = string + strlen(string); |
| |
| if (!string) return length; |
| |
| while(1) { |
| const char *q; |
| /* Skip over initial whitespace. */ |
| string += strspn(string, whitespace); |
| if(!*string) break; |
| |
| for(q = quoteCharacters; *q; ++q) { |
| if(*string == *q) break; |
| } |
| if(*q) { |
| /* Token is quoted. */ |
| char quote = *string++; |
| tokenEnd = strchr(string, quote); |
| /* If there is no endquote, the token is the rest of the string. */ |
| if(!tokenEnd) tokenEnd = end; |
| } else { |
| tokenEnd = string + strcspn(string, whitespace); |
| } |
| |
| *tokenEnd = 0; |
| |
| { |
| char **new_tokens; |
| int newlen = length + 1; |
| new_tokens = realloc(*tokens, (newlen + 1) * sizeof(char *)); |
| if(!new_tokens) { |
| /* Out of memory. */ |
| return -1; |
| } |
| |
| *tokens = new_tokens; |
| (*tokens)[length] = string; |
| length = newlen; |
| } |
| if(tokenEnd == end) break; |
| string = tokenEnd + 1; |
| } |
| |
| return length; |
| } |
| |
| static void _getmainargs(int *argc, char ***argv, wchar_t *wcommandline) { |
| int commandline_len = 0; |
| if(wcommandline) commandline_len = wcslen(wcommandline) * 2; |
| |
| *argv = malloc(sizeof (char *) * 1); |
| if(!*argv) ExitProcess(-1); |
| |
| **argv = malloc(commandline_len + 1); |
| if(!**argv) ExitProcess(-1); |
| |
| if(commandline_len > 0) { |
| char *argv0 = **argv; |
| wcstombs(argv0, wcommandline, commandline_len + 1); |
| *argc = _parse_tokens(argv0, argv, 0); |
| if(*argc < 0) ExitProcess(-1); |
| } |
| (*argv)[*argc] = 0; |
| return; |
| } |
| |
| void NtProcessStartup() { |
| int _argc = 0; |
| char **_argv = 0; |
| char **_envp = 0; |
| PROCESS_BASIC_INFORMATION pbi; |
| RTL_USER_PROCESS_PARAMETERS *process_parameters; |
| NtQueryInformationProcess((void *)-1, ProcessBasicInformation, &pbi, sizeof pbi, NULL); |
| process_parameters = RtlNormalizeProcessParams(pbi.PebBaseAddress->ProcessParameters); |
| Heap = pbi.PebBaseAddress->ProcessHeap = RtlCreateHeap(HEAP_GROWABLE, NULL, 0, 0, NULL, NULL); |
| _getmainargs(&_argc, &_argv, process_parameters->CommandLine.Buffer); |
| wchar_t *s = process_parameters->Environment; |
| if(s) { |
| char **e = _envp = malloc(256 * sizeof(char *)); |
| while(*s) { |
| size_t len = wcslen(s) * 2; |
| *e = malloc(len * sizeof(char)); |
| wcstombs(*e++, s, len); |
| while(*s++); |
| } |
| *e = NULL; |
| } |
| NtTerminateProcess((void *)-1, main(_argc, _argv, _envp)); |
| } |