REDIVIVUS

Proposals / #1094

The qserver token list holds each game's hash handle, not an SGAMEDATA pointer

checked · by dtchitt · submitted 2026-11-03

gaQServerGameByToken is typed SGAMEDATA *[1025], but no reader dereferences a slot. Every reader null- and -1-checks the slot and hands it to QSERVER_FindAndLockGame as the hash key: QSERVER_GetClientCountByServerId loads it (0052eca6 MOV EAX,[EAX*4+0x882d34]), keeps it in ESI, then 0052ecc5 MOV ECX,ESI and 0052ecc7 CALL QSERVER_FindAndLockGame. The one writer, QSERVER_PutNewGameOnTokenList, stores its first argument there (0052c12c MOV ECX,[EBP+8]; 0052c134 MOV [EAX*4+0x882d34],ECX). GAME_CreateBattleNetGame passes the game's unique handle: GenerateUniqueHandle at 0053096e, kept in [EBP-8] at 0053097c and passed as the TSHashTable::New key, reloaded at 00530b88 and pushed at 00530b8c for the call at 00530b8d. So both become uint32_t, which removes the (SGAMEDATA*)nHashToken and (uint32_t)nToken casts on both sides.

Changes 2, applied together

  1. Retype global win 0x00882d34

    typeSGAMEDATA *[1025] (4100 bytes)→uint32_t[1025]
  2. Retype variable win 0x0052c110 Stack[0x4]

    typeSGAMEDATA *→uint32_t