клиентские как раньше ищутся, а серверные обработчики немного по другому
находим сначала NetClient::OneMessageReady
Код:
void __thiscall NetClient__OneMessageReady(void *this, int a2, int a3, int a4, signed int a5)
{
void *v5; // ebx@1
int v6; // edi@1
signed int v7; // eax@3
int v8; // eax@6
int v9; // eax@7
size_t v10; // esi@8
int v11; // eax@9
int v12; // ecx@13
signed int v13; // [sp-4h] [bp-12Ch]@19
char v14; // [sp+10h] [bp-118h]@8
void *v15; // [sp+10Ch] [bp-1Ch]@1
int (__stdcall **v16)(int, int, int); // [sp+110h] [bp-18h]@17
int v17; // [sp+114h] [bp-14h]@8
int v18; // [sp+118h] [bp-10h]@8
size_t v19; // [sp+11Ch] [bp-Ch]@8
int v20; // [sp+120h] [bp-8h]@8
int v21; // [sp+124h] [bp-4h]@8
int v22; // [sp+13Ch] [bp+14h]@9
v6 = a5;
v5 = this;
v15 = this;
if ( a5 < 4 || !a4 || (v7 = sub_653578(this, a2), v7 >= 4) )
goto LABEL_4;
v8 = (int)(v5 + v7 + 1650);
if ( *(_BYTE *)v8 )
{
v11 = *(_DWORD *)a4;
v22 = *(_DWORD *)a4;
if ( *(_DWORD *)a4 == 1882 )
{
v13 = 0;
}
else
{
if ( *(_DWORD *)a4 == 1994 )
{
NetClient__DecompressAndProcess(a2, a4 + 4, v6 - 4);
return;
}
if ( *(_DWORD *)a4 != 5962 )
{
if ( *(_DWORD *)a4 == 6105 )
{
NetClient__HandleMultiplePackets(a2, a3, a4 + 4, v6 - 4);
}
else
{
v12 = (v11 - 1) & 0xF6E;
if ( v12 == 1864 || v12 == 1896 )
{
v18 = 0;
v19 = -1;
v21 = 0;
v16 = &off_D62168;
v17 = a4 + 4;
v20 = v6 - 4;
NetClient__JAMClientConnectionDispatch(a2, a3, v11, &v16);
v16 = &off_D62168;
CDataStore__InternalDestroy(&v16);
}
else
{
if ( sub_6541A4(v5, a2) )
sub_6252E0(v22, (int)v5, a2, a4, v6);
}
}
return;
}
v13 = 1;
}
sub_653613(a2, a4 + 4, v6 - 4, v13);
return;
}
*(_BYTE *)v8 = 1;
v9 = strlen("WORLD OF WARCRAFT CONNECTION - SERVER TO CLIENT");
if ( sub_A3DE62(a4, "WORLD OF WARCRAFT CONNECTION - SERVER TO CLIENT", v9) )
{
LABEL_4:
sub_653F7D(a2, 3u);
sub_957D2F((LPCRITICAL_SECTION)a2);
return;
}
v10 = strlen("WORLD OF WARCRAFT CONNECTION - CLIENT TO SERVER") + 1;
memmove_0(&v14, "WORLD OF WARCRAFT CONNECTION - CLIENT TO SERVER", v10);
v17 = (int)&v14;
v18 = 0;
v19 = v10;
v20 = 4;
v21 = 0;
WowConnection__Send(&v17, 1);
sub_53ACB3(
v18,
"d:\\buildserver\\wow\\4\\work\\wow-code\\branches\\wow-patch-6_0_3-branch-fastpatch-1\\wow\\source\\wowservices\\PacketPipe.h",
34,
0);
}
Эта штука проверяет айди коннекта, куда пришел опкод, определяет группу, к которой принадлежит опкод, и если все ок то ставит в очередь
Код:
if ( sub_6541A4(v5, a2) )
sub_6252E0(v22, (int)v5, a2, a4, v6);
вот этим, собственно, и ставит
Код:
if ( (unsigned __int8)(*(int (__cdecl **)(_DWORD, _DWORD, _DWORD, _DWORD, _DWORD))(*(_DWORD *)v7 + 0x18))(
a2,
a1,
a3,
a4,
a5) )
массив собой представляет массив структур что-то вроде
Код:
[StructLayout(LayoutKind.Sequential)]
struct SMSGHandler
{
public IntPtr pName; // 0x0
public uint checker; // 0x4
public uint _2; // 0x8
public uint _3; // 0xC
public uint _4; // 0x10
public uint dataHandler; // 0x14
public uint connectionChecker; // 0x18
}
я глубоко не вникал
pName - имя группы, checker - проверка принадлежности группы, dataHandler - адрес обработчика группы, connectionChecker - проверяет номер соединения (?)
вот так это выглядит в 19116
Код:
'ClientQuest'
Checker: 5F4D44
Connection Checker: 5F4D86
DataHandler: 5F4DD3
_2: 0
_3: 0
_4: 5F4D5C
'Client'
Checker: 5F8F77
Connection Checker: 5FF895
DataHandler: 5F90B3
_2: 0
_3: 0
_4: 5FF74D
'ClientGuild'
Checker: 61F2BD
Connection Checker: 61F2FF
DataHandler: 61F34C
_2: 0
_3: 0
_4: 61F2D5
'ClientSocial'
Checker: 62A9FD
Connection Checker: 62AA15
DataHandler: 62AA43
_2: 0
_3: 0
_4: 250000
'ClientSpell'
Checker: CAE449
Connection Checker: CAE52D
DataHandler: CAE5C8
_2: 0
_3: 0
_4: CAE4B5
'ClientMovement'
Checker: CB96EE
Connection Checker: CB9898
DataHandler: CB997B
_2: 0
_3: 0
_4: CB97BF
'ClientLFG'
Checker: CBC9E4
Connection Checker: CBCA26
DataHandler: CBCA54
_2: 0
_3: 0
_4: CBC9FC
'ClientChat'
Checker: CBFCED
Connection Checker: CBFD2F
DataHandler: CBFD5D
_2: 0
_3: 0
_4: CBFD05
'ClientGarrison'
Checker: CC1461
Connection Checker: CC1501
DataHandler: CC155D
_2: 0
_3: 0
_4: CC14AB
Собственно, в sub_6252E0 вызывается connectionChecker, например вот
Код:
char __cdecl sub_5FF895(int a1, int a2, int a3, int a4, int a5)
{
int v5; // eax@1
int v6; // ecx@3
int v7; // ecx@13
int v8; // ecx@16
int v9; // eax@18
char result; // al@22
v5 = a2 - 1;
if ( (((_WORD)a2 - 1) & 0x1F54) != 4608
&& (v5 & 0x1DDC) != 208
&& (v6 = v5 & 0xDDC, v6 != 256)
&& v6 != 2304
&& (v5 & 0x5D4) != 384
&& (v5 & 0x5D6) != 272
&& (v5 & 0x76C) != 832
&& (v5 & 0x5F4) != 480
&& (v5 & 0x15D4) != 4
&& (v5 & 0x15C4) != 260
&& (v5 & 0x15BE) != 5256
&& (v5 & 0x174E) != 1288
&& (v7 = v5 & 0x74E, v7 != 1292)
&& v7 != 1294
&& (v5 & 0x74A) != 1800
&& (v8 = v5 & 0xFCE, v8 != 1352)
&& v8 != 1480
&& (v9 = v5 & 0xDCE, v9 != 1354)
&& v9 != 1482
|| (unsigned __int8)sub_5FA1D7(a2) && sub_653578((void *)a1, a3) != 1 )
{
result = 0;
}
else
{
NETEVENTQUEUE__AddEvent_2(a1, 23, a3, a4, a5);
result = 1;
}
return result;
}
Сами обработчики вызываются в NetClient::ProcessMessage
Код:
char __thiscall NetClient__ProcessMessage(void *this, int a2, int a3, int a4, int a5)
{
char result; // al@1
int v6; // esi@1
void *v7; // edi@1
++dword_10B8FC4;
v6 = a4;
v7 = this;
CDataStore__GetInt32(&a4);
result = sub_625285(v7, a2, a3, a4, v6);
if ( !result )
result = (*(int (__thiscall **)(_DWORD))(*(_DWORD *)v6 + 24))(v6);
return result;
}
В sub_625285 идет та же итерация по структуре, и если опкод принадлежит к группе, то вызывается dataHandler этой группы
при желании для этого всего можно тоже сделать OpcodeTools