Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

425 lines
7.4 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. // conproc.c -- support for qhost
  9. #include "dedicated.h"
  10. #include <stdio.h>
  11. #include <process.h>
  12. #include <windows.h>
  13. #include "conproc.h"
  14. #include "isys.h"
  15. #include "tier0/icommandline.h"
  16. static HANDLE heventDone;
  17. static HANDLE hfileBuffer;
  18. static HANDLE heventChildSend;
  19. static HANDLE heventParentSend;
  20. static HANDLE hStdout;
  21. static HANDLE hStdin;
  22. /*
  23. ==============
  24. SetConsoleCXCY
  25. ==============
  26. */
  27. BOOL SetConsoleCXCY(HANDLE hStdout, int cx, int cy)
  28. {
  29. CONSOLE_SCREEN_BUFFER_INFO info;
  30. COORD coordMax;
  31. coordMax = GetLargestConsoleWindowSize(hStdout);
  32. if (cy > coordMax.Y)
  33. cy = coordMax.Y;
  34. if (cx > coordMax.X)
  35. cx = coordMax.X;
  36. if (!GetConsoleScreenBufferInfo(hStdout, &info))
  37. return FALSE;
  38. // height
  39. info.srWindow.Left = 0;
  40. info.srWindow.Right = info.dwSize.X - 1;
  41. info.srWindow.Top = 0;
  42. info.srWindow.Bottom = cy - 1;
  43. if (cy < info.dwSize.Y)
  44. {
  45. if (!SetConsoleWindowInfo(hStdout, TRUE, &info.srWindow))
  46. return FALSE;
  47. info.dwSize.Y = cy;
  48. if (!SetConsoleScreenBufferSize(hStdout, info.dwSize))
  49. return FALSE;
  50. }
  51. else if (cy > info.dwSize.Y)
  52. {
  53. info.dwSize.Y = cy;
  54. if (!SetConsoleScreenBufferSize(hStdout, info.dwSize))
  55. return FALSE;
  56. if (!SetConsoleWindowInfo(hStdout, TRUE, &info.srWindow))
  57. return FALSE;
  58. }
  59. if (!GetConsoleScreenBufferInfo(hStdout, &info))
  60. return FALSE;
  61. // width
  62. info.srWindow.Left = 0;
  63. info.srWindow.Right = cx - 1;
  64. info.srWindow.Top = 0;
  65. info.srWindow.Bottom = info.dwSize.Y - 1;
  66. if (cx < info.dwSize.X)
  67. {
  68. if (!SetConsoleWindowInfo(hStdout, TRUE, &info.srWindow))
  69. return FALSE;
  70. info.dwSize.X = cx;
  71. if (!SetConsoleScreenBufferSize(hStdout, info.dwSize))
  72. return FALSE;
  73. }
  74. else if (cx > info.dwSize.X)
  75. {
  76. info.dwSize.X = cx;
  77. if (!SetConsoleScreenBufferSize(hStdout, info.dwSize))
  78. return FALSE;
  79. if (!SetConsoleWindowInfo(hStdout, TRUE, &info.srWindow))
  80. return FALSE;
  81. }
  82. return TRUE;
  83. }
  84. /*
  85. ==============
  86. GetMappedBuffer
  87. ==============
  88. */
  89. LPVOID GetMappedBuffer (HANDLE hfileBuffer)
  90. {
  91. LPVOID pBuffer;
  92. pBuffer = MapViewOfFile (hfileBuffer,
  93. FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
  94. return pBuffer;
  95. }
  96. /*
  97. ==============
  98. ReleaseMappedBuffer
  99. ==============
  100. */
  101. void ReleaseMappedBuffer (LPVOID pBuffer)
  102. {
  103. UnmapViewOfFile (pBuffer);
  104. }
  105. /*
  106. ==============
  107. GetScreenBufferLines
  108. ==============
  109. */
  110. BOOL GetScreenBufferLines (int *piLines)
  111. {
  112. CONSOLE_SCREEN_BUFFER_INFO info;
  113. BOOL bRet;
  114. bRet = GetConsoleScreenBufferInfo (hStdout, &info);
  115. if (bRet)
  116. *piLines = info.dwSize.Y;
  117. return bRet;
  118. }
  119. /*
  120. ==============
  121. SetScreenBufferLines
  122. ==============
  123. */
  124. BOOL SetScreenBufferLines (int iLines)
  125. {
  126. return SetConsoleCXCY (hStdout, 80, iLines);
  127. }
  128. /*
  129. ==============
  130. ReadText
  131. ==============
  132. */
  133. BOOL ReadText (LPTSTR pszText, int iBeginLine, int iEndLine)
  134. {
  135. COORD coord;
  136. DWORD dwRead;
  137. BOOL bRet;
  138. coord.X = 0;
  139. coord.Y = iBeginLine;
  140. bRet = ReadConsoleOutputCharacter(
  141. hStdout,
  142. pszText,
  143. 80 * (iEndLine - iBeginLine + 1),
  144. coord,
  145. &dwRead);
  146. // Make sure it's null terminated.
  147. if (bRet)
  148. pszText[dwRead] = '\0';
  149. return bRet;
  150. }
  151. /*
  152. ==============
  153. CharToCode
  154. ==============
  155. */
  156. int CharToCode (char c)
  157. {
  158. char upper;
  159. upper = toupper(c);
  160. switch (c)
  161. {
  162. case 13:
  163. return 28;
  164. default:
  165. break;
  166. }
  167. if (isalpha(c))
  168. return (30 + upper - 65);
  169. if (isdigit(c))
  170. return (1 + upper - 47);
  171. return c;
  172. }
  173. /*
  174. ==============
  175. WriteText
  176. ==============
  177. */
  178. BOOL WriteText (LPCTSTR szText)
  179. {
  180. DWORD dwWritten;
  181. INPUT_RECORD rec;
  182. char upper, *sz;
  183. sz = (LPTSTR) szText;
  184. while (*sz)
  185. {
  186. // 13 is the code for a carriage return (\n) instead of 10.
  187. if (*sz == 10)
  188. *sz = 13;
  189. upper = toupper(*sz);
  190. rec.EventType = KEY_EVENT;
  191. rec.Event.KeyEvent.bKeyDown = TRUE;
  192. rec.Event.KeyEvent.wRepeatCount = 1;
  193. rec.Event.KeyEvent.wVirtualKeyCode = upper;
  194. rec.Event.KeyEvent.wVirtualScanCode = CharToCode (*sz);
  195. rec.Event.KeyEvent.uChar.AsciiChar = *sz;
  196. rec.Event.KeyEvent.uChar.UnicodeChar = *sz;
  197. rec.Event.KeyEvent.dwControlKeyState = isupper(*sz) ? 0x80 : 0x0;
  198. WriteConsoleInput(
  199. hStdin,
  200. &rec,
  201. 1,
  202. &dwWritten);
  203. rec.Event.KeyEvent.bKeyDown = FALSE;
  204. WriteConsoleInput(
  205. hStdin,
  206. &rec,
  207. 1,
  208. &dwWritten);
  209. sz++;
  210. }
  211. return TRUE;
  212. }
  213. /*
  214. ==============
  215. RequestProc
  216. ==============
  217. */
  218. unsigned _stdcall RequestProc (void *arg)
  219. {
  220. int *pBuffer;
  221. DWORD dwRet;
  222. HANDLE heventWait[2];
  223. int iBeginLine, iEndLine;
  224. heventWait[0] = heventParentSend;
  225. heventWait[1] = heventDone;
  226. while (1)
  227. {
  228. dwRet = WaitForMultipleObjects (2, heventWait, FALSE, INFINITE);
  229. // heventDone fired, so we're exiting.
  230. if (dwRet == WAIT_OBJECT_0 + 1)
  231. break;
  232. pBuffer = (int *) GetMappedBuffer (hfileBuffer);
  233. // hfileBuffer is invalid. Just leave.
  234. if (!pBuffer)
  235. {
  236. sys->Printf ("Request Proc: Invalid -HFILE handle\n");
  237. break;
  238. }
  239. switch (pBuffer[0])
  240. {
  241. case CCOM_WRITE_TEXT:
  242. // Param1 : Text
  243. pBuffer[0] = WriteText ((LPCTSTR) (pBuffer + 1));
  244. break;
  245. case CCOM_GET_TEXT:
  246. // Param1 : Begin line
  247. // Param2 : End line
  248. iBeginLine = pBuffer[1];
  249. iEndLine = pBuffer[2];
  250. pBuffer[0] = ReadText ((LPTSTR) (pBuffer + 1), iBeginLine,
  251. iEndLine);
  252. break;
  253. case CCOM_GET_SCR_LINES:
  254. // No params
  255. pBuffer[0] = GetScreenBufferLines (&pBuffer[1]);
  256. break;
  257. case CCOM_SET_SCR_LINES:
  258. // Param1 : Number of lines
  259. pBuffer[0] = SetScreenBufferLines (pBuffer[1]);
  260. break;
  261. }
  262. ReleaseMappedBuffer (pBuffer);
  263. SetEvent (heventChildSend);
  264. }
  265. _endthreadex (0);
  266. return 0;
  267. }
  268. /*
  269. ==============
  270. DeinitConProc
  271. ==============
  272. */
  273. void DeinitConProc (void)
  274. {
  275. if ( heventDone )
  276. {
  277. SetEvent ( heventDone );
  278. }
  279. }
  280. /*
  281. ==============
  282. InitConProc
  283. ==============
  284. */
  285. void InitConProc ( void )
  286. {
  287. unsigned threadAddr;
  288. HANDLE hFile = (HANDLE)0;
  289. HANDLE heventParent = (HANDLE)0;
  290. HANDLE heventChild = (HANDLE)0;
  291. int WantHeight = 50;
  292. const char *p;
  293. // give external front ends a chance to hook into the console
  294. if ( CommandLine()->CheckParm ( "-HFILE", &p ) && p )
  295. {
  296. hFile = (HANDLE)atoi ( p );
  297. }
  298. if ( CommandLine()->CheckParm ( "-HPARENT", &p ) && p )
  299. {
  300. heventParent = (HANDLE)atoi ( p );
  301. }
  302. if ( CommandLine()->CheckParm ( "-HCHILD", &p ) && p )
  303. {
  304. heventChild = (HANDLE)atoi ( p );
  305. }
  306. // ignore if we don't have all the events.
  307. if ( !hFile || !heventParent || !heventChild )
  308. {
  309. //sys->Printf ("\n\nNo external front end present.\n" );
  310. return;
  311. }
  312. sys->Printf( "\n\nInitConProc: Setting up external control.\n" );
  313. hfileBuffer = hFile;
  314. heventParentSend = heventParent;
  315. heventChildSend = heventChild;
  316. // So we'll know when to go away.
  317. heventDone = CreateEvent (NULL, FALSE, FALSE, NULL);
  318. if (!heventDone)
  319. {
  320. sys->Printf ("InitConProc: Couldn't create heventDone\n");
  321. return;
  322. }
  323. if (!_beginthreadex (NULL, 0, RequestProc, NULL, 0, &threadAddr))
  324. {
  325. CloseHandle (heventDone);
  326. sys->Printf ("InitConProc: Couldn't create third party thread\n");
  327. return;
  328. }
  329. // save off the input/output handles.
  330. hStdout = GetStdHandle (STD_OUTPUT_HANDLE);
  331. hStdin = GetStdHandle (STD_INPUT_HANDLE);
  332. if ( CommandLine()->CheckParm( "-conheight", &p ) && p )
  333. {
  334. WantHeight = atoi( p );
  335. }
  336. // Force 80 character width, at least 25 character height
  337. SetConsoleCXCY( hStdout, 80, WantHeight );
  338. }