DS2Revival/mods/common/dp8.h

283 lines
18 KiB
C++

// The part of the public DirectPlay 8 API (dplay8.h / dpaddr.h, DirectX 9.0c SDK) that DS2 uses, declared here
// because current Windows SDKs no longer ship those headers. Values and layouts are the documented API; the
// method order is the COM vtable order. Used by the ds2dev DirectPlay trace and the DS2Multiplayer DirectPlay shim
// (docs/multiplayer/dp8-shim.md).
#pragma once
#include <objbase.h>
namespace dp8 {
using DPNID = DWORD;
using DPNHANDLE = DWORD;
using PFNDPNMESSAGEHANDLER = HRESULT(WINAPI*)(void* userContext, DWORD messageId, void* message);
// {743F1DC6-5ABA-429F-8BDF-C54D03253DC2} etc.
constexpr GUID CLSID_Client = {0x743F1DC6, 0x5ABA, 0x429F, {0x8B, 0xDF, 0xC5, 0x4D, 0x03, 0x25, 0x3D, 0xC2}};
constexpr GUID CLSID_Server = {0xDA825E1B, 0x6830, 0x43D7, {0x83, 0x5D, 0x0B, 0x5A, 0xD8, 0x29, 0x56, 0xA2}};
constexpr GUID CLSID_Peer = {0x286F484D, 0x375E, 0x4458, {0xA2, 0x72, 0xB1, 0x38, 0xE2, 0xF8, 0x0A, 0x6A}};
constexpr GUID CLSID_Address = {0x934A9523, 0xA3CA, 0x4BC5, {0xAD, 0xA0, 0xD6, 0xD9, 0x5D, 0x97, 0x94, 0x21}};
// DirectPlay8ThreadPool: the game creates one next to every Client/Server (NetPipe, 0x8d29f4 / 0x8d2cfe) and only
// ever calls GetThreadCount (slot 5), DoWork (7) and Close (4) on it; failing to create it is fatal for the game.
constexpr GUID CLSID_ThreadPool = {0xFC47060E, 0x6153, 0x4B34, {0xB9, 0x75, 0x8E, 0x41, 0x21, 0xEB, 0x7F, 0x3C}};
constexpr GUID IID_ThreadPool = {0x0D22EE73, 0x4A46, 0x4A0D, {0x89, 0xB2, 0x04, 0x5B, 0x4D, 0x66, 0x64, 0x25}};
constexpr GUID IID_Client = {0x5102DACD, 0x241B, 0x11D3, {0xAE, 0xA7, 0x00, 0x60, 0x97, 0xB0, 0x14, 0x11}};
constexpr GUID IID_Server = {0x5102DACE, 0x241B, 0x11D3, {0xAE, 0xA7, 0x00, 0x60, 0x97, 0xB0, 0x14, 0x11}};
constexpr GUID IID_Address = {0x83783300, 0x4063, 0x4C8A, {0x9D, 0xB3, 0x82, 0x83, 0x0A, 0x7F, 0xEB, 0x31}};
constexpr GUID IID_AddressIP = {0xE5A0E990, 0x2BAD, 0x430B, {0x87, 0xDA, 0xA1, 0x42, 0xCF, 0x75, 0xDE, 0x58}};
constexpr GUID SP_TCPIP = {0xEBFE7BA0, 0x628D, 0x11D2, {0xAE, 0x0F, 0x00, 0x60, 0x97, 0xB0, 0x14, 0x11}};
// Messages (DPN_MSGID_*).
enum : DWORD {
MSG_ADD_PLAYER_TO_GROUP = 0xFFFF0001, MSG_APPLICATION_DESC, MSG_ASYNC_OP_COMPLETE, MSG_CLIENT_INFO,
MSG_CONNECT_COMPLETE, MSG_CREATE_GROUP, MSG_CREATE_PLAYER, MSG_DESTROY_GROUP, MSG_DESTROY_PLAYER,
MSG_ENUM_HOSTS_QUERY, MSG_ENUM_HOSTS_RESPONSE, MSG_GROUP_INFO, MSG_HOST_MIGRATE, MSG_INDICATE_CONNECT,
MSG_INDICATED_CONNECT_ABORTED, MSG_PEER_INFO, MSG_RECEIVE, MSG_REMOVE_PLAYER_FROM_GROUP, MSG_RETURN_BUFFER,
MSG_SEND_COMPLETE, MSG_SERVER_INFO, MSG_TERMINATE_SESSION, MSG_CREATE_THREAD, MSG_DESTROY_THREAD,
MSG_NAT_RESOLVER_QUERY = 0xFFFF0101,
};
// Flags.
constexpr DWORD OP_SYNC = 0x80000000;
constexpr DWORD SEND_NOCOPY = 0x0001, SEND_NOCOMPLETE = 0x0002, SEND_COMPLETEONPROCESS = 0x0004,
SEND_GUARANTEED = 0x0008, SEND_NONSEQUENTIAL = 0x0010, SEND_NOLOOPBACK = 0x0020,
SEND_PRIORITY_LOW = 0x0040, SEND_PRIORITY_HIGH = 0x0080, SEND_COALESCE = 0x0100;
constexpr DWORD RECEIVE_GUARANTEED = 0x0001, RECEIVE_COALESCED = 0x0002;
constexpr DWORD SENDCOMPLETE_GUARANTEED = 0x0001;
constexpr DWORD SESSION_CLIENT_SERVER = 0x0001, SESSION_MIGRATE_HOST = 0x0004, SESSION_NODPNSVR = 0x0040,
SESSION_REQUIREPASSWORD = 0x0080, SESSION_NOENUMS = 0x0100;
constexpr DWORD INFO_NAME = 0x0001, INFO_DATA = 0x0002;
constexpr DWORD PLAYER_LOCAL = 0x0002, PLAYER_HOST = 0x0004;
constexpr DWORD CANCEL_CONNECT = 0x0001, CANCEL_ENUM = 0x0002, CANCEL_SEND = 0x0004, CANCEL_ALL = 0x8000;
constexpr DWORD DESTROY_NORMAL = 1, DESTROY_CONNECTIONLOST = 2, DESTROY_SESSIONTERMINATED = 3,
DESTROY_HOSTDESTROYEDPLAYER = 4;
constexpr DWORD DATATYPE_STRING = 1, DATATYPE_DWORD = 2, DATATYPE_GUID = 3, DATATYPE_BINARY = 4,
DATATYPE_STRING_ANSI = 5;
constexpr DPNID ALL_PLAYERS_GROUP = 0;
// HRESULTs (facility 0x15, base 0x8000).
constexpr HRESULT MakeErr(DWORD code) { return static_cast<HRESULT>(0x80158000u + code); }
constexpr HRESULT S_PENDING = static_cast<HRESULT>(0x0015800Eu); // DPNSUCCESS_PENDING
constexpr HRESULT E_ALREADYINITIALIZED = MakeErr(0x80), E_BUFFERTOOSMALL = MakeErr(0x100),
E_CONNECTIONLOST = MakeErr(0x160), E_DOESNOTEXIST = MakeErr(0x180),
E_HOSTREJECTEDCONNECTION = MakeErr(0x260), E_HOSTTERMINATEDSESSION = MakeErr(0x270),
E_INVALIDHANDLE = MakeErr(0x360), E_INVALIDPLAYER = MakeErr(0x420), E_NOCONNECTION = MakeErr(0x480),
E_NOTHOST = MakeErr(0x530), E_SESSIONFULL = MakeErr(0x610), E_TIMEDOUT = MakeErr(0x630),
E_UNINITIALIZED = MakeErr(0x640), E_USERCANCEL = MakeErr(0x650), E_NOTALLOWED = MakeErr(0x520),
E_INVALIDURL = MakeErr(0x450), E_NOHOSTPLAYER = MakeErr(0x490), E_ADDRESSING = MakeErr(0x40);
struct APPLICATION_DESC {
DWORD dwSize, dwFlags;
GUID guidInstance, guidApplication;
DWORD dwMaxPlayers, dwCurrentPlayers;
WCHAR* pwszSessionName;
WCHAR* pwszPassword;
void* pvReservedData;
DWORD dwReservedDataSize;
void* pvApplicationReservedData;
DWORD dwApplicationReservedDataSize;
};
struct BUFFER_DESC {
DWORD dwBufferSize;
BYTE* pBufferData;
};
struct CAPS {
DWORD dwSize, dwFlags, dwConnectTimeout, dwConnectRetries, dwTimeoutUntilKeepAlive;
};
struct SP_CAPS {
DWORD dwSize, dwFlags, dwNumThreads, dwDefaultEnumCount, dwDefaultEnumRetryInterval, dwDefaultEnumTimeout,
dwMaxEnumPayloadSize, dwBuffersPerThread, dwSystemBufferSize;
};
struct CONNECTION_INFO {
DWORD dwSize, dwRoundTripLatencyMS, dwThroughputBPS, dwPeakThroughputBPS, dwBytesSentGuaranteed,
dwPacketsSentGuaranteed, dwBytesSentNonGuaranteed, dwPacketsSentNonGuaranteed, dwBytesRetried,
dwPacketsRetried, dwBytesDropped, dwPacketsDropped, dwMessagesTransmittedHighPriority,
dwMessagesTimedOutHighPriority, dwMessagesTransmittedNormalPriority, dwMessagesTimedOutNormalPriority,
dwMessagesTransmittedLowPriority, dwMessagesTimedOutLowPriority, dwBytesReceivedGuaranteed,
dwPacketsReceivedGuaranteed, dwBytesReceivedNonGuaranteed, dwPacketsReceivedNonGuaranteed,
dwMessagesReceived;
};
struct PLAYER_INFO { // also DPN_GROUP_INFO (same layout)
DWORD dwSize, dwInfoFlags;
WCHAR* pwszName;
void* pvData;
DWORD dwDataSize, dwPlayerFlags;
};
struct SERVICE_PROVIDER_INFO {
DWORD dwFlags;
GUID guid;
WCHAR* pwszName;
void* pvReserved;
DWORD dwReserved;
};
struct IDirectPlay8Address;
// Callback messages.
struct MSG_ASYNC_OP_COMPLETE_T { DWORD dwSize; DPNHANDLE hAsyncOp; void* pvUserContext; HRESULT hResultCode; };
struct MSG_CLIENT_INFO_T { DWORD dwSize; DPNID dpnidClient; void* pvPlayerContext; };
struct MSG_CONNECT_COMPLETE_T {
DWORD dwSize;
DPNHANDLE hAsyncOp;
void* pvUserContext;
HRESULT hResultCode;
void* pvApplicationReplyData;
DWORD dwApplicationReplyDataSize;
DPNID dpnidLocal;
};
struct MSG_CREATE_PLAYER_T { DWORD dwSize; DPNID dpnidPlayer; void* pvPlayerContext; };
struct MSG_DESTROY_PLAYER_T { DWORD dwSize; DPNID dpnidPlayer; void* pvPlayerContext; DWORD dwReason; };
struct MSG_ENUM_HOSTS_QUERY_T {
DWORD dwSize;
IDirectPlay8Address* pAddressSender;
IDirectPlay8Address* pAddressDevice;
void* pvReceivedData;
DWORD dwReceivedDataSize, dwMaxResponseDataSize;
void* pvResponseData;
DWORD dwResponseDataSize;
void* pvResponseContext;
};
struct MSG_ENUM_HOSTS_RESPONSE_T {
DWORD dwSize;
IDirectPlay8Address* pAddressSender;
IDirectPlay8Address* pAddressDevice;
const APPLICATION_DESC* pApplicationDescription;
void* pvResponseData;
DWORD dwResponseDataSize;
void* pvUserContext;
DWORD dwRoundTripLatencyMS;
};
struct MSG_INDICATE_CONNECT_T {
DWORD dwSize;
void* pvUserConnectData;
DWORD dwUserConnectDataSize;
void* pvReplyData;
DWORD dwReplyDataSize;
void* pvReplyContext;
void* pvPlayerContext;
IDirectPlay8Address* pAddressPlayer;
IDirectPlay8Address* pAddressDevice;
};
struct MSG_INDICATED_CONNECT_ABORTED_T { DWORD dwSize; void* pvPlayerContext; };
struct MSG_RECEIVE_T {
DWORD dwSize;
DPNID dpnidSender;
void* pvPlayerContext;
BYTE* pReceiveData;
DWORD dwReceiveDataSize;
DPNHANDLE hBufferHandle;
DWORD dwReceiveFlags;
};
struct MSG_RETURN_BUFFER_T { DWORD dwSize; HRESULT hResultCode; void* pvBuffer; void* pvUserContext; };
struct MSG_SEND_COMPLETE_T {
DWORD dwSize;
DPNHANDLE hAsyncOp;
void* pvUserContext;
HRESULT hResultCode;
DWORD dwSendTime, dwFirstFrameRTT, dwFirstFrameRetryCount, dwSendCompleteFlags;
BUFFER_DESC* pBuffers;
DWORD dwNumBuffers;
};
struct MSG_SERVER_INFO_T { DWORD dwSize; DPNID dpnidServer; void* pvPlayerContext; };
struct MSG_TERMINATE_SESSION_T { DWORD dwSize; HRESULT hResultCode; void* pvTerminateData; DWORD dwTerminateDataSize; };
struct MSG_CREATE_THREAD_T { DWORD dwSize, dwFlags, dwProcessorNum; void* pvUserContext; };
// Interfaces, in vtable order.
struct IDirectPlay8Address : IUnknown {
virtual HRESULT __stdcall BuildFromURLW(WCHAR* url) = 0; // 3
virtual HRESULT __stdcall BuildFromURLA(CHAR* url) = 0; // 4
virtual HRESULT __stdcall Duplicate(IDirectPlay8Address** out) = 0; // 5
virtual HRESULT __stdcall SetEqual(IDirectPlay8Address* other) = 0; // 6
virtual HRESULT __stdcall IsEqual(IDirectPlay8Address* other) = 0; // 7
virtual HRESULT __stdcall Clear() = 0; // 8
virtual HRESULT __stdcall GetURLW(WCHAR* url, DWORD* chars) = 0; // 9
virtual HRESULT __stdcall GetURLA(CHAR* url, DWORD* chars) = 0; // 10
virtual HRESULT __stdcall GetSP(GUID* sp) = 0; // 11
virtual HRESULT __stdcall GetUserData(void* data, DWORD* size) = 0; // 12
virtual HRESULT __stdcall SetSP(const GUID* sp) = 0; // 13
virtual HRESULT __stdcall SetUserData(const void* data, DWORD size) = 0; // 14
virtual HRESULT __stdcall GetNumComponents(DWORD* n) = 0; // 15
virtual HRESULT __stdcall GetComponentByName(const WCHAR* name, void* buf, DWORD* size, DWORD* type) = 0; // 16
virtual HRESULT __stdcall GetComponentByIndex(DWORD index, WCHAR* name, DWORD* nameLen, void* buf, DWORD* size,
DWORD* type) = 0; // 17
virtual HRESULT __stdcall AddComponent(const WCHAR* name, const void* data, DWORD size, DWORD type) = 0; // 18
virtual HRESULT __stdcall GetDevice(GUID* device) = 0; // 19
virtual HRESULT __stdcall SetDevice(const GUID* device) = 0; // 20
virtual HRESULT __stdcall BuildFromDPADDRESS(void* address, DWORD size) = 0; // 21
};
struct IDirectPlay8ThreadPool : IUnknown {
virtual HRESULT __stdcall Initialize(void* ctx, PFNDPNMESSAGEHANDLER handler, DWORD flags) = 0; // 3
virtual HRESULT __stdcall Close(DWORD flags) = 0; // 4
virtual HRESULT __stdcall GetThreadCount(DWORD processor, DWORD* count, DWORD flags) = 0; // 5
virtual HRESULT __stdcall SetThreadCount(DWORD processor, DWORD count, DWORD flags) = 0; // 6
virtual HRESULT __stdcall DoWork(DWORD allowedTimeSlice, DWORD flags) = 0; // 7
};
struct IDirectPlay8Client : IUnknown {
virtual HRESULT __stdcall Initialize(void* ctx, PFNDPNMESSAGEHANDLER handler, DWORD flags) = 0; // 3
virtual HRESULT __stdcall EnumServiceProviders(const GUID* sp, const GUID* app, SERVICE_PROVIDER_INFO* buf,
DWORD* size, DWORD* count, DWORD flags) = 0; // 4
virtual HRESULT __stdcall EnumHosts(APPLICATION_DESC* desc, IDirectPlay8Address* host, IDirectPlay8Address* device,
void* data, DWORD size, DWORD count, DWORD retryMs, DWORD timeoutMs,
void* ctx, DPNHANDLE* handle, DWORD flags) = 0; // 5
virtual HRESULT __stdcall CancelAsyncOperation(DPNHANDLE handle, DWORD flags) = 0; // 6
virtual HRESULT __stdcall Connect(const APPLICATION_DESC* desc, IDirectPlay8Address* host,
IDirectPlay8Address* device, const void* security, const void* credentials,
const void* data, DWORD size, void* ctx, DPNHANDLE* handle, DWORD flags) = 0; // 7
virtual HRESULT __stdcall Send(const BUFFER_DESC* bufs, DWORD count, DWORD timeoutMs, void* ctx, DPNHANDLE* handle,
DWORD flags) = 0; // 8
virtual HRESULT __stdcall GetSendQueueInfo(DWORD* msgs, DWORD* bytes, DWORD flags) = 0; // 9
virtual HRESULT __stdcall GetApplicationDesc(APPLICATION_DESC* buf, DWORD* size, DWORD flags) = 0; // 10
virtual HRESULT __stdcall SetClientInfo(const PLAYER_INFO* info, void* ctx, DPNHANDLE* handle, DWORD flags) = 0; // 11
virtual HRESULT __stdcall GetServerInfo(PLAYER_INFO* info, DWORD* size, DWORD flags) = 0; // 12
virtual HRESULT __stdcall GetServerAddress(IDirectPlay8Address** out, DWORD flags) = 0; // 13
virtual HRESULT __stdcall Close(DWORD flags) = 0; // 14
virtual HRESULT __stdcall ReturnBuffer(DPNHANDLE handle, DWORD flags) = 0; // 15
virtual HRESULT __stdcall GetCaps(CAPS* caps, DWORD flags) = 0; // 16
virtual HRESULT __stdcall SetCaps(const CAPS* caps, DWORD flags) = 0; // 17
virtual HRESULT __stdcall SetSPCaps(const GUID* sp, const SP_CAPS* caps, DWORD flags) = 0; // 18
virtual HRESULT __stdcall GetSPCaps(const GUID* sp, SP_CAPS* caps, DWORD flags) = 0; // 19
virtual HRESULT __stdcall GetConnectionInfo(CONNECTION_INFO* info, DWORD flags) = 0; // 20
virtual HRESULT __stdcall RegisterLobby(DPNHANDLE handle, void* lobby, DWORD flags) = 0; // 21
};
struct IDirectPlay8Server : IUnknown {
virtual HRESULT __stdcall Initialize(void* ctx, PFNDPNMESSAGEHANDLER handler, DWORD flags) = 0; // 3
virtual HRESULT __stdcall EnumServiceProviders(const GUID* sp, const GUID* app, SERVICE_PROVIDER_INFO* buf,
DWORD* size, DWORD* count, DWORD flags) = 0; // 4
virtual HRESULT __stdcall CancelAsyncOperation(DPNHANDLE handle, DWORD flags) = 0; // 5
virtual HRESULT __stdcall GetSendQueueInfo(DPNID id, DWORD* msgs, DWORD* bytes, DWORD flags) = 0; // 6
virtual HRESULT __stdcall GetApplicationDesc(APPLICATION_DESC* buf, DWORD* size, DWORD flags) = 0; // 7
virtual HRESULT __stdcall SetServerInfo(const PLAYER_INFO* info, void* ctx, DPNHANDLE* handle, DWORD flags) = 0; // 8
virtual HRESULT __stdcall GetClientInfo(DPNID id, PLAYER_INFO* info, DWORD* size, DWORD flags) = 0; // 9
virtual HRESULT __stdcall GetClientAddress(DPNID id, IDirectPlay8Address** out, DWORD flags) = 0; // 10
virtual HRESULT __stdcall GetLocalHostAddresses(IDirectPlay8Address** out, DWORD* count, DWORD flags) = 0; // 11
virtual HRESULT __stdcall SetApplicationDesc(const APPLICATION_DESC* desc, DWORD flags) = 0; // 12
virtual HRESULT __stdcall Host(const APPLICATION_DESC* desc, IDirectPlay8Address** devices, DWORD count,
const void* security, const void* credentials, void* playerCtx, DWORD flags) = 0; // 13
virtual HRESULT __stdcall SendTo(DPNID id, const BUFFER_DESC* bufs, DWORD count, DWORD timeoutMs, void* ctx,
DPNHANDLE* handle, DWORD flags) = 0; // 14
virtual HRESULT __stdcall CreateGroup(const PLAYER_INFO* info, void* groupCtx, void* ctx, DPNHANDLE* handle,
DWORD flags) = 0; // 15
virtual HRESULT __stdcall DestroyGroup(DPNID group, void* ctx, DPNHANDLE* handle, DWORD flags) = 0; // 16
virtual HRESULT __stdcall AddPlayerToGroup(DPNID group, DPNID client, void* ctx, DPNHANDLE* handle, DWORD flags) = 0; // 17
virtual HRESULT __stdcall RemovePlayerFromGroup(DPNID group, DPNID client, void* ctx, DPNHANDLE* handle,
DWORD flags) = 0; // 18
virtual HRESULT __stdcall SetGroupInfo(DPNID group, PLAYER_INFO* info, void* ctx, DPNHANDLE* handle, DWORD flags) = 0; // 19
virtual HRESULT __stdcall GetGroupInfo(DPNID group, PLAYER_INFO* info, DWORD* size, DWORD flags) = 0; // 20
virtual HRESULT __stdcall EnumPlayersAndGroups(DPNID* ids, DWORD* count, DWORD flags) = 0; // 21
virtual HRESULT __stdcall EnumGroupMembers(DPNID group, DPNID* ids, DWORD* count, DWORD flags) = 0; // 22
virtual HRESULT __stdcall Close(DWORD flags) = 0; // 23
virtual HRESULT __stdcall DestroyClient(DPNID id, const void* data, DWORD size, DWORD flags) = 0; // 24
virtual HRESULT __stdcall ReturnBuffer(DPNHANDLE handle, DWORD flags) = 0; // 25
virtual HRESULT __stdcall GetPlayerContext(DPNID id, void** ctx, DWORD flags) = 0; // 26
virtual HRESULT __stdcall GetGroupContext(DPNID id, void** ctx, DWORD flags) = 0; // 27
virtual HRESULT __stdcall GetCaps(CAPS* caps, DWORD flags) = 0; // 28
virtual HRESULT __stdcall SetCaps(const CAPS* caps, DWORD flags) = 0; // 29
virtual HRESULT __stdcall SetSPCaps(const GUID* sp, const SP_CAPS* caps, DWORD flags) = 0; // 30
virtual HRESULT __stdcall GetSPCaps(const GUID* sp, SP_CAPS* caps, DWORD flags) = 0; // 31
virtual HRESULT __stdcall GetConnectionInfo(DPNID id, CONNECTION_INFO* info, DWORD flags) = 0; // 32
virtual HRESULT __stdcall RegisterLobby(DPNHANDLE handle, void* lobby, DWORD flags) = 0; // 33
};
} // namespace dp8