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.

674 lines
16 KiB

  1. //wthkdll.c
  2. /* Here, we just record a bunch of packets with a WTH_RECORD hook, and put them
  3. in a big list. If there is more than one context giving us packets, then
  4. we are in trouble; in real life, we would have to sort the packets by
  5. context. We should probably also check to see that the lcPktData
  6. and lcPktMode of each context doesn't change. */
  7. #include <malloc.h>
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include <windows.h>
  11. #include <wintab.h>
  12. #define PACKETDATA PK_CONTEXT | PK_STATUS | PK_TIME | PK_CHANGED | PK_SERIAL_NUMBER | PK_CURSOR | PK_BUTTONS | PK_X | PK_Y | PK_Z | PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE | PK_ROTATION
  13. #define PACKETMODE 0
  14. #include <pktdef.h>
  15. /* 16-bit does not have a 64-bit integer type */
  16. #ifndef hyper
  17. #define hyper long
  18. #endif
  19. #define NCONTEXTS 32
  20. /* Shared memory */
  21. static HANDLE shmem;
  22. static unsigned hyper shmem_size;
  23. static unsigned char *shmem_view = 0;
  24. static unsigned hyper shmem_buf_size;
  25. static unsigned char *shmem_buf = 0; /* Store everyone's packets in this buffer */
  26. static HCTX *shmem_ctx = 0; /* One for each possible context (NCONTEXTS) */
  27. static unsigned hyper *shmem_buf_pos = 0;
  28. static unsigned hyper *shmem_buf_play_pos = 0;
  29. static unsigned long *shmem_pkts_recorded = 0;
  30. static unsigned long *shmem_pkts_played = 0;
  31. static unsigned long *shmem_time = 0;
  32. static HWTHOOK *shmem_hHook = 0;
  33. #ifdef _WIN32
  34. void
  35. shutdown_shared_mem( void )
  36. {
  37. if( shmem_view )
  38. UnmapViewOfFile( shmem_view );
  39. if( shmem )
  40. CloseHandle( shmem );
  41. }
  42. BOOL
  43. init_shared_mem( void )
  44. {
  45. BOOL fInit;
  46. shmem_size = 0x100000;
  47. shmem_buf_size = shmem_size - (NCONTEXTS + 1)*sizeof(hyper) - (NCONTEXTS+2)*sizeof(long) - NCONTEXTS*sizeof(HCTX);
  48. shmem = CreateFileMapping(
  49. (HANDLE) 0xFFFFFFFF, // use paging file
  50. 0, // no security attributes
  51. PAGE_READWRITE, // read/write access
  52. (unsigned long)((shmem_size >> 32) & 0xffffffff), // size: high 32-bits
  53. (unsigned long)(shmem_size & 0xffffffff), // size: low 32-bits
  54. "wthkdll.dll: shared memory"); // name of map object
  55. if (shmem == NULL)
  56. return FALSE;
  57. fInit = (GetLastError() != ERROR_ALREADY_EXISTS);
  58. shmem_view = MapViewOfFile(
  59. shmem, // object to map view of
  60. FILE_MAP_WRITE, // read/write access
  61. 0, // high offset: map from
  62. 0, // low offset: beginning
  63. 0); // default: map entire file
  64. if( !shmem_view ) {
  65. shutdown_shared_mem();
  66. return FALSE;
  67. }
  68. shmem_buf_pos = (unsigned hyper*)shmem_view;
  69. shmem_buf_play_pos = shmem_buf_pos + 1;
  70. shmem_pkts_recorded = (long *)(shmem_buf_play_pos + NCONTEXTS);
  71. shmem_pkts_played = shmem_pkts_recorded + 1;
  72. shmem_hHook = (HWTHOOK)(shmem_pkts_played + 1);
  73. shmem_ctx = (HCTX *)(shmem_hHook + 1);
  74. shmem_time = (unsigned long *)(shmem_ctx + NCONTEXTS);
  75. shmem_buf = (unsigned char *)(shmem_time + NCONTEXTS);
  76. if( fInit ) {
  77. unsigned i;
  78. for( i = 0; i < NCONTEXTS; i++ ) {
  79. shmem_ctx[i] = 0;
  80. shmem_buf_pos[i] = 0;
  81. shmem_buf_play_pos[i] = 0;
  82. shmem_pkts_recorded[i] = 0;
  83. shmem_pkts_played[i] = 0;
  84. shmem_time[i] = 0;
  85. }
  86. *shmem_hHook = 0;
  87. }
  88. return TRUE;
  89. }
  90. /******************************************************************/
  91. /* Windows DLL entry/exit points */
  92. /* 32-bit entrypoint */
  93. BOOL WINAPI DllMain (HANDLE hInst,
  94. unsigned long ul_reason_for_call,
  95. void far * lpReserved)
  96. {
  97. BOOL retval;
  98. switch( ul_reason_for_call ) {
  99. case DLL_PROCESS_ATTACH:
  100. retval = init_shared_mem();
  101. break;
  102. case DLL_THREAD_ATTACH:
  103. retval = TRUE;
  104. break;
  105. case DLL_THREAD_DETACH:
  106. retval = TRUE;
  107. break;
  108. case DLL_PROCESS_DETACH:
  109. shutdown_shared_mem();
  110. retval = TRUE;
  111. break;
  112. default:
  113. retval = FALSE;
  114. }
  115. return retval;
  116. }
  117. #endif /* WIN32 */
  118. /* 16-bit dll entrypoint */
  119. BOOL WINAPI LibMain(HANDLE hModule, WORD wDataSeg, WORD cbHeapSize,
  120. LPSTR lpCmdLine)
  121. {
  122. unsigned i;
  123. if( !shmem_buf_pos ) {
  124. shmem_buf_pos = calloc( 1, sizeof(hyper) );
  125. if( !shmem_buf_pos )
  126. return FALSE;
  127. }
  128. if( !shmem_buf_play_pos ) {
  129. shmem_buf_play_pos = calloc( 32, sizeof(hyper) );
  130. if( !shmem_buf_play_pos ) {
  131. free( shmem_buf_pos );
  132. shmem_buf_pos = 0;
  133. return FALSE;
  134. }
  135. }
  136. if( !shmem_pkts_recorded ) {
  137. shmem_pkts_recorded = calloc( 1, sizeof(hyper) );
  138. if( !shmem_pkts_recorded ) {
  139. free( shmem_buf_play_pos );
  140. free( shmem_buf_pos );
  141. shmem_buf_play_pos = 0;
  142. shmem_buf_pos = 0;
  143. return FALSE;
  144. }
  145. }
  146. if( !shmem_pkts_played ) {
  147. shmem_pkts_played = calloc( 1, sizeof(hyper) );
  148. if( !shmem_pkts_played ) {
  149. free( shmem_buf_play_pos );
  150. free( shmem_buf_pos );
  151. free( shmem_pkts_recorded );
  152. shmem_buf_play_pos = 0;
  153. shmem_buf_pos = 0;
  154. shmem_pkts_recorded = 0;
  155. return FALSE;
  156. }
  157. }
  158. if( !shmem_hHook ) {
  159. shmem_hHook = malloc( sizeof(HWTHOOK) );
  160. if( !shmem_hHook ) {
  161. free( shmem_buf_pos );
  162. shmem_buf_pos = 0;
  163. free( shmem_buf_play_pos );
  164. shmem_buf_play_pos = 0;
  165. free( shmem_pkts_recorded );
  166. free( shmem_pkts_played );
  167. shmem_pkts_recorded = 0;
  168. shmem_pkts_played = 0;
  169. return FALSE;
  170. }
  171. *shmem_hHook = 0;
  172. }
  173. if( !shmem_buf ) {
  174. shmem_buf_size = 0xff00;
  175. shmem_buf = calloc( 32, (size_t)shmem_buf_size );
  176. if( !shmem_buf ) {
  177. free( shmem_buf_pos );
  178. shmem_buf_pos = 0;
  179. free( shmem_buf_play_pos );
  180. shmem_buf_play_pos = 0;
  181. free( shmem_pkts_recorded );
  182. free( shmem_pkts_played );
  183. shmem_pkts_recorded = 0;
  184. shmem_pkts_played = 0;
  185. free( shmem_hHook );
  186. shmem_hHook = 0;
  187. return FALSE;
  188. }
  189. }
  190. if( !shmem_ctx ) {
  191. shmem_ctx = calloc( 32, sizeof(HCTX) );
  192. if( !shmem_ctx ) {
  193. free( shmem_buf_pos );
  194. shmem_buf_pos = 0;
  195. free( shmem_buf_play_pos );
  196. shmem_buf_play_pos = 0;
  197. free( shmem_pkts_recorded );
  198. free( shmem_pkts_played );
  199. shmem_pkts_recorded = 0;
  200. shmem_pkts_played = 0;
  201. free( shmem_hHook );
  202. shmem_hHook = 0;
  203. free( shmem_buf );
  204. shmem_buf = 0;
  205. shmem_buf_size = 0;
  206. return FALSE;
  207. }
  208. }
  209. if( !shmem_time ) {
  210. shmem_time = calloc( 32, sizeof(long) );
  211. if( !shmem_time ) {
  212. free( shmem_buf_pos );
  213. shmem_buf_pos = 0;
  214. free( shmem_buf_play_pos );
  215. shmem_buf_play_pos = 0;
  216. free( shmem_pkts_recorded );
  217. free( shmem_pkts_played );
  218. shmem_pkts_recorded = 0;
  219. shmem_pkts_played = 0;
  220. free( shmem_hHook );
  221. shmem_hHook = 0;
  222. free( shmem_buf );
  223. shmem_buf = 0;
  224. shmem_buf_size = 0;
  225. free( shmem_ctx );
  226. shmem_ctx = 0;
  227. return FALSE;
  228. }
  229. }
  230. for( i = 0; i < NCONTEXTS; i++ ) {
  231. shmem_ctx[i] = 0;
  232. shmem_buf_pos[i] = 0;
  233. shmem_buf_play_pos[i] = 0;
  234. shmem_pkts_recorded[i] = 0;
  235. shmem_pkts_played[i] = 0;
  236. shmem_time[i] = 0;
  237. }
  238. return TRUE;
  239. }
  240. /* Win16 dll exit point. */
  241. int WINAPI WEP(int nSystemExit)
  242. {
  243. if( shmem_buf )
  244. free( shmem_buf );
  245. if( shmem_buf_play_pos )
  246. free( shmem_buf_play_pos );
  247. if( shmem_buf_pos )
  248. free( shmem_buf_pos );
  249. if( shmem_pkts_recorded )
  250. free( shmem_pkts_recorded );
  251. if( shmem_pkts_played )
  252. free( shmem_pkts_played );
  253. if( shmem_hHook )
  254. free( shmem_hHook );
  255. return TRUE;
  256. }
  257. /******************************************************************/
  258. /* Packet Decode Functions */
  259. static const struct {
  260. WTPKT tag; size_t size; int nargs; char *str;
  261. } pkt_data_info[] = {
  262. {PK_CONTEXT, sizeof(HCTX), 1, "Context: %u"},
  263. {PK_STATUS, sizeof(UINT), 1, "Status: %u"},
  264. {PK_TIME, sizeof(LONG), 1, "Time: %li"},
  265. {PK_CHANGED, sizeof(WTPKT), 1, "Changed: %u"},
  266. {PK_SERIAL_NUMBER, sizeof(UINT), 1, "Serial Number: %u"},
  267. {PK_CURSOR, sizeof(UINT), 1, "Cursor: %u"},
  268. {PK_BUTTONS, sizeof(DWORD), 1, "Buttons: %lu"},
  269. {PK_X, sizeof(DWORD), 1, "X: %lu"},
  270. {PK_Y, sizeof(DWORD), 1, "Y: %lu"},
  271. {PK_Z, sizeof(DWORD), 1, "Z: %lu"},
  272. {PK_NORMAL_PRESSURE, sizeof(UINT), 1, "Normal Pressure: %u"},
  273. {PK_TANGENT_PRESSURE, sizeof(UINT), 1, "Tangent Pressure: %u"},
  274. {PK_ORIENTATION, sizeof(ORIENTATION), 3, "Orientation: %i, %i, %i"},
  275. {PK_ROTATION, sizeof(ROTATION), 3, "Rotation: %i, %i, %i"},
  276. {0, 0, -1, 0}
  277. };
  278. size_t
  279. compute_packet_size( WTPKT lcPktData )
  280. {
  281. unsigned i = 0;
  282. size_t size = 0;
  283. while( pkt_data_info[i].nargs > 0 ) {
  284. if( lcPktData & pkt_data_info[i].tag )
  285. size += pkt_data_info[i].size;
  286. i++;
  287. }
  288. /* Check for extension data */
  289. i = 0;
  290. while( WTInfo( WTI_EXTENSIONS + i, EXT_NAME, 0 ) ) {
  291. UINT ext_size[2];
  292. WTPKT mask;
  293. if( WTInfo( WTI_EXTENSIONS + i, EXT_MASK, &mask ) && (mask & lcPktData) ) {
  294. WTInfo( WTI_EXTENSIONS + i, EXT_SIZE, ext_size );
  295. size += ext_size[0];
  296. }
  297. i++;
  298. }
  299. return size;
  300. }
  301. long
  302. get_packet_offset( WTPKT lcPktData, WTPKT field )
  303. {
  304. unsigned i = 0;
  305. long offset = 0;
  306. while( pkt_data_info[i].nargs > 0 && pkt_data_info[i].tag != field ) {
  307. if( lcPktData & pkt_data_info[i].tag )
  308. offset += pkt_data_info[i].size;
  309. i++;
  310. }
  311. if( pkt_data_info[i].nargs == -1 )
  312. offset = -1;
  313. return offset;
  314. }
  315. size_t
  316. display_packet( WTPKT lcPktData, unsigned char *packet )
  317. {
  318. unsigned i = 0;
  319. size_t size = 0;
  320. char outstring[2048] = "";
  321. char str[128];
  322. while( lcPktData && pkt_data_info[i].nargs > 0 ) {
  323. if( lcPktData & pkt_data_info[i].tag ) {
  324. if( pkt_data_info[i].nargs == 1 )
  325. if( pkt_data_info[i].size == 2 )
  326. sprintf( str, pkt_data_info[i].str, *((WORD *)packet) );
  327. else
  328. sprintf( str, pkt_data_info[i].str, *((DWORD *)packet) );
  329. if( pkt_data_info[i].nargs == 3 )
  330. sprintf( str, pkt_data_info[i].str, packet, *((WORD *)packet + 1), *((WORD *)packet + 2) );
  331. strcat( outstring, str );
  332. strcat( outstring, "\n" );
  333. packet += pkt_data_info[i].size;
  334. size += pkt_data_info[i].size;
  335. }
  336. i++;
  337. }
  338. /* Display extension data fields */
  339. i = 0;
  340. while( WTInfo( WTI_EXTENSIONS + i, EXT_NAME, str ) ) {
  341. WTPKT mask;
  342. if( WTInfo( WTI_EXTENSIONS + i, EXT_MASK, &mask ) && (mask & lcPktData) ) {
  343. UINT ext_size[2];
  344. UINT j;
  345. WTInfo( WTI_EXTENSIONS + i, EXT_SIZE, ext_size );
  346. strcat( outstring, str );
  347. strcat( outstring, ": " );
  348. for( j = 0; j < ext_size[0] / sizeof(int); j++ ) {
  349. sprintf( str, "%8x", *((int *)packet + j) );
  350. strcat( outstring, str );
  351. strcat( outstring, " " );
  352. }
  353. strcat( outstring, "\n" );
  354. packet += ext_size[0];
  355. size += ext_size[0];
  356. }
  357. i++;
  358. }
  359. MessageBox( 0, outstring, "wthook", MB_OK );
  360. return size;
  361. }
  362. int
  363. hCtx_index( HCTX hCtx )
  364. {
  365. unsigned i = 0;
  366. while( i < NCONTEXTS && shmem_ctx[i] && shmem_ctx[i] != hCtx )
  367. i++;
  368. if( i == NCONTEXTS )
  369. return -1;
  370. if( !shmem_ctx[i] )
  371. shmem_ctx[i] = hCtx;
  372. return i;
  373. }
  374. void *
  375. find_next_ctx_packet( HCTX hCtx, WTPKT *lcPktData, DWORD * time_change, size_t *size )
  376. {
  377. HCTX packet_hCtx;
  378. void *retval;
  379. int index = hCtx_index(hCtx);
  380. if( index > -1 ) {
  381. /* Let shmem_buf_play_pos[index] end up pointing to the packet which we return */
  382. *size = 0;
  383. do {
  384. if( *size )
  385. shmem_buf_play_pos[index] += sizeof(WTPKT) + sizeof(HCTX) + sizeof(DWORD) + *size;
  386. retval = shmem_buf + shmem_buf_play_pos[index];
  387. *lcPktData = *((WTPKT *)(shmem_buf + shmem_buf_play_pos[index]));
  388. packet_hCtx = *((HCTX *)(shmem_buf + sizeof(WTPKT) + shmem_buf_play_pos[index]));
  389. *time_change = *((DWORD *)(shmem_buf + sizeof(WTPKT) + sizeof(HCTX) + shmem_buf_play_pos[index]));
  390. *size = compute_packet_size( *lcPktData );
  391. } while( shmem_buf_play_pos[index] < *shmem_buf_pos && packet_hCtx != hCtx );
  392. if( packet_hCtx != hCtx )
  393. retval = 0;
  394. } else
  395. retval = 0;
  396. return retval;
  397. }
  398. /******************************************************************/
  399. /* Wintab hook functions */
  400. LRESULT
  401. WINAPI RecordHook(int nCode,WPARAM wParam,LPARAM lParam)
  402. {
  403. DWORD curtime;
  404. if( nCode >= 0 ) {
  405. LOGCONTEXT lc;
  406. size_t packet_size;
  407. /* We need to find the packet data size */
  408. WTGet((HCTX)wParam, &lc);
  409. packet_size = compute_packet_size( lc.lcPktData );
  410. /* If we have space left in our shared memory buffer, */
  411. if( *shmem_buf_pos < shmem_buf_size - packet_size - sizeof(WTPKT) ) {
  412. int index = hCtx_index( (HCTX)wParam );
  413. /* There's no garauntee that the contexts will be giving us the
  414. data that we need in their packets, so explicitly calculate
  415. everything we need here: */
  416. /* Write lc.lcPktData */
  417. *((WTPKT *)(shmem_buf + *shmem_buf_pos)) = lc.lcPktData;
  418. (*shmem_buf_pos) += sizeof(WTPKT);
  419. /* Write hCtx */
  420. *((HCTX *)(shmem_buf + *shmem_buf_pos)) = (HCTX)wParam;
  421. (*shmem_buf_pos) += sizeof(HCTX);
  422. /* Write time change (since previous packet of this context) */
  423. curtime = timeGetTime();
  424. if( shmem_time[index] == 0 ) {
  425. shmem_time[index] = curtime;
  426. *((DWORD *)(shmem_buf + *shmem_buf_pos)) = 0;
  427. } else {
  428. *((DWORD *)(shmem_buf + *shmem_buf_pos)) = curtime - shmem_time[index];
  429. shmem_time[index] = curtime;
  430. }
  431. (*shmem_buf_pos) += sizeof(DWORD);
  432. /* Write packet data */
  433. memcpy( shmem_buf + *shmem_buf_pos, (LPVOID)lParam, packet_size );
  434. (*shmem_buf_pos) += packet_size;
  435. (*shmem_pkts_recorded)++;
  436. }
  437. return TRUE;
  438. } else /* Let Wintab continue processing the packet */
  439. return WTMgrPacketHookNext(*shmem_hHook,nCode,wParam,lParam);
  440. }
  441. LRESULT WINAPI PlayHook(int nCode, WPARAM wParam, LPARAM lParam)
  442. {
  443. DWORD delay;
  444. void *packet;
  445. size_t size;
  446. WTPKT lcPktData;
  447. LRESULT retval;
  448. int index;
  449. /* Find the next packet corrisponding to this context */
  450. packet = find_next_ctx_packet( (HCTX)wParam, &size, &lcPktData, &delay );
  451. if( packet ) {
  452. switch( nCode ) {
  453. case WTHC_GETNEXT:
  454. /* Copy the packet to the buffer */
  455. memcpy( (LPVOID)lParam, packet, size );
  456. retval = delay;
  457. break;
  458. case WTHC_SKIP:
  459. index = hCtx_index( (HCTX)wParam );
  460. shmem_buf_play_pos[index] +=
  461. size + sizeof(WTPKT) + sizeof(DWORD) + sizeof(HCTX);
  462. retval = 0;
  463. (*shmem_pkts_played)++;
  464. break;
  465. default:
  466. break;
  467. }
  468. } else
  469. retval = WTMgrPacketHookNext(*shmem_hHook, nCode, wParam, lParam);
  470. return retval;
  471. }
  472. /******************************************************************/
  473. /* Exported user functions */
  474. long WINAPI get_num_pkts_recorded( void )
  475. {
  476. return *shmem_pkts_recorded;
  477. }
  478. long WINAPI get_num_pkts_played( void )
  479. {
  480. return *shmem_pkts_played;
  481. }
  482. BOOL WINAPI Record(BOOL fEnable, HMGR hMgr)
  483. {
  484. BOOL result = FALSE;
  485. if (fEnable) {
  486. if (!*shmem_hHook)
  487. *shmem_hHook = WTMgrPacketHookEx(hMgr, WTH_RECORD,
  488. "wthkdll.dll", "RecordHook");
  489. result = !!*shmem_hHook;
  490. } else {
  491. if (*shmem_hHook) {
  492. WTMgrPacketUnhook(*shmem_hHook);
  493. *shmem_hHook = 0;
  494. }
  495. result = TRUE;
  496. }
  497. return result;
  498. }
  499. void
  500. WINAPI display_record(void)
  501. {
  502. unsigned char *ptr = shmem_buf;
  503. while( ptr < shmem_buf + *shmem_buf_pos ) {
  504. WTPKT lcPktData;
  505. HCTX hCtx;
  506. DWORD time;
  507. lcPktData = *((WTPKT *)ptr);
  508. ptr += sizeof(WTPKT);
  509. hCtx = *((HCTX *)ptr);
  510. ptr += sizeof(HCTX);
  511. time = *((DWORD *)ptr);
  512. ptr += sizeof(DWORD);
  513. ptr += display_packet( lcPktData, ptr );
  514. }
  515. }
  516. BOOL WINAPI Playback(BOOL fEnable, HMGR hMgr)
  517. {
  518. BOOL result = FALSE;
  519. if( fEnable ) {
  520. if( !*shmem_hHook )
  521. *shmem_hHook = WTMgrPacketHookEx( hMgr, WTH_PLAYBACK,
  522. "wthkdll.dll", "PlayHook" );
  523. result = !!*shmem_hHook;
  524. } else {
  525. if( *shmem_hHook ) {
  526. WTMgrPacketUnhook( *shmem_hHook );
  527. *shmem_hHook = 0;
  528. }
  529. result = TRUE;
  530. }
  531. return result;
  532. }
  533. /* Even when wthook.exe ends, the shared memory of the dll is still hanging
  534. around, since the dll is loaded by wintab32 into other people's address spaces.
  535. We have to reset the shared memory, so that the next time wthook runs, it doesn't
  536. pick up the old shared memory contents. */
  537. void
  538. WINAPI reset( void )
  539. {
  540. /* Just set the counters back to zero */
  541. *shmem_buf_pos = 0;
  542. *shmem_buf_play_pos = 0;
  543. *shmem_pkts_recorded = 0;
  544. *shmem_pkts_played = 0;
  545. }