# DBCServer_Release_x64.exe — finding ledger - SHA-256 `d9e4fccdf3482e50247686d4452c0b13c75a53efc4bd7320668eece8d1ce828c`, 3,542,016 bytes - PE32+ x86-64, MSVC 10 (VS2010), timestamp 2013-02-06 10:01:47 UTC - PDB reference `c:\work\Project\Output\Exe\DBCServer_Release_x64.pdb` (GUID 3dbb7ebc-82fb-4496-8a47-78f2cc1f8e51, age 1) — not available - Imports: KERNEL32, USER32, ADVAPI32, ole32, OLEAUT32, MSVCP100, RPCRT4, WINMM, MSVCR100, dbghelp, MSWSOCK, WS2_32, BugTrapU-x64. There is no ADO import; ADO is reached through COM (`ADODB.Command`, `_com_issue_errorex`) - REA/Ghidra 12.1.2: 20,732 procedures, 3,363 strings (`ev_389cbf95…`). Evidence bundle: `evidence-bundle.json` - Language C++ (RTTI, `__CxxFrameHandler3`). Libraries: ProudNet, TinyXML 2.5.x, BugTrap, ATL/COM `_com_ptr`. Nothing new beyond `third-party/README.md` - Single instance via mutex `Global\RustyHearts_DBC` (S) - Static analysis only. Shared conclusions are in `docs/DATABASE.md` and `docs/CONFIG.md`. This ledger holds the binary-specific evidence. ## Outputs | Path | Content | |---|---| | `full/functions/*.c`, `full/index.tsv` | 20,334 functions. 2 failed: `0x14000e4d0` (SERVERS2DBC stub dispatcher, timeout) and `0x1400a8190` (worker command dispatcher, flow limit) | | `full/vtables.tsv` | 2,043 vftable slots | | `cmd_dispatch.tsv` | Command ID 1001–1317 → `DBReq` function → procedures, decoded from the jump table at `0x1400a9dd4` | | `dbreq_methods.tsv` | 511 catch funclets → (`source .cpp`, `CDBLobbyWriteQuery::DBReq*`, procedure); 281 methods | | `rmi_to_proc.tsv` | SERVERS2DBC RMI → stub slot → command → `DBReq` → procedure → database | | `rmi_tables.tsv` | RMI ID/name tables found in proxy code (DBC2SERVERS 76, SERVER2AGENT 11) | | `.pseudo.c` | Key functions cited below | ## Findings | # | Conclusion | Type | Evidence | |---|---|---|---| | 1 | The SERVERS2DBC ID→name table (262 entries) is identical to MessageServer's | O | `0x140041b90`; diff against `decomp/shared/rmi_from_MessageServer.tsv` | | 2 | Stub handlers enqueue `{size, cmd_id, args}` into write queue `[idx<1000]` and signal a semaphore; they do no SQL themselves | O | `0x140050d20`, `0x140144730` | | 3 | The worker dispatches commands 1001–1317 through a jump table to `DBReq*` methods | O (disassembly) | `0x1400a8190`, `cmd_dispatch.tsv` | | 4 | Each `DBReq*` runs one stored procedure through `ADODB.Command` with named parameters, and maps recordset fields by name | O | `0x1400acbb0` (`up_create_character`) | | 5 | Four connection types: 1 WEB(`db_web`), 2 AUTH(`db_account`), 3 GAME(`db_game`), 4 GAME LOG(`db_game_log`). AUTH uses the WEB timeout (bug). Timeout 0 → 500. String length ≤255 | O | `0x1400a7aa0` (REA `ev_00545a3e…`) | | 6 | Startup opens AUTH and GAME connections, allocates 1000-slot write-queue arrays (125 iterations × 8 pointers), and logs connect failures to `Error_ADO DB Connect.Log` | O | `0x140042cf0`, `0x1400a80c0` | | 7 | 210 of 262 RMIs map to a procedure. 7 of those procedures are missing from the shipped schema | O + D | `rmi_to_proc.tsv` | | 8 | Original source layout: `DBLobbyWriteQuery.cpp` ×28 plus `DBWriteQueryServerOption.cpp` | O (`__FILE__` strings) | `dbreq_methods.tsv` | | 9 | The option-loader layout equals MessageServer's (same offsets for every element) | O | `0x140156650`, `0x140155420` | | 10 | The `customoption.xml` parser is the same as MessageServer's; the shipped file doesn't match it | O | `0x14015ca50` | | 11 | `option\server_info.ini` is referenced only as a string, and there is no INI API import | S/I | — | | 12 | Only `up_read_world_server` touches topology data here. `up_read_all_serveroption` lives in AgentManager | S | strings | ## Open - Decode `0x14000e4d0` (stub dispatcher) from its jump table. That would turn the slot→RMI assumption into an observation. - Find which connection each queue/`DBReq` uses. - Resolve the 52 unmapped RMIs, mainly logs, likely handled by DBCServer_LOG. - Pair DBC2SERVERS replies with their requests.