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.
 
 
 
 
 
 

675 lines
16 KiB

//wthkdll.c
/* Here, we just record a bunch of packets with a WTH_RECORD hook, and put them
in a big list. If there is more than one context giving us packets, then
we are in trouble; in real life, we would have to sort the packets by
context. We should probably also check to see that the lcPktData
and lcPktMode of each context doesn't change. */
#include <malloc.h>
#include <stdio.h>
#include <string.h>
#include <windows.h>
#include <wintab.h>
#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
#define PACKETMODE 0
#include <pktdef.h>
/* 16-bit does not have a 64-bit integer type */
#ifndef hyper
#define hyper long
#endif
#define NCONTEXTS 32
/* Shared memory */
static HANDLE shmem;
static unsigned hyper shmem_size;
static unsigned char *shmem_view = 0;
static unsigned hyper shmem_buf_size;
static unsigned char *shmem_buf = 0; /* Store everyone's packets in this buffer */
static HCTX *shmem_ctx = 0; /* One for each possible context (NCONTEXTS) */
static unsigned hyper *shmem_buf_pos = 0;
static unsigned hyper *shmem_buf_play_pos = 0;
static unsigned long *shmem_pkts_recorded = 0;
static unsigned long *shmem_pkts_played = 0;
static unsigned long *shmem_time = 0;
static HWTHOOK *shmem_hHook = 0;
#ifdef _WIN32
void
shutdown_shared_mem( void )
{
if( shmem_view )
UnmapViewOfFile( shmem_view );
if( shmem )
CloseHandle( shmem );
}
BOOL
init_shared_mem( void )
{
BOOL fInit;
shmem_size = 0x100000;
shmem_buf_size = shmem_size - (NCONTEXTS + 1)*sizeof(hyper) - (NCONTEXTS+2)*sizeof(long) - NCONTEXTS*sizeof(HCTX);
shmem = CreateFileMapping(
(HANDLE) 0xFFFFFFFF, // use paging file
0, // no security attributes
PAGE_READWRITE, // read/write access
(unsigned long)((shmem_size >> 32) & 0xffffffff), // size: high 32-bits
(unsigned long)(shmem_size & 0xffffffff), // size: low 32-bits
"wthkdll.dll: shared memory"); // name of map object
if (shmem == NULL)
return FALSE;
fInit = (GetLastError() != ERROR_ALREADY_EXISTS);
shmem_view = MapViewOfFile(
shmem, // object to map view of
FILE_MAP_WRITE, // read/write access
0, // high offset: map from
0, // low offset: beginning
0); // default: map entire file
if( !shmem_view ) {
shutdown_shared_mem();
return FALSE;
}
shmem_buf_pos = (unsigned hyper*)shmem_view;
shmem_buf_play_pos = shmem_buf_pos + 1;
shmem_pkts_recorded = (long *)(shmem_buf_play_pos + NCONTEXTS);
shmem_pkts_played = shmem_pkts_recorded + 1;
shmem_hHook = (HWTHOOK)(shmem_pkts_played + 1);
shmem_ctx = (HCTX *)(shmem_hHook + 1);
shmem_time = (unsigned long *)(shmem_ctx + NCONTEXTS);
shmem_buf = (unsigned char *)(shmem_time + NCONTEXTS);
if( fInit ) {
unsigned i;
for( i = 0; i < NCONTEXTS; i++ ) {
shmem_ctx[i] = 0;
shmem_buf_pos[i] = 0;
shmem_buf_play_pos[i] = 0;
shmem_pkts_recorded[i] = 0;
shmem_pkts_played[i] = 0;
shmem_time[i] = 0;
}
*shmem_hHook = 0;
}
return TRUE;
}
/******************************************************************/
/* Windows DLL entry/exit points */
/* 32-bit entrypoint */
BOOL WINAPI DllMain (HANDLE hInst,
unsigned long ul_reason_for_call,
void far * lpReserved)
{
BOOL retval;
switch( ul_reason_for_call ) {
case DLL_PROCESS_ATTACH:
retval = init_shared_mem();
break;
case DLL_THREAD_ATTACH:
retval = TRUE;
break;
case DLL_THREAD_DETACH:
retval = TRUE;
break;
case DLL_PROCESS_DETACH:
shutdown_shared_mem();
retval = TRUE;
break;
default:
retval = FALSE;
}
return retval;
}
#endif /* WIN32 */
/* 16-bit dll entrypoint */
BOOL WINAPI LibMain(HANDLE hModule, WORD wDataSeg, WORD cbHeapSize,
LPSTR lpCmdLine)
{
unsigned i;
if( !shmem_buf_pos ) {
shmem_buf_pos = calloc( 1, sizeof(hyper) );
if( !shmem_buf_pos )
return FALSE;
}
if( !shmem_buf_play_pos ) {
shmem_buf_play_pos = calloc( 32, sizeof(hyper) );
if( !shmem_buf_play_pos ) {
free( shmem_buf_pos );
shmem_buf_pos = 0;
return FALSE;
}
}
if( !shmem_pkts_recorded ) {
shmem_pkts_recorded = calloc( 1, sizeof(hyper) );
if( !shmem_pkts_recorded ) {
free( shmem_buf_play_pos );
free( shmem_buf_pos );
shmem_buf_play_pos = 0;
shmem_buf_pos = 0;
return FALSE;
}
}
if( !shmem_pkts_played ) {
shmem_pkts_played = calloc( 1, sizeof(hyper) );
if( !shmem_pkts_played ) {
free( shmem_buf_play_pos );
free( shmem_buf_pos );
free( shmem_pkts_recorded );
shmem_buf_play_pos = 0;
shmem_buf_pos = 0;
shmem_pkts_recorded = 0;
return FALSE;
}
}
if( !shmem_hHook ) {
shmem_hHook = malloc( sizeof(HWTHOOK) );
if( !shmem_hHook ) {
free( shmem_buf_pos );
shmem_buf_pos = 0;
free( shmem_buf_play_pos );
shmem_buf_play_pos = 0;
free( shmem_pkts_recorded );
free( shmem_pkts_played );
shmem_pkts_recorded = 0;
shmem_pkts_played = 0;
return FALSE;
}
*shmem_hHook = 0;
}
if( !shmem_buf ) {
shmem_buf_size = 0xff00;
shmem_buf = calloc( 32, (size_t)shmem_buf_size );
if( !shmem_buf ) {
free( shmem_buf_pos );
shmem_buf_pos = 0;
free( shmem_buf_play_pos );
shmem_buf_play_pos = 0;
free( shmem_pkts_recorded );
free( shmem_pkts_played );
shmem_pkts_recorded = 0;
shmem_pkts_played = 0;
free( shmem_hHook );
shmem_hHook = 0;
return FALSE;
}
}
if( !shmem_ctx ) {
shmem_ctx = calloc( 32, sizeof(HCTX) );
if( !shmem_ctx ) {
free( shmem_buf_pos );
shmem_buf_pos = 0;
free( shmem_buf_play_pos );
shmem_buf_play_pos = 0;
free( shmem_pkts_recorded );
free( shmem_pkts_played );
shmem_pkts_recorded = 0;
shmem_pkts_played = 0;
free( shmem_hHook );
shmem_hHook = 0;
free( shmem_buf );
shmem_buf = 0;
shmem_buf_size = 0;
return FALSE;
}
}
if( !shmem_time ) {
shmem_time = calloc( 32, sizeof(long) );
if( !shmem_time ) {
free( shmem_buf_pos );
shmem_buf_pos = 0;
free( shmem_buf_play_pos );
shmem_buf_play_pos = 0;
free( shmem_pkts_recorded );
free( shmem_pkts_played );
shmem_pkts_recorded = 0;
shmem_pkts_played = 0;
free( shmem_hHook );
shmem_hHook = 0;
free( shmem_buf );
shmem_buf = 0;
shmem_buf_size = 0;
free( shmem_ctx );
shmem_ctx = 0;
return FALSE;
}
}
for( i = 0; i < NCONTEXTS; i++ ) {
shmem_ctx[i] = 0;
shmem_buf_pos[i] = 0;
shmem_buf_play_pos[i] = 0;
shmem_pkts_recorded[i] = 0;
shmem_pkts_played[i] = 0;
shmem_time[i] = 0;
}
return TRUE;
}
/* Win16 dll exit point. */
int WINAPI WEP(int nSystemExit)
{
if( shmem_buf )
free( shmem_buf );
if( shmem_buf_play_pos )
free( shmem_buf_play_pos );
if( shmem_buf_pos )
free( shmem_buf_pos );
if( shmem_pkts_recorded )
free( shmem_pkts_recorded );
if( shmem_pkts_played )
free( shmem_pkts_played );
if( shmem_hHook )
free( shmem_hHook );
return TRUE;
}
/******************************************************************/
/* Packet Decode Functions */
static const struct {
WTPKT tag; size_t size; int nargs; char *str;
} pkt_data_info[] = {
{PK_CONTEXT, sizeof(HCTX), 1, "Context: %u"},
{PK_STATUS, sizeof(UINT), 1, "Status: %u"},
{PK_TIME, sizeof(LONG), 1, "Time: %li"},
{PK_CHANGED, sizeof(WTPKT), 1, "Changed: %u"},
{PK_SERIAL_NUMBER, sizeof(UINT), 1, "Serial Number: %u"},
{PK_CURSOR, sizeof(UINT), 1, "Cursor: %u"},
{PK_BUTTONS, sizeof(DWORD), 1, "Buttons: %lu"},
{PK_X, sizeof(DWORD), 1, "X: %lu"},
{PK_Y, sizeof(DWORD), 1, "Y: %lu"},
{PK_Z, sizeof(DWORD), 1, "Z: %lu"},
{PK_NORMAL_PRESSURE, sizeof(UINT), 1, "Normal Pressure: %u"},
{PK_TANGENT_PRESSURE, sizeof(UINT), 1, "Tangent Pressure: %u"},
{PK_ORIENTATION, sizeof(ORIENTATION), 3, "Orientation: %i, %i, %i"},
{PK_ROTATION, sizeof(ROTATION), 3, "Rotation: %i, %i, %i"},
{0, 0, -1, 0}
};
size_t
compute_packet_size( WTPKT lcPktData )
{
unsigned i = 0;
size_t size = 0;
while( pkt_data_info[i].nargs > 0 ) {
if( lcPktData & pkt_data_info[i].tag )
size += pkt_data_info[i].size;
i++;
}
/* Check for extension data */
i = 0;
while( WTInfo( WTI_EXTENSIONS + i, EXT_NAME, 0 ) ) {
UINT ext_size[2];
WTPKT mask;
if( WTInfo( WTI_EXTENSIONS + i, EXT_MASK, &mask ) && (mask & lcPktData) ) {
WTInfo( WTI_EXTENSIONS + i, EXT_SIZE, ext_size );
size += ext_size[0];
}
i++;
}
return size;
}
long
get_packet_offset( WTPKT lcPktData, WTPKT field )
{
unsigned i = 0;
long offset = 0;
while( pkt_data_info[i].nargs > 0 && pkt_data_info[i].tag != field ) {
if( lcPktData & pkt_data_info[i].tag )
offset += pkt_data_info[i].size;
i++;
}
if( pkt_data_info[i].nargs == -1 )
offset = -1;
return offset;
}
size_t
display_packet( WTPKT lcPktData, unsigned char *packet )
{
unsigned i = 0;
size_t size = 0;
char outstring[2048] = "";
char str[128];
while( lcPktData && pkt_data_info[i].nargs > 0 ) {
if( lcPktData & pkt_data_info[i].tag ) {
if( pkt_data_info[i].nargs == 1 )
if( pkt_data_info[i].size == 2 )
sprintf( str, pkt_data_info[i].str, *((WORD *)packet) );
else
sprintf( str, pkt_data_info[i].str, *((DWORD *)packet) );
if( pkt_data_info[i].nargs == 3 )
sprintf( str, pkt_data_info[i].str, packet, *((WORD *)packet + 1), *((WORD *)packet + 2) );
strcat( outstring, str );
strcat( outstring, "\n" );
packet += pkt_data_info[i].size;
size += pkt_data_info[i].size;
}
i++;
}
/* Display extension data fields */
i = 0;
while( WTInfo( WTI_EXTENSIONS + i, EXT_NAME, str ) ) {
WTPKT mask;
if( WTInfo( WTI_EXTENSIONS + i, EXT_MASK, &mask ) && (mask & lcPktData) ) {
UINT ext_size[2];
UINT j;
WTInfo( WTI_EXTENSIONS + i, EXT_SIZE, ext_size );
strcat( outstring, str );
strcat( outstring, ": " );
for( j = 0; j < ext_size[0] / sizeof(int); j++ ) {
sprintf( str, "%8x", *((int *)packet + j) );
strcat( outstring, str );
strcat( outstring, " " );
}
strcat( outstring, "\n" );
packet += ext_size[0];
size += ext_size[0];
}
i++;
}
MessageBox( 0, outstring, "wthook", MB_OK );
return size;
}
int
hCtx_index( HCTX hCtx )
{
unsigned i = 0;
while( i < NCONTEXTS && shmem_ctx[i] && shmem_ctx[i] != hCtx )
i++;
if( i == NCONTEXTS )
return -1;
if( !shmem_ctx[i] )
shmem_ctx[i] = hCtx;
return i;
}
void *
find_next_ctx_packet( HCTX hCtx, WTPKT *lcPktData, DWORD * time_change, size_t *size )
{
HCTX packet_hCtx;
void *retval;
int index = hCtx_index(hCtx);
if( index > -1 ) {
/* Let shmem_buf_play_pos[index] end up pointing to the packet which we return */
*size = 0;
do {
if( *size )
shmem_buf_play_pos[index] += sizeof(WTPKT) + sizeof(HCTX) + sizeof(DWORD) + *size;
retval = shmem_buf + shmem_buf_play_pos[index];
*lcPktData = *((WTPKT *)(shmem_buf + shmem_buf_play_pos[index]));
packet_hCtx = *((HCTX *)(shmem_buf + sizeof(WTPKT) + shmem_buf_play_pos[index]));
*time_change = *((DWORD *)(shmem_buf + sizeof(WTPKT) + sizeof(HCTX) + shmem_buf_play_pos[index]));
*size = compute_packet_size( *lcPktData );
} while( shmem_buf_play_pos[index] < *shmem_buf_pos && packet_hCtx != hCtx );
if( packet_hCtx != hCtx )
retval = 0;
} else
retval = 0;
return retval;
}
/******************************************************************/
/* Wintab hook functions */
LRESULT
WINAPI RecordHook(int nCode,WPARAM wParam,LPARAM lParam)
{
DWORD curtime;
if( nCode >= 0 ) {
LOGCONTEXT lc;
size_t packet_size;
/* We need to find the packet data size */
WTGet((HCTX)wParam, &lc);
packet_size = compute_packet_size( lc.lcPktData );
/* If we have space left in our shared memory buffer, */
if( *shmem_buf_pos < shmem_buf_size - packet_size - sizeof(WTPKT) ) {
int index = hCtx_index( (HCTX)wParam );
/* There's no garauntee that the contexts will be giving us the
data that we need in their packets, so explicitly calculate
everything we need here: */
/* Write lc.lcPktData */
*((WTPKT *)(shmem_buf + *shmem_buf_pos)) = lc.lcPktData;
(*shmem_buf_pos) += sizeof(WTPKT);
/* Write hCtx */
*((HCTX *)(shmem_buf + *shmem_buf_pos)) = (HCTX)wParam;
(*shmem_buf_pos) += sizeof(HCTX);
/* Write time change (since previous packet of this context) */
curtime = timeGetTime();
if( shmem_time[index] == 0 ) {
shmem_time[index] = curtime;
*((DWORD *)(shmem_buf + *shmem_buf_pos)) = 0;
} else {
*((DWORD *)(shmem_buf + *shmem_buf_pos)) = curtime - shmem_time[index];
shmem_time[index] = curtime;
}
(*shmem_buf_pos) += sizeof(DWORD);
/* Write packet data */
memcpy( shmem_buf + *shmem_buf_pos, (LPVOID)lParam, packet_size );
(*shmem_buf_pos) += packet_size;
(*shmem_pkts_recorded)++;
}
return TRUE;
} else /* Let Wintab continue processing the packet */
return WTMgrPacketHookNext(*shmem_hHook,nCode,wParam,lParam);
}
LRESULT WINAPI PlayHook(int nCode, WPARAM wParam, LPARAM lParam)
{
DWORD delay;
void *packet;
size_t size;
WTPKT lcPktData;
LRESULT retval;
int index;
/* Find the next packet corrisponding to this context */
packet = find_next_ctx_packet( (HCTX)wParam, &size, &lcPktData, &delay );
if( packet ) {
switch( nCode ) {
case WTHC_GETNEXT:
/* Copy the packet to the buffer */
memcpy( (LPVOID)lParam, packet, size );
retval = delay;
break;
case WTHC_SKIP:
index = hCtx_index( (HCTX)wParam );
shmem_buf_play_pos[index] +=
size + sizeof(WTPKT) + sizeof(DWORD) + sizeof(HCTX);
retval = 0;
(*shmem_pkts_played)++;
break;
default:
break;
}
} else
retval = WTMgrPacketHookNext(*shmem_hHook, nCode, wParam, lParam);
return retval;
}
/******************************************************************/
/* Exported user functions */
long WINAPI get_num_pkts_recorded( void )
{
return *shmem_pkts_recorded;
}
long WINAPI get_num_pkts_played( void )
{
return *shmem_pkts_played;
}
BOOL WINAPI Record(BOOL fEnable, HMGR hMgr)
{
BOOL result = FALSE;
if (fEnable) {
if (!*shmem_hHook)
*shmem_hHook = WTMgrPacketHookEx(hMgr, WTH_RECORD,
"wthkdll.dll", "RecordHook");
result = !!*shmem_hHook;
} else {
if (*shmem_hHook) {
WTMgrPacketUnhook(*shmem_hHook);
*shmem_hHook = 0;
}
result = TRUE;
}
return result;
}
void
WINAPI display_record(void)
{
unsigned char *ptr = shmem_buf;
while( ptr < shmem_buf + *shmem_buf_pos ) {
WTPKT lcPktData;
HCTX hCtx;
DWORD time;
lcPktData = *((WTPKT *)ptr);
ptr += sizeof(WTPKT);
hCtx = *((HCTX *)ptr);
ptr += sizeof(HCTX);
time = *((DWORD *)ptr);
ptr += sizeof(DWORD);
ptr += display_packet( lcPktData, ptr );
}
}
BOOL WINAPI Playback(BOOL fEnable, HMGR hMgr)
{
BOOL result = FALSE;
if( fEnable ) {
if( !*shmem_hHook )
*shmem_hHook = WTMgrPacketHookEx( hMgr, WTH_PLAYBACK,
"wthkdll.dll", "PlayHook" );
result = !!*shmem_hHook;
} else {
if( *shmem_hHook ) {
WTMgrPacketUnhook( *shmem_hHook );
*shmem_hHook = 0;
}
result = TRUE;
}
return result;
}
/* Even when wthook.exe ends, the shared memory of the dll is still hanging
around, since the dll is loaded by wintab32 into other people's address spaces.
We have to reset the shared memory, so that the next time wthook runs, it doesn't
pick up the old shared memory contents. */
void
WINAPI reset( void )
{
/* Just set the counters back to zero */
*shmem_buf_pos = 0;
*shmem_buf_play_pos = 0;
*shmem_pkts_recorded = 0;
*shmem_pkts_played = 0;
}