conproc.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. /*
  2. Copyright (C) 1997-2001 Id Software, Inc.
  3. This program is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU General Public License
  5. as published by the Free Software Foundation; either version 2
  6. of the License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. See the GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  14. */
  15. // conproc.c -- support for qhost
  16. #include <stdio.h>
  17. #include <process.h>
  18. #include <windows.h>
  19. #include "conproc.h"
  20. #define CCOM_WRITE_TEXT 0x2
  21. // Param1 : Text
  22. #define CCOM_GET_TEXT 0x3
  23. // Param1 : Begin line
  24. // Param2 : End line
  25. #define CCOM_GET_SCR_LINES 0x4
  26. // No params
  27. #define CCOM_SET_SCR_LINES 0x5
  28. // Param1 : Number of lines
  29. HANDLE heventDone;
  30. HANDLE hfileBuffer;
  31. HANDLE heventChildSend;
  32. HANDLE heventParentSend;
  33. HANDLE hStdout;
  34. HANDLE hStdin;
  35. unsigned _stdcall RequestProc (void *arg);
  36. LPVOID GetMappedBuffer (HANDLE hfileBuffer);
  37. void ReleaseMappedBuffer (LPVOID pBuffer);
  38. BOOL GetScreenBufferLines (int *piLines);
  39. BOOL SetScreenBufferLines (int iLines);
  40. BOOL ReadText (LPTSTR pszText, int iBeginLine, int iEndLine);
  41. BOOL WriteText (LPCTSTR szText);
  42. int CharToCode (char c);
  43. BOOL SetConsoleCXCY(HANDLE hStdout, int cx, int cy);
  44. int ccom_argc;
  45. char **ccom_argv;
  46. /*
  47. ================
  48. CCheckParm
  49. Returns the position (1 to argc-1) in the program's argument list
  50. where the given parameter apears, or 0 if not present
  51. ================
  52. */
  53. int CCheckParm (char *parm)
  54. {
  55. int i;
  56. for (i=1 ; i<ccom_argc ; i++)
  57. {
  58. if (!ccom_argv[i])
  59. continue;
  60. if (!strcmp (parm,ccom_argv[i]))
  61. return i;
  62. }
  63. return 0;
  64. }
  65. void InitConProc (int argc, char **argv)
  66. {
  67. unsigned threadAddr;
  68. HANDLE hFile;
  69. HANDLE heventParent;
  70. HANDLE heventChild;
  71. int t;
  72. ccom_argc = argc;
  73. ccom_argv = argv;
  74. // give QHOST a chance to hook into the console
  75. if ((t = CCheckParm ("-HFILE")) > 0)
  76. {
  77. if (t < argc)
  78. hFile = (HANDLE)atoi (ccom_argv[t+1]);
  79. }
  80. if ((t = CCheckParm ("-HPARENT")) > 0)
  81. {
  82. if (t < argc)
  83. heventParent = (HANDLE)atoi (ccom_argv[t+1]);
  84. }
  85. if ((t = CCheckParm ("-HCHILD")) > 0)
  86. {
  87. if (t < argc)
  88. heventChild = (HANDLE)atoi (ccom_argv[t+1]);
  89. }
  90. // ignore if we don't have all the events.
  91. if (!hFile || !heventParent || !heventChild)
  92. {
  93. printf ("Qhost not present.\n");
  94. return;
  95. }
  96. printf ("Initializing for qhost.\n");
  97. hfileBuffer = hFile;
  98. heventParentSend = heventParent;
  99. heventChildSend = heventChild;
  100. // so we'll know when to go away.
  101. heventDone = CreateEvent (NULL, FALSE, FALSE, NULL);
  102. if (!heventDone)
  103. {
  104. printf ("Couldn't create heventDone\n");
  105. return;
  106. }
  107. if (!_beginthreadex (NULL, 0, RequestProc, NULL, 0, &threadAddr))
  108. {
  109. CloseHandle (heventDone);
  110. printf ("Couldn't create QHOST thread\n");
  111. return;
  112. }
  113. // save off the input/output handles.
  114. hStdout = GetStdHandle (STD_OUTPUT_HANDLE);
  115. hStdin = GetStdHandle (STD_INPUT_HANDLE);
  116. // force 80 character width, at least 25 character height
  117. SetConsoleCXCY (hStdout, 80, 25);
  118. }
  119. void DeinitConProc (void)
  120. {
  121. if (heventDone)
  122. SetEvent (heventDone);
  123. }
  124. unsigned _stdcall RequestProc (void *arg)
  125. {
  126. int *pBuffer;
  127. DWORD dwRet;
  128. HANDLE heventWait[2];
  129. int iBeginLine, iEndLine;
  130. heventWait[0] = heventParentSend;
  131. heventWait[1] = heventDone;
  132. while (1)
  133. {
  134. dwRet = WaitForMultipleObjects (2, heventWait, FALSE, INFINITE);
  135. // heventDone fired, so we're exiting.
  136. if (dwRet == WAIT_OBJECT_0 + 1)
  137. break;
  138. pBuffer = (int *) GetMappedBuffer (hfileBuffer);
  139. // hfileBuffer is invalid. Just leave.
  140. if (!pBuffer)
  141. {
  142. printf ("Invalid hfileBuffer\n");
  143. break;
  144. }
  145. switch (pBuffer[0])
  146. {
  147. case CCOM_WRITE_TEXT:
  148. // Param1 : Text
  149. pBuffer[0] = WriteText ((LPCTSTR) (pBuffer + 1));
  150. break;
  151. case CCOM_GET_TEXT:
  152. // Param1 : Begin line
  153. // Param2 : End line
  154. iBeginLine = pBuffer[1];
  155. iEndLine = pBuffer[2];
  156. pBuffer[0] = ReadText ((LPTSTR) (pBuffer + 1), iBeginLine,
  157. iEndLine);
  158. break;
  159. case CCOM_GET_SCR_LINES:
  160. // No params
  161. pBuffer[0] = GetScreenBufferLines (&pBuffer[1]);
  162. break;
  163. case CCOM_SET_SCR_LINES:
  164. // Param1 : Number of lines
  165. pBuffer[0] = SetScreenBufferLines (pBuffer[1]);
  166. break;
  167. }
  168. ReleaseMappedBuffer (pBuffer);
  169. SetEvent (heventChildSend);
  170. }
  171. _endthreadex (0);
  172. return 0;
  173. }
  174. LPVOID GetMappedBuffer (HANDLE hfileBuffer)
  175. {
  176. LPVOID pBuffer;
  177. pBuffer = MapViewOfFile (hfileBuffer,
  178. FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
  179. return pBuffer;
  180. }
  181. void ReleaseMappedBuffer (LPVOID pBuffer)
  182. {
  183. UnmapViewOfFile (pBuffer);
  184. }
  185. BOOL GetScreenBufferLines (int *piLines)
  186. {
  187. CONSOLE_SCREEN_BUFFER_INFO info;
  188. BOOL bRet;
  189. bRet = GetConsoleScreenBufferInfo (hStdout, &info);
  190. if (bRet)
  191. *piLines = info.dwSize.Y;
  192. return bRet;
  193. }
  194. BOOL SetScreenBufferLines (int iLines)
  195. {
  196. return SetConsoleCXCY (hStdout, 80, iLines);
  197. }
  198. BOOL ReadText (LPTSTR pszText, int iBeginLine, int iEndLine)
  199. {
  200. COORD coord;
  201. DWORD dwRead;
  202. BOOL bRet;
  203. coord.X = 0;
  204. coord.Y = iBeginLine;
  205. bRet = ReadConsoleOutputCharacter(
  206. hStdout,
  207. pszText,
  208. 80 * (iEndLine - iBeginLine + 1),
  209. coord,
  210. &dwRead);
  211. // Make sure it's null terminated.
  212. if (bRet)
  213. pszText[dwRead] = '\0';
  214. return bRet;
  215. }
  216. BOOL WriteText (LPCTSTR szText)
  217. {
  218. DWORD dwWritten;
  219. INPUT_RECORD rec;
  220. char upper, *sz;
  221. sz = (LPTSTR) szText;
  222. while (*sz)
  223. {
  224. // 13 is the code for a carriage return (\n) instead of 10.
  225. if (*sz == 10)
  226. *sz = 13;
  227. upper = toupper(*sz);
  228. rec.EventType = KEY_EVENT;
  229. rec.Event.KeyEvent.bKeyDown = TRUE;
  230. rec.Event.KeyEvent.wRepeatCount = 1;
  231. rec.Event.KeyEvent.wVirtualKeyCode = upper;
  232. rec.Event.KeyEvent.wVirtualScanCode = CharToCode (*sz);
  233. rec.Event.KeyEvent.uChar.AsciiChar = *sz;
  234. rec.Event.KeyEvent.uChar.UnicodeChar = *sz;
  235. rec.Event.KeyEvent.dwControlKeyState = isupper(*sz) ? 0x80 : 0x0;
  236. WriteConsoleInput(
  237. hStdin,
  238. &rec,
  239. 1,
  240. &dwWritten);
  241. rec.Event.KeyEvent.bKeyDown = FALSE;
  242. WriteConsoleInput(
  243. hStdin,
  244. &rec,
  245. 1,
  246. &dwWritten);
  247. sz++;
  248. }
  249. return TRUE;
  250. }
  251. int CharToCode (char c)
  252. {
  253. char upper;
  254. upper = toupper(c);
  255. switch (c)
  256. {
  257. case 13:
  258. return 28;
  259. default:
  260. break;
  261. }
  262. if (isalpha(c))
  263. return (30 + upper - 65);
  264. if (isdigit(c))
  265. return (1 + upper - 47);
  266. return c;
  267. }
  268. BOOL SetConsoleCXCY(HANDLE hStdout, int cx, int cy)
  269. {
  270. CONSOLE_SCREEN_BUFFER_INFO info;
  271. COORD coordMax;
  272. coordMax = GetLargestConsoleWindowSize(hStdout);
  273. if (cy > coordMax.Y)
  274. cy = coordMax.Y;
  275. if (cx > coordMax.X)
  276. cx = coordMax.X;
  277. if (!GetConsoleScreenBufferInfo(hStdout, &info))
  278. return FALSE;
  279. // height
  280. info.srWindow.Left = 0;
  281. info.srWindow.Right = info.dwSize.X - 1;
  282. info.srWindow.Top = 0;
  283. info.srWindow.Bottom = cy - 1;
  284. if (cy < info.dwSize.Y)
  285. {
  286. if (!SetConsoleWindowInfo(hStdout, TRUE, &info.srWindow))
  287. return FALSE;
  288. info.dwSize.Y = cy;
  289. if (!SetConsoleScreenBufferSize(hStdout, info.dwSize))
  290. return FALSE;
  291. }
  292. else if (cy > info.dwSize.Y)
  293. {
  294. info.dwSize.Y = cy;
  295. if (!SetConsoleScreenBufferSize(hStdout, info.dwSize))
  296. return FALSE;
  297. if (!SetConsoleWindowInfo(hStdout, TRUE, &info.srWindow))
  298. return FALSE;
  299. }
  300. if (!GetConsoleScreenBufferInfo(hStdout, &info))
  301. return FALSE;
  302. // width
  303. info.srWindow.Left = 0;
  304. info.srWindow.Right = cx - 1;
  305. info.srWindow.Top = 0;
  306. info.srWindow.Bottom = info.dwSize.Y - 1;
  307. if (cx < info.dwSize.X)
  308. {
  309. if (!SetConsoleWindowInfo(hStdout, TRUE, &info.srWindow))
  310. return FALSE;
  311. info.dwSize.X = cx;
  312. if (!SetConsoleScreenBufferSize(hStdout, info.dwSize))
  313. return FALSE;
  314. }
  315. else if (cx > info.dwSize.X)
  316. {
  317. info.dwSize.X = cx;
  318. if (!SetConsoleScreenBufferSize(hStdout, info.dwSize))
  319. return FALSE;
  320. if (!SetConsoleWindowInfo(hStdout, TRUE, &info.srWindow))
  321. return FALSE;
  322. }
  323. return TRUE;
  324. }