| 1 | #include <windows.h>
|
|---|
| 2 | #include <psapi.h>
|
|---|
| 3 | #include <stdio.h>
|
|---|
| 4 | #include <string.h>
|
|---|
| 5 |
|
|---|
| 6 |
|
|---|
| 7 | struct ProcessBasicInformation {
|
|---|
| 8 | DWORD ExitStatus;
|
|---|
| 9 | PVOID PebBaseAddress;
|
|---|
| 10 | DWORD AffinityMask;
|
|---|
| 11 | DWORD BasePriority;
|
|---|
| 12 | ULONG UniqueProcessId;
|
|---|
| 13 | ULONG InheritedFromUniqueProcessId;
|
|---|
| 14 | };
|
|---|
| 15 |
|
|---|
| 16 | /* Try to get the (Windows) pid of the parent process; return it, or
|
|---|
| 17 | return 0 on failure. There doesn't seem to be a higher-level way
|
|---|
| 18 | to do this.
|
|---|
| 19 | */
|
|---|
| 20 |
|
|---|
| 21 | typedef LONG (__stdcall *FPTR_NtQueryInformationProcess ) (HANDLE, INT, PVOID, ULONG, PULONG);
|
|---|
| 22 |
|
|---|
| 23 | ULONG
|
|---|
| 24 | getppid()
|
|---|
| 25 | {
|
|---|
| 26 | ULONG ppid = 0, pid = GetCurrentProcessId();
|
|---|
| 27 | HANDLE hcurrent = OpenProcess(PROCESS_QUERY_INFORMATION,FALSE,pid);
|
|---|
| 28 | if (hcurrent) {
|
|---|
| 29 | FPTR_NtQueryInformationProcess NtQueryInformationProcess = (FPTR_NtQueryInformationProcess) GetProcAddress(GetModuleHandleA("ntdll"), "NtQueryInformationProcess");
|
|---|
| 30 | if (NtQueryInformationProcess != NULL) {
|
|---|
| 31 | struct ProcessBasicInformation pbi;
|
|---|
| 32 | if (NtQueryInformationProcess(hcurrent, 0, (void *)&pbi, sizeof(pbi), NULL) == 0) {
|
|---|
| 33 | ppid = pbi.InheritedFromUniqueProcessId;
|
|---|
| 34 | }
|
|---|
| 35 | }
|
|---|
| 36 | CloseHandle(hcurrent);
|
|---|
| 37 | }
|
|---|
| 38 | return ppid;
|
|---|
| 39 | }
|
|---|
| 40 |
|
|---|
| 41 | char *
|
|---|
| 42 | parent_process_name(ULONG ppid)
|
|---|
| 43 | {
|
|---|
| 44 | char procname[1024], *result = NULL;
|
|---|
| 45 | DWORD namelen;
|
|---|
| 46 | HANDLE hprocess = OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ, FALSE, ppid);
|
|---|
| 47 |
|
|---|
| 48 | if (hprocess) {
|
|---|
| 49 | namelen = GetModuleBaseNameA(hprocess, NULL, procname, sizeof(procname)-1);
|
|---|
| 50 | if (namelen && (namelen <= sizeof(procname))) {
|
|---|
| 51 | result = strdup(procname);
|
|---|
| 52 | }
|
|---|
| 53 | CloseHandle(hprocess);
|
|---|
| 54 | }
|
|---|
| 55 | return result;
|
|---|
| 56 | }
|
|---|
| 57 |
|
|---|
| 58 |
|
|---|
| 59 | int
|
|---|
| 60 | write_pending_console_input(HANDLE input, HANDLE output)
|
|---|
| 61 | {
|
|---|
| 62 | DWORD ninput_events, i, n, nread, nwritten;
|
|---|
| 63 | char buf[1024];
|
|---|
| 64 | INPUT_RECORD ir;
|
|---|
| 65 |
|
|---|
| 66 | switch (WaitForSingleObject(input, 100)) {
|
|---|
| 67 | case WAIT_TIMEOUT:
|
|---|
| 68 | return 0;
|
|---|
| 69 | break;
|
|---|
| 70 | case WAIT_OBJECT_0:
|
|---|
| 71 | ninput_events = 0;
|
|---|
| 72 | if (GetNumberOfConsoleInputEvents(input, &ninput_events)) {
|
|---|
| 73 | for (i = 0; i < ninput_events; i++) {
|
|---|
| 74 | PeekConsoleInput(input, &ir, 1, &n);
|
|---|
| 75 | if ((ir.EventType == KEY_EVENT)) {
|
|---|
| 76 | if (!ReadFile(input, buf, sizeof(buf), &nread, NULL)) {
|
|---|
| 77 | return -1;
|
|---|
| 78 | }
|
|---|
| 79 | if (!WriteFile(output, buf, nread, &nwritten, NULL)) {
|
|---|
| 80 | return -1;
|
|---|
| 81 | }
|
|---|
| 82 | return 0;
|
|---|
| 83 | } else {
|
|---|
| 84 | ReadConsoleInput(input, &ir, 1, &n);
|
|---|
| 85 | }
|
|---|
| 86 | }
|
|---|
| 87 | }
|
|---|
| 88 | return 0;
|
|---|
| 89 | break;
|
|---|
| 90 |
|
|---|
| 91 | default:
|
|---|
| 92 | return -1;
|
|---|
| 93 | break;
|
|---|
| 94 | }
|
|---|
| 95 | }
|
|---|
| 96 |
|
|---|
| 97 |
|
|---|
| 98 | int
|
|---|
| 99 | write_pipe_input_to_console(HANDLE hpipe, HANDLE conout)
|
|---|
| 100 | {
|
|---|
| 101 | unsigned char buf[1024];
|
|---|
| 102 | DWORD navail, n, m;
|
|---|
| 103 |
|
|---|
| 104 | while (PeekNamedPipe(hpipe, NULL, 0, NULL, &navail, NULL) != 0) {
|
|---|
| 105 | if (navail == 0) {
|
|---|
| 106 | return 0;
|
|---|
| 107 | }
|
|---|
| 108 | if (navail > sizeof(buf)) {
|
|---|
| 109 | n = sizeof(buf);
|
|---|
| 110 | } else {
|
|---|
| 111 | n = navail;
|
|---|
| 112 | }
|
|---|
| 113 | if (!ReadFile(hpipe, buf, n, &m, NULL)) {
|
|---|
| 114 | return -1;
|
|---|
| 115 | }
|
|---|
| 116 | if (!WriteFile(conout, buf, m, &n, NULL)) {
|
|---|
| 117 | return -1;
|
|---|
| 118 | }
|
|---|
| 119 | }
|
|---|
| 120 | return -1;
|
|---|
| 121 | }
|
|---|
| 122 |
|
|---|
| 123 | int APIENTRY WinMain(HINSTANCE a,HINSTANCE b,LPSTR c,int d)
|
|---|
| 124 | {
|
|---|
| 125 | HANDLE in, out, conin, conout, hppid;
|
|---|
| 126 | DWORD navail, err, exitcode;
|
|---|
| 127 | ULONG ppid;
|
|---|
| 128 | HWND window;
|
|---|
| 129 | HMENU menu;
|
|---|
| 130 | char title[2048], *procname, buf[1024];
|
|---|
| 131 |
|
|---|
| 132 | in = GetStdHandle(STD_INPUT_HANDLE);
|
|---|
| 133 | out = GetStdHandle(STD_OUTPUT_HANDLE);
|
|---|
| 134 |
|
|---|
| 135 | while (1) {
|
|---|
| 136 | navail = 0;
|
|---|
| 137 | if (PeekNamedPipe(in, NULL, 0, NULL, &navail, NULL) == 0) {
|
|---|
| 138 | exit(0); /* error or EOF */
|
|---|
| 139 | }
|
|---|
| 140 | if (navail != 0) {
|
|---|
| 141 | break;
|
|---|
| 142 | }
|
|---|
| 143 | Sleep(100);
|
|---|
| 144 | }
|
|---|
| 145 |
|
|---|
| 146 | AllocConsole();
|
|---|
| 147 |
|
|---|
| 148 | conin = CreateFileA("CONIN$",GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
|
|---|
| 149 | conout = CreateFileA("CONOUT$",GENERIC_WRITE,FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
|
|---|
| 150 |
|
|---|
| 151 | ppid = getppid();
|
|---|
| 152 | procname = parent_process_name(ppid);
|
|---|
| 153 | hppid = OpenProcess(PROCESS_QUERY_INFORMATION|SYNCHRONIZE,FALSE,ppid);
|
|---|
| 154 | if (!procname) {
|
|---|
| 155 | procname = "<Unknown>";
|
|---|
| 156 | }
|
|---|
| 157 | sprintf(title, "WaltConsole for %s (pid 0x%x)", procname, ppid);
|
|---|
| 158 | SetConsoleTitleA(title);
|
|---|
| 159 |
|
|---|
| 160 | window = GetConsoleWindow();
|
|---|
| 161 | menu = GetSystemMenu(window, FALSE);
|
|---|
| 162 | EnableMenuItem(menu, SC_CLOSE, MF_BYCOMMAND|MF_GRAYED);
|
|---|
| 163 |
|
|---|
| 164 | ShowWindow(window, SW_SHOW);
|
|---|
| 165 | ShowWindow(window, SW_SHOW);
|
|---|
| 166 |
|
|---|
| 167 | do {
|
|---|
| 168 | if (WaitForSingleObject(hppid, 0) == WAIT_OBJECT_0) {
|
|---|
| 169 | break;
|
|---|
| 170 | }
|
|---|
| 171 | if (write_pipe_input_to_console(in, conout) < 0) {
|
|---|
| 172 | break;
|
|---|
| 173 | }
|
|---|
| 174 | write_pending_console_input(conin, out);
|
|---|
| 175 | } while (1);
|
|---|
| 176 |
|
|---|
| 177 | EnableMenuItem(menu, SC_CLOSE, MF_BYCOMMAND|MF_ENABLED);
|
|---|
| 178 | sprintf(buf,"\n\nProcess %s (pid 0x%x) has exited; press any key to close this window.", procname, ppid);
|
|---|
| 179 | WriteFile(conout, buf, strlen(buf), &navail, NULL);
|
|---|
| 180 | FlushConsoleInputBuffer(conin);
|
|---|
| 181 | ReadConsoleA(conin,buf,1,&navail,NULL);
|
|---|
| 182 |
|
|---|
| 183 | }
|
|---|