source: trunk/aux/cocotron/win32/cocotron/WaltConsole/WaltConsole.c @ 12824

Last change on this file since 12824 was 12824, checked in by gb, 11 years ago

moved here

File size: 4.5 KB
Line 
1#include <windows.h>
2#include <psapi.h>
3#include <stdio.h>
4#include <string.h>
5
6
7struct 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
21typedef LONG (__stdcall *FPTR_NtQueryInformationProcess ) (HANDLE, INT, PVOID, ULONG, PULONG);
22
23ULONG
24getppid()
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
41char *
42parent_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
59int
60write_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
98int
99write_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
123int 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}
Note: See TracBrowser for help on using the repository browser.