diff --git a/rostests/winetests/CMakeLists.txt b/rostests/winetests/CMakeLists.txt index 920b715b98a..a07aa0bd1f1 100644 --- a/rostests/winetests/CMakeLists.txt +++ b/rostests/winetests/CMakeLists.txt @@ -20,6 +20,7 @@ add_subdirectory(cryptnet) add_subdirectory(cryptui) add_subdirectory(dinput) add_subdirectory(dnsapi) +add_subdirectory(dplayx) add_subdirectory(dsound) add_subdirectory(faultrep) add_subdirectory(fusion) diff --git a/rostests/winetests/dplayx/CMakeLists.txt b/rostests/winetests/dplayx/CMakeLists.txt new file mode 100644 index 00000000000..c51fde57461 --- /dev/null +++ b/rostests/winetests/dplayx/CMakeLists.txt @@ -0,0 +1,5 @@ + +add_executable(dplayx_winetest dplayx.c testlist.c) +set_module_type(dplayx_winetest win32cui) +add_importlibs(dplayx_winetest dplayx ole32 msvcrt kernel32) +add_cd_file(TARGET dplayx_winetest DESTINATION reactos/bin FOR all) diff --git a/rostests/winetests/dplayx/dplayx.c b/rostests/winetests/dplayx/dplayx.c new file mode 100644 index 00000000000..17ab59d4031 --- /dev/null +++ b/rostests/winetests/dplayx/dplayx.c @@ -0,0 +1,6592 @@ +/* DirectPlay Conformance Tests + * + * Copyright 2007 - Alessandro Pignotti + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define COBJMACROS +#include "wine/test.h" +#include +#define INITGUID +#include +#include + + +#define check(expected, result) \ + ok( (expected) == (result), \ + "expected=%d got=%d\n", \ + (int)(expected), (int)(result) ); +#define checkLP(expected, result) \ + ok( (expected) == (result), \ + "expected=%p got=%p\n", \ + expected, result ); +#define checkHR(expected, result) \ + ok( (expected) == (result), \ + "expected=%s got=%s\n", \ + dpResult2str(expected), dpResult2str(result) ); +#define checkStr(expected, result) \ + ok( (result != NULL) && (!strcmp(expected, result)), \ + "expected=%s got=%s\n", \ + expected, result ); +#define checkFlags(expected, result, flags) \ + ok( (expected) == (result), \ + "expected=0x%08x(%s) got=0x%08x(%s)\n", \ + expected, dwFlags2str(expected, flags), \ + result, dwFlags2str(result, flags) ); +#define checkGuid(expected, result) \ + ok( IsEqualGUID(expected, result), \ + "expected=%s got=%s\n", \ + Guid2str(expected), Guid2str(result) ); +#define checkConv(expected, result, function) \ + ok( (expected) == (result), \ + "expected=0x%08x(%s) got=0x%08x(%s)\n", \ + expected, function(expected), \ + result, function(result) ); + + +DEFINE_GUID(appGuid, 0xbdcfe03e, 0xf0ec, 0x415b, 0x82, 0x11, 0x6f, 0x86, 0xd8, 0x19, 0x7f, 0xe1); +DEFINE_GUID(appGuid2, 0x93417d3f, 0x7d26, 0x46ba, 0xb5, 0x76, 0xfe, 0x4b, 0x20, 0xbb, 0xad, 0x70); +DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0); + + +typedef struct tagCallbackData +{ + IDirectPlay4 *pDP; + UINT dwCounter1, dwCounter2; + DWORD dwFlags; + char szTrace1[1024], szTrace2[1024]; + DPID *dpid; + UINT dpidSize; +} CallbackData, *lpCallbackData; + + +static LPSTR get_temp_buffer(void) +{ + static UINT index = 0; + static char buff[10][256]; + + index = (index + 1) % 10; + *buff[index] = 0; + + return buff[index]; +} + + +static LPCSTR Guid2str(const GUID *guid) +{ + LPSTR buffer = get_temp_buffer(); + + if (!guid) return "(null)"; + + /* Service providers */ + if (IsEqualGUID(guid, &DPSPGUID_IPX)) + return "DPSPGUID_IPX"; + if (IsEqualGUID(guid, &DPSPGUID_TCPIP)) + return "DPSPGUID_TCPIP"; + if (IsEqualGUID(guid, &DPSPGUID_SERIAL)) + return "DPSPGUID_SERIAL"; + if (IsEqualGUID(guid, &DPSPGUID_MODEM)) + return "DPSPGUID_MODEM"; + /* DirectPlay Address IDs */ + if (IsEqualGUID(guid, &DPAID_TotalSize)) + return "DPAID_TotalSize"; + if (IsEqualGUID(guid, &DPAID_ServiceProvider)) + return "DPAID_ServiceProvider"; + if (IsEqualGUID(guid, &DPAID_LobbyProvider)) + return "DPAID_LobbyProvider"; + if (IsEqualGUID(guid, &DPAID_Phone)) + return "DPAID_Phone"; + if (IsEqualGUID(guid, &DPAID_PhoneW)) + return "DPAID_PhoneW"; + if (IsEqualGUID(guid, &DPAID_Modem)) + return "DPAID_Modem"; + if (IsEqualGUID(guid, &DPAID_ModemW)) + return "DPAID_ModemW"; + if (IsEqualGUID(guid, &DPAID_INet)) + return "DPAID_INet"; + if (IsEqualGUID(guid, &DPAID_INetW)) + return "DPAID_INetW"; + if (IsEqualGUID(guid, &DPAID_INetPort)) + return "DPAID_INetPort"; + if (IsEqualGUID(guid, &DPAID_ComPort)) + return "DPAID_ComPort"; + + sprintf( buffer, "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", + guid->Data1, guid->Data2, guid->Data3, + guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3], + guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7] ); + return buffer; + +} + + +static LPCSTR dpResult2str(HRESULT hr) +{ + switch (hr) + { + case DP_OK: return "DP_OK"; + case DPERR_ALREADYINITIALIZED: return "DPERR_ALREADYINITIALIZED"; + case DPERR_ACCESSDENIED: return "DPERR_ACCESSDENIED"; + case DPERR_ACTIVEPLAYERS: return "DPERR_ACTIVEPLAYERS"; + case DPERR_BUFFERTOOSMALL: return "DPERR_BUFFERTOOSMALL"; + case DPERR_CANTADDPLAYER: return "DPERR_CANTADDPLAYER"; + case DPERR_CANTCREATEGROUP: return "DPERR_CANTCREATEGROUP"; + case DPERR_CANTCREATEPLAYER: return "DPERR_CANTCREATEPLAYER"; + case DPERR_CANTCREATESESSION: return "DPERR_CANTCREATESESSION"; + case DPERR_CAPSNOTAVAILABLEYET: return "DPERR_CAPSNOTAVAILABLEYET"; + case DPERR_EXCEPTION: return "DPERR_EXCEPTION"; + case DPERR_GENERIC: return "DPERR_GENERIC"; + case DPERR_INVALIDFLAGS: return "DPERR_INVALIDFLAGS"; + case DPERR_INVALIDOBJECT: return "DPERR_INVALIDOBJECT"; + case DPERR_INVALIDPARAMS: return "DPERR_INVALIDPARAMS"; + /* symbol with the same value: DPERR_INVALIDPARAM */ + case DPERR_INVALIDPLAYER: return "DPERR_INVALIDPLAYER"; + case DPERR_INVALIDGROUP: return "DPERR_INVALIDGROUP"; + case DPERR_NOCAPS: return "DPERR_NOCAPS"; + case DPERR_NOCONNECTION: return "DPERR_NOCONNECTION"; + case DPERR_NOMEMORY: return "DPERR_NOMEMORY"; + /* symbol with the same value: DPERR_OUTOFMEMORY */ + case DPERR_NOMESSAGES: return "DPERR_NOMESSAGES"; + case DPERR_NONAMESERVERFOUND: return "DPERR_NONAMESERVERFOUND"; + case DPERR_NOPLAYERS: return "DPERR_NOPLAYERS"; + case DPERR_NOSESSIONS: return "DPERR_NOSESSIONS"; + case DPERR_PENDING: return "DPERR_PENDING"; + case DPERR_SENDTOOBIG: return "DPERR_SENDTOOBIG"; + case DPERR_TIMEOUT: return "DPERR_TIMEOUT"; + case DPERR_UNAVAILABLE: return "DPERR_UNAVAILABLE"; + case DPERR_UNSUPPORTED: return "DPERR_UNSUPPORTED"; + case DPERR_BUSY: return "DPERR_BUSY"; + case DPERR_USERCANCEL: return "DPERR_USERCANCEL"; + case DPERR_NOINTERFACE: return "DPERR_NOINTERFACE"; + case DPERR_CANNOTCREATESERVER: return "DPERR_CANNOTCREATESERVER"; + case DPERR_PLAYERLOST: return "DPERR_PLAYERLOST"; + case DPERR_SESSIONLOST: return "DPERR_SESSIONLOST"; + case DPERR_UNINITIALIZED: return "DPERR_UNINITIALIZED"; + case DPERR_NONEWPLAYERS: return "DPERR_NONEWPLAYERS"; + case DPERR_INVALIDPASSWORD: return "DPERR_INVALIDPASSWORD"; + case DPERR_CONNECTING: return "DPERR_CONNECTING"; + case DPERR_CONNECTIONLOST: return "DPERR_CONNECTIONLOST"; + case DPERR_UNKNOWNMESSAGE: return "DPERR_UNKNOWNMESSAGE"; + case DPERR_CANCELFAILED: return "DPERR_CANCELFAILED"; + case DPERR_INVALIDPRIORITY: return "DPERR_INVALIDPRIORITY"; + case DPERR_NOTHANDLED: return "DPERR_NOTHANDLED"; + case DPERR_CANCELLED: return "DPERR_CANCELLED"; + case DPERR_ABORTED: return "DPERR_ABORTED"; + case DPERR_BUFFERTOOLARGE: return "DPERR_BUFFERTOOLARGE"; + case DPERR_CANTCREATEPROCESS: return "DPERR_CANTCREATEPROCESS"; + case DPERR_APPNOTSTARTED: return "DPERR_APPNOTSTARTED"; + case DPERR_INVALIDINTERFACE: return "DPERR_INVALIDINTERFACE"; + case DPERR_NOSERVICEPROVIDER: return "DPERR_NOSERVICEPROVIDER"; + case DPERR_UNKNOWNAPPLICATION: return "DPERR_UNKNOWNAPPLICATION"; + case DPERR_NOTLOBBIED: return "DPERR_NOTLOBBIED"; + case DPERR_SERVICEPROVIDERLOADED: return "DPERR_SERVICEPROVIDERLOADED"; + case DPERR_ALREADYREGISTERED: return "DPERR_ALREADYREGISTERED"; + case DPERR_NOTREGISTERED: return "DPERR_NOTREGISTERED"; + case DPERR_AUTHENTICATIONFAILED: return "DPERR_AUTHENTICATIONFAILED"; + case DPERR_CANTLOADSSPI: return "DPERR_CANTLOADSSPI"; + case DPERR_ENCRYPTIONFAILED: return "DPERR_ENCRYPTIONFAILED"; + case DPERR_SIGNFAILED: return "DPERR_SIGNFAILED"; + case DPERR_CANTLOADSECURITYPACKAGE: return "DPERR_CANTLOADSECURITYPACKAGE"; + case DPERR_ENCRYPTIONNOTSUPPORTED: return "DPERR_ENCRYPTIONNOTSUPPORTED"; + case DPERR_CANTLOADCAPI: return "DPERR_CANTLOADCAPI"; + case DPERR_NOTLOGGEDIN: return "DPERR_NOTLOGGEDIN"; + case DPERR_LOGONDENIED: return "DPERR_LOGONDENIED"; + case CLASS_E_NOAGGREGATION: return "CLASS_E_NOAGGREGATION"; + + default: + { + LPSTR buffer = get_temp_buffer(); + sprintf( buffer, "%d", HRESULT_CODE(hr) ); + return buffer; + } + } +} + +static LPCSTR dpMsgType2str(DWORD dwType) +{ + switch(dwType) + { + case DPSYS_CREATEPLAYERORGROUP: return "DPSYS_CREATEPLAYERORGROUP"; + case DPSYS_DESTROYPLAYERORGROUP: return "DPSYS_DESTROYPLAYERORGROUP"; + case DPSYS_ADDPLAYERTOGROUP: return "DPSYS_ADDPLAYERTOGROUP"; + case DPSYS_DELETEPLAYERFROMGROUP: return "DPSYS_DELETEPLAYERFROMGROUP"; + case DPSYS_SESSIONLOST: return "DPSYS_SESSIONLOST"; + case DPSYS_HOST: return "DPSYS_HOST"; + case DPSYS_SETPLAYERORGROUPDATA: return "DPSYS_SETPLAYERORGROUPDATA"; + case DPSYS_SETPLAYERORGROUPNAME: return "DPSYS_SETPLAYERORGROUPNAME"; + case DPSYS_SETSESSIONDESC: return "DPSYS_SETSESSIONDESC"; + case DPSYS_ADDGROUPTOGROUP: return "DPSYS_ADDGROUPTOGROUP"; + case DPSYS_DELETEGROUPFROMGROUP: return "DPSYS_DELETEGROUPFROMGROUP"; + case DPSYS_SECUREMESSAGE: return "DPSYS_SECUREMESSAGE"; + case DPSYS_STARTSESSION: return "DPSYS_STARTSESSION"; + case DPSYS_CHAT: return "DPSYS_DPSYS_CHAT"; + case DPSYS_SETGROUPOWNER: return "DPSYS_SETGROUPOWNER"; + case DPSYS_SENDCOMPLETE: return "DPSYS_SENDCOMPLETE"; + + default: return "UNKNOWN"; + } +} + +static LPCSTR dwFlags2str(DWORD dwFlags, DWORD flagType) +{ + +#define FLAGS_DPCONNECTION (1<<0) +#define FLAGS_DPENUMPLAYERS (1<<1) +#define FLAGS_DPENUMGROUPS (1<<2) +#define FLAGS_DPPLAYER (1<<3) +#define FLAGS_DPGROUP (1<<4) +#define FLAGS_DPENUMSESSIONS (1<<5) +#define FLAGS_DPGETCAPS (1<<6) +#define FLAGS_DPGET (1<<7) +#define FLAGS_DPRECEIVE (1<<8) +#define FLAGS_DPSEND (1<<9) +#define FLAGS_DPSET (1<<10) +#define FLAGS_DPMESSAGEQUEUE (1<<11) +#define FLAGS_DPCONNECT (1<<12) +#define FLAGS_DPOPEN (1<<13) +#define FLAGS_DPSESSION (1<<14) +#define FLAGS_DPLCONNECTION (1<<15) +#define FLAGS_DPESC (1<<16) +#define FLAGS_DPCAPS (1<<17) + + LPSTR flags = get_temp_buffer(); + + /* EnumConnections */ + + if (flagType & FLAGS_DPCONNECTION) + { + if (dwFlags & DPCONNECTION_DIRECTPLAY) + strcat(flags, "DPCONNECTION_DIRECTPLAY,"); + if (dwFlags & DPCONNECTION_DIRECTPLAYLOBBY) + strcat(flags, "DPCONNECTION_DIRECTPLAYLOBBY,"); + } + + /* EnumPlayers, + EnumGroups */ + + if (flagType & FLAGS_DPENUMPLAYERS) + { + if (dwFlags == DPENUMPLAYERS_ALL) + strcat(flags, "DPENUMPLAYERS_ALL,"); + if (dwFlags & DPENUMPLAYERS_LOCAL) + strcat(flags, "DPENUMPLAYERS_LOCAL,"); + if (dwFlags & DPENUMPLAYERS_REMOTE) + strcat(flags, "DPENUMPLAYERS_REMOTE,"); + if (dwFlags & DPENUMPLAYERS_GROUP) + strcat(flags, "DPENUMPLAYERS_GROUP,"); + if (dwFlags & DPENUMPLAYERS_SESSION) + strcat(flags, "DPENUMPLAYERS_SESSION,"); + if (dwFlags & DPENUMPLAYERS_SERVERPLAYER) + strcat(flags, "DPENUMPLAYERS_SERVERPLAYER,"); + if (dwFlags & DPENUMPLAYERS_SPECTATOR) + strcat(flags, "DPENUMPLAYERS_SPECTATOR,"); + if (dwFlags & DPENUMPLAYERS_OWNER) + strcat(flags, "DPENUMPLAYERS_OWNER,"); + } + if (flagType & FLAGS_DPENUMGROUPS) + { + if (dwFlags == DPENUMGROUPS_ALL) + strcat(flags, "DPENUMGROUPS_ALL,"); + if (dwFlags & DPENUMPLAYERS_LOCAL) + strcat(flags, "DPENUMGROUPS_LOCAL,"); + if (dwFlags & DPENUMPLAYERS_REMOTE) + strcat(flags, "DPENUMGROUPS_REMOTE,"); + if (dwFlags & DPENUMPLAYERS_GROUP) + strcat(flags, "DPENUMGROUPS_GROUP,"); + if (dwFlags & DPENUMPLAYERS_SESSION) + strcat(flags, "DPENUMGROUPS_SESSION,"); + if (dwFlags & DPENUMGROUPS_SHORTCUT) + strcat(flags, "DPENUMGROUPS_SHORTCUT,"); + if (dwFlags & DPENUMGROUPS_STAGINGAREA) + strcat(flags, "DPENUMGROUPS_STAGINGAREA,"); + if (dwFlags & DPENUMGROUPS_HIDDEN) + strcat(flags, "DPENUMGROUPS_HIDDEN,"); + } + + /* CreatePlayer */ + + if (flagType & FLAGS_DPPLAYER) + { + if (dwFlags & DPPLAYER_SERVERPLAYER) + strcat(flags, "DPPLAYER_SERVERPLAYER,"); + if (dwFlags & DPPLAYER_SPECTATOR) + strcat(flags, "DPPLAYER_SPECTATOR,"); + if (dwFlags & DPPLAYER_LOCAL) + strcat(flags, "DPPLAYER_LOCAL,"); + if (dwFlags & DPPLAYER_OWNER) + strcat(flags, "DPPLAYER_OWNER,"); + } + + /* CreateGroup */ + + if (flagType & FLAGS_DPGROUP) + { + if (dwFlags & DPGROUP_STAGINGAREA) + strcat(flags, "DPGROUP_STAGINGAREA,"); + if (dwFlags & DPGROUP_LOCAL) + strcat(flags, "DPGROUP_LOCAL,"); + if (dwFlags & DPGROUP_HIDDEN) + strcat(flags, "DPGROUP_HIDDEN,"); + } + + /* EnumSessions */ + + if (flagType & FLAGS_DPENUMSESSIONS) + { + if (dwFlags & DPENUMSESSIONS_AVAILABLE) + strcat(flags, "DPENUMSESSIONS_AVAILABLE,"); + if (dwFlags & DPENUMSESSIONS_ALL) + strcat(flags, "DPENUMSESSIONS_ALL,"); + if (dwFlags & DPENUMSESSIONS_ASYNC) + strcat(flags, "DPENUMSESSIONS_ASYNC,"); + if (dwFlags & DPENUMSESSIONS_STOPASYNC) + strcat(flags, "DPENUMSESSIONS_STOPASYNC,"); + if (dwFlags & DPENUMSESSIONS_PASSWORDREQUIRED) + strcat(flags, "DPENUMSESSIONS_PASSWORDREQUIRED,"); + if (dwFlags & DPENUMSESSIONS_RETURNSTATUS) + strcat(flags, "DPENUMSESSIONS_RETURNSTATUS,"); + } + + /* GetCaps, + GetPlayerCaps */ + + if (flagType & FLAGS_DPGETCAPS) + { + if (dwFlags & DPGETCAPS_GUARANTEED) + strcat(flags, "DPGETCAPS_GUARANTEED,"); + } + + /* GetGroupData, + GetPlayerData */ + + if (flagType & FLAGS_DPGET) + { + if (dwFlags == DPGET_REMOTE) + strcat(flags, "DPGET_REMOTE,"); + if (dwFlags & DPGET_LOCAL) + strcat(flags, "DPGET_LOCAL,"); + } + + /* Receive */ + + if (flagType & FLAGS_DPRECEIVE) + { + if (dwFlags & DPRECEIVE_ALL) + strcat(flags, "DPRECEIVE_ALL,"); + if (dwFlags & DPRECEIVE_TOPLAYER) + strcat(flags, "DPRECEIVE_TOPLAYER,"); + if (dwFlags & DPRECEIVE_FROMPLAYER) + strcat(flags, "DPRECEIVE_FROMPLAYER,"); + if (dwFlags & DPRECEIVE_PEEK) + strcat(flags, "DPRECEIVE_PEEK,"); + } + + /* Send */ + + if (flagType & FLAGS_DPSEND) + { + /*if (dwFlags == DPSEND_NONGUARANTEED) + strcat(flags, "DPSEND_NONGUARANTEED,");*/ + if (dwFlags == DPSEND_MAX_PRIORITY) /* = DPSEND_MAX_PRI */ + { + strcat(flags, "DPSEND_MAX_PRIORITY,"); + } + else + { + if (dwFlags & DPSEND_GUARANTEED) + strcat(flags, "DPSEND_GUARANTEED,"); + if (dwFlags & DPSEND_HIGHPRIORITY) + strcat(flags, "DPSEND_HIGHPRIORITY,"); + if (dwFlags & DPSEND_OPENSTREAM) + strcat(flags, "DPSEND_OPENSTREAM,"); + if (dwFlags & DPSEND_CLOSESTREAM) + strcat(flags, "DPSEND_CLOSESTREAM,"); + if (dwFlags & DPSEND_SIGNED) + strcat(flags, "DPSEND_SIGNED,"); + if (dwFlags & DPSEND_ENCRYPTED) + strcat(flags, "DPSEND_ENCRYPTED,"); + if (dwFlags & DPSEND_LOBBYSYSTEMMESSAGE) + strcat(flags, "DPSEND_LOBBYSYSTEMMESSAGE,"); + if (dwFlags & DPSEND_ASYNC) + strcat(flags, "DPSEND_ASYNC,"); + if (dwFlags & DPSEND_NOSENDCOMPLETEMSG) + strcat(flags, "DPSEND_NOSENDCOMPLETEMSG,"); + } + } + + /* SetGroupData, + SetGroupName, + SetPlayerData, + SetPlayerName, + SetSessionDesc */ + + if (flagType & FLAGS_DPSET) + { + if (dwFlags == DPSET_REMOTE) + strcat(flags, "DPSET_REMOTE,"); + if (dwFlags & DPSET_LOCAL) + strcat(flags, "DPSET_LOCAL,"); + if (dwFlags & DPSET_GUARANTEED) + strcat(flags, "DPSET_GUARANTEED,"); + } + + /* GetMessageQueue */ + + if (flagType & FLAGS_DPMESSAGEQUEUE) + { + if (dwFlags & DPMESSAGEQUEUE_SEND) + strcat(flags, "DPMESSAGEQUEUE_SEND,"); + if (dwFlags & DPMESSAGEQUEUE_RECEIVE) + strcat(flags, "DPMESSAGEQUEUE_RECEIVE,"); + } + + /* Connect */ + + if (flagType & FLAGS_DPCONNECT) + { + if (dwFlags & DPCONNECT_RETURNSTATUS) + strcat(flags, "DPCONNECT_RETURNSTATUS,"); + } + + /* Open */ + + if (flagType & FLAGS_DPOPEN) + { + if (dwFlags & DPOPEN_JOIN) + strcat(flags, "DPOPEN_JOIN,"); + if (dwFlags & DPOPEN_CREATE) + strcat(flags, "DPOPEN_CREATE,"); + if (dwFlags & DPOPEN_RETURNSTATUS) + strcat(flags, "DPOPEN_RETURNSTATUS,"); + } + + /* DPSESSIONDESC2 */ + + if (flagType & FLAGS_DPSESSION) + { + if (dwFlags & DPSESSION_NEWPLAYERSDISABLED) + strcat(flags, "DPSESSION_NEWPLAYERSDISABLED,"); + if (dwFlags & DPSESSION_MIGRATEHOST) + strcat(flags, "DPSESSION_MIGRATEHOST,"); + if (dwFlags & DPSESSION_NOMESSAGEID) + strcat(flags, "DPSESSION_NOMESSAGEID,"); + if (dwFlags & DPSESSION_JOINDISABLED) + strcat(flags, "DPSESSION_JOINDISABLED,"); + if (dwFlags & DPSESSION_KEEPALIVE) + strcat(flags, "DPSESSION_KEEPALIVE,"); + if (dwFlags & DPSESSION_NODATAMESSAGES) + strcat(flags, "DPSESSION_NODATAMESSAGES,"); + if (dwFlags & DPSESSION_SECURESERVER) + strcat(flags, "DPSESSION_SECURESERVER,"); + if (dwFlags & DPSESSION_PRIVATE) + strcat(flags, "DPSESSION_PRIVATE,"); + if (dwFlags & DPSESSION_PASSWORDREQUIRED) + strcat(flags, "DPSESSION_PASSWORDREQUIRED,"); + if (dwFlags & DPSESSION_MULTICASTSERVER) + strcat(flags, "DPSESSION_MULTICASTSERVER,"); + if (dwFlags & DPSESSION_CLIENTSERVER) + strcat(flags, "DPSESSION_CLIENTSERVER,"); + + if (dwFlags & DPSESSION_DIRECTPLAYPROTOCOL) + strcat(flags, "DPSESSION_DIRECTPLAYPROTOCOL,"); + if (dwFlags & DPSESSION_NOPRESERVEORDER) + strcat(flags, "DPSESSION_NOPRESERVEORDER,"); + if (dwFlags & DPSESSION_OPTIMIZELATENCY) + strcat(flags, "DPSESSION_OPTIMIZELATENCY,"); + + } + + /* DPLCONNECTION */ + + if (flagType & FLAGS_DPLCONNECTION) + { + if (dwFlags & DPLCONNECTION_CREATESESSION) + strcat(flags, "DPLCONNECTION_CREATESESSION,"); + if (dwFlags & DPLCONNECTION_JOINSESSION) + strcat(flags, "DPLCONNECTION_JOINSESSION,"); + } + + /* EnumSessionsCallback2 */ + + if (flagType & FLAGS_DPESC) + { + if (dwFlags & DPESC_TIMEDOUT) + strcat(flags, "DPESC_TIMEDOUT,"); + } + + /* GetCaps, + GetPlayerCaps */ + + if (flagType & FLAGS_DPCAPS) + { + if (dwFlags & DPCAPS_ISHOST) + strcat(flags, "DPCAPS_ISHOST,"); + if (dwFlags & DPCAPS_GROUPOPTIMIZED) + strcat(flags, "DPCAPS_GROUPOPTIMIZED,"); + if (dwFlags & DPCAPS_KEEPALIVEOPTIMIZED) + strcat(flags, "DPCAPS_KEEPALIVEOPTIMIZED,"); + if (dwFlags & DPCAPS_GUARANTEEDOPTIMIZED) + strcat(flags, "DPCAPS_GUARANTEEDOPTIMIZED,"); + if (dwFlags & DPCAPS_GUARANTEEDSUPPORTED) + strcat(flags, "DPCAPS_GUARANTEEDSUPPORTED,"); + if (dwFlags & DPCAPS_SIGNINGSUPPORTED) + strcat(flags, "DPCAPS_SIGNINGSUPPORTED,"); + if (dwFlags & DPCAPS_ENCRYPTIONSUPPORTED) + strcat(flags, "DPCAPS_ENCRYPTIONSUPPORTED,"); + if (dwFlags & DPCAPS_ASYNCCANCELSUPPORTED) + strcat(flags, "DPCAPS_ASYNCCANCELSUPPORTED,"); + if (dwFlags & DPCAPS_ASYNCCANCELALLSUPPORTED) + strcat(flags, "DPCAPS_ASYNCCANCELALLSUPPORTED,"); + if (dwFlags & DPCAPS_SENDTIMEOUTSUPPORTED) + strcat(flags, "DPCAPS_SENDTIMEOUTSUPPORTED,"); + if (dwFlags & DPCAPS_SENDPRIORITYSUPPORTED) + strcat(flags, "DPCAPS_SENDPRIORITYSUPPORTED,"); + if (dwFlags & DPCAPS_ASYNCSUPPORTED) + strcat(flags, "DPCAPS_ASYNCSUPPORTED,"); + + if (dwFlags & DPPLAYERCAPS_LOCAL) + strcat(flags, "DPPLAYERCAPS_LOCAL,"); + } + + if ((strlen(flags) == 0) && (dwFlags != 0)) + strcpy(flags, "UNKNOWN"); + else + flags[strlen(flags)-1] = '\0'; + + return flags; +} + +static char dpid2char(DPID* dpid, DWORD dpidSize, DPID idPlayer) +{ + UINT i; + if ( idPlayer == DPID_SYSMSG ) + return 'S'; + for (i=0; idwCounter1: Number of messages received. + * callbackData->szTrace1: Traces for sender and receiver. + * We store the position a dpid holds in the dpid array. + * Example: + * + * trace string: "01,02,03,14" + * expanded: [ '01', '02', '03', '14' ] + * \ \ \ \ + * \ \ \ ) message 3: from 1 to 4 + * \ \ ) message 2: from 0 to 3 + * \ ) message 1: from 0 to 2 + * ) message 0: from 0 to 1 + * + * In general terms: + * sender of message i = character in place 3*i of the array + * receiver of message i = character in place 3*i+1 of the array + * + * A sender value of 'S' means DPID_SYSMSG, this is, a system message. + * + * callbackData->szTrace2: Traces for message sizes. + */ + + DPID idFrom, idTo; + UINT i; + DWORD dwDataSize = 1024; + LPVOID lpData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize ); + HRESULT hr; + char temp[5]; + + callbackData->szTrace2[0] = '\0'; + + i = 0; + while ( DP_OK == (hr = IDirectPlayX_Receive( pDP, &idFrom, &idTo, 0, + lpData, &dwDataSize )) ) + { + + callbackData->szTrace1[ 3*i ] = dpid2char( dpid, dpidSize, idFrom ); + callbackData->szTrace1[ 3*i+1 ] = dpid2char( dpid, dpidSize, idTo ); + callbackData->szTrace1[ 3*i+2 ] = ','; + + sprintf( temp, "%d,", dwDataSize ); + strcat( callbackData->szTrace2, temp ); + + dwDataSize = 1024; + ++i; + } + + checkHR( DPERR_NOMESSAGES, hr ); + + callbackData->szTrace1[ 3*i ] = '\0'; + callbackData->dwCounter1 = i; + + + HeapFree( GetProcessHeap(), 0, lpData ); +} + +static void init_TCPIP_provider( IDirectPlay4 *pDP, LPCSTR strIPAddressString, WORD port ) +{ + + DPCOMPOUNDADDRESSELEMENT addressElements[3]; + LPVOID pAddress = NULL; + DWORD dwAddressSize = 0; + IDirectPlayLobby3 *pDPL; + HRESULT hr; + + hr = CoCreateInstance( &CLSID_DirectPlayLobby, NULL, CLSCTX_ALL, + &IID_IDirectPlayLobby3A, (LPVOID*) &pDPL ); + ok (SUCCEEDED (hr), "CCI of CLSID_DirectPlayLobby / IID_IDirectPlayLobby3A failed\n"); + if (FAILED (hr)) return; + + /* Service provider */ + addressElements[0].guidDataType = DPAID_ServiceProvider; + addressElements[0].dwDataSize = sizeof(GUID); + addressElements[0].lpData = (LPVOID) &DPSPGUID_TCPIP; + + /* IP address string */ + addressElements[1].guidDataType = DPAID_INet; + addressElements[1].dwDataSize = lstrlen(strIPAddressString) + 1; + addressElements[1].lpData = (LPVOID) strIPAddressString; + + /* Optional Port number */ + if( port > 0 ) + { + addressElements[2].guidDataType = DPAID_INetPort; + addressElements[2].dwDataSize = sizeof(WORD); + addressElements[2].lpData = &port; + } + + + hr = IDirectPlayLobby_CreateCompoundAddress( pDPL, addressElements, 2, + NULL, &dwAddressSize ); + checkHR( DPERR_BUFFERTOOSMALL, hr ); + + if( hr == DPERR_BUFFERTOOSMALL ) + { + pAddress = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwAddressSize ); + hr = IDirectPlayLobby_CreateCompoundAddress( pDPL, addressElements, 2, + pAddress, &dwAddressSize ); + checkHR( DP_OK, hr ); + } + + hr = IDirectPlayX_InitializeConnection( pDP, pAddress, 0 ); + todo_wine checkHR( DP_OK, hr ); + + HeapFree( GetProcessHeap(), 0, pAddress ); + +} + +static BOOL CALLBACK EnumSessions_cb_join( LPCDPSESSIONDESC2 lpThisSD, + LPDWORD lpdwTimeOut, + DWORD dwFlags, + LPVOID lpContext ) +{ + IDirectPlay4 *pDP = lpContext; + DPSESSIONDESC2 dpsd; + HRESULT hr; + + if (dwFlags & DPESC_TIMEDOUT) + { + return FALSE; + } + + ZeroMemory( &dpsd, sizeof(DPSESSIONDESC2) ); + dpsd.dwSize = sizeof(DPSESSIONDESC2); + dpsd.guidApplication = appGuid; + dpsd.guidInstance = lpThisSD->guidInstance; + + hr = IDirectPlayX_Open( pDP, &dpsd, DPOPEN_JOIN ); + checkHR( DP_OK, hr ); + + return TRUE; +} + + +/* DirectPlayCreate */ + +static void test_DirectPlayCreate(void) +{ + + IDirectPlay *pDP; + HRESULT hr; + + /* TODO: Check how it behaves with pUnk!=NULL */ + + /* pDP==NULL */ + hr = DirectPlayCreate( NULL, NULL, NULL ); + checkHR( DPERR_INVALIDPARAMS, hr ); + hr = DirectPlayCreate( (LPGUID) &GUID_NULL, NULL, NULL ); + checkHR( DPERR_INVALIDPARAMS, hr ); + hr = DirectPlayCreate( (LPGUID) &DPSPGUID_TCPIP, NULL, NULL ); + checkHR( DPERR_INVALIDPARAMS, hr ); + + /* pUnk==NULL, pDP!=NULL */ + hr = DirectPlayCreate( NULL, &pDP, NULL ); + checkHR( DPERR_INVALIDPARAMS, hr ); + hr = DirectPlayCreate( (LPGUID) &GUID_NULL, &pDP, NULL ); + checkHR( DP_OK, hr ); + if ( hr == DP_OK ) + IDirectPlayX_Release( pDP ); + hr = DirectPlayCreate( (LPGUID) &DPSPGUID_TCPIP, &pDP, NULL ); + todo_wine checkHR( DP_OK, hr ); + if ( hr == DP_OK ) + IDirectPlayX_Release( pDP ); + +} + +/* EnumConnections */ + +static BOOL CALLBACK EnumAddress_cb2( REFGUID guidDataType, + DWORD dwDataSize, + LPCVOID lpData, + LPVOID lpContext ) +{ + lpCallbackData callbackData = lpContext; + + static REFGUID types[] = { &DPAID_TotalSize, + &DPAID_ServiceProvider, + &GUID_NULL }; + static DWORD sizes[] = { 4, 16, 0 }; + static REFGUID sps[] = { &DPSPGUID_SERIAL, &DPSPGUID_MODEM, + &DPSPGUID_IPX, &DPSPGUID_TCPIP }; + + + checkGuid( types[ callbackData->dwCounter2 ], guidDataType ); + check( sizes[ callbackData->dwCounter2 ], dwDataSize ); + + if ( IsEqualGUID( types[0], guidDataType ) ) + { + todo_wine check( 80, *((LPDWORD) lpData) ); + } + else if ( IsEqualGUID( types[1], guidDataType ) ) + { + todo_wine checkGuid( sps[ callbackData->dwCounter1 ], lpData ); + } + + callbackData->dwCounter2++; + + return TRUE; +} + +static BOOL CALLBACK EnumConnections_cb( LPCGUID lpguidSP, + LPVOID lpConnection, + DWORD dwConnectionSize, + LPCDPNAME lpName, + DWORD dwFlags, + LPVOID lpContext ) +{ + + lpCallbackData callbackData = lpContext; + IDirectPlayLobby *pDPL; + HRESULT hr; + + + if (!callbackData->dwFlags) + { + callbackData->dwFlags = DPCONNECTION_DIRECTPLAY; + } + + checkFlags( callbackData->dwFlags, dwFlags, FLAGS_DPCONNECTION ); + + /* Get info from lpConnection */ + hr = CoCreateInstance( &CLSID_DirectPlayLobby, NULL, CLSCTX_ALL, + &IID_IDirectPlayLobby3A, (LPVOID*) &pDPL ); + ok( SUCCEEDED(hr), "CCI of CLSID_DirectPlayLobby / IID_IDirectPlayLobby3A failed\n"); + if (FAILED(hr)) + return FALSE; + + callbackData->dwCounter2 = 0; + IDirectPlayLobby_EnumAddress( pDPL, EnumAddress_cb2, lpConnection, + dwConnectionSize, callbackData ); + todo_wine check( 3, callbackData->dwCounter2 ); + + callbackData->dwCounter1++; + + return TRUE; +} + +static void test_EnumConnections(void) +{ + + IDirectPlay4 *pDP; + CallbackData callbackData; + HRESULT hr; + + + hr = CoCreateInstance( &CLSID_DirectPlay, NULL, CLSCTX_ALL, + &IID_IDirectPlay4A, (LPVOID*) &pDP ); + + ok (SUCCEEDED(hr), "CCI of CLSID_DirectPlay / IID_IDirectPlay4A failed\n"); + if (FAILED(hr)) return; + + callbackData.dwCounter1 = 0; + callbackData.dwFlags = 0; + hr = IDirectPlayX_EnumConnections( pDP, &appGuid, EnumConnections_cb, + &callbackData, callbackData.dwFlags ); + checkHR( DP_OK, hr ); + check( 4, callbackData.dwCounter1 ); + + callbackData.dwCounter1 = 0; + callbackData.dwFlags = 0; + hr = IDirectPlayX_EnumConnections( pDP, NULL, EnumConnections_cb, + &callbackData, callbackData.dwFlags ); + checkHR( DP_OK, hr ); + check( 4, callbackData.dwCounter1 ); + + callbackData.dwCounter1 = 0; + callbackData.dwFlags = 0; + hr = IDirectPlayX_EnumConnections( pDP, &appGuid, NULL, + &callbackData, callbackData.dwFlags ); + checkHR( DPERR_INVALIDPARAMS, hr ); + check( 0, callbackData.dwCounter1 ); + + + /* Flag tests */ + callbackData.dwCounter1 = 0; + callbackData.dwFlags = DPCONNECTION_DIRECTPLAY; + hr = IDirectPlayX_EnumConnections( pDP, &appGuid, EnumConnections_cb, + &callbackData, callbackData.dwFlags ); + checkHR( DP_OK, hr ); + check( 4, callbackData.dwCounter1 ); + + callbackData.dwCounter1 = 0; + callbackData.dwFlags = DPCONNECTION_DIRECTPLAYLOBBY; + hr = IDirectPlayX_EnumConnections( pDP, &appGuid, EnumConnections_cb, + &callbackData, callbackData.dwFlags ); + checkHR( DP_OK, hr ); + check( 0, callbackData.dwCounter1 ); + + callbackData.dwCounter1 = 0; + callbackData.dwFlags = ( DPCONNECTION_DIRECTPLAY | + DPCONNECTION_DIRECTPLAYLOBBY ); + hr = IDirectPlayX_EnumConnections( pDP, &appGuid, EnumConnections_cb, + &callbackData, callbackData.dwFlags ); + checkHR( DP_OK, hr ); + check( 4, callbackData.dwCounter1 ); + + callbackData.dwCounter1 = 0; + callbackData.dwFlags = ~( DPCONNECTION_DIRECTPLAY | + DPCONNECTION_DIRECTPLAYLOBBY ); + hr = IDirectPlayX_EnumConnections( pDP, &appGuid, EnumConnections_cb, + &callbackData, callbackData.dwFlags ); + checkHR( DPERR_INVALIDFLAGS, hr ); + check( 0, callbackData.dwCounter1 ); + + + IDirectPlayX_Release( pDP ); +} + +/* InitializeConnection */ + +static BOOL CALLBACK EnumConnections_cb2( LPCGUID lpguidSP, + LPVOID lpConnection, + DWORD dwConnectionSize, + LPCDPNAME lpName, + DWORD dwFlags, + LPVOID lpContext ) +{ + IDirectPlay4 *pDP = lpContext; + HRESULT hr; + + /* Incorrect parameters */ + hr = IDirectPlayX_InitializeConnection( pDP, NULL, 1 ); + checkHR( DPERR_INVALIDPARAMS, hr ); + hr = IDirectPlayX_InitializeConnection( pDP, lpConnection, 1 ); + checkHR( DPERR_INVALIDFLAGS, hr ); + + /* Normal operation. + We're only interested in ensuring that the TCP/IP provider works */ + + if( IsEqualGUID(lpguidSP, &DPSPGUID_TCPIP) ) + { + hr = IDirectPlayX_InitializeConnection( pDP, lpConnection, 0 ); + todo_wine checkHR( DP_OK, hr ); + hr = IDirectPlayX_InitializeConnection( pDP, lpConnection, 0 ); + todo_wine checkHR( DPERR_ALREADYINITIALIZED, hr ); + } + + return TRUE; +} + +static void test_InitializeConnection(void) +{ + + IDirectPlay4 *pDP; + HRESULT hr; + + hr = CoCreateInstance( &CLSID_DirectPlay, NULL, CLSCTX_ALL, + &IID_IDirectPlay4A, (LPVOID*) &pDP ); + + ok (SUCCEEDED(hr), "CCI of CLSID_DirectPlay / IID_IDirectPlay4A failed\n"); + if (FAILED(hr)) return; + + IDirectPlayX_EnumConnections( pDP, &appGuid, EnumConnections_cb2, pDP, 0 ); + + IDirectPlayX_Release( pDP ); +} + +/* GetCaps */ + +static void test_GetCaps(void) +{ + + IDirectPlay4 *pDP; + DPCAPS dpcaps; + DWORD dwFlags; + HRESULT hr; + + + hr = CoCreateInstance( &CLSID_DirectPlay, NULL, CLSCTX_ALL, + &IID_IDirectPlay4A, (LPVOID*) &pDP ); + ok (SUCCEEDED(hr), "CCI of CLSID_DirectPlay / IID_IDirectPlay4A failed\n"); + if (FAILED(hr)) return; + + ZeroMemory( &dpcaps, sizeof(DPCAPS) ); + + /* Service provider not ininitialized */ + hr = IDirectPlayX_GetCaps( pDP, &dpcaps, 0 ); + checkHR( DPERR_UNINITIALIZED, hr ); + + init_TCPIP_provider( pDP, "127.0.0.1", 0 ); + + /* dpcaps not ininitialized */ + hr = IDirectPlayX_GetCaps( pDP, &dpcaps, 0 ); + todo_wine checkHR( DPERR_INVALIDPARAMS, hr ); + + dpcaps.dwSize = sizeof(DPCAPS); + + for (dwFlags=0; + dwFlags<=DPGETCAPS_GUARANTEED; + dwFlags+=DPGETCAPS_GUARANTEED) + { + + hr = IDirectPlayX_GetCaps( pDP, &dpcaps, dwFlags ); + todo_wine checkHR( DP_OK, hr ); + + + if ( hr == DP_OK ) + { + check( sizeof(DPCAPS), dpcaps.dwSize ); + check( DPCAPS_ASYNCSUPPORTED | + DPCAPS_GUARANTEEDOPTIMIZED | + DPCAPS_GUARANTEEDSUPPORTED, + dpcaps.dwFlags ); + check( 0, dpcaps.dwMaxQueueSize ); + check( 0, dpcaps.dwHundredBaud ); + check( 500, dpcaps.dwLatency ); + check( 65536, dpcaps.dwMaxLocalPlayers ); + check( 20, dpcaps.dwHeaderLength ); + check( 5000, dpcaps.dwTimeout ); + + switch (dwFlags) + { + case 0: + check( 65479, dpcaps.dwMaxBufferSize ); + check( 65536, dpcaps.dwMaxPlayers ); + break; + case DPGETCAPS_GUARANTEED: + check( 1048547, dpcaps.dwMaxBufferSize ); + check( 64, dpcaps.dwMaxPlayers ); + break; + default: break; + } + } + } + + IDirectPlayX_Release( pDP ); +} + +/* Open */ + +static BOOL CALLBACK EnumSessions_cb2( LPCDPSESSIONDESC2 lpThisSD, + LPDWORD lpdwTimeOut, + DWORD dwFlags, + LPVOID lpContext ) +{ + IDirectPlay4 *pDP = lpContext; + DPSESSIONDESC2 dpsd; + HRESULT hr; + + if (dwFlags & DPESC_TIMEDOUT) + return FALSE; + + + ZeroMemory( &dpsd, sizeof(DPSESSIONDESC2) ); + dpsd.dwSize = sizeof(DPSESSIONDESC2); + dpsd.guidApplication = appGuid; + dpsd.guidInstance = lpThisSD->guidInstance; + + if ( lpThisSD->dwFlags & DPSESSION_PASSWORDREQUIRED ) + { + /* Incorrect password */ + U2(dpsd).lpszPasswordA = (LPSTR) "sonic boom"; + hr = IDirectPlayX_Open( pDP, &dpsd, DPOPEN_JOIN ); + checkHR( DPERR_INVALIDPASSWORD, hr ); + + /* Correct password */ + U2(dpsd).lpszPasswordA = (LPSTR) "hadouken"; + hr = IDirectPlayX_Open( pDP, &dpsd, DPOPEN_JOIN ); + checkHR( DP_OK, hr ); + } + else + { + hr = IDirectPlayX_Open( pDP, &dpsd, DPOPEN_JOIN ); + checkHR( DP_OK, hr ); + } + + hr = IDirectPlayX_Close( pDP ); + checkHR( DP_OK, hr ); + + return TRUE; +} + +static void test_Open(void) +{ + + IDirectPlay4 *pDP, *pDP_server; + DPSESSIONDESC2 dpsd, dpsd_server; + HRESULT hr; + + + hr = CoCreateInstance( &CLSID_DirectPlay, NULL, CLSCTX_ALL, + &IID_IDirectPlay4A, (LPVOID*) &pDP_server ); + ok( SUCCEEDED(hr), "CCI of CLSID_DirectPlay / IID_IDirectPlay4A failed\n" ); + if (FAILED(hr)) return; + + hr = CoCreateInstance( &CLSID_DirectPlay, NULL, CLSCTX_ALL, + &IID_IDirectPlay4A, (LPVOID*) &pDP ); + ok( SUCCEEDED(hr), "CCI of CLSID_DirectPlay / IID_IDirectPlay4A failed\n" ); + if (FAILED(hr)) return; + + ZeroMemory( &dpsd_server, sizeof(DPSESSIONDESC2) ); + ZeroMemory( &dpsd, sizeof(DPSESSIONDESC2) ); + + /* Service provider not initialized */ + hr = IDirectPlayX_Open( pDP_server, &dpsd_server, DPOPEN_CREATE ); + todo_wine checkHR( DPERR_INVALIDPARAMS, hr ); + + init_TCPIP_provider( pDP_server, "127.0.0.1", 0 ); + init_TCPIP_provider( pDP, "127.0.0.1", 0 ); + + /* Uninitialized dpsd */ + hr = IDirectPlayX_Open( pDP_server, &dpsd_server, DPOPEN_CREATE ); + todo_wine checkHR( DPERR_INVALIDPARAMS, hr ); + + + dpsd_server.dwSize = sizeof(DPSESSIONDESC2); + dpsd_server.guidApplication = appGuid; + dpsd_server.dwMaxPlayers = 10; + + + /* Regular operation */ + hr = IDirectPlayX_Open( pDP_server, &dpsd_server, DPOPEN_CREATE ); + todo_wine checkHR( DP_OK, hr ); + + /* Opening twice */ + hr = IDirectPlayX_Open( pDP_server, &dpsd_server, DPOPEN_CREATE ); + todo_wine checkHR( DPERR_ALREADYINITIALIZED, hr ); + + /* Session flags */ + IDirectPlayX_Close( pDP_server ); + + dpsd_server.dwFlags = DPSESSION_CLIENTSERVER | DPSESSION_MIGRATEHOST; + hr = IDirectPlayX_Open( pDP_server, &dpsd_server, DPOPEN_CREATE ); + todo_wine checkHR( DPERR_INVALIDFLAGS, hr ); + + dpsd_server.dwFlags = DPSESSION_MULTICASTSERVER | DPSESSION_MIGRATEHOST; + hr = IDirectPlayX_Open( pDP_server, &dpsd_server, DPOPEN_CREATE ); + todo_wine checkHR( DPERR_INVALIDFLAGS, hr ); + + dpsd_server.dwFlags = DPSESSION_SECURESERVER | DPSESSION_MIGRATEHOST; + hr = IDirectPlayX_Open( pDP_server, &dpsd_server, DPOPEN_CREATE ); + todo_wine checkHR( DPERR_INVALIDFLAGS, hr ); + + + /* Joining sessions */ + /* - Checking how strict dplay is with sizes */ + dpsd.dwSize = 0; + hr = IDirectPlayX_Open( pDP, &dpsd, DPOPEN_JOIN ); + todo_wine checkHR( DPERR_INVALIDPARAMS, hr ); + + dpsd.dwSize = sizeof(DPSESSIONDESC2)-1; + hr = IDirectPlayX_Open( pDP, &dpsd, DPOPEN_JOIN ); + todo_wine checkHR( DPERR_INVALIDPARAMS, hr ); + + dpsd.dwSize = sizeof(DPSESSIONDESC2)+1; + hr = IDirectPlayX_Open( pDP, &dpsd, DPOPEN_JOIN ); + todo_wine checkHR( DPERR_INVALIDPARAMS, hr ); + + dpsd.dwSize = sizeof(DPSESSIONDESC2); + hr = IDirectPlayX_Open( pDP, &dpsd, DPOPEN_JOIN ); + todo_wine checkHR( DPERR_NOSESSIONS, hr ); /* Only checks for size, not guids */ + + + dpsd.guidApplication = appGuid; + dpsd.guidInstance = appGuid; + + + hr = IDirectPlayX_Open( pDP, &dpsd, DPOPEN_JOIN ); + todo_wine checkHR( DPERR_NOSESSIONS, hr ); + hr = IDirectPlayX_Open( pDP, &dpsd, DPOPEN_JOIN | DPOPEN_CREATE ); + todo_wine checkHR( DPERR_NOSESSIONS, hr ); /* Second flag is ignored */ + + dpsd_server.dwFlags = 0; + + + /* Join to normal session */ + hr = IDirectPlayX_Open( pDP_server, &dpsd_server, DPOPEN_CREATE ); + todo_wine checkHR( DP_OK, hr ); + + IDirectPlayX_EnumSessions( pDP, &dpsd, 0, EnumSessions_cb2, pDP, 0 ); + + + /* Already initialized session */ + hr = IDirectPlayX_Open( pDP_server, &dpsd_server, DPOPEN_CREATE ); + todo_wine checkHR( DPERR_ALREADYINITIALIZED, hr ); + + + /* Checking which is the error checking order */ + dpsd_server.dwSize = 0; + + hr = IDirectPlayX_Open( pDP_server, &dpsd_server, DPOPEN_CREATE ); + todo_wine checkHR( DPERR_INVALIDPARAMS, hr ); + + dpsd_server.dwSize = sizeof(DPSESSIONDESC2); + + + /* Join to protected session */ + IDirectPlayX_Close( pDP_server ); + U2(dpsd_server).lpszPasswordA = (LPSTR) "hadouken"; + hr = IDirectPlayX_Open( pDP_server, &dpsd_server, DPOPEN_CREATE ); + todo_wine checkHR( DP_OK, hr ); + + IDirectPlayX_EnumSessions( pDP, &dpsd, 0, EnumSessions_cb2, + pDP, DPENUMSESSIONS_PASSWORDREQUIRED ); + + + IDirectPlayX_Release( pDP ); + IDirectPlayX_Release( pDP_server ); + +} + +/* EnumSessions */ + +static BOOL CALLBACK EnumSessions_cb( LPCDPSESSIONDESC2 lpThisSD, + LPDWORD lpdwTimeOut, + DWORD dwFlags, + LPVOID lpContext ) +{ + lpCallbackData callbackData = lpContext; + callbackData->dwCounter1++; + + if ( dwFlags & DPESC_TIMEDOUT ) + { + check( TRUE, lpThisSD == NULL ); + return FALSE; + } + check( FALSE, lpThisSD == NULL ); + + + if ( U2(*lpThisSD).lpszPasswordA != NULL ) + { + check( TRUE, (lpThisSD->dwFlags & DPSESSION_PASSWORDREQUIRED) != 0 ); + } + + if ( lpThisSD->dwFlags & DPSESSION_NEWPLAYERSDISABLED ) + { + check( 0, lpThisSD->dwCurrentPlayers ); + } + + check( sizeof(*lpThisSD), lpThisSD->dwSize ); + checkLP( NULL, U2(*lpThisSD).lpszPasswordA ); + + return TRUE; +} + +static IDirectPlay4 *create_session(DPSESSIONDESC2 *lpdpsd) +{ + + IDirectPlay4 *pDP; + DPNAME name; + DPID dpid; + HRESULT hr; + + hr = CoCreateInstance( &CLSID_DirectPlay, NULL, CLSCTX_ALL, + &IID_IDirectPlay4A, (LPVOID*) &pDP ); + ok( SUCCEEDED(hr), "CCI of CLSID_DirectPlay / IID_IDirectPlay4A failed\n" ); + if (FAILED(hr)) return NULL; + + init_TCPIP_provider( pDP, "127.0.0.1", 0 ); + + hr = IDirectPlayX_Open( pDP, lpdpsd, DPOPEN_CREATE ); + todo_wine checkHR( DP_OK, hr ); + + if ( ! (lpdpsd->dwFlags & DPSESSION_NEWPLAYERSDISABLED) ) + { + ZeroMemory( &name, sizeof(DPNAME) ); + name.dwSize = sizeof(DPNAME); + U1(name).lpszShortNameA = (LPSTR) "bofh"; + + hr = IDirectPlayX_CreatePlayer( pDP, &dpid, &name, NULL, NULL, + 0, DPPLAYER_SERVERPLAYER ); + todo_wine checkHR( DP_OK, hr ); + } + + return pDP; + +} + +static void test_EnumSessions(void) +{ + +#define N_SESSIONS 6 + + IDirectPlay4 *pDP, *pDPserver[N_SESSIONS]; + DPSESSIONDESC2 dpsd, dpsd_server[N_SESSIONS]; + CallbackData callbackData; + HRESULT hr; + UINT i; + + + hr = CoCreateInstance( &CLSID_DirectPlay, NULL, CLSCTX_ALL, + &IID_IDirectPlay4A, (LPVOID*) &pDP ); + ok( SUCCEEDED(hr), "CCI of CLSID_DirectPlay / IID_IDirectPlay4A failed\n" ); + if (FAILED(hr)) return; + + ZeroMemory( &dpsd, sizeof(DPSESSIONDESC2) ); + callbackData.dwCounter1 = -1; /* So that after a call to EnumSessions + we get the exact number of sessions */ + callbackData.dwFlags = 0; + + + /* Service provider not initialized */ + hr = IDirectPlayX_EnumSessions( pDP, &dpsd, 0, EnumSessions_cb, + &callbackData, 0 ); + checkHR( DPERR_UNINITIALIZED, hr ); + + + init_TCPIP_provider( pDP, "127.0.0.1", 0 ); + + + /* Session with no size */ + hr = IDirectPlayX_EnumSessions( pDP, &dpsd, 0, EnumSessions_cb, + &callbackData, 0 ); + todo_wine checkHR( DPERR_INVALIDPARAMS, hr ); + + if ( hr == DPERR_UNINITIALIZED ) + { + todo_wine win_skip( "EnumSessions not implemented\n" ); + return; + } + + dpsd.dwSize = sizeof(DPSESSIONDESC2); + + + /* No sessions */ + callbackData.dwCounter1 = -1; + hr = IDirectPlayX_EnumSessions( pDP, &dpsd, 0, EnumSessions_cb, + &callbackData, 0 ); + checkHR( DP_OK, hr ); + check( 0, callbackData.dwCounter1 ); + + + dpsd.guidApplication = appGuid; + + /* Set up sessions */ + for (i=0; idwSize ); + checkGuid( &appGuid, &lpData[i]->guidApplication ); + check( dpsd.dwMaxPlayers, lpData[i]->dwMaxPlayers ); + } + + checkGuid( &lpData[0]->guidInstance, &lpData[1]->guidInstance ); + + /* Set: Regular operation */ + U1(dpsd).lpszSessionNameA = (LPSTR) "Wahaa"; + hr = IDirectPlayX_SetSessionDesc( pDP[0], &dpsd, 0 ); + checkHR( DP_OK, hr ); + + dwDataSize = 1024; + hr = IDirectPlayX_GetSessionDesc( pDP[1], lpData[1], &dwDataSize ); + checkHR( DP_OK, hr ); + checkStr( U1(dpsd).lpszSessionNameA, U1(*lpData[1]).lpszSessionNameA ); + + + /* Set: Failing to modify a remote session */ + hr = IDirectPlayX_SetSessionDesc( pDP[1], &dpsd, 0 ); + checkHR( DPERR_ACCESSDENIED, hr ); + + /* Trying to change immutable properties */ + /* Flags */ + hr = IDirectPlayX_SetSessionDesc( pDP[0], &dpsd, 0 ); + checkHR( DP_OK, hr ); + dpsd.dwFlags = DPSESSION_SECURESERVER; + hr = IDirectPlayX_SetSessionDesc( pDP[0], &dpsd, 0 ); + checkHR( DPERR_INVALIDPARAMS, hr ); + dpsd.dwFlags = 0; + hr = IDirectPlayX_SetSessionDesc( pDP[0], &dpsd, 0 ); + checkHR( DP_OK, hr ); + /* Size */ + dpsd.dwSize = 2048; + hr = IDirectPlayX_SetSessionDesc( pDP[0], &dpsd, 0 ); + checkHR( DPERR_INVALIDPARAMS, hr ); + dpsd.dwSize = sizeof(DPSESSIONDESC2); + hr = IDirectPlayX_SetSessionDesc( pDP[0], &dpsd, 0 ); + checkHR( DP_OK, hr ); + + /* Changing the GUIDs and size is ignored */ + dpsd.guidApplication = appGuid2; + hr = IDirectPlayX_SetSessionDesc( pDP[0], &dpsd, 0 ); + checkHR( DP_OK, hr ); + dpsd.guidInstance = appGuid2; + hr = IDirectPlayX_SetSessionDesc( pDP[0], &dpsd, 0 ); + checkHR( DP_OK, hr ); + + hr = IDirectPlayX_GetSessionDesc( pDP[0], lpData[0], &dwDataSize ); + checkHR( DP_OK, hr ); + checkGuid( &appGuid, &lpData[0]->guidApplication ); + checkGuid( &lpData[1]->guidInstance, &lpData[0]->guidInstance ); + check( sizeof(DPSESSIONDESC2), lpData[0]->dwSize ); + + + /* Checking system messages */ + check_messages( pDP[0], dpid, 2, &callbackData ); + checkStr( "S0,S0,S0,S0,S0,S0,S0,", callbackData.szTrace1 ); + checkStr( "48,90,90,90,90,90,90,", callbackData.szTrace2 ); + check_messages( pDP[1], dpid, 2, &callbackData ); + checkStr( "S1,S1,S1,S1,S1,S1,", callbackData.szTrace1 ); + checkStr( "90,90,90,90,90,90,", callbackData.szTrace2 ); + + HeapFree( GetProcessHeap(), 0, lpDataMsg ); + for (i=0; i<2; i++) + { + HeapFree( GetProcessHeap(), 0, lpData[i] ); + IDirectPlayX_Release( pDP[i] ); + } + +} + +/* CreatePlayer */ + +static void test_CreatePlayer(void) +{ + + IDirectPlay4 *pDP[2]; + DPSESSIONDESC2 dpsd; + DPNAME name; + DPID dpid; + HRESULT hr; + + + hr = CoCreateInstance( &CLSID_DirectPlay, NULL, CLSCTX_ALL, + &IID_IDirectPlay4A, (LPVOID*) &pDP[0] ); + ok( SUCCEEDED(hr), "CCI of CLSID_DirectPlay / IID_IDirectPlay4A failed\n" ); + if (FAILED(hr)) return; + + hr = CoCreateInstance( &CLSID_DirectPlay, NULL, CLSCTX_ALL, + &IID_IDirectPlay4A, (LPVOID*) &pDP[1] ); + ok( SUCCEEDED(hr), "CCI of CLSID_DirectPlay / IID_IDirectPlay4A failed\n" ); + if (FAILED(hr)) return; + + ZeroMemory( &dpsd, sizeof(DPSESSIONDESC2) ); + ZeroMemory( &name, sizeof(DPNAME) ); + + + /* Connection not initialized */ + hr = IDirectPlayX_CreatePlayer( pDP[0], &dpid, NULL, NULL, NULL, 0, 0 ); + checkHR( DPERR_UNINITIALIZED, hr ); + + + init_TCPIP_provider( pDP[0], "127.0.0.1", 0 ); + init_TCPIP_provider( pDP[1], "127.0.0.1", 0 ); + + + /* Session not open */ + hr = IDirectPlayX_CreatePlayer( pDP[0], &dpid, NULL, NULL, NULL, 0, 0 ); + todo_wine checkHR( DPERR_INVALIDPARAMS, hr ); + + if ( hr == DPERR_UNINITIALIZED ) + { + todo_wine win_skip( "CreatePlayer not implemented\n" ); + return; + } + + dpsd.dwSize = sizeof(DPSESSIONDESC2); + dpsd.guidApplication = appGuid; + IDirectPlayX_Open( pDP[0], &dpsd, DPOPEN_CREATE ); + + + /* Player name */ + hr = IDirectPlayX_CreatePlayer( pDP[0], &dpid, NULL, NULL, NULL, 0, 0 ); + checkHR( DP_OK, hr ); + + + name.dwSize = -1; + + + hr = IDirectPlayX_CreatePlayer( pDP[0], &dpid, &name, NULL, NULL, 0, 0 ); + checkHR( DP_OK, hr ); + + + name.dwSize = sizeof(DPNAME); + U1(name).lpszShortNameA = (LPSTR) "test"; + U2(name).lpszLongNameA = NULL; + + + hr = IDirectPlayX_CreatePlayer( pDP[0], &dpid, &name, NULL, NULL, + 0, 0 ); + checkHR( DP_OK, hr ); + + + /* Null dpid */ + hr = IDirectPlayX_CreatePlayer( pDP[0], NULL, NULL, NULL, NULL, + 0, 0 ); + checkHR( DPERR_INVALIDPARAMS, hr ); + + + /* There can only be one server player */ + hr = IDirectPlayX_CreatePlayer( pDP[0], &dpid, NULL, NULL, NULL, + 0, DPPLAYER_SERVERPLAYER ); + checkHR( DP_OK, hr ); + check( DPID_SERVERPLAYER, dpid ); + + hr = IDirectPlayX_CreatePlayer( pDP[0], &dpid, NULL, NULL, NULL, + 0, DPPLAYER_SERVERPLAYER ); + checkHR( DPERR_CANTCREATEPLAYER, hr ); + + IDirectPlayX_DestroyPlayer( pDP[0], dpid ); + + hr = IDirectPlayX_CreatePlayer( pDP[0], &dpid, NULL, NULL, NULL, + 0, DPPLAYER_SERVERPLAYER ); + checkHR( DP_OK, hr ); + check( DPID_SERVERPLAYER, dpid ); + IDirectPlayX_DestroyPlayer( pDP[0], dpid ); + + + /* Flags */ + hr = IDirectPlayX_CreatePlayer( pDP[0], &dpid, NULL, NULL, NULL, + 0, 0 ); + checkHR( DP_OK, hr ); + + hr = IDirectPlayX_CreatePlayer( pDP[0], &dpid, NULL, NULL, NULL, + 0, DPPLAYER_SERVERPLAYER ); + checkHR( DP_OK, hr ); + check( DPID_SERVERPLAYER, dpid ); + IDirectPlayX_DestroyPlayer( pDP[0], dpid ); + + hr = IDirectPlayX_CreatePlayer( pDP[0], &dpid, NULL, NULL, NULL, + 0, DPPLAYER_SPECTATOR ); + checkHR( DP_OK, hr ); + + hr = IDirectPlayX_CreatePlayer( pDP[0], &dpid, NULL, NULL, NULL, + 0, ( DPPLAYER_SERVERPLAYER | + DPPLAYER_SPECTATOR ) ); + checkHR( DP_OK, hr ); + check( DPID_SERVERPLAYER, dpid ); + IDirectPlayX_DestroyPlayer( pDP[0], dpid ); + + + /* Session with DPSESSION_NEWPLAYERSDISABLED */ + IDirectPlayX_Close( pDP[0] ); + dpsd.dwFlags = DPSESSION_NEWPLAYERSDISABLED; + hr = IDirectPlayX_Open( pDP[0], &dpsd, DPOPEN_CREATE ); + checkHR( DP_OK, hr ); + + + hr = IDirectPlayX_CreatePlayer( pDP[0], &dpid, NULL, NULL, NULL, + 0, 0 ); + checkHR( DPERR_CANTCREATEPLAYER, hr ); + + hr = IDirectPlayX_CreatePlayer( pDP[0], &dpid, NULL, NULL, NULL, + 0, DPPLAYER_SERVERPLAYER ); + checkHR( DPERR_CANTCREATEPLAYER, hr ); + + hr = IDirectPlayX_CreatePlayer( pDP[0], &dpid, NULL, NULL, NULL, + 0, DPPLAYER_SPECTATOR ); + checkHR( DPERR_CANTCREATEPLAYER, hr ); + + + /* Creating players in a Client/Server session */ + IDirectPlayX_Close( pDP[0] ); + dpsd.dwFlags = DPSESSION_CLIENTSERVER; + hr = IDirectPlayX_Open( pDP[0], &dpsd, DPOPEN_CREATE ); + checkHR( DP_OK, hr ); + hr = IDirectPlayX_EnumSessions( pDP[1], &dpsd, 0, EnumSessions_cb_join, + pDP[1], 0 ); + checkHR( DP_OK, hr ); + + + hr = IDirectPlayX_CreatePlayer( pDP[0], &dpid, NULL, NULL, NULL, + 0, 0 ); + checkHR( DPERR_ACCESSDENIED, hr ); + + hr = IDirectPlayX_CreatePlayer( pDP[0], &dpid, NULL, NULL, NULL, + 0, DPPLAYER_SERVERPLAYER ); + checkHR( DP_OK, hr ); + check( DPID_SERVERPLAYER, dpid ); + + hr = IDirectPlayX_CreatePlayer( pDP[1], &dpid, NULL, NULL, NULL, + 0, DPPLAYER_SERVERPLAYER ); + checkHR( DPERR_INVALIDFLAGS, hr ); + + hr = IDirectPlayX_CreatePlayer( pDP[1], &dpid, NULL, NULL, NULL, + 0, 0 ); + checkHR( DP_OK, hr ); + + + IDirectPlayX_Release( pDP[0] ); + IDirectPlayX_Release( pDP[1] ); + +} + +/* GetPlayerCaps */ + +static void test_GetPlayerCaps(void) +{ + + IDirectPlay4 *pDP[2]; + DPSESSIONDESC2 dpsd; + DPID dpid[2]; + HRESULT hr; + UINT i; + + DPCAPS playerCaps; + DWORD dwFlags; + + + for (i=0; i<2; i++) + { + hr= CoCreateInstance( &CLSID_DirectPlay, NULL, CLSCTX_ALL, + &IID_IDirectPlay4A, (LPVOID*) &pDP[i] ); + ok( SUCCEEDED(hr), "CCI of CLSID_DirectPlay / IID_IDirectPlay4A failed\n" ); + if (FAILED(hr)) return; + } + ZeroMemory( &dpsd, sizeof(DPSESSIONDESC2) ); + dpsd.dwSize = sizeof(DPSESSIONDESC2); + dpsd.guidApplication = appGuid; + dpsd.dwMaxPlayers = 10; + + ZeroMemory( &playerCaps, sizeof(DPCAPS) ); + + + /* Uninitialized service provider */ + playerCaps.dwSize = 0; + hr = IDirectPlayX_GetPlayerCaps( pDP[0], 0, &playerCaps, 0 ); + checkHR( DPERR_UNINITIALIZED, hr ); + + playerCaps.dwSize = sizeof(DPCAPS); + hr = IDirectPlayX_GetPlayerCaps( pDP[0], 0, &playerCaps, 0 ); + checkHR( DPERR_UNINITIALIZED, hr ); + + + init_TCPIP_provider( pDP[0], "127.0.0.1", 0 ); + init_TCPIP_provider( pDP[1], "127.0.0.1", 0 ); + + + /* No session */ + playerCaps.dwSize = 0; + + hr = IDirectPlayX_GetPlayerCaps( pDP[0], 0, &playerCaps, 0 ); + todo_wine checkHR( DPERR_INVALIDPARAMS, hr ); + + if ( hr == DPERR_UNINITIALIZED ) + { + todo_wine win_skip( "GetPlayerCaps not implemented\n" ); + return; + } + + playerCaps.dwSize = sizeof(DPCAPS); + + hr = IDirectPlayX_GetPlayerCaps( pDP[0], 0, &playerCaps, 0 ); + checkHR( DPERR_INVALIDPLAYER, hr ); + + hr = IDirectPlayX_GetPlayerCaps( pDP[0], 2, &playerCaps, 0 ); + checkHR( DPERR_INVALIDPLAYER, hr ); + + + hr = IDirectPlayX_Open( pDP[0], &dpsd, DPOPEN_CREATE ); + checkHR( DP_OK, hr ); + hr = IDirectPlayX_EnumSessions( pDP[1], &dpsd, 0, EnumSessions_cb_join, + pDP[1], 0 ); + checkHR( DP_OK, hr ); + + for (i=0; i<2; i++) + { + hr = IDirectPlayX_CreatePlayer( pDP[i], &dpid[i], + NULL, NULL, NULL, 0, 0 ); + checkHR( DP_OK, hr ); + } + + + /* Uninitialized playerCaps */ + playerCaps.dwSize = 0; + + hr = IDirectPlayX_GetPlayerCaps( pDP[0], 0, &playerCaps, 0 ); + checkHR( DPERR_INVALIDPARAMS, hr ); + + hr = IDirectPlayX_GetPlayerCaps( pDP[0], 2, &playerCaps, 0 ); + checkHR( DPERR_INVALIDPARAMS, hr ); + + hr = IDirectPlayX_GetPlayerCaps( pDP[0], dpid[0], &playerCaps, 0 ); + checkHR( DPERR_INVALIDPARAMS, hr ); + + + /* Invalid player */ + playerCaps.dwSize = sizeof(DPCAPS); + + hr = IDirectPlayX_GetPlayerCaps( pDP[0], 0, &playerCaps, 0 ); + checkHR( DPERR_INVALIDPLAYER, hr ); + + hr = IDirectPlayX_GetPlayerCaps( pDP[0], 2, &playerCaps, 0 ); + checkHR( DPERR_INVALIDPLAYER, hr ); + + hr = IDirectPlayX_GetPlayerCaps( pDP[0], dpid[0], &playerCaps, 0 ); + checkHR( DP_OK, hr ); + + + /* Regular parameters */ + for (i=0; i<2; i++) + { + for (dwFlags=0; + dwFlags<=DPGETCAPS_GUARANTEED; + dwFlags+=DPGETCAPS_GUARANTEED) + { + + hr = IDirectPlayX_GetPlayerCaps( pDP[0], dpid[i], + &playerCaps, dwFlags ); + checkHR( DP_OK, hr ); + + + check( sizeof(DPCAPS), playerCaps.dwSize ); + check( 40, playerCaps.dwSize ); + check( 0, playerCaps.dwMaxQueueSize ); + check( 0, playerCaps.dwHundredBaud ); + check( 0, playerCaps.dwLatency ); + check( 65536, playerCaps.dwMaxLocalPlayers ); + check( 20, playerCaps.dwHeaderLength ); + + if ( i == 0 ) + { + checkFlags( DPCAPS_ISHOST | + DPCAPS_GUARANTEEDOPTIMIZED | + DPCAPS_GUARANTEEDSUPPORTED | + DPCAPS_ASYNCSUPPORTED | + DPPLAYERCAPS_LOCAL, + playerCaps.dwFlags, FLAGS_DPCAPS ); + } + else + checkFlags( DPCAPS_ISHOST | + DPCAPS_GUARANTEEDOPTIMIZED | + DPCAPS_GUARANTEEDSUPPORTED | + DPCAPS_ASYNCSUPPORTED, + playerCaps.dwFlags, FLAGS_DPCAPS ); + + if ( dwFlags == DPGETCAPS_GUARANTEED ) + { + check( 1048547, playerCaps.dwMaxBufferSize ); + check( 64, playerCaps.dwMaxPlayers ); + } + else + { + check( 65479, playerCaps.dwMaxBufferSize ); + check( 65536, playerCaps.dwMaxPlayers ); + } + + } + } + + + IDirectPlayX_Release( pDP[0] ); + IDirectPlayX_Release( pDP[1] ); + +} + +/* SetPlayerData + GetPlayerData */ + +static void test_PlayerData(void) +{ + IDirectPlay4 *pDP; + DPSESSIONDESC2 dpsd; + DPID dpid; + HRESULT hr; + + /* lpDataFake has to be bigger than the rest, limits lpDataGet size */ + LPCSTR lpDataFake = "big_fake_data_chunk"; + DWORD dwDataSizeFake = strlen(lpDataFake)+1; + + LPCSTR lpData = "remote_data"; + DWORD dwDataSize = strlen(lpData)+1; + + LPCSTR lpDataLocal = "local_data"; + DWORD dwDataSizeLocal = strlen(lpDataLocal)+1; + + LPSTR lpDataGet = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, + dwDataSizeFake ); + DWORD dwDataSizeGet = dwDataSizeFake; + + + hr = CoCreateInstance( &CLSID_DirectPlay, NULL, CLSCTX_ALL, + &IID_IDirectPlay4A, (LPVOID*) &pDP ); + ok( SUCCEEDED(hr), "CCI of CLSID_DirectPlay / IID_IDirectPlay4A failed\n" ); + if (FAILED(hr)) return; + + /* No service provider */ + hr = IDirectPlayX_SetPlayerData( pDP, 0, (LPVOID) lpData, + dwDataSize, 0 ); + checkHR( DPERR_UNINITIALIZED, hr ); + + hr = IDirectPlayX_GetPlayerData( pDP, 0, lpDataGet, &dwDataSizeGet, 0 ); + checkHR( DPERR_UNINITIALIZED, hr ); + + + init_TCPIP_provider( pDP, "127.0.0.1", 0 ); + + ZeroMemory( &dpsd, sizeof(DPSESSIONDESC2) ); + dpsd.dwSize = sizeof(DPSESSIONDESC2); + dpsd.guidApplication = appGuid; + IDirectPlayX_Open( pDP, &dpsd, DPOPEN_CREATE ); + + + /* Invalid player */ + hr = IDirectPlayX_SetPlayerData( pDP, 0, (LPVOID) lpData, + dwDataSize, 0 ); + todo_wine checkHR( DPERR_INVALIDPLAYER, hr ); + + hr = IDirectPlayX_GetPlayerData( pDP, 0, lpDataGet, &dwDataSizeGet, 0 ); + todo_wine checkHR( DPERR_INVALIDPLAYER, hr ); + + if ( hr == DPERR_UNINITIALIZED ) + { + todo_wine win_skip( "Get/SetPlayerData not implemented\n" ); + return; + } + + /* Create the player */ + /* By default, the data is remote */ + hr = IDirectPlayX_CreatePlayer( pDP, &dpid, NULL, NULL, (LPVOID) lpData, + dwDataSize, 0 ); + checkHR( DP_OK, hr ); + + /* Invalid parameters */ + hr = IDirectPlayX_SetPlayerData( pDP, dpid, NULL, dwDataSize, 0 ); + checkHR( DPERR_INVALIDPARAMS, hr ); + hr = IDirectPlayX_SetPlayerData( pDP, dpid, lpDataGet, -1, 0 ); + checkHR( DPERR_INVALIDPARAMS, hr ); + + hr = IDirectPlayX_GetPlayerData( pDP, dpid, lpDataGet, NULL, 0 ); + checkHR( DPERR_INVALIDPARAMS, hr ); + + + /* + * Remote data (default) + */ + + + /* Buffer redimension */ + dwDataSizeGet = dwDataSizeFake; + strcpy(lpDataGet, lpDataFake); + hr = IDirectPlayX_GetPlayerData( pDP, dpid, NULL, + &dwDataSizeGet, 0 ); + check( DPERR_BUFFERTOOSMALL, hr ); + check( dwDataSize, dwDataSizeGet ); + checkStr( lpDataFake, lpDataGet ); + + dwDataSizeGet = 2; + strcpy(lpDataGet, lpDataFake); + hr = IDirectPlayX_GetPlayerData( pDP, dpid, lpDataGet, &dwDataSizeGet, 0 ); + check( DPERR_BUFFERTOOSMALL, hr ); + check( dwDataSize, dwDataSizeGet ); + + strcpy(lpDataGet, lpDataFake); + hr = IDirectPlayX_GetPlayerData( pDP, dpid, lpDataGet, &dwDataSizeGet, 0 ); + checkHR( DP_OK, hr ); + check( dwDataSize, dwDataSizeGet ); + checkStr( lpData, lpDataGet ); + + /* Normal operation */ + dwDataSizeGet = dwDataSizeFake; + strcpy(lpDataGet, lpDataFake); + hr = IDirectPlayX_GetPlayerData( pDP, dpid, lpDataGet, &dwDataSizeGet, 0 ); + checkHR( DP_OK, hr ); + check( dwDataSize, dwDataSizeGet ); + checkStr( lpData, lpDataGet ); + + /* Flag tests */ + dwDataSizeGet = dwDataSizeFake; + strcpy(lpDataGet, lpDataFake); + hr = IDirectPlayX_GetPlayerData( pDP, dpid, lpDataGet, &dwDataSizeGet, 0 ); + checkHR( DP_OK, hr ); + check( dwDataSize, dwDataSizeGet ); /* Remote: works as expected */ + checkStr( lpData, lpDataGet ); + + dwDataSizeGet = dwDataSizeFake; + strcpy(lpDataGet, lpDataFake); + hr = IDirectPlayX_GetPlayerData( pDP, dpid, lpDataGet, &dwDataSizeGet, + DPGET_REMOTE ); + checkHR( DP_OK, hr ); + check( dwDataSize, dwDataSizeGet ); /* Same behaviour as in previous test */ + checkStr( lpData, lpDataGet ); + + dwDataSizeGet = dwDataSizeFake; + strcpy(lpDataGet, lpDataFake); + hr = IDirectPlayX_GetPlayerData( pDP, dpid, lpDataGet, &dwDataSizeGet, + DPGET_LOCAL ); + checkHR( DP_OK, hr ); + check( 0, dwDataSizeGet ); /* Sets size to 0 (as local data doesn't exist) */ + checkStr( lpDataFake, lpDataGet ); + + dwDataSizeGet = dwDataSizeFake; + strcpy(lpDataGet, lpDataFake); + hr = IDirectPlayX_GetPlayerData( pDP, dpid, lpDataGet, &dwDataSizeGet, + DPGET_LOCAL | DPGET_REMOTE ); + checkHR( DP_OK, hr ); + check( 0, dwDataSizeGet ); /* Same behaviour as in previous test */ + checkStr( lpDataFake, lpDataGet ); + + /* Getting local data (which doesn't exist), buffer size is ignored */ + dwDataSizeGet = 0; + strcpy(lpDataGet, lpDataFake); + hr = IDirectPlayX_GetPlayerData( pDP, dpid, lpDataGet, &dwDataSizeGet, + DPGET_LOCAL ); + checkHR( DP_OK, hr ); + check( 0, dwDataSizeGet ); /* Sets size to 0 */ + checkStr( lpDataFake, lpDataGet ); + + dwDataSizeGet = dwDataSizeFake; + strcpy(lpDataGet, lpDataFake); + hr = IDirectPlayX_GetPlayerData( pDP, dpid, NULL, &dwDataSizeGet, + DPGET_LOCAL ); + checkHR( DP_OK, hr ); + check( 0, dwDataSizeGet ); /* Sets size to 0 */ + checkStr( lpDataFake, lpDataGet ); + + + /* + * Local data + */ + + + /* Invalid flags */ + hr = IDirectPlayX_SetPlayerData( pDP, dpid, (LPVOID) lpDataLocal, + dwDataSizeLocal, + DPSET_LOCAL | DPSET_GUARANTEED ); + checkHR( DPERR_INVALIDPARAMS, hr ); + + /* Correct parameters */ + hr = IDirectPlayX_SetPlayerData( pDP, dpid, (LPVOID) lpDataLocal, + dwDataSizeLocal, DPSET_LOCAL ); + checkHR( DP_OK, hr ); + + /* Flag tests (again) */ + dwDataSizeGet = dwDataSizeFake; + strcpy(lpDataGet, lpDataFake); + hr = IDirectPlayX_GetPlayerData( pDP, dpid, lpDataGet, &dwDataSizeGet, 0 ); + checkHR( DP_OK, hr ); + check( dwDataSize, dwDataSizeGet ); /* Remote: works as expected */ + checkStr( lpData, lpDataGet ); + + dwDataSizeGet = dwDataSizeFake; + strcpy(lpDataGet, lpDataFake); + hr = IDirectPlayX_GetPlayerData( pDP, dpid, lpDataGet, &dwDataSizeGet, + DPGET_REMOTE ); + checkHR( DP_OK, hr ); + check( dwDataSize, dwDataSizeGet ); /* Like in previous test */ + checkStr( lpData, lpDataGet ); + + dwDataSizeGet = dwDataSizeFake; + strcpy(lpDataGet, lpDataFake); + hr = IDirectPlayX_GetPlayerData( pDP, dpid, lpDataGet, &dwDataSizeGet, + DPGET_LOCAL ); + checkHR( DP_OK, hr ); + check( dwDataSizeLocal, dwDataSizeGet ); /* Local: works as expected */ + checkStr( lpDataLocal, lpDataGet ); + + dwDataSizeGet = dwDataSizeFake; + strcpy(lpDataGet, lpDataFake); + hr = IDirectPlayX_GetPlayerData( pDP, dpid, lpDataGet, &dwDataSizeGet, + DPGET_LOCAL | DPGET_REMOTE ); + checkHR( DP_OK, hr ); + check( dwDataSizeLocal, dwDataSizeGet ); /* Like in previous test */ + checkStr( lpDataLocal, lpDataGet ); + + /* Small buffer works as expected again */ + dwDataSizeGet = 0; + strcpy(lpDataGet, lpDataFake); + hr = IDirectPlayX_GetPlayerData( pDP, dpid, lpDataGet, &dwDataSizeGet, + DPGET_LOCAL ); + checkHR( DPERR_BUFFERTOOSMALL, hr ); + check( dwDataSizeLocal, dwDataSizeGet ); + checkStr( lpDataFake, lpDataGet ); + + dwDataSizeGet = dwDataSizeFake; + strcpy(lpDataGet, lpDataFake); + hr = IDirectPlayX_GetPlayerData( pDP, dpid, NULL, + &dwDataSizeGet, DPGET_LOCAL ); + check( DPERR_BUFFERTOOSMALL, hr ); + check( dwDataSizeLocal, dwDataSizeGet ); + checkStr( lpDataFake, lpDataGet ); + + + /* + * Changing remote data + */ + + + /* Remote data := local data */ + hr = IDirectPlayX_SetPlayerData( pDP, dpid, (LPVOID) lpDataLocal, + dwDataSizeLocal, + DPSET_GUARANTEED | DPSET_REMOTE ); + checkHR( DP_OK, hr ); + hr = IDirectPlayX_SetPlayerData( pDP, dpid, (LPVOID) lpDataLocal, + dwDataSizeLocal, 0 ); + checkHR( DP_OK, hr ); + + dwDataSizeGet = dwDataSizeFake; + strcpy(lpDataGet, lpDataFake); + hr = IDirectPlayX_GetPlayerData( pDP, dpid, lpDataGet, &dwDataSizeGet, 0 ); + checkHR( DP_OK, hr ); + check( dwDataSizeLocal, dwDataSizeGet ); + checkStr( lpDataLocal, lpDataGet ); + + /* Remote data := fake data */ + hr = IDirectPlayX_SetPlayerData( pDP, dpid, (LPVOID) lpDataFake, + dwDataSizeFake, DPSET_REMOTE ); + checkHR( DP_OK, hr ); + + dwDataSizeGet = dwDataSizeFake + 1; + strcpy(lpDataGet, lpData); + hr = IDirectPlayX_GetPlayerData( pDP, dpid, lpDataGet, &dwDataSizeGet, 0 ); + checkHR( DP_OK, hr ); + check( dwDataSizeFake, dwDataSizeGet ); + checkStr( lpDataFake, lpDataGet ); + + + HeapFree( GetProcessHeap(), 0, lpDataGet ); + IDirectPlayX_Release( pDP ); +} + +/* GetPlayerName + SetPlayerName */ + +static void test_PlayerName(void) +{ + + IDirectPlay4 *pDP[2]; + DPSESSIONDESC2 dpsd; + DPID dpid[2]; + HRESULT hr; + UINT i; + + DPNAME playerName; + DWORD dwDataSize = 1024; + LPVOID lpData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize ); + CallbackData callbackData; + + + for (i=0; i<2; i++) + { + hr= CoCreateInstance( &CLSID_DirectPlay, NULL, CLSCTX_ALL, + &IID_IDirectPlay4A, (LPVOID*) &pDP[i] ); + ok( SUCCEEDED(hr), "CCI of CLSID_DirectPlay / IID_IDirectPlay4A failed\n" ); + if (FAILED(hr)) return; + } + ZeroMemory( &dpsd, sizeof(DPSESSIONDESC2) ); + ZeroMemory( &playerName, sizeof(DPNAME) ); + + + /* Service provider not initialized */ + hr = IDirectPlayX_SetPlayerName( pDP[0], 0, &playerName, 0 ); + checkHR( DPERR_UNINITIALIZED, hr ); + + dwDataSize = 1024; + hr = IDirectPlayX_GetPlayerName( pDP[0], 0, lpData, &dwDataSize ); + checkHR( DPERR_UNINITIALIZED, hr ); + check( 1024, dwDataSize ); + + + init_TCPIP_provider( pDP[0], "127.0.0.1", 0 ); + init_TCPIP_provider( pDP[1], "127.0.0.1", 0 ); + + + /* Session not initialized */ + hr = IDirectPlayX_SetPlayerName( pDP[0], 0, &playerName, 0 ); + todo_wine checkHR( DPERR_INVALIDPLAYER, hr ); + + if ( hr == DPERR_UNINITIALIZED ) + { + todo_wine win_skip( "Get/SetPlayerName not implemented\n" ); + return; + } + + dwDataSize = 1024; + hr = IDirectPlayX_GetPlayerName( pDP[0], 0, lpData, &dwDataSize ); + checkHR( DPERR_INVALIDPLAYER, hr ); + check( 1024, dwDataSize ); + + + dpsd.dwSize = sizeof(DPSESSIONDESC2); + dpsd.guidApplication = appGuid; + dpsd.dwMaxPlayers = 10; + IDirectPlayX_Open( pDP[0], &dpsd, DPOPEN_CREATE ); + IDirectPlayX_EnumSessions( pDP[1], &dpsd, 0, EnumSessions_cb_join, + pDP[1], 0 ); + + IDirectPlayX_CreatePlayer( pDP[0], &dpid[0], NULL, NULL, NULL, 0, 0 ); + IDirectPlayX_CreatePlayer( pDP[1], &dpid[1], NULL, NULL, NULL, 0, 0 ); + + + /* Name not initialized */ + playerName.dwSize = -1; + hr = IDirectPlayX_SetPlayerName( pDP[0], dpid[0], &playerName, 0 ); + checkHR( DP_OK, hr ); + + dwDataSize = 1024; + hr = IDirectPlayX_GetPlayerName( pDP[0], 0, lpData, &dwDataSize ); + checkHR( DPERR_INVALIDPLAYER, hr ); + check( 1024, dwDataSize ); + + + playerName.dwSize = sizeof(DPNAME); + U1(playerName).lpszShortNameA = (LPSTR) "player_name"; + U2(playerName).lpszLongNameA = (LPSTR) "player_long_name"; + + + /* Invalid parameters */ + hr = IDirectPlayX_SetPlayerName( pDP[0], -1, &playerName, 0 ); + checkHR( DPERR_INVALIDPLAYER, hr ); + hr = IDirectPlayX_SetPlayerName( pDP[0], 0, &playerName, 0 ); + checkHR( DPERR_INVALIDPLAYER, hr ); + hr = IDirectPlayX_SetPlayerName( pDP[0], dpid[0], &playerName, -1 ); + checkHR( DPERR_INVALIDPARAMS, hr ); + + dwDataSize = 1024; + hr = IDirectPlayX_GetPlayerName( pDP[0], 0, lpData, &dwDataSize ); + checkHR( DPERR_INVALIDPLAYER, hr ); + check( 1024, dwDataSize ); + + dwDataSize = -1; + hr = IDirectPlayX_GetPlayerName( pDP[0], dpid[0], lpData, &dwDataSize ); + checkHR( DPERR_INVALIDPARAMS, hr ); + check( -1, dwDataSize ); + + hr = IDirectPlayX_GetPlayerName( pDP[0], dpid[0], lpData, NULL ); + checkHR( DPERR_INVALIDPARAMS, hr ); + + /* Trying to modify remote player */ + hr = IDirectPlayX_SetPlayerName( pDP[0], dpid[1], &playerName, 0 ); + checkHR( DPERR_ACCESSDENIED, hr ); + + + /* Regular operation */ + hr = IDirectPlayX_SetPlayerName( pDP[0], dpid[0], &playerName, 0 ); + checkHR( DP_OK, hr ); + dwDataSize = 1024; + hr = IDirectPlayX_GetPlayerName( pDP[0], dpid[0], lpData, &dwDataSize ); + checkHR( DP_OK, hr ); + check( 45, dwDataSize ); + checkStr( U1(playerName).lpszShortNameA, U1(*(LPDPNAME)lpData).lpszShortNameA ); + checkStr( U2(playerName).lpszLongNameA, U2(*(LPDPNAME)lpData).lpszLongNameA ); + check( 0, ((LPDPNAME)lpData)->dwFlags ); + + hr = IDirectPlayX_SetPlayerName( pDP[0], dpid[0], NULL, 0 ); + checkHR( DP_OK, hr ); + dwDataSize = 1024; + hr = IDirectPlayX_GetPlayerName( pDP[0], dpid[0], lpData, &dwDataSize ); + checkHR( DP_OK, hr ); + check( 16, dwDataSize ); + checkLP( NULL, U1(*(LPDPNAME)lpData).lpszShortNameA ); + checkLP( NULL, U2(*(LPDPNAME)lpData).lpszLongNameA ); + check( 0, ((LPDPNAME)lpData)->dwFlags ); + + + /* Small buffer in get operation */ + dwDataSize = 1024; + hr = IDirectPlayX_GetPlayerName( pDP[0], dpid[0], NULL, &dwDataSize ); + checkHR( DPERR_BUFFERTOOSMALL, hr ); + check( 16, dwDataSize ); + + dwDataSize = 0; + hr = IDirectPlayX_GetPlayerName( pDP[0], dpid[0], lpData, &dwDataSize ); + checkHR( DPERR_BUFFERTOOSMALL, hr ); + check( 16, dwDataSize ); + + hr = IDirectPlayX_GetPlayerName( pDP[0], dpid[0], lpData, &dwDataSize ); + checkHR( DP_OK, hr ); + check( 16, dwDataSize ); + checkLP( NULL, U1(*(LPDPNAME)lpData).lpszShortNameA ); + checkLP( NULL, U2(*(LPDPNAME)lpData).lpszLongNameA ); + check( 0, ((LPDPNAME)lpData)->dwFlags ); + + + /* Flags */ + hr = IDirectPlayX_SetPlayerName( pDP[0], dpid[0], &playerName, + DPSET_GUARANTEED ); + checkHR( DP_OK, hr ); + dwDataSize = 1024; + hr = IDirectPlayX_GetPlayerName( pDP[0], dpid[0], lpData, &dwDataSize ); + checkHR( DP_OK, hr ); + check( 45, dwDataSize ); + checkStr( U1(playerName).lpszShortNameA, U1(*(LPDPNAME)lpData).lpszShortNameA ); + checkStr( U2(playerName).lpszLongNameA, U2(*(LPDPNAME)lpData).lpszLongNameA ); + check( 0, ((LPDPNAME)lpData)->dwFlags ); + + /* - Local (no propagation) */ + U1(playerName).lpszShortNameA = (LPSTR) "no_propagation"; + hr = IDirectPlayX_SetPlayerName( pDP[0], dpid[0], &playerName, + DPSET_LOCAL ); + checkHR( DP_OK, hr ); + + dwDataSize = 1024; + hr = IDirectPlayX_GetPlayerName( pDP[0], dpid[0], + lpData, &dwDataSize ); /* Local fetch */ + checkHR( DP_OK, hr ); + check( 48, dwDataSize ); + checkStr( "no_propagation", U1(*(LPDPNAME)lpData).lpszShortNameA ); + + dwDataSize = 1024; + hr = IDirectPlayX_GetPlayerName( pDP[1], dpid[0], + lpData, &dwDataSize ); /* Remote fetch */ + checkHR( DP_OK, hr ); + check( 45, dwDataSize ); + checkStr( "player_name", U1(*(LPDPNAME)lpData).lpszShortNameA ); + + /* -- 2 */ + + U1(playerName).lpszShortNameA = (LPSTR) "no_propagation_2"; + hr = IDirectPlayX_SetPlayerName( pDP[0], dpid[0], &playerName, + DPSET_LOCAL | DPSET_REMOTE ); + checkHR( DP_OK, hr ); + + dwDataSize = 1024; + hr = IDirectPlayX_GetPlayerName( pDP[0], dpid[0], + lpData, &dwDataSize ); /* Local fetch */ + checkHR( DP_OK, hr ); + check( 50, dwDataSize ); + checkStr( "no_propagation_2", U1(*(LPDPNAME)lpData).lpszShortNameA ); + + dwDataSize = 1024; + hr = IDirectPlayX_GetPlayerName( pDP[1], dpid[0], + lpData, &dwDataSize ); /* Remote fetch */ + checkHR( DP_OK, hr ); + check( 45, dwDataSize ); + checkStr( "player_name", U1(*(LPDPNAME)lpData).lpszShortNameA ); + + /* - Remote (propagation, default) */ + U1(playerName).lpszShortNameA = (LPSTR) "propagation"; + hr = IDirectPlayX_SetPlayerName( pDP[0], dpid[0], &playerName, + DPSET_REMOTE ); + checkHR( DP_OK, hr ); + + dwDataSize = 1024; + hr = IDirectPlayX_GetPlayerName( pDP[1], dpid[0], + lpData, &dwDataSize ); /* Remote fetch */ + checkHR( DP_OK, hr ); + check( 45, dwDataSize ); + checkStr( "propagation", U1(*(LPDPNAME)lpData).lpszShortNameA ); + + /* -- 2 */ + U1(playerName).lpszShortNameA = (LPSTR) "propagation_2"; + hr = IDirectPlayX_SetPlayerName( pDP[0], dpid[0], &playerName, + 0 ); + checkHR( DP_OK, hr ); + + dwDataSize = 1024; + hr = IDirectPlayX_GetPlayerName( pDP[1], dpid[0], + lpData, &dwDataSize ); /* Remote fetch */ + checkHR( DP_OK, hr ); + check( 47, dwDataSize ); + checkStr( "propagation_2", U1(*(LPDPNAME)lpData).lpszShortNameA ); + + + /* Checking system messages */ + check_messages( pDP[0], dpid, 2, &callbackData ); + checkStr( "S0,S0,S0,S0,S0,S0,S0,", callbackData.szTrace1 ); + checkStr( "48,28,57,28,57,57,59,", callbackData.szTrace2 ); + check_messages( pDP[1], dpid, 2, &callbackData ); + checkStr( "S1,S1,S1,S1,S1,S1,", callbackData.szTrace1 ); + checkStr( "28,57,28,57,57,59,", callbackData.szTrace2 ); + + + HeapFree( GetProcessHeap(), 0, lpData ); + IDirectPlayX_Release( pDP[0] ); + IDirectPlayX_Release( pDP[1] ); + +} + +/* GetPlayerAccount */ + +static BOOL CALLBACK EnumSessions_cb_join_secure( LPCDPSESSIONDESC2 lpThisSD, + LPDWORD lpdwTimeOut, + DWORD dwFlags, + LPVOID lpContext ) +{ + IDirectPlay4 *pDP = lpContext; + DPSESSIONDESC2 dpsd; + DPCREDENTIALS dpCredentials; + HRESULT hr; + + if (dwFlags & DPESC_TIMEDOUT) + { + return FALSE; + } + + checkFlags( DPSESSION_SECURESERVER, lpThisSD->dwFlags, FLAGS_DPSESSION ); + + ZeroMemory( &dpsd, sizeof(DPSESSIONDESC2) ); + dpsd.dwSize = sizeof(DPSESSIONDESC2); + dpsd.guidApplication = appGuid; + dpsd.guidInstance = lpThisSD->guidInstance; + + ZeroMemory( &dpCredentials, sizeof(DPCREDENTIALS) ); + dpCredentials.dwSize = sizeof(DPCREDENTIALS); + U1(dpCredentials).lpszUsernameA = (LPSTR) "user"; + U2(dpCredentials).lpszPasswordA = (LPSTR) "pass"; + hr = IDirectPlayX_SecureOpen( pDP, &dpsd, DPOPEN_JOIN, + NULL, &dpCredentials ); + checkHR( DPERR_LOGONDENIED, hr ); /* TODO: Make this work */ + + return TRUE; +} + +static void test_GetPlayerAccount(void) +{ + + IDirectPlay4 *pDP[2]; + DPSESSIONDESC2 dpsd; + DPID dpid[2]; + HRESULT hr; + UINT i; + + DWORD dwDataSize = 1024; + LPVOID lpData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize ); + + + for (i=0; i<2; i++) + { + hr = CoCreateInstance( &CLSID_DirectPlay, NULL, CLSCTX_ALL, + &IID_IDirectPlay4A, (LPVOID*) &pDP[i] ); + ok( SUCCEEDED(hr), "CCI of CLSID_DirectPlay / IID_IDirectPlay4A failed\n" ); + if (FAILED(hr)) return; + } + ZeroMemory( &dpsd, sizeof(DPSESSIONDESC2) ); + dpsd.dwSize = sizeof(DPSESSIONDESC2); + dpsd.guidApplication = appGuid; + dpsd.dwMaxPlayers = 10; + + /* Uninitialized service provider */ + hr = IDirectPlayX_GetPlayerAccount( pDP[0], 0, 0, lpData, &dwDataSize ); + todo_wine checkHR( DPERR_UNINITIALIZED, hr ); + + if ( hr == DP_OK ) + { + todo_wine win_skip( "GetPlayerAccount not implemented\n" ); + return; + } + + + init_TCPIP_provider( pDP[0], "127.0.0.1", 0 ); + init_TCPIP_provider( pDP[1], "127.0.0.1", 0 ); + + + /* No session */ + hr = IDirectPlayX_GetPlayerAccount( pDP[0], 0, 0, lpData, &dwDataSize ); + checkHR( DPERR_NOSESSIONS, hr ); + + + IDirectPlayX_Open( pDP[0], &dpsd, DPOPEN_CREATE ); + IDirectPlayX_EnumSessions( pDP[1], &dpsd, 0, EnumSessions_cb_join, + pDP[1], 0 ); + + for (i=0; i<2; i++) + { + hr = IDirectPlayX_CreatePlayer( pDP[i], &dpid[i], NULL, NULL, NULL, + 0, 0 ); + checkHR( DP_OK, hr ); + } + + + /* Session is not secure */ + dwDataSize = 1024; + hr = IDirectPlayX_GetPlayerAccount( pDP[0], dpid[0], 0, + lpData, &dwDataSize ); + checkHR( DPERR_UNSUPPORTED, hr ); + check( 1024, dwDataSize ); + + + /* Open a secure session */ + for (i=0; i<2; i++) + { + hr = IDirectPlayX_Close( pDP[i] ); + checkHR( DP_OK, hr ); + } + + dpsd.dwFlags = DPSESSION_SECURESERVER; + hr = IDirectPlayX_SecureOpen( pDP[0], &dpsd, DPOPEN_CREATE, NULL, NULL ); + checkHR( DP_OK, hr ); + + hr = IDirectPlayX_CreatePlayer( pDP[0], &dpid[0], + NULL, NULL, NULL, 0, 0 ); + checkHR( DP_OK, hr ); + + hr = IDirectPlayX_EnumSessions( pDP[1], &dpsd, 0, + EnumSessions_cb_join_secure, pDP[1], 0 ); + checkHR( DP_OK, hr ); + + hr = IDirectPlayX_CreatePlayer( pDP[1], &dpid[1], + NULL, NULL, NULL, 0, 0 ); + checkHR( DPERR_INVALIDPARAMS, hr ); + + /* TODO: Player creation so that this works */ + + /* Invalid player */ + dwDataSize = 1024; + hr = IDirectPlayX_GetPlayerAccount( pDP[0], 0, 0, + lpData, &dwDataSize ); + checkHR( DPERR_INVALIDPLAYER, hr ); + check( 1024, dwDataSize ); + + /* Invalid flags */ + dwDataSize = 1024; + hr = IDirectPlayX_GetPlayerAccount( pDP[0], dpid[0], -1, + lpData, &dwDataSize ); + checkHR( DPERR_INVALIDFLAGS, hr ); + check( 1024, dwDataSize ); + + dwDataSize = 1024; + hr = IDirectPlayX_GetPlayerAccount( pDP[0], dpid[0], 1, + lpData, &dwDataSize ); + checkHR( DPERR_INVALIDFLAGS, hr ); + check( 1024, dwDataSize ); + + /* Small buffer */ + dwDataSize = 1024; + hr = IDirectPlayX_GetPlayerAccount( pDP[0], dpid[0], 0, + NULL, &dwDataSize ); + checkHR( DPERR_INVALIDPLAYER, hr ); + check( 0, dwDataSize ); + + dwDataSize = 0; + hr = IDirectPlayX_GetPlayerAccount( pDP[0], dpid[0], 0, + lpData, &dwDataSize ); + checkHR( DPERR_INVALIDPLAYER, hr ); + check( 0, dwDataSize ); + + hr = IDirectPlayX_GetPlayerAccount( pDP[0], dpid[0], 0, + lpData, &dwDataSize ); + checkHR( DPERR_INVALIDPLAYER, hr ); + check( 0, dwDataSize ); + + /* Normal operation */ + dwDataSize = 1024; + hr = IDirectPlayX_GetPlayerAccount( pDP[0], dpid[0], 0, + lpData, &dwDataSize ); + checkHR( DPERR_INVALIDPLAYER, hr ); + check( 1024, dwDataSize ); + + + HeapFree( GetProcessHeap(), 0, lpData ); + IDirectPlayX_Release( pDP[0] ); + IDirectPlayX_Release( pDP[1] ); + +} + +/* GetPlayerAddress */ + +static BOOL CALLBACK EnumAddress_cb( REFGUID guidDataType, + DWORD dwDataSize, + LPCVOID lpData, + LPVOID lpContext ) +{ + lpCallbackData callbackData = lpContext; + static REFGUID types[] = { &DPAID_TotalSize, + &DPAID_ServiceProvider, + &DPAID_INet, + &DPAID_INetW }; + static DWORD sizes[] = { 4, 16, 12, 24, 4, 16, 10, 20 }; + + + checkGuid( types[callbackData->dwCounter1%4], guidDataType ); + check( sizes[callbackData->dwCounter1], dwDataSize ); + + switch(callbackData->dwCounter1) + { + case 0: + check( 136, *(LPDWORD) lpData ); + break; + case 4: + check( 130, *(LPDWORD) lpData ); + break; + case 1: + case 5: + checkGuid( &DPSPGUID_TCPIP, lpData ); + break; + case 6: + checkStr( "127.0.0.1", (LPSTR) lpData ); + break; + default: break; + } + + + callbackData->dwCounter1++; + + return TRUE; +} + +static void test_GetPlayerAddress(void) +{ + + IDirectPlay4 *pDP[2]; + IDirectPlayLobby3 *pDPL; + DPSESSIONDESC2 dpsd; + DPID dpid[2]; + CallbackData callbackData; + HRESULT hr; + UINT i; + + DWORD dwDataSize = 1024; + LPVOID lpData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize ); + + + for (i=0; i<2; i++) + { + hr = CoCreateInstance( &CLSID_DirectPlay, NULL, CLSCTX_ALL, + &IID_IDirectPlay4A, (LPVOID*) &pDP[i] ); + ok( SUCCEEDED(hr), "CCI of CLSID_DirectPlay / IID_IDirectPlay4A failed\n" ); + if (FAILED(hr)) return; + } + ZeroMemory( &dpsd, sizeof(DPSESSIONDESC2) ); + hr = CoCreateInstance( &CLSID_DirectPlayLobby, NULL, CLSCTX_ALL, + &IID_IDirectPlayLobby3A, (LPVOID*) &pDPL ); + ok( SUCCEEDED(hr), "CCI of CLSID_DirectPlayLobby / IID_IDirectPlayLobby3A failed\n" ); + if (FAILED(hr)) return; + + /* Uninitialized service provider */ + hr = IDirectPlayX_GetPlayerAddress( pDP[0], 0, lpData, &dwDataSize ); + todo_wine checkHR( DPERR_UNINITIALIZED, hr ); + + if ( hr == DP_OK ) + { + todo_wine win_skip( "GetPlayerAddress not implemented\n" ); + return; + } + + init_TCPIP_provider( pDP[0], "127.0.0.1", 0 ); + init_TCPIP_provider( pDP[1], "127.0.0.1", 0 ); + + + /* No session */ + dwDataSize = 1024; + hr = IDirectPlayX_GetPlayerAddress( pDP[0], 0, lpData, &dwDataSize ); + checkHR( DPERR_UNSUPPORTED, hr ); + check( 1024, dwDataSize ); + + dwDataSize = 1024; + hr = IDirectPlayX_GetPlayerAddress( pDP[0], 1, lpData, &dwDataSize ); + checkHR( DPERR_INVALIDPLAYER, hr ); + check( 1024, dwDataSize ); + + + dpsd.dwSize = sizeof(DPSESSIONDESC2); + dpsd.guidApplication = appGuid; + dpsd.dwMaxPlayers = 10; + IDirectPlayX_Open( pDP[0], &dpsd, DPOPEN_CREATE ); + IDirectPlayX_EnumSessions( pDP[1], &dpsd, 0, EnumSessions_cb_join, + pDP[1], 0 ); + + for (i=0; i<2; i++) + { + hr = IDirectPlayX_CreatePlayer( pDP[i], &dpid[i], NULL, NULL, NULL, + 0, 0 ); + checkHR( DP_OK, hr ); + } + + /* Invalid player */ + dwDataSize = 1024; + hr = IDirectPlayX_GetPlayerAddress( pDP[0], 0, + lpData, &dwDataSize ); + checkHR( DPERR_UNSUPPORTED, hr ); + check( 1024, dwDataSize ); + + dwDataSize = 1024; + hr = IDirectPlayX_GetPlayerAddress( pDP[0], 1, + lpData, &dwDataSize ); + checkHR( DPERR_INVALIDPLAYER, hr ); + check( 1024, dwDataSize ); + + /* Small buffer */ + dwDataSize = 1024; + hr = IDirectPlayX_GetPlayerAddress( pDP[0], dpid[0], + NULL, &dwDataSize ); + checkHR( DPERR_BUFFERTOOSMALL, hr ); + check( 136, dwDataSize ); + + dwDataSize = 0; + hr = IDirectPlayX_GetPlayerAddress( pDP[0], dpid[0], + lpData, &dwDataSize ); + checkHR( DPERR_BUFFERTOOSMALL, hr ); + check( 136, dwDataSize ); + + hr = IDirectPlayX_GetPlayerAddress( pDP[0], dpid[0], + lpData, &dwDataSize ); + checkHR( DP_OK, hr ); + check( 136, dwDataSize ); + + + /* Regular parameters */ + callbackData.dwCounter1 = 0; + + /* - Local */ + dwDataSize = 1024; + hr = IDirectPlayX_GetPlayerAddress( pDP[0], dpid[0], + lpData, &dwDataSize ); + checkHR( DP_OK, hr ); + check( 136, dwDataSize ); + + hr = IDirectPlayLobby_EnumAddress( pDPL, EnumAddress_cb, lpData, dwDataSize, + &callbackData ); + checkHR( DP_OK, hr ); + + check( 4, callbackData.dwCounter1 ); + + /* - Remote */ + dwDataSize = 1024; + hr = IDirectPlayX_GetPlayerAddress( pDP[0], dpid[1], + lpData, &dwDataSize ); + checkHR( DP_OK, hr ); + check( 130, dwDataSize ); + + hr = IDirectPlayLobby_EnumAddress( pDPL, EnumAddress_cb, lpData, dwDataSize, + &callbackData ); + checkHR( DP_OK, hr ); + + check( 8, callbackData.dwCounter1 ); + + + HeapFree( GetProcessHeap(), 0, lpData ); + IDirectPlayX_Release( pDP[0] ); + IDirectPlayX_Release( pDP[1] ); + +} + +/* GetPlayerFlags */ + +static void test_GetPlayerFlags(void) +{ + + IDirectPlay4 *pDP[2]; + DPSESSIONDESC2 dpsd; + DPID dpid[4]; + HRESULT hr; + UINT i; + + DWORD dwFlags = 0; + + + for (i=0; i<2; i++) + { + hr= CoCreateInstance( &CLSID_DirectPlay, NULL, CLSCTX_ALL, + &IID_IDirectPlay4A, (LPVOID*) &pDP[i] ); + ok( SUCCEEDED(hr), "CCI of CLSID_DirectPlay / IID_IDirectPlay4A failed\n" ); + if (FAILED(hr)) return; + } + ZeroMemory( &dpsd, sizeof(DPSESSIONDESC2) ); + dpsd.dwSize = sizeof(DPSESSIONDESC2); + dpsd.guidApplication = appGuid; + dpsd.dwMaxPlayers = 10; + + /* Uninitialized service provider */ + hr = IDirectPlayX_GetPlayerFlags( pDP[0], 0, &dwFlags ); + todo_wine checkHR( DPERR_UNINITIALIZED, hr ); + + if ( hr == DP_OK ) + { + todo_wine win_skip( "GetPlayerFlags not implemented\n" ); + return; + } + + init_TCPIP_provider( pDP[0], "127.0.0.1", 0 ); + init_TCPIP_provider( pDP[1], "127.0.0.1", 0 ); + + + /* No session */ + hr = IDirectPlayX_GetPlayerFlags( pDP[0], 0, &dwFlags ); + checkHR( DPERR_INVALIDPLAYER, hr ); + + hr = IDirectPlayX_GetPlayerFlags( pDP[0], 1, &dwFlags ); + checkHR( DPERR_INVALIDPLAYER, hr ); + + + IDirectPlayX_Open( pDP[0], &dpsd, DPOPEN_CREATE ); + IDirectPlayX_EnumSessions( pDP[1], &dpsd, 0, EnumSessions_cb_join, + pDP[1], 0 ); + + for (i=0; i<2; i++) + { + hr = IDirectPlayX_CreatePlayer( pDP[i], &dpid[i], + NULL, NULL, NULL, 0, 0 ); + checkHR( DP_OK, hr ); + } + hr = IDirectPlayX_CreatePlayer( pDP[0], &dpid[2], + NULL, NULL, NULL, + 0, DPPLAYER_SPECTATOR ); + checkHR( DP_OK, hr ); + hr = IDirectPlayX_CreatePlayer( pDP[0], &dpid[3], + NULL, NULL, NULL, + 0, DPPLAYER_SERVERPLAYER ); + checkHR( DP_OK, hr ); + + + /* Invalid player */ + hr = IDirectPlayX_GetPlayerFlags( pDP[0], 0, &dwFlags ); + checkHR( DPERR_INVALIDPLAYER, hr ); + + hr = IDirectPlayX_GetPlayerFlags( pDP[0], 2, &dwFlags ); + checkHR( DPERR_INVALIDPLAYER, hr ); + + /* Invalid parameters */ + hr = IDirectPlayX_GetPlayerFlags( pDP[0], dpid[0], NULL ); + checkHR( DPERR_INVALIDPARAMS, hr ); + + + /* Regular parameters */ + hr = IDirectPlayX_GetPlayerFlags( pDP[0], dpid[0], &dwFlags ); + checkHR( DP_OK, hr ); + checkFlags( dwFlags, DPPLAYER_LOCAL, FLAGS_DPPLAYER ); + + hr = IDirectPlayX_GetPlayerFlags( pDP[1], dpid[1], &dwFlags ); + checkHR( DP_OK, hr ); + checkFlags( dwFlags, DPPLAYER_LOCAL, FLAGS_DPPLAYER ); + + hr = IDirectPlayX_GetPlayerFlags( pDP[0], dpid[1], &dwFlags ); + checkHR( DP_OK, hr ); + checkFlags( dwFlags, 0, FLAGS_DPPLAYER ); + + hr = IDirectPlayX_GetPlayerFlags( pDP[0], dpid[2], &dwFlags ); + checkHR( DP_OK, hr ); + checkFlags( dwFlags, DPPLAYER_SPECTATOR | DPPLAYER_LOCAL, FLAGS_DPPLAYER ); + + hr = IDirectPlayX_GetPlayerFlags( pDP[1], dpid[3], &dwFlags ); + checkHR( DP_OK, hr ); + checkFlags( dwFlags, DPPLAYER_SERVERPLAYER, FLAGS_DPPLAYER ); + + + IDirectPlayX_Release( pDP[0] ); + IDirectPlayX_Release( pDP[1] ); + +} + +/* CreateGroup + CreateGroupInGroup */ + +static void test_CreateGroup(void) +{ + + IDirectPlay4 *pDP; + DPSESSIONDESC2 dpsd; + DPID idFrom, idTo, dpid, idGroup, idGroupParent; + DPNAME groupName; + HRESULT hr; + UINT i; + + LPCSTR lpData = "data"; + DWORD dwDataSize = strlen(lpData)+1; + LPDPMSG_CREATEPLAYERORGROUP lpDataGet = HeapAlloc( GetProcessHeap(), + HEAP_ZERO_MEMORY, + 1024 ); + DWORD dwDataSizeGet = 1024; + CallbackData callbackData; + + + hr= CoCreateInstance( &CLSID_DirectPlay, NULL, CLSCTX_ALL, + &IID_IDirectPlay4A, (LPVOID*) &pDP ); + ok( SUCCEEDED(hr), "CCI of CLSID_DirectPlay / IID_IDirectPlay4A failed\n" ); + if (FAILED(hr)) return; + ZeroMemory( &dpsd, sizeof(DPSESSIONDESC2) ); + dpsd.dwSize = sizeof(DPSESSIONDESC2); + dpsd.guidApplication = appGuid; + dpsd.dwMaxPlayers = 10; + ZeroMemory( &groupName, sizeof(DPNAME) ); + + + /* No service provider */ + hr = IDirectPlayX_CreateGroup( pDP, &idGroup, NULL, NULL, 0, 0 ); + checkHR( DPERR_UNINITIALIZED, hr ); + + hr = IDirectPlayX_CreateGroupInGroup( pDP, 0, &idGroup, NULL, NULL, 0, 0 ); + checkHR( DPERR_UNINITIALIZED, hr ); + + + + init_TCPIP_provider( pDP, "127.0.0.1", 0 ); + + + /* No session */ + hr = IDirectPlayX_CreateGroup( pDP, &idGroup, + NULL, NULL, 0, 0 ); + todo_wine checkHR( DPERR_INVALIDPARAMS, hr ); + + if ( hr == DPERR_UNINITIALIZED ) + { + todo_wine win_skip( "CreateGroup not implemented\n" ); + return; + } + + hr = IDirectPlayX_CreateGroupInGroup( pDP, 0, &idGroup, + NULL, NULL, 0, 0 ); + checkHR( DPERR_INVALIDGROUP, hr ); + + hr = IDirectPlayX_CreateGroupInGroup( pDP, 2, &idGroup, + NULL, NULL, 0, 0 ); + checkHR( DPERR_INVALIDGROUP, hr ); + + + hr = IDirectPlayX_Open( pDP, &dpsd, DPOPEN_CREATE ); + checkHR( DP_OK, hr ); + IDirectPlayX_CreatePlayer( pDP, &dpid, + NULL, NULL, NULL, 0, 0 ); + + + + /* With name */ + hr = IDirectPlayX_CreateGroup( pDP, &idGroup, + NULL, NULL, 0, 0 ); + checkHR( DP_OK, hr ); + + hr = IDirectPlayX_CreateGroupInGroup( pDP, idGroup, &idGroup, + NULL, NULL, 0, 0 ); + checkHR( DP_OK, hr ); + + hr = IDirectPlayX_CreateGroup( pDP, &idGroup, + &groupName, NULL, 0, 0 ); + checkHR( DP_OK, hr ); + + hr = IDirectPlayX_CreateGroupInGroup( pDP, idGroup, &idGroup, + &groupName, NULL, 0, 0 ); + checkHR( DP_OK, hr ); + + + groupName.dwSize = sizeof(DPNAME); + U1(groupName).lpszShortNameA = (LPSTR) lpData; + + + hr = IDirectPlayX_CreateGroup( pDP, &idGroup, + &groupName, NULL, 0, 0 ); + checkHR( DP_OK, hr ); + + hr = IDirectPlayX_CreateGroupInGroup( pDP, idGroup, &idGroup, + &groupName, NULL, 0, 0 ); + checkHR( DP_OK, hr ); + + + /* Message checking */ + for (i=0; i<6; i++) + { + dwDataSizeGet = 1024; + hr = IDirectPlayX_Receive( pDP, &idFrom, &idTo, 0, lpDataGet, + &dwDataSizeGet ); + checkHR( DP_OK, hr ); + if ( NULL == U1(lpDataGet->dpnName).lpszShortNameA ) + { + check( 48, dwDataSizeGet ); + } + else + { + check( 48 + dwDataSize, dwDataSizeGet ); + checkStr( lpData, U1(lpDataGet->dpnName).lpszShortNameA ); + } + check( DPID_SYSMSG, idFrom ); + checkConv( DPSYS_CREATEPLAYERORGROUP, lpDataGet->dwType, dpMsgType2str ); + check( DPPLAYERTYPE_GROUP, lpDataGet->dwPlayerType ); + checkFlags( DPGROUP_LOCAL, lpDataGet->dwFlags, FLAGS_DPGROUP ); + } + check_messages( pDP, &dpid, 1, &callbackData ); + checkStr( "", callbackData.szTrace1 ); + + + /* With data */ + hr = IDirectPlayX_CreateGroup( pDP, &idGroup, + NULL, (LPVOID) lpData, -1, 0 ); + checkHR( DPERR_INVALIDPARAMS, hr ); + + hr = IDirectPlayX_CreateGroup( pDP, &idGroup, + NULL, (LPVOID) lpData, 0, 0 ); + checkHR( DP_OK, hr ); + + hr = IDirectPlayX_CreateGroup( pDP, &idGroup, + NULL, NULL, dwDataSize, 0 ); + checkHR( DPERR_INVALIDPARAMS, hr ); + + hr = IDirectPlayX_CreateGroup( pDP, &idGroup, + NULL, (LPVOID) lpData, dwDataSize, 0 ); + checkHR( DP_OK, hr ); + + + hr = IDirectPlayX_CreateGroupInGroup( pDP, idGroup, &idGroup, + NULL, (LPVOID) lpData, -1, 0 ); + checkHR( DPERR_INVALIDPARAMS, hr ); + + hr = IDirectPlayX_CreateGroupInGroup( pDP, idGroup, &idGroup, + NULL, (LPVOID) lpData, 0, 0 ); + checkHR( DP_OK, hr ); + + hr = IDirectPlayX_CreateGroupInGroup( pDP, idGroup, &idGroup, + NULL, NULL, dwDataSize, 0 ); + checkHR( DPERR_INVALIDPARAMS, hr ); + + hr = IDirectPlayX_CreateGroupInGroup( pDP, idGroup, &idGroup, + NULL, (LPVOID)lpData, dwDataSize, 0 ); + checkHR( DP_OK, hr ); + + + hr = IDirectPlayX_CreateGroup( pDP, &idGroupParent, + NULL, NULL, 0, 0 ); + checkHR( DP_OK, hr ); + + + /* Message checking */ + for (i=0; i<5; i++) + { + dwDataSizeGet = 1024; + hr = IDirectPlayX_Receive( pDP, &idFrom, &idTo, 0, lpDataGet, + &dwDataSizeGet ); + checkHR( DP_OK, hr ); + check( 48 + lpDataGet->dwDataSize, dwDataSizeGet ); + check( DPID_SYSMSG, idFrom ); + checkConv( DPSYS_CREATEPLAYERORGROUP, lpDataGet->dwType, dpMsgType2str ); + check( DPPLAYERTYPE_GROUP, lpDataGet->dwPlayerType ); + checkFlags( DPGROUP_LOCAL, lpDataGet->dwFlags, FLAGS_DPGROUP ); + } + check_messages( pDP, &dpid, 1, &callbackData ); + checkStr( "", callbackData.szTrace1 ); + + + /* Flags and idGroupParent */ + hr = IDirectPlayX_CreateGroup( pDP, &idGroup, + NULL, NULL, 0, 0 ); + checkHR( DP_OK, hr ); + + hr = IDirectPlayX_CreateGroup( pDP, &idGroup, + NULL, NULL, 0, DPGROUP_HIDDEN ); + checkHR( DP_OK, hr ); + + hr = IDirectPlayX_CreateGroup( pDP, &idGroup, + NULL, NULL, 0, DPGROUP_STAGINGAREA ); + checkHR( DP_OK, hr ); + + hr = IDirectPlayX_CreateGroup( pDP, &idGroup, + NULL, NULL, 0, + DPGROUP_HIDDEN | DPGROUP_STAGINGAREA ); + checkHR( DP_OK, hr ); + + + hr = IDirectPlayX_CreateGroupInGroup( pDP, idGroupParent, &idGroup, + NULL, NULL, 0, 0 ); + checkHR( DP_OK, hr ); + + hr = IDirectPlayX_CreateGroupInGroup( pDP, idGroupParent, &idGroup, + NULL, NULL, 0, DPGROUP_HIDDEN ); + checkHR( DP_OK, hr ); + + hr = IDirectPlayX_CreateGroupInGroup( pDP, idGroupParent, &idGroup, + NULL, NULL, 0, DPGROUP_STAGINGAREA ); + checkHR( DP_OK, hr ); + + hr = IDirectPlayX_CreateGroupInGroup( pDP, idGroupParent, &idGroup, + NULL, NULL, 0, + DPGROUP_HIDDEN | + DPGROUP_STAGINGAREA ); + checkHR( DP_OK, hr ); + + + /* Message checking */ + for (i=0; i<8; i++) + { + dwDataSizeGet = 1024; + hr = IDirectPlayX_Receive( pDP, &idFrom, &idTo, 0, lpDataGet, + &dwDataSizeGet ); + checkHR( DP_OK, hr ); + check( 48, dwDataSizeGet ); + check( DPID_SYSMSG, idFrom ); + checkConv( DPSYS_CREATEPLAYERORGROUP, lpDataGet->dwType, dpMsgType2str ); + check( DPPLAYERTYPE_GROUP, lpDataGet->dwPlayerType ); + + if ( lpDataGet->dpIdParent != 0 ) + { + check( idGroupParent, lpDataGet->dpIdParent ); + } + + switch (i%4) + { + case 0: + checkFlags( DPGROUP_LOCAL, + lpDataGet->dwFlags, FLAGS_DPGROUP ); + break; + case 1: + checkFlags( DPGROUP_LOCAL | DPGROUP_HIDDEN, + lpDataGet->dwFlags, FLAGS_DPGROUP ); + break; + case 2: + checkFlags( DPGROUP_STAGINGAREA | DPGROUP_LOCAL, + lpDataGet->dwFlags, FLAGS_DPGROUP ); + break; + case 3: + checkFlags( DPGROUP_STAGINGAREA | DPGROUP_LOCAL | DPGROUP_HIDDEN, + lpDataGet->dwFlags, FLAGS_DPGROUP ); + break; + default: break; + } + } + check_messages( pDP, &dpid, 1, &callbackData ); + checkStr( "", callbackData.szTrace1 ); + + + /* If a group is created in C/S mode, no messages are sent */ + + /* - Peer 2 peer */ + IDirectPlayX_Close( pDP ); + + dpsd.dwFlags = 0; + hr = IDirectPlayX_Open( pDP, &dpsd, DPOPEN_CREATE ); + checkHR( DP_OK, hr ); + hr = IDirectPlayX_CreatePlayer( pDP, &dpid, NULL, NULL, NULL, 0, 0 ); + checkHR( DP_OK, hr ); + + hr = IDirectPlayX_CreateGroup( pDP, &idGroup, NULL, NULL, 0, 0 ); + checkHR( DP_OK, hr ); + + /* Messages are received */ + check_messages( pDP, &dpid, 1, &callbackData ); + checkStr( "S0,", callbackData.szTrace1 ); + + + /* - Client/Server */ + IDirectPlayX_Close( pDP ); + + dpsd.dwFlags = DPSESSION_CLIENTSERVER; + hr = IDirectPlayX_Open( pDP, &dpsd, DPOPEN_CREATE ); + checkHR( DP_OK, hr ); + hr = IDirectPlayX_CreatePlayer( pDP, &dpid, + NULL, NULL, NULL, 0, + DPPLAYER_SERVERPLAYER ); + checkHR( DP_OK, hr ); + + hr = IDirectPlayX_CreateGroup( pDP, &idGroup, + NULL, NULL, 0, 0 ); + checkHR( DP_OK, hr ); + + /* No messages */ + check_messages( pDP, &dpid, 1, &callbackData ); + checkStr( "S0,", callbackData.szTrace1 ); /* Or at least there + shouldn't be messages... */ + + + HeapFree( GetProcessHeap(), 0, lpDataGet ); + IDirectPlayX_Release( pDP ); + +} + +/* GroupOwner */ + +static void test_GroupOwner(void) +{ + + IDirectPlay4 *pDP[2]; + DPSESSIONDESC2 dpsd; + DPID dpid[2], idGroup, idOwner; + HRESULT hr; + UINT i; + + + for (i=0; i<2; i++) + { + hr = CoCreateInstance( &CLSID_DirectPlay, NULL, CLSCTX_ALL, + &IID_IDirectPlay4A, (LPVOID*) &pDP[i] ); + ok( SUCCEEDED(hr), "CCI of CLSID_DirectPlay / IID_IDirectPlay4A failed\n" ); + if (FAILED(hr)) return; + } + ZeroMemory( &dpsd, sizeof(DPSESSIONDESC2) ); + dpsd.dwSize = sizeof(DPSESSIONDESC2); + dpsd.guidApplication = appGuid; + dpsd.dwMaxPlayers = 10; + idGroup = 0; + idOwner = 0; + + /* Service provider not initialized */ + hr = IDirectPlayX_GetGroupOwner( pDP[0], idGroup, &idOwner ); + todo_wine checkHR( DPERR_UNINITIALIZED, hr ); + check( 0, idOwner ); + + if ( hr == DP_OK ) + { + todo_wine win_skip( "GetGroupOwner not implemented\n" ); + return; + } + + + for (i=0; i<2; i++) + init_TCPIP_provider( pDP[i], "127.0.0.1", 0 ); + + hr = IDirectPlayX_Open( pDP[0], &dpsd, DPOPEN_CREATE ); + checkHR( DP_OK, hr ); + hr = IDirectPlayX_EnumSessions( pDP[1], &dpsd, 0, EnumSessions_cb_join, + pDP[1], 0 ); + checkHR( DP_OK, hr ); + + for (i=0; i<2; i++) + { + hr = IDirectPlayX_CreatePlayer( pDP[i], &dpid[i], + NULL, NULL, NULL, 0, 0 ); + checkHR( DP_OK, hr ); + } + + /* Invalid group */ + hr = IDirectPlayX_GetGroupOwner( pDP[0], idGroup, &idOwner ); + checkHR( DPERR_INVALIDGROUP, hr ); + + hr = IDirectPlayX_CreateGroup( pDP[0], &idGroup, NULL, NULL, 0, 0 ); + checkHR( DP_OK, hr ); + + /* Fails, because we need a lobby session */ + hr = IDirectPlayX_GetGroupOwner( pDP[0], idGroup, &idOwner ); + checkHR( DPERR_UNSUPPORTED, hr ); + + + /* TODO: + * - Make this work + * - Check migration of the ownership of a group + * when the owner leaves + */ + + + IDirectPlayX_Release( pDP[0] ); + IDirectPlayX_Release( pDP[1] ); + +} + +/* EnumPlayers */ + +static BOOL CALLBACK EnumPlayers_cb( DPID dpId, + DWORD dwPlayerType, + LPCDPNAME lpName, + DWORD dwFlags, + LPVOID lpContext ) +{ + lpCallbackData callbackData = lpContext; + char playerIndex = dpid2char( callbackData->dpid, + callbackData->dpidSize, + dpId ); + + + /* Trace to study player ids */ + callbackData->szTrace1[ callbackData->dwCounter1 ] = playerIndex; + callbackData->dwCounter1++; + callbackData->szTrace1[ callbackData->dwCounter1 ] = '\0'; + + /* Trace to study flags received */ + strcat( callbackData->szTrace2, + ( dwFlags2str(dwFlags, FLAGS_DPENUMPLAYERS) + + strlen("DPENUMPLAYERS_") ) ); + strcat( callbackData->szTrace2, ":" ); + + + if ( playerIndex < '5' ) + { + check( DPPLAYERTYPE_PLAYER, dwPlayerType ); + } + else + { + check( DPPLAYERTYPE_GROUP, dwPlayerType ); + } + + return TRUE; + +} + +static BOOL CALLBACK EnumSessions_cb_EnumPlayers( LPCDPSESSIONDESC2 lpThisSD, + LPDWORD lpdwTimeOut, + DWORD dwFlags, + LPVOID lpContext ) +{ + lpCallbackData callbackData = lpContext; + HRESULT hr; + + if (dwFlags & DPESC_TIMEDOUT) + { + return FALSE; + } + + /* guid = NULL */ + callbackData->dwCounter1 = 0; + hr = IDirectPlayX_EnumPlayers( callbackData->pDP, NULL, EnumPlayers_cb, + &callbackData, 0 ); + checkHR( DPERR_NOSESSIONS, hr ); + check( 0, callbackData->dwCounter1 ); + + /* guid = appGuid */ + callbackData->dwCounter1 = 0; + hr = IDirectPlayX_EnumPlayers( callbackData->pDP, (LPGUID) &appGuid, + EnumPlayers_cb, &callbackData, 0 ); + checkHR( DPERR_NOSESSIONS, hr ); + check( 0, callbackData->dwCounter1 ); + + callbackData->dwCounter1 = 0; + hr = IDirectPlayX_EnumPlayers( callbackData->pDP, (LPGUID) &appGuid, + EnumPlayers_cb, &callbackData, + DPENUMPLAYERS_SESSION ); + checkHR( DPERR_NOSESSIONS, hr ); + check( 0, callbackData->dwCounter1 ); + + /* guid = guidInstance */ + callbackData->dwCounter1 = 0; + hr = IDirectPlayX_EnumPlayers( callbackData->pDP, + (LPGUID) &lpThisSD->guidInstance, + EnumPlayers_cb, &callbackData, 0 ); + checkHR( DPERR_NOSESSIONS, hr ); + check( 0, callbackData->dwCounter1 ); + + callbackData->dwCounter1 = 0; + hr = IDirectPlayX_EnumPlayers( callbackData->pDP, + (LPGUID) &lpThisSD->guidInstance, + EnumPlayers_cb, &callbackData, + DPENUMPLAYERS_SESSION ); + checkHR( DPERR_GENERIC, hr ); /* Why? */ + check( 0, callbackData->dwCounter1 ); + + return TRUE; + +} + +static void test_EnumPlayers(void) +{ + IDirectPlay4 *pDP[3]; + DPSESSIONDESC2 dpsd[3]; + DPID dpid[5+2]; /* 5 players, 2 groups */ + CallbackData callbackData; + HRESULT hr; + UINT i; + + + for (i=0; i<3; i++) + { + hr = CoCreateInstance( &CLSID_DirectPlay, NULL, CLSCTX_ALL, + &IID_IDirectPlay4A, (LPVOID*) &pDP[i] ); + ok( SUCCEEDED(hr), "CCI of CLSID_DirectPlay / IID_IDirectPlay4A failed\n" ); + if (FAILED(hr)) return; + + ZeroMemory( &dpsd[i], sizeof(DPSESSIONDESC2) ); + dpsd[i].dwSize = sizeof(DPSESSIONDESC2); + } + + dpsd[0].guidApplication = appGuid; + dpsd[1].guidApplication = appGuid2; + dpsd[2].guidApplication = GUID_NULL; + + callbackData.dpid = dpid; + callbackData.dpidSize = 5+2; + + + /* Uninitialized service provider */ + callbackData.dwCounter1 = 0; + hr = IDirectPlayX_EnumPlayers( pDP[0], (LPGUID) &appGuid, NULL, + &callbackData, 0 ); + checkHR( DPERR_UNINITIALIZED, hr ); + check( 0, callbackData.dwCounter1 ); + + + init_TCPIP_provider( pDP[0], "127.0.0.1", 0 ); + init_TCPIP_provider( pDP[1], "127.0.0.1", 0 ); + init_TCPIP_provider( pDP[2], "127.0.0.1", 0 ); + + + /* No session */ + callbackData.dwCounter1 = 0; + hr = IDirectPlayX_EnumPlayers( pDP[0], NULL, EnumPlayers_cb, + &callbackData, 0 ); + todo_wine checkHR( DPERR_NOSESSIONS, hr ); + check( 0, callbackData.dwCounter1 ); + + if ( hr == DPERR_UNINITIALIZED ) + { + todo_wine win_skip( "EnumPlayers not implemented\n" ); + return; + } + + callbackData.dwCounter1 = 0; + hr = IDirectPlayX_EnumPlayers( pDP[0], (LPGUID) &appGuid, EnumPlayers_cb, + &callbackData, 0 ); + checkHR( DPERR_NOSESSIONS, hr ); + check( 0, callbackData.dwCounter1 ); + + callbackData.dwCounter1 = 0; + hr = IDirectPlayX_EnumPlayers( pDP[0], (LPGUID) &appGuid, EnumPlayers_cb, + &callbackData, DPENUMPLAYERS_SESSION ); + checkHR( DPERR_NOSESSIONS, hr ); + check( 0, callbackData.dwCounter1 ); + + + hr = IDirectPlayX_Open( pDP[0], &dpsd[0], DPOPEN_CREATE ); + checkHR( DP_OK, hr ); + hr = IDirectPlayX_Open( pDP[1], &dpsd[1], DPOPEN_CREATE ); + checkHR( DP_OK, hr ); + + + /* No players */ + callbackData.dwCounter1 = 0; + hr = IDirectPlayX_EnumPlayers( pDP[0], NULL, EnumPlayers_cb, + &callbackData, 0 ); + checkHR( DP_OK, hr ); + check( 0, callbackData.dwCounter1 ); + + + /* Create players */ + hr = IDirectPlayX_CreatePlayer( pDP[0], &dpid[0], + NULL, NULL, NULL, 0, + DPPLAYER_SERVERPLAYER ); + checkHR( DP_OK, hr ); + hr = IDirectPlayX_CreatePlayer( pDP[1], &dpid[1], + NULL, NULL, NULL, 0, + 0 ); + checkHR( DP_OK, hr ); + + hr = IDirectPlayX_CreatePlayer( pDP[0], &dpid[2], + NULL, NULL, NULL, 0, + 0 ); + checkHR( DP_OK, hr ); + hr = IDirectPlayX_CreateGroup( pDP[0], &dpid[5], + NULL, NULL, 0, 0 ); + checkHR( DP_OK, hr ); + + + /* Invalid parameters */ + callbackData.dwCounter1 = 0; + hr = IDirectPlayX_EnumPlayers( pDP[0], (LPGUID) &appGuid, NULL, + &callbackData, 0 ); + checkHR( DPERR_INVALIDPARAMS, hr ); + check( 0, callbackData.dwCounter1 ); + + callbackData.dwCounter1 = 0; + hr = IDirectPlayX_EnumPlayers( pDP[0], NULL, EnumPlayers_cb, + &callbackData, DPENUMPLAYERS_SESSION ); + checkHR( DPERR_INVALIDPARAMS, hr ); + check( 0, callbackData.dwCounter1 ); + + + /* Regular operation */ + callbackData.dwCounter1 = 0; + callbackData.szTrace2[0] = 0; + hr = IDirectPlayX_EnumPlayers( pDP[0], NULL, EnumPlayers_cb, + &callbackData, 0 ); + checkHR( DP_OK, hr ); + check( 2, callbackData.dwCounter1 ); + checkStr( "20", callbackData.szTrace1 ); + checkStr( "ALL:SERVERPLAYER:", callbackData.szTrace2 ); + + callbackData.dwCounter1 = 0; + callbackData.szTrace2[0] = 0; + hr = IDirectPlayX_EnumPlayers( pDP[1], NULL, EnumPlayers_cb, + &callbackData, 0 ); + checkHR( DP_OK, hr ); + check( 1, callbackData.dwCounter1 ); + checkStr( "1", callbackData.szTrace1 ); + checkStr( "ALL:", callbackData.szTrace2 ); + + callbackData.dwCounter1 = 0; + callbackData.szTrace2[0] = 0; + hr = IDirectPlayX_EnumPlayers( pDP[0], (LPGUID) &appGuid, EnumPlayers_cb, + &callbackData, 0 ); + checkHR( DP_OK, hr ); + check( 2, callbackData.dwCounter1 ); /* Guid is ignored */ + checkStr( "20", callbackData.szTrace1 ); + checkStr( "ALL:SERVERPLAYER:", callbackData.szTrace2 ); + + + /* Enumerating from a remote session */ + /* - Session not open */ + callbackData.pDP = pDP[2]; + hr = IDirectPlayX_EnumSessions( pDP[2], &dpsd[2], 0, + EnumSessions_cb_EnumPlayers, + &callbackData, 0 ); + checkHR( DP_OK, hr ); + + + /* - Open session */ + callbackData.pDP = pDP[2]; + hr = IDirectPlayX_EnumSessions( pDP[2], &dpsd[0], 0, EnumSessions_cb_join, + pDP[2], 0 ); + checkHR( DP_OK, hr ); + hr = IDirectPlayX_CreatePlayer( pDP[2], &dpid[3], + NULL, NULL, NULL, 0, + DPPLAYER_SPECTATOR ); + checkHR( DP_OK, hr ); + hr = IDirectPlayX_CreatePlayer( pDP[2], &dpid[4], + NULL, NULL, NULL, 0, + 0 ); + checkHR( DP_OK, hr ); + hr = IDirectPlayX_CreateGroup( pDP[2], &dpid[6], + NULL, NULL, 0, 0 ); + checkHR( DP_OK, hr ); + + callbackData.dwCounter1 = 0; + callbackData.szTrace2[0] = 0; + hr = IDirectPlayX_EnumPlayers( pDP[2], NULL, EnumPlayers_cb, + &callbackData, 0 ); + checkHR( DP_OK, hr ); + check( 4, callbackData.dwCounter1 ); + checkStr( "4302", callbackData.szTrace1 ); + checkStr( "ALL:SPECTATOR:SERVERPLAYER:ALL:", callbackData.szTrace2 ); + + + /* Flag tests */ + + callbackData.dwCounter1 = 0; + callbackData.szTrace2[0] = 0; + hr = IDirectPlayX_EnumPlayers( pDP[2], NULL, EnumPlayers_cb, + &callbackData, DPENUMPLAYERS_ALL ); + checkHR( DP_OK, hr ); + check( 4, callbackData.dwCounter1 ); + checkStr( "4302", callbackData.szTrace1 ); + checkStr( "ALL:SPECTATOR:SERVERPLAYER:ALL:", callbackData.szTrace2 ); + + callbackData.dwCounter1 = 0; + callbackData.szTrace2[0] = 0; + hr = IDirectPlayX_EnumPlayers( pDP[2], NULL, EnumPlayers_cb, + &callbackData, DPENUMPLAYERS_GROUP ); + checkHR( DP_OK, hr ); + check( 6, callbackData.dwCounter1 ); + checkStr( "430256", callbackData.szTrace1 ); + checkStr( "GROUP:" + "GROUP,DPENUMPLAYERS_SPECTATOR:" + "GROUP,DPENUMPLAYERS_SERVERPLAYER:" + "GROUP:ALL:ALL:", callbackData.szTrace2 ); + + callbackData.dwCounter1 = 0; + callbackData.szTrace2[0] = 0; + hr = IDirectPlayX_EnumPlayers( pDP[2], NULL, EnumPlayers_cb, + &callbackData, DPENUMPLAYERS_LOCAL ); + checkHR( DP_OK, hr ); + check( 2, callbackData.dwCounter1 ); + checkStr( "43", callbackData.szTrace1 ); + checkStr( "LOCAL:" + "LOCAL,DPENUMPLAYERS_SPECTATOR:", callbackData.szTrace2 ); + + callbackData.dwCounter1 = 0; + callbackData.szTrace2[0] = 0; + hr = IDirectPlayX_EnumPlayers( pDP[2], NULL, EnumPlayers_cb, + &callbackData, DPENUMPLAYERS_SERVERPLAYER ); + checkHR( DP_OK, hr ); + check( 1, callbackData.dwCounter1 ); + checkStr( "0", callbackData.szTrace1 ); + checkStr( "SERVERPLAYER:", callbackData.szTrace2 ); + + callbackData.dwCounter1 = 0; + callbackData.szTrace2[0] = 0; + hr = IDirectPlayX_EnumPlayers( pDP[2], NULL, EnumPlayers_cb, + &callbackData, DPENUMPLAYERS_SPECTATOR ); + checkHR( DP_OK, hr ); + check( 1, callbackData.dwCounter1 ); + checkStr( "3", callbackData.szTrace1 ); + checkStr( "SPECTATOR:", callbackData.szTrace2 ); + + + IDirectPlayX_Release( pDP[0] ); + IDirectPlayX_Release( pDP[1] ); + IDirectPlayX_Release( pDP[2] ); + +} + +/* EnumGroups */ + +static BOOL CALLBACK EnumGroups_cb( DPID dpId, + DWORD dwPlayerType, + LPCDPNAME lpName, + DWORD dwFlags, + LPVOID lpContext ) +{ + lpCallbackData callbackData = lpContext; + char playerIndex = dpid2char( callbackData->dpid, + callbackData->dpidSize, + dpId ); + + + /* Trace to study player ids */ + callbackData->szTrace1[ callbackData->dwCounter1 ] = playerIndex; + callbackData->dwCounter1++; + callbackData->szTrace1[ callbackData->dwCounter1 ] = '\0'; + + /* Trace to study flags received */ + strcat( callbackData->szTrace2, + ( dwFlags2str(dwFlags, FLAGS_DPENUMGROUPS) + + strlen("DPENUMGROUPS_") ) ); + strcat( callbackData->szTrace2, ":" ); + + + check( DPPLAYERTYPE_GROUP, dwPlayerType ); + + return TRUE; +} + +static BOOL CALLBACK EnumSessions_cb_EnumGroups( LPCDPSESSIONDESC2 lpThisSD, + LPDWORD lpdwTimeOut, + DWORD dwFlags, + LPVOID lpContext ) +{ + lpCallbackData callbackData = lpContext; + HRESULT hr; + + if (dwFlags & DPESC_TIMEDOUT) + { + return FALSE; + } + + /* guid = NULL */ + callbackData->dwCounter1 = 0; + hr = IDirectPlayX_EnumGroups( callbackData->pDP, NULL, + EnumGroups_cb, &callbackData, 0 ); + checkHR( DPERR_NOSESSIONS, hr ); + check( 0, callbackData->dwCounter1 ); + + /* guid = appGuid */ + callbackData->dwCounter1 = 0; + hr = IDirectPlayX_EnumGroups( callbackData->pDP, (LPGUID) &appGuid, + EnumGroups_cb, &callbackData, 0 ); + checkHR( DPERR_NOSESSIONS, hr ); + check( 0, callbackData->dwCounter1 ); + + callbackData->dwCounter1 = 0; + hr = IDirectPlayX_EnumGroups( callbackData->pDP, (LPGUID) &appGuid, + EnumGroups_cb, &callbackData, + DPENUMGROUPS_SESSION ); + checkHR( DPERR_NOSESSIONS, hr ); + check( 0, callbackData->dwCounter1 ); + + /* guid = guidInstance */ + callbackData->dwCounter1 = 0; + hr = IDirectPlayX_EnumGroups( callbackData->pDP, + (LPGUID) &lpThisSD->guidInstance, + EnumGroups_cb, &callbackData, 0 ); + checkHR( DPERR_NOSESSIONS, hr ); + check( 0, callbackData->dwCounter1 ); + + callbackData->dwCounter1 = 0; + hr = IDirectPlayX_EnumGroups( callbackData->pDP, + (LPGUID) &lpThisSD->guidInstance, + EnumGroups_cb, &callbackData, + DPENUMGROUPS_SESSION ); + checkHR( DPERR_GENERIC, hr ); /* Why? */ + check( 0, callbackData->dwCounter1 ); + + return TRUE; + +} + +static void test_EnumGroups(void) +{ + IDirectPlay4 *pDP[3]; + DPSESSIONDESC2 dpsd[3]; + DPID dpid[5]; + CallbackData callbackData; + HRESULT hr; + UINT i; + + + for (i=0; i<3; i++) + { + hr = CoCreateInstance( &CLSID_DirectPlay, NULL, CLSCTX_ALL, + &IID_IDirectPlay4A, (LPVOID*) &pDP[i] ); + ok( SUCCEEDED(hr), "CCI of CLSID_DirectPlay / IID_IDirectPlay4A failed\n" ); + if (FAILED(hr)) return; + + ZeroMemory( &dpsd[i], sizeof(DPSESSIONDESC2) ); + dpsd[i].dwSize = sizeof(DPSESSIONDESC2); + } + + dpsd[0].guidApplication = appGuid; + dpsd[1].guidApplication = appGuid2; + dpsd[2].guidApplication = GUID_NULL; + + callbackData.dpid = dpid; + callbackData.dpidSize = 5; + + + /* Uninitialized service provider */ + callbackData.dwCounter1 = 0; + hr = IDirectPlayX_EnumGroups( pDP[0], NULL, EnumGroups_cb, + &callbackData, 0 ); + checkHR( DPERR_UNINITIALIZED, hr ); + check( 0, callbackData.dwCounter1 ); + + + init_TCPIP_provider( pDP[0], "127.0.0.1", 0 ); + init_TCPIP_provider( pDP[1], "127.0.0.1", 0 ); + init_TCPIP_provider( pDP[2], "127.0.0.1", 0 ); + + + /* No session */ + callbackData.dwCounter1 = 0; + hr = IDirectPlayX_EnumGroups( pDP[0], NULL, EnumGroups_cb, + &callbackData, 0 ); + todo_wine checkHR( DPERR_NOSESSIONS, hr ); + check( 0, callbackData.dwCounter1 ); + + if ( hr == DPERR_UNINITIALIZED ) + { + todo_wine win_skip( "EnumGroups not implemented\n" ); + return; + } + + callbackData.dwCounter1 = 0; + hr = IDirectPlayX_EnumGroups( pDP[0], (LPGUID) &appGuid, EnumGroups_cb, + &callbackData, 0 ); + checkHR( DPERR_NOSESSIONS, hr ); + check( 0, callbackData.dwCounter1 ); + + callbackData.dwCounter1 = 0; + hr = IDirectPlayX_EnumGroups( pDP[0], (LPGUID) &appGuid, EnumGroups_cb, + &callbackData, DPENUMGROUPS_SESSION ); + checkHR( DPERR_NOSESSIONS, hr ); + check( 0, callbackData.dwCounter1 ); + + + hr = IDirectPlayX_Open( pDP[0], &dpsd[0], DPOPEN_CREATE ); + checkHR( DP_OK, hr ); + hr = IDirectPlayX_Open( pDP[1], &dpsd[1], DPOPEN_CREATE ); + checkHR( DP_OK, hr ); + + + /* No groups */ + callbackData.dwCounter1 = 0; + hr = IDirectPlayX_EnumGroups( pDP[0], NULL, EnumGroups_cb, + &callbackData, 0 ); + checkHR( DP_OK, hr ); + check( 0, callbackData.dwCounter1 ); + + + /* Create groups */ + hr = IDirectPlayX_CreateGroup( pDP[0], &dpid[0], + NULL, NULL, 0, 0 ); + checkHR( DP_OK, hr ); + hr = IDirectPlayX_CreateGroupInGroup( pDP[0], dpid[0], &dpid[3], + NULL, NULL, 0, 0 ); + checkHR( DP_OK, hr ); /* Not a superior level group, + won't appear in the enumerations */ + hr = IDirectPlayX_CreateGroup( pDP[1], &dpid[1], + NULL, NULL, 0, 0 ); + checkHR( DP_OK, hr ); + hr = IDirectPlayX_CreateGroup( pDP[0], &dpid[2], + NULL, NULL, 0, DPGROUP_HIDDEN ); + checkHR( DP_OK, hr ); + + + /* Invalid parameters */ + callbackData.dwCounter1 = 0; + hr = IDirectPlayX_EnumGroups( pDP[0], (LPGUID) &appGuid, NULL, + &callbackData, 0 ); + checkHR( DPERR_INVALIDPARAMS, hr ); + check( 0, callbackData.dwCounter1 ); + + callbackData.dwCounter1 = 0; + hr = IDirectPlayX_EnumGroups( pDP[0], NULL, EnumGroups_cb, + &callbackData, DPENUMGROUPS_SESSION ); + checkHR( DPERR_INVALIDPARAMS, hr ); + check( 0, callbackData.dwCounter1 ); + + + /* Regular operation */ + callbackData.dwCounter1 = 0; + callbackData.szTrace2[0] = 0; + hr = IDirectPlayX_EnumGroups( pDP[0], NULL, EnumGroups_cb, + &callbackData, 0 ); + checkHR( DP_OK, hr ); + check( 2, callbackData.dwCounter1 ); + checkStr( "02", callbackData.szTrace1 ); + checkStr( "ALL:HIDDEN:", callbackData.szTrace2 ); + + callbackData.dwCounter1 = 0; + callbackData.szTrace2[0] = 0; + hr = IDirectPlayX_EnumGroups( pDP[1], NULL, EnumGroups_cb, + &callbackData, 0 ); + checkHR( DP_OK, hr ); + check( 1, callbackData.dwCounter1 ); + checkStr( "1", callbackData.szTrace1 ); + checkStr( "ALL:", callbackData.szTrace2 ); + + callbackData.dwCounter1 = 0; + callbackData.szTrace2[0] = 0; + hr = IDirectPlayX_EnumGroups( pDP[0], (LPGUID) &appGuid, EnumGroups_cb, + &callbackData, 0 ); + checkHR( DP_OK, hr ); + check( 2, callbackData.dwCounter1 ); /* Guid is ignored */ + checkStr( "02", callbackData.szTrace1 ); + checkStr( "ALL:HIDDEN:", callbackData.szTrace2 ); + + + /* Enumerating from a remote session */ + /* - Session not open */ + callbackData.pDP = pDP[2]; + hr = IDirectPlayX_EnumSessions( pDP[2], &dpsd[2], 0, + EnumSessions_cb_EnumGroups, + &callbackData, 0 ); + checkHR( DP_OK, hr ); + + /* - Open session */ + callbackData.pDP = pDP[2]; + hr = IDirectPlayX_EnumSessions( pDP[2], &dpsd[0], 0, EnumSessions_cb_join, + pDP[2], 0 ); + checkHR( DP_OK, hr ); + + hr = IDirectPlayX_CreateGroup( pDP[2], &dpid[3], + NULL, NULL, 0, 0 ); + checkHR( DP_OK, hr ); + hr = IDirectPlayX_CreateGroup( pDP[2], &dpid[4], + NULL, NULL, 0, DPGROUP_STAGINGAREA ); + checkHR( DP_OK, hr ); + + + callbackData.dwCounter1 = 0; + callbackData.szTrace2[0] = 0; + hr = IDirectPlayX_EnumGroups( pDP[2], NULL, EnumGroups_cb, + &callbackData, 0 ); + checkHR( DP_OK, hr ); + check( 4, callbackData.dwCounter1 ); + checkStr( "0234", callbackData.szTrace1 ); + checkStr( "ALL:HIDDEN:ALL:STAGINGAREA:", callbackData.szTrace2 ); + + /* Flag tests */ + callbackData.dwCounter1 = 0; + callbackData.szTrace2[0] = 0; + hr = IDirectPlayX_EnumGroups( pDP[2], NULL, EnumGroups_cb, + &callbackData, DPENUMGROUPS_ALL ); + checkHR( DP_OK, hr ); + check( 4, callbackData.dwCounter1 ); + checkStr( "0234", callbackData.szTrace1 ); + checkStr( "ALL:HIDDEN:ALL:STAGINGAREA:", callbackData.szTrace2 ); + + callbackData.dwCounter1 = 0; + callbackData.szTrace2[0] = 0; + hr = IDirectPlayX_EnumGroups( pDP[2], NULL, EnumGroups_cb, + &callbackData, DPENUMGROUPS_HIDDEN ); + checkHR( DP_OK, hr ); + check( 1, callbackData.dwCounter1 ); + checkStr( "2", callbackData.szTrace1 ); + checkStr( "HIDDEN:", callbackData.szTrace2 ); + + callbackData.dwCounter1 = 0; + callbackData.szTrace2[0] = 0; + hr = IDirectPlayX_EnumGroups( pDP[2], NULL, EnumGroups_cb, + &callbackData, DPENUMGROUPS_LOCAL ); + checkHR( DP_OK, hr ); + check( 2, callbackData.dwCounter1 ); + checkStr( "34", callbackData.szTrace1 ); + checkStr( "LOCAL:" + "LOCAL,DPENUMGROUPS_STAGINGAREA:", callbackData.szTrace2 ); + + callbackData.dwCounter1 = 0; + callbackData.szTrace2[0] = 0; + hr = IDirectPlayX_EnumGroups( pDP[2], NULL, EnumGroups_cb, + &callbackData, DPENUMGROUPS_REMOTE ); + checkHR( DP_OK, hr ); + check( 2, callbackData.dwCounter1 ); + checkStr( "02", callbackData.szTrace1 ); + checkStr( "REMOTE:" + "REMOTE,DPENUMGROUPS_HIDDEN:", callbackData.szTrace2 ); + + callbackData.dwCounter1 = 0; + callbackData.szTrace2[0] = 0; + hr = IDirectPlayX_EnumGroups( pDP[2], NULL, EnumGroups_cb, + &callbackData, DPENUMGROUPS_STAGINGAREA ); + checkHR( DP_OK, hr ); + check( 1, callbackData.dwCounter1 ); + checkStr( "4", callbackData.szTrace1 ); + checkStr( "STAGINGAREA:", callbackData.szTrace2 ); + + + IDirectPlayX_Release( pDP[0] ); + IDirectPlayX_Release( pDP[1] ); + IDirectPlayX_Release( pDP[2] ); + +} + +static void test_EnumGroupsInGroup(void) +{ + IDirectPlay4 *pDP[2]; + DPSESSIONDESC2 dpsd[2]; + DPID dpid[6]; + CallbackData callbackData; + HRESULT hr; + UINT i; + + + for (i=0; i<2; i++) + { + hr = CoCreateInstance( &CLSID_DirectPlay, NULL, CLSCTX_ALL, + &IID_IDirectPlay4A, (LPVOID*) &pDP[i] ); + ok( SUCCEEDED(hr), "CCI of CLSID_DirectPlay / IID_IDirectPlay4A failed\n" ); + if (FAILED(hr)) return; + + ZeroMemory( &dpsd[i], sizeof(DPSESSIONDESC2) ); + dpsd[i].dwSize = sizeof(DPSESSIONDESC2); + } + + dpsd[0].guidApplication = appGuid; + dpsd[1].guidApplication = GUID_NULL; + + callbackData.dpid = dpid; + callbackData.dpidSize = 6; + + + /* Uninitialized service provider */ + callbackData.dwCounter1 = 0; + hr = IDirectPlayX_EnumGroupsInGroup( pDP[0], 0, NULL, EnumGroups_cb, + &callbackData, 0 ); + checkHR( DPERR_UNINITIALIZED, hr ); + check( 0, callbackData.dwCounter1 ); + + + init_TCPIP_provider( pDP[0], "127.0.0.1", 0 ); + init_TCPIP_provider( pDP[1], "127.0.0.1", 0 ); + + hr = IDirectPlayX_Open( pDP[0], &dpsd[0], DPOPEN_CREATE ); + todo_wine checkHR( DP_OK, hr ); + + if ( hr == DPERR_UNINITIALIZED ) + { + todo_wine win_skip( "EnumGroupsInGroup not implemented\n" ); + return; + } + + /* Create groups */ + /* + * 0 + * / 2 + * 1 | 3 + * | 4 + * \ 5 (shortcut) + */ + hr = IDirectPlayX_CreateGroup( pDP[0], &dpid[0], + NULL, NULL, 0, 0 ); + checkHR( DP_OK, hr ); + hr = IDirectPlayX_CreateGroup( pDP[0], &dpid[1], + NULL, NULL, 0, 0 ); + checkHR( DP_OK, hr ); + hr = IDirectPlayX_CreateGroupInGroup( pDP[0], dpid[1], &dpid[2], + NULL, NULL, 0, 0 ); + checkHR( DP_OK, hr ); + hr = IDirectPlayX_CreateGroupInGroup( pDP[0], dpid[1], &dpid[3], + NULL, NULL, 0, + DPGROUP_HIDDEN ); + checkHR( DP_OK, hr ); + hr = IDirectPlayX_CreateGroupInGroup( pDP[0], dpid[1], &dpid[4], + NULL, NULL, 0, + DPGROUP_STAGINGAREA ); + checkHR( DP_OK, hr ); + hr = IDirectPlayX_CreateGroup( pDP[0], &dpid[5], + NULL, NULL, 0, 0 ); + checkHR( DP_OK, hr ); + + hr = IDirectPlayX_AddGroupToGroup( pDP[0], dpid[1], dpid[5] ); + checkHR( DP_OK, hr ); + + + /* Invalid parameters */ + callbackData.dwCounter1 = 0; + hr = IDirectPlayX_EnumGroupsInGroup( pDP[0], 0, NULL, EnumGroups_cb, + &callbackData, 0 ); + checkHR( DPERR_INVALIDGROUP, hr ); + check( 0, callbackData.dwCounter1 ); + + callbackData.dwCounter1 = 0; + hr = IDirectPlayX_EnumGroupsInGroup( pDP[0], 10, NULL, EnumGroups_cb, + &callbackData, 0 ); + checkHR( DPERR_INVALIDGROUP, hr ); + check( 0, callbackData.dwCounter1 ); + + callbackData.dwCounter1 = 0; + hr = IDirectPlayX_EnumGroupsInGroup( pDP[0], dpid[1], (LPGUID) &appGuid, + NULL, &callbackData, 0 ); + checkHR( DPERR_INVALIDPARAMS, hr ); + check( 0, callbackData.dwCounter1 ); + + callbackData.dwCounter1 = 0; + hr = IDirectPlayX_EnumGroupsInGroup( pDP[0], dpid[1], NULL, EnumGroups_cb, + &callbackData, DPENUMGROUPS_SESSION ); + checkHR( DPERR_INVALIDPARAMS, hr ); + check( 0, callbackData.dwCounter1 ); + + + /* Regular operation */ + callbackData.dwCounter1 = 0; + hr = IDirectPlayX_EnumGroupsInGroup( pDP[0], dpid[0], NULL, EnumGroups_cb, + &callbackData, 0 ); + checkHR( DP_OK, hr ); + check( 0, callbackData.dwCounter1 ); + + callbackData.dwCounter1 = 0; + callbackData.szTrace2[0] = 0; + hr = IDirectPlayX_EnumGroupsInGroup( pDP[0], dpid[1], NULL, EnumGroups_cb, + &callbackData, 0 ); + checkHR( DP_OK, hr ); + check( 4, callbackData.dwCounter1 ); + checkStr( "5432", callbackData.szTrace1 ); + checkStr( "SHORTCUT:STAGINGAREA:HIDDEN:ALL:", callbackData.szTrace2 ); + + callbackData.dwCounter1 = 0; + callbackData.szTrace2[0] = 0; + hr = IDirectPlayX_EnumGroupsInGroup( pDP[0], dpid[1], (LPGUID) &appGuid, + EnumGroups_cb, &callbackData, 0 ); + checkHR( DP_OK, hr ); + check( 4, callbackData.dwCounter1 ); /* Guid is ignored */ + checkStr( "5432", callbackData.szTrace1 ); + checkStr( "SHORTCUT:STAGINGAREA:HIDDEN:ALL:", callbackData.szTrace2 ); + + + /* Enumerating from a remote session */ + /* - Session not open */ + callbackData.pDP = pDP[1]; + hr = IDirectPlayX_EnumSessions( pDP[1], &dpsd[1], 0, + EnumSessions_cb_EnumGroups, + &callbackData, 0 ); + checkHR( DP_OK, hr ); + + /* - Open session */ + hr = IDirectPlayX_EnumSessions( pDP[1], &dpsd[0], 0, EnumSessions_cb_join, + pDP[1], 0 ); + checkHR( DP_OK, hr ); + + + callbackData.dwCounter1 = 0; + callbackData.szTrace2[0] = 0; + hr = IDirectPlayX_EnumGroupsInGroup( pDP[1], dpid[1], NULL, EnumGroups_cb, + &callbackData, 0 ); + checkHR( DP_OK, hr ); + check( 4, callbackData.dwCounter1 ); + checkStr( "5432", callbackData.szTrace1 ); + checkStr( "SHORTCUT:STAGINGAREA:HIDDEN:ALL:", callbackData.szTrace2 ); + + /* Flag tests */ + callbackData.dwCounter1 = 0; + callbackData.szTrace2[0] = 0; + hr = IDirectPlayX_EnumGroupsInGroup( pDP[0], dpid[1], NULL, EnumGroups_cb, + &callbackData, DPENUMGROUPS_ALL ); + checkHR( DP_OK, hr ); + check( 4, callbackData.dwCounter1 ); + checkStr( "5432", callbackData.szTrace1 ); + checkStr( "SHORTCUT:STAGINGAREA:HIDDEN:ALL:", callbackData.szTrace2 ); + + callbackData.dwCounter1 = 0; + callbackData.szTrace2[0] = 0; + hr = IDirectPlayX_EnumGroupsInGroup( pDP[0], dpid[1], NULL, EnumGroups_cb, + &callbackData, DPENUMGROUPS_HIDDEN ); + checkHR( DP_OK, hr ); + check( 1, callbackData.dwCounter1 ); + checkStr( "3", callbackData.szTrace1 ); + checkStr( "HIDDEN:", callbackData.szTrace2 ); + + callbackData.dwCounter1 = 0; + callbackData.szTrace2[0] = 0; + hr = IDirectPlayX_EnumGroupsInGroup( pDP[0], dpid[1], NULL, EnumGroups_cb, + &callbackData, DPENUMGROUPS_LOCAL ); + checkHR( DP_OK, hr ); + check( 4, callbackData.dwCounter1 ); + checkStr( "5432", callbackData.szTrace1 ); + checkStr( "LOCAL,DPENUMGROUPS_SHORTCUT:" + "LOCAL,DPENUMGROUPS_STAGINGAREA:" + "LOCAL,DPENUMGROUPS_HIDDEN:LOCAL:", callbackData.szTrace2 ); + + callbackData.dwCounter1 = 0; + hr = IDirectPlayX_EnumGroupsInGroup( pDP[0], dpid[1], NULL, EnumGroups_cb, + &callbackData, DPENUMGROUPS_REMOTE ); + checkHR( DP_OK, hr ); + check( 0, callbackData.dwCounter1 ); + + callbackData.dwCounter1 = 0; + hr = IDirectPlayX_EnumGroupsInGroup( pDP[1], dpid[1], NULL, EnumGroups_cb, + &callbackData, DPENUMGROUPS_LOCAL ); + checkHR( DP_OK, hr ); + check( 0, callbackData.dwCounter1 ); + + callbackData.dwCounter1 = 0; + callbackData.szTrace2[0] = 0; + hr = IDirectPlayX_EnumGroupsInGroup( pDP[1], dpid[1], NULL, EnumGroups_cb, + &callbackData, DPENUMGROUPS_REMOTE ); + checkHR( DP_OK, hr ); + check( 4, callbackData.dwCounter1 ); + checkStr( "5432", callbackData.szTrace1 ); + checkStr( "REMOTE,DPENUMGROUPS_SHORTCUT:" + "REMOTE,DPENUMGROUPS_STAGINGAREA:" + "REMOTE,DPENUMGROUPS_HIDDEN:REMOTE:", callbackData.szTrace2 ); + + callbackData.dwCounter1 = 0; + callbackData.szTrace2[0] = 0; + hr = IDirectPlayX_EnumGroupsInGroup( pDP[0], dpid[1], NULL, EnumGroups_cb, + &callbackData, DPENUMGROUPS_SHORTCUT ); + checkHR( DP_OK, hr ); + check( 1, callbackData.dwCounter1 ); + checkStr( "5", callbackData.szTrace1 ); + checkStr( "SHORTCUT:", callbackData.szTrace2 ); + + callbackData.dwCounter1 = 0; + callbackData.szTrace2[0] = 0; + hr = IDirectPlayX_EnumGroupsInGroup( pDP[0], dpid[1], NULL, EnumGroups_cb, + &callbackData, + DPENUMGROUPS_STAGINGAREA ); + checkHR( DP_OK, hr ); + check( 1, callbackData.dwCounter1 ); + checkStr( "4", callbackData.szTrace1 ); + checkStr( "STAGINGAREA:", callbackData.szTrace2 ); + + + IDirectPlayX_Release( pDP[0] ); + IDirectPlayX_Release( pDP[1] ); + +} + +static void test_groups_p2p(void) +{ + + IDirectPlay4 *pDP[2]; + DPSESSIONDESC2 dpsd; + DPID idPlayer[6], idGroup[3]; + HRESULT hr; + UINT i; + + DWORD dwDataSize = 1024; + LPVOID lpData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 1024 ); + CallbackData callbackData; + + + for (i=0; i<2; i++) + { + hr = CoCreateInstance( &CLSID_DirectPlay, NULL, CLSCTX_ALL, + &IID_IDirectPlay4A, (LPVOID*) &pDP[i] ); + ok( SUCCEEDED(hr), "CCI of CLSID_DirectPlay / IID_IDirectPlay4A failed\n" ); + if (FAILED(hr)) return; + } + ZeroMemory( &dpsd, sizeof(DPSESSIONDESC2) ); + dpsd.dwSize = sizeof(DPSESSIONDESC2); + dpsd.guidApplication = appGuid; + dpsd.dwMaxPlayers = 10; + + + init_TCPIP_provider( pDP[0], "127.0.0.1", 0 ); + init_TCPIP_provider( pDP[1], "127.0.0.1", 0 ); + + hr = IDirectPlayX_Open( pDP[0], &dpsd, DPOPEN_CREATE ); + todo_wine checkHR( DP_OK, hr ); + hr = IDirectPlayX_EnumSessions( pDP[1], &dpsd, 0, EnumSessions_cb_join, + pDP[1], 0 ); + todo_wine checkHR( DP_OK, hr ); + + if ( hr == DPERR_UNINITIALIZED ) + { + todo_wine win_skip( "dplay not implemented enough for this test yet\n" ); + return; + } + + + /* Create players */ + hr = IDirectPlayX_CreatePlayer( pDP[0], &idPlayer[0], + NULL, NULL, NULL, 0, 0 ); + checkHR( DP_OK, hr ); + hr = IDirectPlayX_CreatePlayer( pDP[0], &idPlayer[1], + NULL, NULL, NULL, 0, 0 ); + checkHR( DP_OK, hr ); + hr = IDirectPlayX_CreatePlayer( pDP[0], &idPlayer[2], + NULL, NULL, NULL, 0, 0 ); + checkHR( DP_OK, hr ); + hr = IDirectPlayX_CreatePlayer( pDP[1], &idPlayer[3], + NULL, NULL, NULL, 0, 0 ); + checkHR( DP_OK, hr ); + hr = IDirectPlayX_CreatePlayer( pDP[1], &idPlayer[4], + NULL, NULL, NULL, 0, 0 ); + checkHR( DP_OK, hr ); + hr = IDirectPlayX_CreatePlayer( pDP[1], &idPlayer[5], + NULL, NULL, NULL, 0, 0 ); + checkHR( DP_OK, hr ); + + hr = IDirectPlayX_CreateGroup( pDP[0], &idGroup[0], + NULL, NULL, 0, 0 ); + checkHR( DP_OK, hr ); + hr = IDirectPlayX_CreateGroup( pDP[1], &idGroup[2], + NULL, NULL, 0, 0 ); + checkHR( DP_OK, hr ); + hr = IDirectPlayX_CreateGroupInGroup( pDP[1], idGroup[2], &idGroup[1], + NULL, NULL, 0, 0 ); + checkHR( DP_OK, hr ); + + + /* Purge queues */ + check_messages( pDP[0], idPlayer, 6, &callbackData ); + checkStr( "S0," "S1,S0," + "S2,S1,S0," "S2,S1,S0," + "S2,S1,S0," "S2,S1,S0," + "S2,S1,S0," "S2,S1,S0,", callbackData.szTrace1 ); + check_messages( pDP[1], idPlayer, 6, &callbackData ); + checkStr( "S3," "S4,S3," + "S5,S4,S3," "S5,S4,S3," + "S5,S4,S3,", callbackData.szTrace1 ); + + + /* + * Player 0 | | + * Player 1 | Group 0 | pDP 0 + * Player 2 | | + * Player 3 | Group 1 ) | + * Player 4 | | Group 2 | pDP 1 + * Player 5 | | + */ + + /* Build groups */ + hr = IDirectPlayX_AddPlayerToGroup( pDP[0], idGroup[0], idPlayer[0] ); + checkHR( DP_OK, hr ); + hr = IDirectPlayX_AddPlayerToGroup( pDP[0], idGroup[0], idPlayer[1] ); + checkHR( DP_OK, hr ); + hr = IDirectPlayX_AddPlayerToGroup( pDP[0], idGroup[0], idPlayer[2] ); + checkHR( DP_OK, hr ); + hr = IDirectPlayX_AddPlayerToGroup( pDP[1], idGroup[1], idPlayer[3] ); + checkHR( DP_OK, hr ); + hr = IDirectPlayX_AddPlayerToGroup( pDP[1], idGroup[1], idPlayer[4] ); + checkHR( DP_OK, hr ); + hr = IDirectPlayX_AddPlayerToGroup( pDP[1], idGroup[2], idPlayer[4] ); + checkHR( DP_OK, hr ); + hr = IDirectPlayX_AddPlayerToGroup( pDP[1], idGroup[2], idPlayer[5] ); + checkHR( DP_OK, hr ); + + hr = IDirectPlayX_AddGroupToGroup( pDP[1], idGroup[2], idGroup[1] ); + checkHR( DP_OK, hr ); + + /* Purge queues */ + check_messages( pDP[0], idPlayer, 6, &callbackData ); + checkStr( "S2,S1,S0," "S2,S1,S0," "S2,S1,S0," + "S2,S1,S0," "S2,S1,S0," "S2,S1,S0," + "S2,S1,S0,", callbackData.szTrace1 ); + check_messages( pDP[1], idPlayer, 6, &callbackData ); + checkStr( "S5,S4,S3," "S5,S4,S3," "S5,S4,S3," + "S5,S4,S3," "S5,S4,S3," "S5,S4,S3," + "S5,S4,S3,", callbackData.szTrace1 ); + + + /* Sending broadcast messages, and checking who receives them */ + + dwDataSize = 4; + /* 0 -> * */ + hr = IDirectPlayX_Send( pDP[0], idPlayer[0], DPID_ALLPLAYERS, 0, + lpData, dwDataSize ); + checkHR( DP_OK, hr ); + check_messages( pDP[0], idPlayer, 6, &callbackData ); + checkStr( "02,01,", callbackData.szTrace1 ); + check_messages( pDP[1], idPlayer, 6, &callbackData ); + checkStr( "05,04,03,", callbackData.szTrace1 ); + + /* 0 -> g0 */ + hr = IDirectPlayX_Send( pDP[0], idPlayer[0], idGroup[0], 0, + lpData, dwDataSize ); + checkHR( DP_OK, hr ); + check_messages( pDP[0], idPlayer, 6, &callbackData ); + checkStr( "02,01,", callbackData.szTrace1 ); + check_messages( pDP[1], idPlayer, 6, &callbackData ); + checkStr( "", callbackData.szTrace1 ); + /* 0 -> g1 */ + hr = IDirectPlayX_Send( pDP[0], idPlayer[0], idGroup[1], 0, + lpData, dwDataSize ); + checkHR( DP_OK, hr ); + check_messages( pDP[0], idPlayer, 6, &callbackData ); + checkStr( "", callbackData.szTrace1 ); + check_messages( pDP[1], idPlayer, 6, &callbackData ); + checkStr( "04,03,", callbackData.szTrace1 ); + /* 0 -> g2 */ + hr = IDirectPlayX_Send( pDP[0], idPlayer[0], idGroup[2], 0, + lpData, dwDataSize ); + checkHR( DP_OK, hr ); + check_messages( pDP[0], idPlayer, 6, &callbackData ); + checkStr( "", callbackData.szTrace1 ); + check_messages( pDP[1], idPlayer, 6, &callbackData ); + checkStr( "05,04,", callbackData.szTrace1 ); + + /* 3 -> * */ + hr = IDirectPlayX_Send( pDP[1], idPlayer[3], DPID_ALLPLAYERS, 0, + lpData, dwDataSize ); + checkHR( DP_OK, hr ); + check_messages( pDP[0], idPlayer, 6, &callbackData ); + checkStr( "32,31,30,", callbackData.szTrace1 ); + check_messages( pDP[1], idPlayer, 6, &callbackData ); + checkStr( "35,34,", callbackData.szTrace1 ); + /* 3 -> g0 */ + hr = IDirectPlayX_Send( pDP[1], idPlayer[3], idGroup[0], 0, + lpData, dwDataSize ); + checkHR( DP_OK, hr ); + check_messages( pDP[0], idPlayer, 6, &callbackData ); + checkStr( "32,31,30,", callbackData.szTrace1 ); + check_messages( pDP[1], idPlayer, 6, &callbackData ); + checkStr( "", callbackData.szTrace1 ); + /* 3 -> g1 */ + hr = IDirectPlayX_Send( pDP[1], idPlayer[3], idGroup[1], 0, + lpData, dwDataSize ); + checkHR( DP_OK, hr ); + check_messages( pDP[0], idPlayer, 6, &callbackData ); + checkStr( "", callbackData.szTrace1 ); + check_messages( pDP[1], idPlayer, 6, &callbackData ); + checkStr( "34,", callbackData.szTrace1 ); + /* 3 -> g2 */ + hr = IDirectPlayX_Send( pDP[1], idPlayer[3], idGroup[2], 0, + lpData, dwDataSize ); + checkHR( DP_OK, hr ); + check_messages( pDP[0], idPlayer, 6, &callbackData ); + checkStr( "", callbackData.szTrace1 ); + check_messages( pDP[1], idPlayer, 6, &callbackData ); + checkStr( "35,34,", callbackData.szTrace1 ); + + /* 5 -> * */ + hr = IDirectPlayX_Send( pDP[1], idPlayer[5], DPID_ALLPLAYERS, 0, + lpData, dwDataSize ); + checkHR( DP_OK, hr ); + check_messages( pDP[0], idPlayer, 6, &callbackData ); + checkStr( "52,51,50,", callbackData.szTrace1 ); + check_messages( pDP[1], idPlayer, 6, &callbackData ); + checkStr( "54,53,", callbackData.szTrace1 ); + /* 5 -> g0 */ + hr = IDirectPlayX_Send( pDP[1], idPlayer[5], idGroup[0], 0, + lpData, dwDataSize ); + checkHR( DP_OK, hr ); + check_messages( pDP[0], idPlayer, 6, &callbackData ); + checkStr( "52,51,50,", callbackData.szTrace1 ); + check_messages( pDP[1], idPlayer, 6, &callbackData ); + checkStr( "", callbackData.szTrace1 ); + /* 5 -> g1 */ + hr = IDirectPlayX_Send( pDP[1], idPlayer[5], idGroup[1], 0, + lpData, dwDataSize ); + checkHR( DP_OK, hr ); + check_messages( pDP[0], idPlayer, 6, &callbackData ); + checkStr( "", callbackData.szTrace1 ); + check_messages( pDP[1], idPlayer, 6, &callbackData ); + checkStr( "54,53,", callbackData.szTrace1 ); + /* 5 -> g2 */ + hr = IDirectPlayX_Send( pDP[1], idPlayer[5], idGroup[2], 0, + lpData, dwDataSize ); + checkHR( DP_OK, hr ); + check_messages( pDP[0], idPlayer, 6, &callbackData ); + checkStr( "", callbackData.szTrace1 ); + check_messages( pDP[1], idPlayer, 6, &callbackData ); + checkStr( "54,", callbackData.szTrace1 ); + + + HeapFree( GetProcessHeap(), 0, lpData ); + IDirectPlayX_Release( pDP[0] ); + IDirectPlayX_Release( pDP[1] ); + +} + +static void test_groups_cs(void) +{ + + IDirectPlay4 *pDP[2]; + DPSESSIONDESC2 dpsd; + DPID idPlayer[6], idGroup[3]; + CallbackData callbackData; + HRESULT hr; + UINT i; + + DWORD dwDataSize = 1024; + LPVOID lpData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 1024 ); + + + for (i=0; i<2; i++) + { + hr = CoCreateInstance( &CLSID_DirectPlay, NULL, CLSCTX_ALL, + &IID_IDirectPlay4A, (LPVOID*) &pDP[i] ); + ok( SUCCEEDED(hr), "CCI of CLSID_DirectPlay / IID_IDirectPlay4A failed\n" ); + if (FAILED(hr)) return; + } + ZeroMemory( &dpsd, sizeof(DPSESSIONDESC2) ); + dpsd.dwSize = sizeof(DPSESSIONDESC2); + dpsd.guidApplication = appGuid; + dpsd.dwMaxPlayers = 10; + + + init_TCPIP_provider( pDP[0], "127.0.0.1", 0 ); + init_TCPIP_provider( pDP[1], "127.0.0.1", 0 ); + + dpsd.dwFlags = DPSESSION_CLIENTSERVER; + hr = IDirectPlayX_Open( pDP[0], &dpsd, DPOPEN_CREATE ); + todo_wine checkHR( DP_OK, hr ); + dpsd.dwFlags = 0; + hr = IDirectPlayX_EnumSessions( pDP[1], &dpsd, 0, EnumSessions_cb_join, + pDP[1], 0 ); + todo_wine checkHR( DP_OK, hr ); + + if ( hr == DPERR_UNINITIALIZED ) + { + todo_wine win_skip( "dplay not implemented enough for this test yet\n" ); + return; + } + + + /* Create players */ + hr = IDirectPlayX_CreatePlayer( pDP[0], &idPlayer[0], + NULL, NULL, NULL, 0, 0 ); + checkHR( DPERR_ACCESSDENIED, hr ); + hr = IDirectPlayX_CreatePlayer( pDP[0], &idPlayer[0], + NULL, NULL, NULL, 0, + DPPLAYER_SERVERPLAYER ); + checkHR( DP_OK, hr ); + hr = IDirectPlayX_CreatePlayer( pDP[0], &idPlayer[1], + NULL, NULL, NULL, 0, 0 ); + checkHR( DPERR_ACCESSDENIED, hr ); + hr = IDirectPlayX_CreatePlayer( pDP[1], &idPlayer[1], + NULL, NULL, NULL, 0, 0 ); + checkHR( DP_OK, hr ); + hr = IDirectPlayX_CreatePlayer( pDP[1], &idPlayer[2], + NULL, NULL, NULL, 0, 0 ); + checkHR( DP_OK, hr ); + hr = IDirectPlayX_CreatePlayer( pDP[1], &idPlayer[3], + NULL, NULL, NULL, 0, 0 ); + checkHR( DP_OK, hr ); + hr = IDirectPlayX_CreatePlayer( pDP[1], &idPlayer[4], + NULL, NULL, NULL, 0, 0 ); + checkHR( DP_OK, hr ); + hr = IDirectPlayX_CreatePlayer( pDP[1], &idPlayer[5], + NULL, NULL, NULL, 0, 0 ); + checkHR( DP_OK, hr ); + + hr = IDirectPlayX_CreateGroup( pDP[0], &idGroup[0], + NULL, NULL, 0, 0 ); + checkHR( DP_OK, hr ); + hr = IDirectPlayX_CreateGroup( pDP[1], &idGroup[2], + NULL, NULL, 0, 0 ); + checkHR( DP_OK, hr ); + hr = IDirectPlayX_CreateGroupInGroup( pDP[1], idGroup[2], &idGroup[1], + NULL, NULL, 0, 0 ); + checkHR( DP_OK, hr ); + + + /* Purge queues */ + check_messages( pDP[0], idPlayer, 6, &callbackData ); + checkStr( "S0,S0,S0,S0,S0,S0,", callbackData.szTrace1 ); + check_messages( pDP[1], idPlayer, 6, &callbackData ); + checkStr( "S1," "S2,S1," "S3,S2,S1," "S4,S3,S2,S1," + "S5,S4,S3,S2,S1," "S5,S4,S3,S2,S1,", callbackData.szTrace1 ); + + /* + * Player 0 | | pDP 0 + * Player 1 | Group 0 | + * Player 2 | | + * Player 3 | Group 1 ) | + * Player 4 | | Group 2 | pDP 1 + * Player 5 | | + */ + + /* Build groups */ + hr = IDirectPlayX_AddPlayerToGroup( pDP[0], idGroup[0], idPlayer[0] ); + checkHR( DP_OK, hr ); + hr = IDirectPlayX_AddPlayerToGroup( pDP[0], idGroup[0], idPlayer[1] ); + checkHR( DP_OK, hr ); + hr = IDirectPlayX_AddPlayerToGroup( pDP[0], idGroup[0], idPlayer[2] ); + checkHR( DP_OK, hr ); + hr = IDirectPlayX_AddPlayerToGroup( pDP[1], idGroup[1], idPlayer[3] ); + checkHR( DP_OK, hr ); + hr = IDirectPlayX_AddPlayerToGroup( pDP[1], idGroup[1], idPlayer[4] ); + checkHR( DP_OK, hr ); + hr = IDirectPlayX_AddPlayerToGroup( pDP[1], idGroup[2], idPlayer[4] ); + checkHR( DP_OK, hr ); + hr = IDirectPlayX_AddPlayerToGroup( pDP[1], idGroup[2], idPlayer[5] ); + checkHR( DP_OK, hr ); + + hr = IDirectPlayX_AddGroupToGroup( pDP[1], idGroup[2], idGroup[1] ); + checkHR( DP_OK, hr ); + + /* Purge queues */ + check_messages( pDP[0], idPlayer, 6, &callbackData ); + checkStr( "S0,S0,S0,S0,", callbackData.szTrace1 ); + check_messages( pDP[1], idPlayer, 6, &callbackData ); + checkStr( "S5," "S4,S3,S2,S1," "S5,S4,S3,S2,S1," + "S5,S4,S3,S2,S1," "S5,S4,S3,S2,S1,", callbackData.szTrace1 ); + + + /* Sending broadcast messages, and checking who receives them */ + dwDataSize = 4; + /* 0 -> * */ + hr = IDirectPlayX_Send( pDP[0], idPlayer[0], DPID_ALLPLAYERS, 0, + lpData, dwDataSize ); + checkHR( DP_OK, hr ); + check_messages( pDP[0], idPlayer, 6, &callbackData ); + checkStr( "", callbackData.szTrace1 ); + check_messages( pDP[1], idPlayer, 6, &callbackData ); + checkStr( "05,04,03,02,01,", callbackData.szTrace1 ); + + /* 0 -> g0 */ + hr = IDirectPlayX_Send( pDP[0], idPlayer[0], idGroup[0], 0, + lpData, dwDataSize ); + checkHR( DP_OK, hr ); + check_messages( pDP[0], idPlayer, 6, &callbackData ); + checkStr( "", callbackData.szTrace1 ); + check_messages( pDP[1], idPlayer, 6, &callbackData ); + checkStr( "02,01,", callbackData.szTrace1 ); + /* 0 -> g1 */ + hr = IDirectPlayX_Send( pDP[0], idPlayer[0], idGroup[1], 0, + lpData, dwDataSize ); + checkHR( DPERR_INVALIDPARAMS, hr ); + check_messages( pDP[0], idPlayer, 6, &callbackData ); + checkStr( "", callbackData.szTrace1 ); + check_messages( pDP[1], idPlayer, 6, &callbackData ); + checkStr( "", callbackData.szTrace1 ); + /* 0 -> g2 */ + hr = IDirectPlayX_Send( pDP[0], idPlayer[0], idGroup[2], 0, + lpData, dwDataSize ); + checkHR( DPERR_INVALIDPARAMS, hr ); + check_messages( pDP[0], idPlayer, 6, &callbackData ); + checkStr( "", callbackData.szTrace1 ); + check_messages( pDP[1], idPlayer, 6, &callbackData ); + checkStr( "", callbackData.szTrace1 ); + + /* 3 -> * */ + hr = IDirectPlayX_Send( pDP[1], idPlayer[3], DPID_ALLPLAYERS, 0, + lpData, dwDataSize ); + checkHR( DP_OK, hr ); + check_messages( pDP[0], idPlayer, 6, &callbackData ); + checkStr( "30,", callbackData.szTrace1 ); + check_messages( pDP[1], idPlayer, 6, &callbackData ); + checkStr( "35,34,32,31,", callbackData.szTrace1 ); + /* 3 -> g0 */ + hr = IDirectPlayX_Send( pDP[1], idPlayer[3], idGroup[0], 0, + lpData, dwDataSize ); + checkHR( DPERR_INVALIDPARAMS, hr ); + check_messages( pDP[0], idPlayer, 6, &callbackData ); + checkStr( "", callbackData.szTrace1 ); + check_messages( pDP[1], idPlayer, 6, &callbackData ); + checkStr( "", callbackData.szTrace1 ); + /* 3 -> g1 */ + hr = IDirectPlayX_Send( pDP[1], idPlayer[3], idGroup[1], 0, + lpData, dwDataSize ); + checkHR( DP_OK, hr ); + check_messages( pDP[0], idPlayer, 6, &callbackData ); + checkStr( "", callbackData.szTrace1 ); + check_messages( pDP[1], idPlayer, 6, &callbackData ); + checkStr( "34,", callbackData.szTrace1 ); + /* 3 -> g2 */ + hr = IDirectPlayX_Send( pDP[1], idPlayer[3], idGroup[2], 0, + lpData, dwDataSize ); + checkHR( DP_OK, hr ); + check_messages( pDP[0], idPlayer, 6, &callbackData ); + checkStr( "", callbackData.szTrace1 ); + check_messages( pDP[1], idPlayer, 6, &callbackData ); + checkStr( "35,34,", callbackData.szTrace1 ); + + /* 5 -> * */ + hr = IDirectPlayX_Send( pDP[1], idPlayer[5], DPID_ALLPLAYERS, 0, + lpData, dwDataSize ); + checkHR( DP_OK, hr ); + check_messages( pDP[0], idPlayer, 6, &callbackData ); + checkStr( "50,", callbackData.szTrace1 ); + check_messages( pDP[1], idPlayer, 6, &callbackData ); + checkStr( "54,53,52,51,", callbackData.szTrace1 ); + /* 5 -> g0 */ + hr = IDirectPlayX_Send( pDP[1], idPlayer[5], idGroup[0], 0, + lpData, dwDataSize ); + checkHR( DPERR_INVALIDPARAMS, hr ); + check_messages( pDP[0], idPlayer, 6, &callbackData ); + checkStr( "", callbackData.szTrace1 ); + check_messages( pDP[1], idPlayer, 6, &callbackData ); + checkStr( "", callbackData.szTrace1 ); + /* 5 -> g1 */ + hr = IDirectPlayX_Send( pDP[1], idPlayer[5], idGroup[1], 0, + lpData, dwDataSize ); + checkHR( DP_OK, hr ); + check_messages( pDP[0], idPlayer, 6, &callbackData ); + checkStr( "", callbackData.szTrace1 ); + check_messages( pDP[1], idPlayer, 6, &callbackData ); + checkStr( "54,53,", callbackData.szTrace1 ); + /* 5 -> g2 */ + hr = IDirectPlayX_Send( pDP[1], idPlayer[5], idGroup[2], 0, + lpData, dwDataSize ); + checkHR( DP_OK, hr ); + check_messages( pDP[0], idPlayer, 6, &callbackData ); + checkStr( "", callbackData.szTrace1 ); + check_messages( pDP[1], idPlayer, 6, &callbackData ); + checkStr( "54,", callbackData.szTrace1 ); + + + HeapFree( GetProcessHeap(), 0, lpData ); + IDirectPlayX_Release( pDP[0] ); + IDirectPlayX_Release( pDP[1] ); + +} + +/* Send */ + +static void test_Send(void) +{ + + IDirectPlay4 *pDP[2]; + DPSESSIONDESC2 dpsd; + DPID dpid[4], idFrom, idTo; + CallbackData callbackData; + HRESULT hr; + LPCSTR message = "message"; + DWORD messageSize = strlen(message) + 1; + DWORD dwDataSize = 1024; + LPDPMSG_GENERIC lpData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize ); + LPDPMSG_SECUREMESSAGE lpDataSecure; + UINT i; + + + for (i=0; i<2; i++) + { + hr = CoCreateInstance( &CLSID_DirectPlay, NULL, CLSCTX_ALL, + &IID_IDirectPlay4A, (LPVOID*) &pDP[i] ); + ok( SUCCEEDED(hr), "CCI of CLSID_DirectPlay / IID_IDirectPlay4A failed\n" ); + if (FAILED(hr)) return; + } + ZeroMemory( &dpsd, sizeof(DPSESSIONDESC2) ); + + + /* Uninitialized service provider */ + hr = IDirectPlayX_Send( pDP[0], 0, 0, 0, + (LPVOID) message, messageSize ); + checkHR( DPERR_UNINITIALIZED, hr ); + + + init_TCPIP_provider( pDP[0], "127.0.0.1", 0 ); + init_TCPIP_provider( pDP[1], "127.0.0.1", 0 ); + + dpsd.dwSize = sizeof(DPSESSIONDESC2); + dpsd.guidApplication = appGuid; + dpsd.dwMaxPlayers = 10; + IDirectPlayX_Open( pDP[0], &dpsd, DPOPEN_CREATE ); + IDirectPlayX_EnumSessions( pDP[1], &dpsd, 0, EnumSessions_cb_join, + pDP[1], 0 ); + IDirectPlayX_Open( pDP[0], &dpsd, DPOPEN_CREATE ); + + + /* Incorrect players */ + hr = IDirectPlayX_Send( pDP[0], 0, 1, 2, + (LPVOID) message, messageSize ); + todo_wine checkHR( DPERR_INVALIDPLAYER, hr ); + + if ( hr == DPERR_UNINITIALIZED ) + { + todo_wine win_skip( "Send not implemented\n" ); + return; + } + + + IDirectPlayX_CreatePlayer( pDP[0], &dpid[0], NULL, NULL, NULL, 0, 0 ); + IDirectPlayX_CreatePlayer( pDP[0], &dpid[1], NULL, NULL, NULL, 0, 0 ); + IDirectPlayX_CreatePlayer( pDP[0], &dpid[2], NULL, NULL, NULL, 0, 0 ); + IDirectPlayX_CreatePlayer( pDP[1], &dpid[3], NULL, NULL, NULL, 0, 0 ); + + /* Purge player creation messages */ + check_messages( pDP[0], dpid, 4, &callbackData ); + checkStr( "S0," "S1,S0," "S2,S1,S0,", callbackData.szTrace1 ); + check_messages( pDP[1], dpid, 4, &callbackData ); + checkStr( "", callbackData.szTrace1 ); + + + /* Message to self: no error, but no message is sent */ + hr = IDirectPlayX_Send( pDP[0], dpid[0], dpid[0], 0, + (LPVOID) message, messageSize ); + checkHR( DP_OK, hr ); + + /* Send a message from a remote player */ + hr = IDirectPlayX_Send( pDP[1], dpid[0], dpid[1], 0, + (LPVOID) message, messageSize ); + checkHR( DPERR_ACCESSDENIED, hr ); + hr = IDirectPlayX_Send( pDP[1], dpid[0], dpid[3], 0, + (LPVOID) message, messageSize ); + checkHR( DPERR_ACCESSDENIED, hr ); + + /* Null message */ + hr = IDirectPlayX_Send( pDP[0], dpid[0], dpid[1], 0, + NULL, messageSize ); + checkHR( DPERR_INVALIDPARAMS, hr ); + hr = IDirectPlayX_Send( pDP[0], dpid[0], dpid[1], 0, + (LPVOID) message, 0 ); + checkHR( DPERR_INVALIDPARAMS, hr ); + + + /* Checking no message was sent */ + check_messages( pDP[0], dpid, 4, &callbackData ); + checkStr( "", callbackData.szTrace1 ); + check_messages( pDP[1], dpid, 4, &callbackData ); + checkStr( "", callbackData.szTrace1 ); + + + /* Regular parameters */ + hr = IDirectPlayX_Send( pDP[0], dpid[0], dpid[1], + 0, + (LPVOID) message, messageSize ); + checkHR( DP_OK, hr ); + + hr = IDirectPlayX_Receive( pDP[0], &dpid[0], &dpid[1], + DPRECEIVE_FROMPLAYER | DPRECEIVE_TOPLAYER, + lpData, &dwDataSize ); + checkHR( DP_OK, hr ); + checkStr( message, (LPSTR) lpData ); + check( strlen(message)+1, dwDataSize ); + + check_messages( pDP[0], dpid, 4, &callbackData ); + checkStr( "", callbackData.szTrace1 ); + check_messages( pDP[1], dpid, 4, &callbackData ); + checkStr( "", callbackData.szTrace1 ); + + + /* Message to a remote player */ + hr = IDirectPlayX_Send( pDP[0], dpid[0], dpid[3], 0, + (LPVOID) message, messageSize ); + checkHR( DP_OK, hr ); + + hr = IDirectPlayX_Receive( pDP[0], &dpid[0], &dpid[3], + DPRECEIVE_FROMPLAYER | DPRECEIVE_TOPLAYER, + lpData, &dwDataSize ); + checkHR( DPERR_NOMESSAGES, hr ); + hr = IDirectPlayX_Receive( pDP[1], &dpid[0], &dpid[3], + DPRECEIVE_FROMPLAYER | DPRECEIVE_TOPLAYER, + lpData, &dwDataSize ); + checkHR( DP_OK, hr ); + checkStr( message, (LPSTR) lpData ); + check( strlen(message)+1, dwDataSize ); + + check_messages( pDP[0], dpid, 4, &callbackData ); + checkStr( "", callbackData.szTrace1 ); + check_messages( pDP[1], dpid, 4, &callbackData ); + checkStr( "", callbackData.szTrace1 ); + + + /* Broadcast */ + + hr = IDirectPlayX_Send( pDP[0], dpid[0], DPID_ALLPLAYERS, 0, + (LPVOID) message, messageSize ); + checkHR( DP_OK, hr ); + + for (i=1; i<3; i++) + { + hr = IDirectPlayX_Receive( pDP[0], &dpid[0], &dpid[i], + DPRECEIVE_FROMPLAYER | DPRECEIVE_TOPLAYER, + lpData, &dwDataSize ); + checkHR( DP_OK, hr ); + checkStr( message, (LPSTR) lpData ); + } + hr = IDirectPlayX_Receive( pDP[1], &dpid[0], &dpid[3], + DPRECEIVE_FROMPLAYER | DPRECEIVE_TOPLAYER, + lpData, &dwDataSize ); + checkHR( DP_OK, hr ); + checkStr( message, (LPSTR) lpData ); + + check_messages( pDP[0], dpid, 4, &callbackData ); + checkStr( "", callbackData.szTrace1 ); + check_messages( pDP[1], dpid, 4, &callbackData ); + checkStr( "", callbackData.szTrace1 ); + + + hr = IDirectPlayX_Send( pDP[0], DPID_ALLPLAYERS, dpid[1], + 0, + (LPVOID) message, messageSize ); + checkHR( DPERR_INVALIDPLAYER, hr ); + hr = IDirectPlayX_Send( pDP[0], DPID_ALLPLAYERS, DPID_ALLPLAYERS, + 0, + (LPVOID) message, messageSize ); + checkHR( DPERR_INVALIDPLAYER, hr ); + + + /* Flags */ + hr = IDirectPlayX_Send( pDP[0], dpid[0], dpid[1], + DPSEND_GUARANTEED, + (LPVOID) message, messageSize ); + checkHR( DP_OK, hr ); + + hr = IDirectPlayX_Receive( pDP[0], &dpid[0], &dpid[1], + DPRECEIVE_FROMPLAYER | DPRECEIVE_TOPLAYER, + lpData, &dwDataSize ); + checkHR( DP_OK, hr ); + checkStr( message, (LPSTR)lpData ); + + /* - Inorrect flags */ + hr = IDirectPlayX_Send( pDP[0], dpid[0], dpid[1], + DPSEND_ENCRYPTED, + (LPVOID) message, messageSize ); + checkHR( DPERR_INVALIDPARAMS, hr ); + hr = IDirectPlayX_Send( pDP[0], dpid[0], dpid[1], + DPSEND_SIGNED, + (LPVOID) message, messageSize ); + checkHR( DPERR_INVALIDPARAMS, hr ); + hr = IDirectPlayX_Send( pDP[0], dpid[0], dpid[1], + DPSEND_ENCRYPTED | DPSEND_SIGNED, + (LPVOID) message, messageSize ); + checkHR( DPERR_INVALIDPARAMS, hr ); + + /* - Correct flags, but session is not secure */ + hr = IDirectPlayX_Send( pDP[0], dpid[0], dpid[1], + DPSEND_ENCRYPTED | DPSEND_GUARANTEED, + (LPVOID) message, messageSize ); + checkHR( DPERR_INVALIDPARAMS, hr ); + hr = IDirectPlayX_Send( pDP[0], dpid[0], dpid[1], + DPSEND_SIGNED | DPSEND_GUARANTEED, + (LPVOID) message, messageSize ); + checkHR( DPERR_INVALIDPARAMS, hr ); + hr = IDirectPlayX_Send( pDP[0], dpid[0], dpid[1], + ( DPSEND_ENCRYPTED | + DPSEND_SIGNED | + DPSEND_GUARANTEED ), + (LPVOID) message, messageSize ); + checkHR( DPERR_INVALIDPARAMS, hr ); + + /* - Correct flags, secure session incorrectly opened (without flags) */ + hr = IDirectPlayX_Close( pDP[0] ); + checkHR( DP_OK, hr ); + + dpsd.dwFlags = 0; + hr = IDirectPlayX_SecureOpen( pDP[0], &dpsd, DPOPEN_CREATE, NULL, NULL ); + checkHR( DP_OK, hr ); + for (i=0; i<2; i++) + IDirectPlayX_CreatePlayer( pDP[0], &dpid[i], NULL, NULL, NULL, 0, 0 ); + + hr = IDirectPlayX_Send( pDP[0], dpid[0], dpid[1], + DPSEND_ENCRYPTED | DPSEND_GUARANTEED, + (LPVOID) message, messageSize ); + checkHR( DPERR_INVALIDPARAMS, hr ); + hr = IDirectPlayX_Send( pDP[0], dpid[0], dpid[1], + DPSEND_SIGNED | DPSEND_GUARANTEED, + (LPVOID) message, messageSize ); + checkHR( DPERR_INVALIDPARAMS, hr ); + hr = IDirectPlayX_Send( pDP[0], dpid[0], dpid[1], + ( DPSEND_ENCRYPTED | + DPSEND_SIGNED | + DPSEND_GUARANTEED ), + (LPVOID) message, messageSize ); + checkHR( DPERR_INVALIDPARAMS, hr ); + + /* - Correct flags, secure session */ + hr = IDirectPlayX_Close( pDP[0] ); + checkHR( DP_OK, hr ); + + dpsd.dwFlags = DPSESSION_SECURESERVER; + hr = IDirectPlayX_SecureOpen( pDP[0], &dpsd, DPOPEN_CREATE, NULL, NULL ); + checkHR( DP_OK, hr ); + IDirectPlayX_CreatePlayer( pDP[0], &dpid[0], NULL, NULL, NULL, 0, 0 ); + IDirectPlayX_CreatePlayer( pDP[0], &dpid[1], NULL, NULL, NULL, 0, 0 ); + + /* Purge */ + check_messages( pDP[0], dpid, 6, &callbackData ); + checkStr( "S0,", callbackData.szTrace1 ); + + + hr = IDirectPlayX_Send( pDP[0], dpid[0], dpid[1], + DPSEND_ENCRYPTED | DPSEND_GUARANTEED, + (LPVOID) message, messageSize ); + checkHR( DP_OK, hr ); + hr = IDirectPlayX_Send( pDP[0], dpid[0], dpid[1], + DPSEND_SIGNED | DPSEND_GUARANTEED, + (LPVOID) message, messageSize ); + checkHR( DP_OK, hr ); + hr = IDirectPlayX_Send( pDP[0], dpid[0], dpid[1], + ( DPSEND_ENCRYPTED | + DPSEND_SIGNED | + DPSEND_GUARANTEED ), + (LPVOID) message, messageSize ); + checkHR( DP_OK, hr ); + + + for (i=0; i<3; i++) + { + dwDataSize = 1024; + hr = IDirectPlayX_Receive( pDP[0], &idFrom, &idTo, 0, lpData, + &dwDataSize ); + + lpDataSecure = (LPDPMSG_SECUREMESSAGE) lpData; + + checkHR( DP_OK, hr ); + checkConv( DPSYS_SECUREMESSAGE, lpData->dwType, dpMsgType2str ); + check( DPID_SYSMSG, idFrom ); + check( dpid[1], idTo ); + check( dpid[0], lpDataSecure->dpIdFrom ); + checkStr( message, (LPSTR) lpDataSecure->lpData ); + check( strlen(message)+1, lpDataSecure->dwDataSize ); + + switch(i) + { + case 0: + checkFlags( DPSEND_ENCRYPTED, + lpDataSecure->dwFlags, + FLAGS_DPSEND ); + break; + case 1: + checkFlags( DPSEND_SIGNED, + lpDataSecure->dwFlags, + FLAGS_DPSEND ); + break; + case 2: + checkFlags( DPSEND_SIGNED | DPSEND_ENCRYPTED, + lpDataSecure->dwFlags, + FLAGS_DPSEND ); + break; + default: break; + } + } + check_messages( pDP[0], dpid, 4, &callbackData ); + checkStr( "", callbackData.szTrace1 ); + + + /* - Even in a secure session, incorrect flags still not working */ + hr = IDirectPlayX_Send( pDP[0], dpid[0], dpid[1], + DPSEND_ENCRYPTED, + (LPVOID) message, messageSize ); + checkHR( DPERR_INVALIDPARAMS, hr ); + hr = IDirectPlayX_Send( pDP[0], dpid[0], dpid[1], + DPSEND_SIGNED, + (LPVOID) message, messageSize ); + checkHR( DPERR_INVALIDPARAMS, hr ); + hr = IDirectPlayX_Send( pDP[0], dpid[0], dpid[1], + DPSEND_ENCRYPTED | DPSEND_SIGNED, + (LPVOID) message, messageSize ); + checkHR( DPERR_INVALIDPARAMS, hr ); + + + HeapFree( GetProcessHeap(), 0, lpData ); + IDirectPlayX_Release( pDP[0] ); + IDirectPlayX_Release( pDP[1] ); + +} + +/* Receive */ + +static void test_Receive(void) +{ + + IDirectPlay4 *pDP; + DPSESSIONDESC2 dpsd; + DPID dpid[4], idFrom, idTo; + HRESULT hr; + LPCSTR message = "message"; + DWORD messageSize = strlen(message) + 1; + DWORD dwDataSize = 1024; + LPDPMSG_GENERIC lpData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, + dwDataSize ); + LPDPMSG_CREATEPLAYERORGROUP lpDataCreate; + LPDPMSG_DESTROYPLAYERORGROUP lpDataDestroy; + + DWORD dwCount; + UINT i; + + + hr = CoCreateInstance( &CLSID_DirectPlay, NULL, CLSCTX_ALL, + &IID_IDirectPlay4A, (LPVOID*) &pDP ); + ok( SUCCEEDED(hr), "CCI of CLSID_DirectPlay / IID_IDirectPlay4A failed\n" ); + if (FAILED(hr)) return; + + ZeroMemory( &dpsd, sizeof(DPSESSIONDESC2) ); + dpsd.dwSize = sizeof(DPSESSIONDESC2); + dpsd.guidApplication = appGuid; + + init_TCPIP_provider( pDP, "127.0.0.1", 0 ); + + IDirectPlayX_Open( pDP, &dpsd, DPOPEN_CREATE ); + + + /* Invalid parameters */ + hr = IDirectPlayX_Receive( pDP, NULL, &idTo, 0, + lpData, &dwDataSize ); + todo_wine checkHR( DPERR_INVALIDPARAMS, hr ); + + if ( hr == DPERR_UNINITIALIZED ) + { + todo_wine win_skip( "Receive not implemented\n" ); + return; + } + + hr = IDirectPlayX_Receive( pDP, &idFrom, NULL, 0, + lpData, &dwDataSize ); + checkHR( DPERR_INVALIDPARAMS, hr ); + hr = IDirectPlayX_Receive( pDP, &idFrom, &idTo, 0, + lpData, NULL ); + checkHR( DPERR_INVALIDPARAMS, hr ); + dwDataSize = -1; + hr = IDirectPlayX_Receive( pDP, &idFrom, &idTo, 0, + lpData, &dwDataSize ); + checkHR( DPERR_INVALIDPARAMS, hr ); + + /* No messages yet */ + hr = IDirectPlayX_Receive( pDP, &idFrom, &idTo, 0, + NULL, &dwDataSize ); + checkHR( DPERR_NOMESSAGES, hr ); + dwDataSize = 0; + hr = IDirectPlayX_Receive( pDP, &idFrom, &idTo, 0, + lpData, &dwDataSize ); + checkHR( DPERR_NOMESSAGES, hr ); + + + IDirectPlayX_CreatePlayer( pDP, &dpid[0], NULL, 0, NULL, 0, 0 ); + IDirectPlayX_CreatePlayer( pDP, &dpid[1], NULL, 0, NULL, 0, + DPPLAYER_SPECTATOR ); + IDirectPlayX_CreatePlayer( pDP, &dpid[2], NULL, 0, NULL, 0, 0 ); + IDirectPlayX_CreatePlayer( pDP, &dpid[3], NULL, 0, NULL, 0, 0 ); + + + /* 0, 1, 2, 3 */ + /* 3, 2, 1, 0 */ + for (i=0; i<4; i++) + { + IDirectPlayX_GetMessageCount( pDP, dpid[i], &dwCount ); + check( 3-i, dwCount ); + } + + + IDirectPlayX_DestroyPlayer( pDP, dpid[3] ); + IDirectPlayX_DestroyPlayer( pDP, dpid[1] ); + + + /* 0, 1, 2, 3 */ + /* 5, 5, 3, 3 */ + IDirectPlayX_GetMessageCount( pDP, dpid[0], &dwCount ); + check( 5, dwCount ); + IDirectPlayX_GetMessageCount( pDP, dpid[1], &dwCount ); + check( 5, dwCount ); + IDirectPlayX_GetMessageCount( pDP, dpid[2], &dwCount ); + check( 3, dwCount ); + IDirectPlayX_GetMessageCount( pDP, dpid[3], &dwCount ); + check( 3, dwCount ); + + + /* Buffer too small */ + hr = IDirectPlayX_Receive( pDP, &idFrom, &idFrom, 0, + NULL, &dwDataSize ); + checkHR( DPERR_BUFFERTOOSMALL, hr ); + check( 48, dwDataSize ); + dwDataSize = 0; + hr = IDirectPlayX_Receive( pDP, &idTo, &idFrom, 0, + lpData, &dwDataSize ); + checkHR( DPERR_BUFFERTOOSMALL, hr ); + check( 48, dwDataSize ); + + + /* Checking the order or reception */ + for (i=0; i<11; i++) + { + dwDataSize = 1024; + hr = IDirectPlayX_Receive( pDP, &idFrom, &idTo, 0, + lpData, &dwDataSize ); + + checkHR( DP_OK, hr ); + check( DPID_SYSMSG, idFrom ); + + if (i<6) /* Player creation */ + { + checkConv( DPSYS_CREATEPLAYERORGROUP, lpData->dwType, dpMsgType2str ); + check( 48, dwDataSize ); + lpDataCreate = (LPDPMSG_CREATEPLAYERORGROUP) lpData; + check( DPPLAYERTYPE_PLAYER, lpDataCreate->dwPlayerType ); + checkLP( NULL, lpDataCreate->lpData ); + check( 0, lpDataCreate->dwDataSize ); + checkLP( NULL, U1(lpDataCreate->dpnName).lpszShortNameA ); + check( 0, lpDataCreate->dpIdParent ); + } + else /* Player destruction */ + { + checkConv( DPSYS_DESTROYPLAYERORGROUP, lpData->dwType, + dpMsgType2str ); + check( 52, dwDataSize ); + lpDataDestroy = (LPDPMSG_DESTROYPLAYERORGROUP) lpData; + check( DPPLAYERTYPE_PLAYER, lpDataDestroy->dwPlayerType ); + checkLP( NULL, lpDataDestroy->lpLocalData ); + check( 0, lpDataDestroy->dwLocalDataSize ); + checkLP( NULL, lpDataDestroy->lpRemoteData ); + check( 0, lpDataDestroy->dwRemoteDataSize ); + checkLP( NULL, U1(lpDataDestroy->dpnName).lpszShortNameA ); + check( 0, lpDataDestroy->dpIdParent ); + } + + switch(i) + { + /* 1 -> 0 */ + case 0: + lpDataCreate = (LPDPMSG_CREATEPLAYERORGROUP) lpData; + check( dpid[0], idTo ); + check( dpid[1], lpDataCreate->dpId ); + check( 1, lpDataCreate->dwCurrentPlayers ); + checkFlags( DPPLAYER_LOCAL|DPPLAYER_SPECTATOR, lpDataCreate->dwFlags, + FLAGS_DPPLAYER|FLAGS_DPGROUP ); + break; + + /* 2 -> 1,0 */ + case 1: + check( dpid[1], idTo ); + lpDataCreate = (LPDPMSG_CREATEPLAYERORGROUP) lpData; + check( dpid[2], lpDataCreate->dpId ); + check( 2, lpDataCreate->dwCurrentPlayers ); + checkFlags( DPPLAYER_LOCAL, lpDataCreate->dwFlags, + FLAGS_DPPLAYER | FLAGS_DPGROUP ); + break; + case 2: + check( dpid[0], idTo ); + lpDataCreate = (LPDPMSG_CREATEPLAYERORGROUP) lpData; + check( dpid[2], lpDataCreate->dpId ); + check( 2, lpDataCreate->dwCurrentPlayers ); + checkFlags( DPPLAYER_LOCAL, lpDataCreate->dwFlags, + FLAGS_DPPLAYER | FLAGS_DPGROUP ); + break; + + /* 3 -> 2,1,0 */ + case 3: + check( dpid[2], idTo ); + lpDataCreate = (LPDPMSG_CREATEPLAYERORGROUP) lpData; + check( dpid[3], lpDataCreate->dpId ); + check( 3, lpDataCreate->dwCurrentPlayers ); + checkFlags( DPPLAYER_LOCAL, lpDataCreate->dwFlags, + FLAGS_DPPLAYER | FLAGS_DPGROUP ); + break; + case 4: + check( dpid[1], idTo ); + lpDataCreate = (LPDPMSG_CREATEPLAYERORGROUP) lpData; + check( dpid[3], lpDataCreate->dpId ); + check( 3, lpDataCreate->dwCurrentPlayers ); + checkFlags( DPPLAYER_LOCAL, lpDataCreate->dwFlags, + FLAGS_DPPLAYER | FLAGS_DPGROUP ); + break; + case 5: + check( dpid[0], idTo ); + lpDataCreate = (LPDPMSG_CREATEPLAYERORGROUP) lpData; + check( dpid[3], lpDataCreate->dpId ); + check( 3, lpDataCreate->dwCurrentPlayers ); + checkFlags( DPPLAYER_LOCAL, lpDataCreate->dwFlags, + FLAGS_DPPLAYER | FLAGS_DPGROUP ); + break; + + /* 3 -> 2,1,0 */ + case 6: + check( dpid[2], idTo ); + lpDataDestroy = (LPDPMSG_DESTROYPLAYERORGROUP) lpData; + check( dpid[3], lpDataDestroy->dpId ); + checkFlags( DPPLAYER_LOCAL, lpDataDestroy->dwFlags, + FLAGS_DPPLAYER | FLAGS_DPGROUP ); + break; + case 7: + check( dpid[1], idTo ); + lpDataDestroy = (LPDPMSG_DESTROYPLAYERORGROUP) lpData; + check( dpid[3], lpDataDestroy->dpId ); + checkFlags( DPPLAYER_LOCAL, lpDataDestroy->dwFlags, + FLAGS_DPPLAYER | FLAGS_DPGROUP ); + break; + case 8: + check( dpid[0], idTo ); + lpDataDestroy = (LPDPMSG_DESTROYPLAYERORGROUP) lpData; + check( dpid[3], lpDataDestroy->dpId ); + checkFlags( DPPLAYER_LOCAL, lpDataDestroy->dwFlags, + FLAGS_DPPLAYER | FLAGS_DPGROUP ); + break; + + /* 1 -> 2,0 */ + case 9: + check( dpid[2], idTo ); + lpDataDestroy = (LPDPMSG_DESTROYPLAYERORGROUP) lpData; + check( dpid[1], lpDataDestroy->dpId ); + checkFlags( DPPLAYER_LOCAL | + DPPLAYER_SPECTATOR, lpDataDestroy->dwFlags, + FLAGS_DPPLAYER | FLAGS_DPGROUP ); + break; + case 10: + check( dpid[0], idTo ); + lpDataDestroy = (LPDPMSG_DESTROYPLAYERORGROUP) lpData; + check( dpid[1], lpDataDestroy->dpId ); + checkFlags( DPPLAYER_LOCAL | + DPPLAYER_SPECTATOR, lpDataDestroy->dwFlags, + FLAGS_DPPLAYER | FLAGS_DPGROUP ); + break; + + default: + trace( "%s\n", dpMsgType2str(lpData->dwType) ); + break; + } + } + + hr = IDirectPlayX_Receive( pDP, &idFrom, &idTo, 0, lpData, &dwDataSize ); + checkHR( DPERR_NOMESSAGES, hr ); + + + /* New data message */ + hr = IDirectPlayX_Send( pDP, dpid[0], dpid[2], 0, + (LPVOID) message, messageSize ); + checkHR( DP_OK, hr ); + + + /* Ensuring DPRECEIVE_PEEK doesn't remove the messages from the queue */ + for (i=0; i<10; i++) + { + hr = IDirectPlayX_Receive( pDP, &idFrom, &idTo, DPRECEIVE_PEEK, + lpData, &dwDataSize ); + checkHR( DP_OK, hr ); + checkStr( message, (LPSTR) lpData ); + } + + /* Removing the message from the queue */ + hr = IDirectPlayX_Receive( pDP, &idFrom, &idTo, 0, lpData, &dwDataSize ); + checkHR( DP_OK, hr ); + check( idFrom, dpid[0] ); + check( idTo, dpid[2] ); + checkStr( message, (LPSTR) lpData ); + + hr = IDirectPlayX_Receive( pDP, &idFrom, &idTo, 0, lpData, &dwDataSize ); + checkHR( DPERR_NOMESSAGES, hr ); + + + HeapFree( GetProcessHeap(), 0, lpData ); + IDirectPlayX_Release( pDP ); + +} + +/* GetMessageCount */ + +static void test_GetMessageCount(void) +{ + + IDirectPlay4 *pDP[2]; + DPSESSIONDESC2 dpsd; + DPID dpid[4]; + HRESULT hr; + UINT i; + DWORD dwCount; + + DWORD dwDataSize = 1024; + LPVOID lpData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize ); + CallbackData callbackData; + + + for (i=0; i<2; i++) + { + hr = CoCreateInstance( &CLSID_DirectPlay, NULL, CLSCTX_ALL, + &IID_IDirectPlay4A, (LPVOID*) &pDP[i] ); + ok( SUCCEEDED(hr), "CCI of CLSID_DirectPlay / IID_IDirectPlay4A failed\n" ); + if (FAILED(hr)) return; + } + ZeroMemory( &dpsd, sizeof(DPSESSIONDESC2) ); + + dwCount = -1; + hr = IDirectPlayX_GetMessageCount( pDP[0], 0, &dwCount ); + todo_wine checkHR( DPERR_UNINITIALIZED, hr ); + check( -1, dwCount ); + + if ( hr == DP_OK ) + { + todo_wine win_skip( "GetMessageCount not implemented\n" ); + return; + } + + + init_TCPIP_provider( pDP[0], "127.0.0.1", 0 ); + init_TCPIP_provider( pDP[1], "127.0.0.1", 0 ); + + + dwCount = -1; + hr = IDirectPlayX_GetMessageCount( pDP[0], 0, &dwCount ); + checkHR( DP_OK, hr ); + check( 0, dwCount ); + + + dpsd.dwSize = sizeof(DPSESSIONDESC2); + dpsd.guidApplication = appGuid; + dpsd.dwMaxPlayers = 10; + IDirectPlayX_Open( pDP[0], &dpsd, DPOPEN_CREATE ); + IDirectPlayX_EnumSessions( pDP[1], &dpsd, 0, EnumSessions_cb_join, + pDP[1], 0 ); + + IDirectPlayX_CreatePlayer( pDP[0], &dpid[0], NULL, NULL, NULL, 0, 0 ); + IDirectPlayX_CreatePlayer( pDP[0], &dpid[1], NULL, NULL, NULL, 0, 0 ); + IDirectPlayX_CreatePlayer( pDP[1], &dpid[3], NULL, NULL, NULL, 0, 0 ); + IDirectPlayX_CreatePlayer( pDP[0], &dpid[2], NULL, NULL, NULL, 0, 0 ); + + + /* Incorrect parameters */ + dwCount = -1; + hr = IDirectPlayX_GetMessageCount( pDP[0], dpid[0], NULL ); + checkHR( DPERR_INVALIDPARAMS, hr ); + check( -1, dwCount ); + + dwCount = -1; + hr = IDirectPlayX_GetMessageCount( pDP[0], 0, NULL ); + checkHR( DPERR_INVALIDPARAMS, hr ); + check( -1, dwCount ); + + dwCount = -1; + hr = IDirectPlayX_GetMessageCount( pDP[0], -1, &dwCount ); + checkHR( DPERR_INVALIDPLAYER, hr ); + check( -1, dwCount ); + + + /* Correct parameters */ + /* Player creation messages */ + dwCount = -1; + hr = IDirectPlayX_GetMessageCount( pDP[0], 0, &dwCount ); + checkHR( DP_OK, hr ); + check( 5, dwCount ); + + dwCount = -1; + hr = IDirectPlayX_GetMessageCount( pDP[1], 0, &dwCount ); + checkHR( DP_OK, hr ); + check( 1, dwCount ); + + dwCount = -1; + hr = IDirectPlayX_GetMessageCount( pDP[0], dpid[0], &dwCount ); + checkHR( DP_OK, hr ); + check( 3, dwCount ); + + dwCount = -1; + hr = IDirectPlayX_GetMessageCount( pDP[0], dpid[1], &dwCount ); + checkHR( DP_OK, hr ); + check( 2, dwCount ); + + dwCount = -1; + hr = IDirectPlayX_GetMessageCount( pDP[0], dpid[3], &dwCount ); + checkHR( DP_OK, hr ); + /* Remote player: doesn't throw error but result is 0 and not 1 */ + check( 0, dwCount ); + + dwCount = -1; + hr = IDirectPlayX_GetMessageCount( pDP[1], dpid[3], &dwCount ); + checkHR( DP_OK, hr ); + check( 1, dwCount ); + + dwCount = -1; + hr = IDirectPlayX_GetMessageCount( pDP[0], dpid[1], &dwCount ); + checkHR( DP_OK, hr ); + check( 2, dwCount ); + + + /* Purge queues */ + check_messages( pDP[0], dpid, 6, &callbackData ); + checkStr( "S0,S1,S0,S1,S0,", callbackData.szTrace1 ); + check_messages( pDP[1], dpid, 6, &callbackData ); + checkStr( "S3,", callbackData.szTrace1 ); + + + /* Ensure queues is purged */ + dwCount = -1; + hr = IDirectPlayX_GetMessageCount( pDP[0], 0, &dwCount ); + checkHR( DP_OK, hr ); + check( 0, dwCount ); + + dwCount = -1; + hr = IDirectPlayX_GetMessageCount( pDP[1], 0, &dwCount ); + checkHR( DP_OK, hr ); + check( 0, dwCount ); + + + /* Send data messages */ + for (i=0; i<5; i++) + IDirectPlayX_Send( pDP[0], dpid[0], dpid[1], 0, lpData, dwDataSize ); + for (i=0; i<6; i++) + IDirectPlayX_Send( pDP[0], dpid[1], dpid[2], 0, lpData, dwDataSize ); + for (i=0; i<7; i++) + IDirectPlayX_Send( pDP[0], dpid[2], dpid[3], 0, lpData, dwDataSize ); + + + /* Check all messages are in the queues */ + dwCount = -1; + hr = IDirectPlayX_GetMessageCount( pDP[0], 0, &dwCount ); + checkHR( DP_OK, hr ); + check( 11, dwCount ); + + dwCount = -1; + hr = IDirectPlayX_GetMessageCount( pDP[1], 0, &dwCount ); + checkHR( DP_OK, hr ); + check( 7, dwCount ); + + dwCount = -1; + hr = IDirectPlayX_GetMessageCount( pDP[0], dpid[0], &dwCount ); + checkHR( DP_OK, hr ); + check( 0, dwCount ); + + dwCount = -1; + hr = IDirectPlayX_GetMessageCount( pDP[0], dpid[1], &dwCount ); + checkHR( DP_OK, hr ); + check( 5, dwCount ); + + dwCount = -1; + hr = IDirectPlayX_GetMessageCount( pDP[0], dpid[2], &dwCount ); + checkHR( DP_OK, hr ); + check( 6, dwCount ); + + dwCount = -1; + hr = IDirectPlayX_GetMessageCount( pDP[1], dpid[3], &dwCount ); + checkHR( DP_OK, hr ); + check( 7, dwCount ); + + + /* Purge queues again */ + check_messages( pDP[0], dpid, 6, &callbackData ); + checkStr( "01,01,01,01,01," + "12,12,12,12,12,12,", callbackData.szTrace1 ); + check_messages( pDP[1], dpid, 6, &callbackData ); + checkStr( "23,23,23,23,23,23,23,", callbackData.szTrace1 ); + + + /* Check queues are purged */ + dwCount = -1; + hr = IDirectPlayX_GetMessageCount( pDP[0], 0, &dwCount ); + checkHR( DP_OK, hr ); + check( 0, dwCount ); + + dwCount = -1; + hr = IDirectPlayX_GetMessageCount( pDP[1], 0, &dwCount ); + checkHR( DP_OK, hr ); + check( 0, dwCount ); + + dwCount = -1; + hr = IDirectPlayX_GetMessageCount( pDP[0], dpid[0], &dwCount ); + checkHR( DP_OK, hr ); + check( 0, dwCount ); + + dwCount = -1; + hr = IDirectPlayX_GetMessageCount( pDP[0], dpid[1], &dwCount ); + checkHR( DP_OK, hr ); + check( 0, dwCount ); + + dwCount = -1; + hr = IDirectPlayX_GetMessageCount( pDP[0], dpid[2], &dwCount ); + checkHR( DP_OK, hr ); + check( 0, dwCount ); + + dwCount = -1; + hr = IDirectPlayX_GetMessageCount( pDP[1], dpid[3], &dwCount ); + checkHR( DP_OK, hr ); + check( 0, dwCount ); + + + HeapFree( GetProcessHeap(), 0, lpData ); + IDirectPlayX_Release( pDP[0] ); + IDirectPlayX_Release( pDP[1] ); + +} + +/* GetMessageQueue */ + +static void test_GetMessageQueue(void) +{ + + IDirectPlay4 *pDP[2]; + DPSESSIONDESC2 dpsd; + DPID dpid[4]; + CallbackData callbackData; + HRESULT hr; + UINT i; + DWORD dwNumMsgs, dwNumBytes; + + DWORD dwDataSize = 1024; + LPVOID lpData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize ); + + + for (i=0; i<2; i++) + { + hr = CoCreateInstance( &CLSID_DirectPlay, NULL, CLSCTX_ALL, + &IID_IDirectPlay4A, (LPVOID*) &pDP[i] ); + ok( SUCCEEDED(hr), "CCI of CLSID_DirectPlay / IID_IDirectPlay4A failed\n" ); + if (FAILED(hr)) return; + } + ZeroMemory( &dpsd, sizeof(DPSESSIONDESC2) ); + + + dwNumMsgs = dwNumBytes = -1; + hr = IDirectPlayX_GetMessageQueue( pDP[0], 0, 0, 0, + &dwNumMsgs, &dwNumBytes ); + todo_wine checkHR( DPERR_UNINITIALIZED, hr ); + check( -1, dwNumMsgs ); + check( -1, dwNumBytes ); + + if ( hr == DP_OK ) + { + todo_wine win_skip( "GetMessageQueue not implemented\n" ); + return; + } + + + init_TCPIP_provider( pDP[0], "127.0.0.1", 0 ); + init_TCPIP_provider( pDP[1], "127.0.0.1", 0 ); + + + dwNumMsgs = dwNumBytes = -1; + hr = IDirectPlayX_GetMessageQueue( pDP[0], 0, 0, 0, + &dwNumMsgs, &dwNumBytes ); + checkHR( DP_OK, hr ); + check( 0, dwNumMsgs ); + check( 0, dwNumBytes ); + + + dpsd.dwSize = sizeof(DPSESSIONDESC2); + dpsd.guidApplication = appGuid; + dpsd.dwMaxPlayers = 10; + IDirectPlayX_Open( pDP[0], &dpsd, DPOPEN_CREATE ); + IDirectPlayX_EnumSessions( pDP[1], &dpsd, 0, EnumSessions_cb_join, + pDP[1], 0 ); + + IDirectPlayX_CreatePlayer( pDP[0], &dpid[0], NULL, NULL, NULL, 0, 0 ); + IDirectPlayX_CreatePlayer( pDP[0], &dpid[1], NULL, NULL, NULL, 0, 0 ); + IDirectPlayX_CreatePlayer( pDP[1], &dpid[3], NULL, NULL, NULL, 0, 0 ); + IDirectPlayX_CreatePlayer( pDP[0], &dpid[2], NULL, NULL, NULL, 0, 0 ); + + + + /* Incorrect parameters */ + dwNumMsgs = dwNumBytes = -1; + hr = IDirectPlayX_GetMessageQueue( pDP[0], -1, dpid[1], + 0, + &dwNumMsgs, &dwNumBytes ); + checkHR( DPERR_INVALIDPLAYER, hr ); + check( -1, dwNumMsgs ); + check( -1, dwNumBytes ); + + dwNumMsgs = dwNumBytes = -1; + hr = IDirectPlayX_GetMessageQueue( pDP[0], dpid[0], -1, + 0, + &dwNumMsgs, &dwNumBytes ); + checkHR( DPERR_INVALIDPLAYER, hr ); + check( -1, dwNumMsgs ); + check( -1, dwNumBytes ); + + dwNumMsgs = dwNumBytes = -1; + hr = IDirectPlayX_GetMessageQueue( pDP[0], dpid[0], dpid[0], + -1, + &dwNumMsgs, &dwNumBytes ); + checkHR( DPERR_INVALIDFLAGS, hr ); + check( -1, dwNumMsgs ); + check( -1, dwNumBytes ); + + dwNumMsgs = dwNumBytes = -1; + hr = IDirectPlayX_GetMessageQueue( pDP[0], dpid[0], dpid[1], + ( DPMESSAGEQUEUE_SEND | + DPMESSAGEQUEUE_RECEIVE ), + &dwNumMsgs, &dwNumBytes ); + checkHR( DPERR_INVALIDFLAGS, hr ); + check( -1, dwNumMsgs ); + check( -1, dwNumBytes ); + + /* - Remote players */ + dwNumMsgs = dwNumBytes = -1; + hr = IDirectPlayX_GetMessageQueue( pDP[0], 0, dpid[3], + DPMESSAGEQUEUE_RECEIVE, + &dwNumMsgs, &dwNumBytes ); + checkHR( DPERR_INVALIDPLAYER, hr ); /* Player 3 is remote */ + check( -1, dwNumMsgs ); + check( -1, dwNumBytes ); + + dwNumMsgs = dwNumBytes = -1; + hr = IDirectPlayX_GetMessageQueue( pDP[0], dpid[3], 0, + DPMESSAGEQUEUE_SEND, + &dwNumMsgs, &dwNumBytes ); + checkHR( DPERR_INVALIDPLAYER, hr ); /* Player 3 is remote */ + check( -1, dwNumMsgs ); + check( -1, dwNumBytes ); + + /* - Remote players, this time in the right place */ + dwNumMsgs = dwNumBytes = -1; + hr = IDirectPlayX_GetMessageQueue( pDP[0], 0, dpid[3], + DPMESSAGEQUEUE_SEND, + &dwNumMsgs, &dwNumBytes ); + checkHR( DP_OK, hr ); + check( 0, dwNumMsgs ); + check( 0, dwNumBytes ); + + dwNumMsgs = dwNumBytes = -1; + hr = IDirectPlayX_GetMessageQueue( pDP[0], dpid[3], 0, + DPMESSAGEQUEUE_RECEIVE, + &dwNumMsgs, &dwNumBytes ); + checkHR( DP_OK, hr ); + check( 0, dwNumMsgs ); + check( 0, dwNumBytes ); + + + /* Correct parameters */ + dwNumMsgs = dwNumBytes = -1; + hr = IDirectPlayX_GetMessageQueue( pDP[0], 0, dpid[1], + DPMESSAGEQUEUE_RECEIVE, + &dwNumMsgs, &dwNumBytes ); + checkHR( DP_OK, hr ); + check( 2, dwNumMsgs ); + check( 96, dwNumBytes ); + + dwNumMsgs = dwNumBytes = -1; + hr = IDirectPlayX_GetMessageQueue( pDP[0], dpid[0], 0, + DPMESSAGEQUEUE_RECEIVE, + &dwNumMsgs, &dwNumBytes ); + checkHR( DP_OK, hr ); + check( 0, dwNumMsgs ); + check( 0, dwNumBytes ); + + dwNumMsgs = dwNumBytes = -1; + hr = IDirectPlayX_GetMessageQueue( pDP[0], 0, 0, + DPMESSAGEQUEUE_RECEIVE, + &dwNumMsgs, &dwNumBytes ); + checkHR( DP_OK, hr ); + check( 5, dwNumMsgs ); + check( 240, dwNumBytes ); + + dwNumMsgs = dwNumBytes = -1; + hr = IDirectPlayX_GetMessageQueue( pDP[0], dpid[0], dpid[1], + DPMESSAGEQUEUE_RECEIVE, + NULL, &dwNumBytes ); + checkHR( DP_OK, hr ); + check( -1, dwNumMsgs ); + check( 0, dwNumBytes ); + + dwNumMsgs = dwNumBytes = -1; + hr = IDirectPlayX_GetMessageQueue( pDP[0], dpid[0], dpid[1], + DPMESSAGEQUEUE_RECEIVE, + &dwNumMsgs, NULL ); + checkHR( DP_OK, hr ); + check( 0, dwNumMsgs ); + check( -1, dwNumBytes ); + + dwNumMsgs = dwNumBytes = -1; + hr = IDirectPlayX_GetMessageQueue( pDP[0], dpid[0], dpid[1], + DPMESSAGEQUEUE_RECEIVE, + NULL, NULL ); + checkHR( DP_OK, hr ); + check( -1, dwNumMsgs ); + check( -1, dwNumBytes ); + + dwNumMsgs = dwNumBytes = -1; + hr = IDirectPlayX_GetMessageQueue( pDP[0], dpid[0], dpid[1], + DPMESSAGEQUEUE_RECEIVE, + &dwNumMsgs, &dwNumBytes ); + checkHR( DP_OK, hr ); + check( 0, dwNumMsgs ); + check( 0, dwNumBytes ); + + + /* Purge messages */ + check_messages( pDP[0], dpid, 6, &callbackData ); + checkStr( "S0,S1,S0,S1,S0,", callbackData.szTrace1 ); + check_messages( pDP[1], dpid, 6, &callbackData ); + checkStr( "S3,", callbackData.szTrace1 ); + + /* Check queues are empty */ + dwNumMsgs = dwNumBytes = -1; + hr = IDirectPlayX_GetMessageQueue( pDP[0], 0, 0, + DPMESSAGEQUEUE_RECEIVE, + &dwNumMsgs, &dwNumBytes ); + checkHR( DP_OK, hr ); + check( 0, dwNumMsgs ); + check( 0, dwNumBytes ); + + + /* Sending 4 data messages from 0 to 1 */ + /* 3 from 0 to 3 */ + /* 2 from 1 to 3 */ + for (i=0; i<4; i++) + IDirectPlayX_Send( pDP[0], dpid[0], dpid[1], 0, lpData, dwDataSize ); + for (i=0; i<3; i++) + IDirectPlayX_Send( pDP[0], dpid[0], dpid[3], 0, lpData, dwDataSize ); + for (i=0; i<2; i++) + IDirectPlayX_Send( pDP[0], dpid[1], dpid[3], 0, lpData, dwDataSize ); + + + dwNumMsgs = dwNumBytes = -1; + hr = IDirectPlayX_GetMessageQueue( pDP[0], dpid[0], dpid[1], + DPMESSAGEQUEUE_RECEIVE, + &dwNumMsgs, &dwNumBytes ); + checkHR( DP_OK, hr ); + check( 4, dwNumMsgs ); + check( 4*dwDataSize, dwNumBytes ); + + dwNumMsgs = dwNumBytes = -1; + hr = IDirectPlayX_GetMessageQueue( pDP[1], dpid[0], dpid[3], + DPMESSAGEQUEUE_RECEIVE, + &dwNumMsgs, &dwNumBytes ); + checkHR( DP_OK, hr ); + check( 3, dwNumMsgs ); + check( 3*dwDataSize, dwNumBytes ); + + dwNumMsgs = dwNumBytes = -1; + hr = IDirectPlayX_GetMessageQueue( pDP[1], dpid[1], dpid[3], + DPMESSAGEQUEUE_RECEIVE, + &dwNumMsgs, &dwNumBytes ); + checkHR( DP_OK, hr ); + check( 2, dwNumMsgs ); + check( 2*dwDataSize, dwNumBytes ); + + dwNumMsgs = dwNumBytes = -1; + hr = IDirectPlayX_GetMessageQueue( pDP[0], dpid[0], 0, + DPMESSAGEQUEUE_RECEIVE, + &dwNumMsgs, &dwNumBytes ); + checkHR( DP_OK, hr ); + check( 4, dwNumMsgs ); + check( 4*dwDataSize, dwNumBytes ); + + dwNumMsgs = dwNumBytes = -1; + hr = IDirectPlayX_GetMessageQueue( pDP[1], dpid[0], 0, + DPMESSAGEQUEUE_RECEIVE, + &dwNumMsgs, &dwNumBytes ); + checkHR( DP_OK, hr ); + check( 3, dwNumMsgs ); + check( 3*dwDataSize, dwNumBytes ); + + dwNumMsgs = dwNumBytes = -1; + hr = IDirectPlayX_GetMessageQueue( pDP[1], 0, dpid[3], + DPMESSAGEQUEUE_RECEIVE, + &dwNumMsgs, &dwNumBytes ); + checkHR( DP_OK, hr ); + check( 5, dwNumMsgs ); + check( 5*dwDataSize, dwNumBytes ); + + dwNumMsgs = dwNumBytes = -1; + hr = IDirectPlayX_GetMessageQueue( pDP[0], 0, 0, + DPMESSAGEQUEUE_RECEIVE, + &dwNumMsgs, &dwNumBytes ); + checkHR( DP_OK, hr ); + check( 4, dwNumMsgs ); + check( 4*dwDataSize, dwNumBytes ); + + dwNumMsgs = dwNumBytes = -1; + hr = IDirectPlayX_GetMessageQueue( pDP[1], 0, 0, + DPMESSAGEQUEUE_RECEIVE, + &dwNumMsgs, &dwNumBytes ); + checkHR( DP_OK, hr ); + check( 5, dwNumMsgs ); + check( 5*dwDataSize, dwNumBytes ); + + + dwNumMsgs = dwNumBytes = -1; + hr = IDirectPlayX_GetMessageQueue( pDP[0], dpid[0], dpid[1], + DPMESSAGEQUEUE_SEND, + &dwNumMsgs, &dwNumBytes ); + checkHR( DP_OK, hr ); + check( 0, dwNumMsgs ); + check( 0, dwNumBytes ); + + dwNumMsgs = dwNumBytes = -1; + hr = IDirectPlayX_GetMessageQueue( pDP[0], dpid[0], dpid[1], + 0, + &dwNumMsgs, &dwNumBytes ); + checkHR( DP_OK, hr ); + check( 0, dwNumMsgs ); + check( 0, dwNumBytes ); + + + HeapFree( GetProcessHeap(), 0, lpData ); + IDirectPlayX_Release( pDP[0] ); + IDirectPlayX_Release( pDP[1] ); + +} + +/* Remote data replication */ + +static void test_remote_data_replication(void) +{ + + IDirectPlay4 *pDP[2]; + DPSESSIONDESC2 dpsd; + DPID dpid[2], idFrom, idTo; + CallbackData callbackData; + HRESULT hr; + UINT i, j; + DWORD dwFlags, dwDataSize = 1024; + DWORD dwCount; + + LPDPMSG_SETPLAYERORGROUPDATA lpData = HeapAlloc( GetProcessHeap(), + HEAP_ZERO_MEMORY, + dwDataSize ); + + LPCSTR lpDataLocal[] = { "local_0", "local_1" }; + LPCSTR lpDataRemote[] = { "remote_0", "remote_1" }; + LPCSTR lpDataFake = "ugly_fake_data"; + LPSTR lpDataGet = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 32 ); + DWORD dwDataSizeLocal = strlen(lpDataLocal[0])+1, + dwDataSizeRemote = strlen(lpDataRemote[0])+1, + dwDataSizeFake = strlen(lpDataFake)+1, + dwDataSizeGet; + + + for (i=0; i<2; i++) + { + hr = CoCreateInstance( &CLSID_DirectPlay, NULL, CLSCTX_ALL, + &IID_IDirectPlay4A, (LPVOID*) &pDP[i] ); + ok( SUCCEEDED(hr), "CCI of CLSID_DirectPlay / IID_IDirectPlay4A failed\n" ); + if (FAILED(hr)) return; + init_TCPIP_provider( pDP[i], "127.0.0.1", 0 ); + } + ZeroMemory( &dpsd, sizeof(DPSESSIONDESC2) ); + dpsd.dwSize = sizeof(DPSESSIONDESC2); + dpsd.guidApplication = appGuid; + + /* Host */ + hr = IDirectPlayX_Open( pDP[0], &dpsd, DPOPEN_CREATE ); + todo_wine checkHR( DP_OK, hr ); + + if ( hr == DPERR_UNINITIALIZED ) + { + todo_wine win_skip( "dplay not implemented enough for this test yet\n" ); + return; + } + + hr = IDirectPlayX_CreatePlayer( pDP[0], &dpid[0], + NULL, NULL, NULL, 0, 0 ); + checkHR( DP_OK, hr ); + + /* Peer */ + hr = IDirectPlayX_EnumSessions( pDP[1], &dpsd, 0, EnumSessions_cb_join, + pDP[1], 0 ); + checkHR( DP_OK, hr ); + + hr = IDirectPlayX_CreatePlayer( pDP[1], &dpid[1], + NULL, NULL, NULL, 0, 0 ); + checkHR( DP_OK, hr ); + + /* Check players */ + for (i=0; i<2; i++) + { + /* Local (0,0) (1,1) */ + IDirectPlayX_GetPlayerFlags( pDP[i], dpid[i], &dwFlags ); + checkFlags( DPPLAYER_LOCAL, dwFlags, FLAGS_DPPLAYER ); + /* Remote (0,1) (1,0) */ + IDirectPlayX_GetPlayerFlags( pDP[i], dpid[!i], &dwFlags ); + checkFlags( 0, dwFlags, FLAGS_DPPLAYER ); + } + + /* Set data for a local player */ + for (i=0; i<2; i++) + { + hr = IDirectPlayX_SetPlayerData( pDP[i], dpid[i], + (LPVOID) lpDataLocal[i], + dwDataSizeLocal, + DPSET_LOCAL ); + checkHR( DP_OK, hr ); + hr = IDirectPlayX_SetPlayerData( pDP[i], dpid[i], + (LPVOID) lpDataRemote[i], + dwDataSizeRemote, + DPSET_REMOTE ); + checkHR( DP_OK, hr ); + } + + /* Retrieve data locally (0->0, 1->1) */ + for (i=0; i<2; i++) + { + dwDataSizeGet = dwDataSizeFake; + strcpy( lpDataGet, lpDataFake ); + hr = IDirectPlayX_GetPlayerData( pDP[i], dpid[i], + lpDataGet, &dwDataSizeGet, + DPGET_LOCAL ); + checkHR( DP_OK, hr ); + check( dwDataSizeLocal, dwDataSizeGet ); + checkStr( lpDataLocal[i], lpDataGet ); + + dwDataSizeGet = dwDataSizeFake; + strcpy( lpDataGet, lpDataFake ); + hr = IDirectPlayX_GetPlayerData( pDP[i], dpid[i], + lpDataGet, &dwDataSizeGet, + DPGET_REMOTE ); + checkHR( DP_OK, hr ); + check( dwDataSizeRemote, dwDataSizeGet ); + checkStr( lpDataRemote[i], lpDataGet ); + } + + + /* Set data for a remote player */ + /* This should fail with DPERR_ACCESSDENIED, + but for some reason it doesn't */ + for (i=0; i<2; i++) + { + IDirectPlayX_SetPlayerData( pDP[i], dpid[!i], + (LPVOID) lpDataLocal[!i], + dwDataSizeLocal, + DPSET_LOCAL ); + checkHR( DP_OK, hr ); + IDirectPlayX_SetPlayerData( pDP[i], dpid[!i], + (LPVOID) lpDataRemote[!i], + dwDataSizeRemote, + DPSET_REMOTE ); + checkHR( DP_OK, hr ); + } + + /* Retrieve crossed data (0->1, 1->0) */ + for (i=0; i<2; i++) + { + dwDataSizeGet = dwDataSizeFake; + strcpy( lpDataGet, lpDataFake ); + hr = IDirectPlayX_GetPlayerData( pDP[i], dpid[!i], + lpDataGet, &dwDataSizeGet, + DPGET_LOCAL ); + checkHR( DP_OK, hr ); + check( dwDataSizeLocal, dwDataSizeGet ); + checkStr( lpDataLocal[!i], lpDataGet ); + + dwDataSizeGet = dwDataSizeFake; + strcpy( lpDataGet, lpDataFake ); + hr = IDirectPlayX_GetPlayerData( pDP[i], dpid[!i], + lpDataGet, &dwDataSizeGet, + DPGET_REMOTE ); + checkHR( DP_OK, hr ); + check( dwDataSizeRemote, dwDataSizeGet ); + checkStr( lpDataRemote[!i], lpDataGet ); + } + + + /* Purge "new player" messages from queue */ + hr = IDirectPlayX_Receive( pDP[0], &idFrom, &idTo, 0, lpData, &dwDataSize ); + checkHR( DP_OK, hr ); + checkConv( DPSYS_CREATEPLAYERORGROUP, lpData->dwType, dpMsgType2str ); + + /* Check number of messages in queue */ + for (i=0; i<2; i++) + { + IDirectPlayX_GetMessageCount( pDP[i], dpid[i], &dwCount ); + check( 2, dwCount ); + IDirectPlayX_GetMessageCount( pDP[i], dpid[!i], &dwCount ); + check( 0, dwCount ); + } + + /* Checking system messages */ + for (i=0; i<2; i++) + { + for (j=0; j<2; j++) + { + hr = IDirectPlayX_Receive( pDP[i], &idFrom, &idTo, 0, lpData, + &dwDataSize ); + checkHR( DP_OK, hr ); + check( 29, dwDataSize ); + check( DPID_SYSMSG, idFrom ); + check( dpid[i], idTo ); + checkConv( DPSYS_SETPLAYERORGROUPDATA, lpData->dwType, + dpMsgType2str ); + check( DPPLAYERTYPE_PLAYER, lpData->dwPlayerType ); + check( dpid[j], lpData->dpId ); + checkStr( lpDataRemote[j], (LPSTR) lpData->lpData ); + check( dwDataSizeRemote, lpData->dwDataSize ); + dwDataSize = 1024; + } + hr = IDirectPlayX_Receive( pDP[i], &idFrom, &idTo, 0, + lpData, &dwDataSize ); + checkHR( DPERR_NOMESSAGES, hr ); + } + + + /* Changing remote data */ + hr = IDirectPlayX_SetPlayerData( pDP[0], dpid[0], + (LPVOID) lpDataRemote[0], dwDataSizeRemote, + DPSET_REMOTE ); + checkHR( DP_OK, hr ); + + /* Checking system messages (j=0) */ + for (i=0; i<2; i++) + { + hr = IDirectPlayX_Receive( pDP[i], &idFrom, &idTo, 0, + lpData, &dwDataSize ); + checkHR( DP_OK, hr ); + check( 29, dwDataSize ); + check( DPID_SYSMSG, idFrom ); + check( dpid[i], idTo ); + checkConv( DPSYS_SETPLAYERORGROUPDATA, lpData->dwType, dpMsgType2str ); + check( DPPLAYERTYPE_PLAYER, lpData->dwPlayerType ); + check( dpid[0], lpData->dpId ); + checkStr( lpDataRemote[0], (LPSTR) lpData->lpData ); + check( dwDataSizeRemote, lpData->dwDataSize ); + dwDataSize = 1024; + } + + /* Queue is empty */ + check_messages( pDP[0], dpid, 2, &callbackData ); + checkStr( "", callbackData.szTrace1 ); + check_messages( pDP[1], dpid, 2, &callbackData ); + checkStr( "", callbackData.szTrace1 ); + + + HeapFree( GetProcessHeap(), 0, lpDataGet ); + HeapFree( GetProcessHeap(), 0, lpData ); + IDirectPlayX_Release( pDP[0] ); + IDirectPlayX_Release( pDP[1] ); + +} + +/* Host migration */ + +static void test_host_migration(void) +{ + + IDirectPlay4 *pDP[2]; + DPSESSIONDESC2 dpsd; + DPID dpid[2], idFrom, idTo; + HRESULT hr; + UINT i; + DWORD dwCount; + + DWORD dwDataSize = 1024; + LPDPMSG_DESTROYPLAYERORGROUP lpData = HeapAlloc( GetProcessHeap(), + HEAP_ZERO_MEMORY, + dwDataSize ); + + + for (i=0; i<2; i++) + { + hr = CoCreateInstance( &CLSID_DirectPlay, NULL, CLSCTX_ALL, + &IID_IDirectPlay4A, (LPVOID*) &pDP[i] ); + ok( SUCCEEDED(hr), "CCI of CLSID_DirectPlay / IID_IDirectPlay4A failed\n" ); + if (FAILED(hr)) return; + init_TCPIP_provider( pDP[i], "127.0.0.1", 0 ); + } + ZeroMemory( &dpsd, sizeof(DPSESSIONDESC2) ); + dpsd.dwSize = sizeof(DPSESSIONDESC2); + dpsd.guidApplication = appGuid; + dpsd.dwMaxPlayers = 10; + dpsd.dwFlags = DPSESSION_MIGRATEHOST; + + /* Host */ + hr = IDirectPlayX_Open( pDP[0], &dpsd, DPOPEN_CREATE ); + todo_wine checkHR( DP_OK, hr ); + + if ( hr != DP_OK ) + { + todo_wine win_skip( "dplay not implemented enough for this test yet\n" ); + return; + } + + hr = IDirectPlayX_CreatePlayer( pDP[0], &dpid[0], NULL, NULL, NULL, 0, 0 ); + checkHR( DP_OK, hr ); + + /* Peer */ + hr = IDirectPlayX_EnumSessions( pDP[1], &dpsd, 0, EnumSessions_cb_join, + pDP[1], 0 ); + checkHR( DP_OK, hr ); + + hr = IDirectPlayX_CreatePlayer( pDP[1], &dpid[1], NULL, NULL, NULL, 0, 0 ); + checkHR( DP_OK, hr ); + + + /* Host: One message in queue */ + IDirectPlayX_GetMessageCount( pDP[0], dpid[0], &dwCount ); + check( 1, dwCount ); + dwDataSize = 1024; + hr = IDirectPlayX_Receive( pDP[0], &idFrom, &idTo, DPRECEIVE_PEEK, + lpData, &dwDataSize ); + checkHR( DP_OK, hr ); + checkConv( DPSYS_CREATEPLAYERORGROUP, lpData->dwType, dpMsgType2str ); + + /* Peer: No messages */ + IDirectPlayX_GetMessageCount( pDP[1], dpid[1], &dwCount ); + check( 0, dwCount ); + hr = IDirectPlayX_Receive( pDP[1], &idFrom, &idTo, DPRECEIVE_PEEK, + lpData, &dwDataSize ); + checkHR( DPERR_NOMESSAGES, hr ); + + + /* Closing host */ + IDirectPlayX_Close( pDP[0] ); + + + /* Host: Queue is cleaned */ + IDirectPlayX_GetMessageCount( pDP[0], dpid[0], &dwCount ); + check( 0, dwCount ); + hr = IDirectPlayX_Receive( pDP[0], &idFrom, &idTo, DPRECEIVE_PEEK, + lpData, &dwDataSize ); + checkHR( DPERR_NOMESSAGES, hr ); + + /* Peer: gets message of player destruction */ + IDirectPlayX_GetMessageCount( pDP[1], dpid[1], &dwCount ); + check( 2, dwCount ); + dwDataSize = 1024; + hr = IDirectPlayX_Receive( pDP[1], &idFrom, &idTo, DPRECEIVE_PEEK, + lpData, &dwDataSize ); + checkHR( DP_OK, hr ); + checkConv( DPSYS_DESTROYPLAYERORGROUP, lpData->dwType, dpMsgType2str ); + + + /* Message analysis */ + for (i=0; i<2; i++) + { + hr = IDirectPlayX_Receive( pDP[1], &idFrom, &idTo, 0, + lpData, &dwDataSize ); + checkHR( DP_OK, hr ); + check( DPID_SYSMSG, idFrom ); + check( dpid[1], idTo ); /* Peer player id */ + switch(i) + { + case 0: + checkConv( DPSYS_DESTROYPLAYERORGROUP, lpData->dwType, + dpMsgType2str ); + check( DPPLAYERTYPE_PLAYER, lpData->dwPlayerType ); + check( dpid[0], lpData->dpId ); /* Host player id */ + checkLP( NULL, lpData->lpLocalData ); + check( 0, lpData->dwLocalDataSize ); + checkLP( NULL, lpData->lpRemoteData ); + check( 0, lpData->dwRemoteDataSize ); + checkLP( NULL, U1(lpData->dpnName).lpszShortNameA ); + check( 0, lpData->dpIdParent ); + checkFlags( 0, lpData->dwFlags, + FLAGS_DPPLAYER | FLAGS_DPGROUP ); + break; + case 1: + checkConv( DPSYS_HOST, lpData->dwType, dpMsgType2str ); + break; + default: + break; + } + dwDataSize = 1024; + } + hr = IDirectPlayX_Receive( pDP[1], &idFrom, &idTo, 0, lpData, &dwDataSize ); + checkHR( DPERR_NOMESSAGES, hr ); + + + HeapFree( GetProcessHeap(), 0, lpData ); + IDirectPlayX_Release( pDP[0] ); + IDirectPlayX_Release( pDP[1] ); + +} + +static void test_COM(void) +{ + IDirectPlay *dp; + IDirectPlay2A *dp2A; + IDirectPlay2 *dp2; + IDirectPlay3A *dp3A; + IDirectPlay3 *dp3; + IDirectPlay4A *dp4A; + IDirectPlay4 *dp4 = (IDirectPlay4*)0xdeadbeef; + IUnknown *unk; + ULONG refcount; + HRESULT hr; + + /* COM aggregation */ + hr = CoCreateInstance(&CLSID_DirectPlay, (IUnknown*)&dp4, CLSCTX_INPROC_SERVER, &IID_IUnknown, + (void**)&dp4); + ok(hr == CLASS_E_NOAGGREGATION || broken(hr == E_INVALIDARG), + "DirectPlay create failed: %08x, expected CLASS_E_NOAGGREGATION\n", hr); + ok(!dp4 || dp4 == (IDirectPlay4*)0xdeadbeef, "dp4 = %p\n", dp4); + + /* Invalid RIID */ + hr = CoCreateInstance(&CLSID_DirectPlay, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectPlayLobby, + (void**)&dp4); + ok(hr == E_NOINTERFACE, "DirectPlay create failed: %08x, expected E_NOINTERFACE\n", hr); + + /* Different refcount for all DirectPlay Interfaces */ + hr = CoCreateInstance(&CLSID_DirectPlay, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectPlay4, + (void**)&dp4); + ok(hr == S_OK, "DirectPlay create failed: %08x, expected S_OK\n", hr); + refcount = IDirectPlayX_AddRef(dp4); + ok(refcount == 2, "refcount == %u, expected 2\n", refcount); + + hr = IDirectPlayX_QueryInterface(dp4, &IID_IDirectPlay2A, (void**)&dp2A); + ok(hr == S_OK, "QueryInterface for IID_IDirectPlay2A failed: %08x\n", hr); + refcount = IDirectPlay2_AddRef(dp2A); + ok(refcount == 2, "refcount == %u, expected 2\n", refcount); + IDirectPlay2_Release(dp2A); + + hr = IDirectPlayX_QueryInterface(dp4, &IID_IDirectPlay2, (void**)&dp2); + ok(hr == S_OK, "QueryInterface for IID_IDirectPlay2 failed: %08x\n", hr); + refcount = IDirectPlay2_AddRef(dp2); + ok(refcount == 2, "refcount == %u, expected 2\n", refcount); + IDirectPlay2_Release(dp2); + + hr = IDirectPlayX_QueryInterface(dp4, &IID_IDirectPlay3A, (void**)&dp3A); + ok(hr == S_OK, "QueryInterface for IID_IDirectPlay3A failed: %08x\n", hr); + refcount = IDirectPlay3_AddRef(dp3A); + ok(refcount == 2, "refcount == %u, expected 2\n", refcount); + IDirectPlay3_Release(dp3A); + + hr = IDirectPlayX_QueryInterface(dp4, &IID_IDirectPlay3, (void**)&dp3); + ok(hr == S_OK, "QueryInterface for IID_IDirectPlay3 failed: %08x\n", hr); + refcount = IDirectPlay3_AddRef(dp3); + ok(refcount == 2, "refcount == %u, expected 2\n", refcount); + IDirectPlay3_Release(dp3); + + hr = IDirectPlayX_QueryInterface(dp4, &IID_IDirectPlay4A, (void**)&dp4A); + ok(hr == S_OK, "QueryInterface for IID_IDirectPlay4A failed: %08x\n", hr); + refcount = IDirectPlayX_AddRef(dp4A); + ok(refcount == 2, "refcount == %u, expected 2\n", refcount); + IDirectPlayX_Release(dp4A); + + /* IDirectPlay and IUnknown share a refcount */ + hr = IDirectPlayX_QueryInterface(dp4, &IID_IDirectPlay, (void**)&dp); + ok(hr == S_OK, "QueryInterface for IID_IDirectPlay failed: %08x\n", hr); + refcount = IDirectPlayX_AddRef(dp); + ok(refcount == 2, "refcount == %u, expected 2\n", refcount); + IDirectPlay_Release(dp); + + hr = IDirectPlayX_QueryInterface(dp4, &IID_IUnknown, (void**)&unk); + ok(hr == S_OK, "QueryInterface for IID_IUnknown failed: %08x\n", hr); + refcount = IUnknown_AddRef(unk); + ok(refcount == 3, "refcount == %u, expected 3\n", refcount); + refcount = IUnknown_Release(unk); + ok(refcount == 2, "refcount == %u, expected 2\n", refcount); + + IUnknown_Release(unk); + IDirectPlay_Release(dp); + IDirectPlayX_Release(dp4A); + IDirectPlay3_Release(dp3); + IDirectPlay3_Release(dp3A); + IDirectPlay2_Release(dp2); + IDirectPlay2_Release(dp2A); + IDirectPlayX_Release(dp4); + refcount = IDirectPlayX_Release(dp4); + ok(refcount == 0, "refcount == %u, expected 0\n", refcount); +} + +static void test_COM_dplobby(void) +{ + IDirectPlayLobby *dpl = (IDirectPlayLobby*)0xdeadbeef; + IDirectPlayLobbyA *dplA; + IDirectPlayLobby2A *dpl2A; + IDirectPlayLobby2 *dpl2; + IDirectPlayLobby3A *dpl3A; + IDirectPlayLobby3 *dpl3; + IUnknown *unk; + ULONG refcount; + HRESULT hr; + + /* COM aggregation */ + hr = CoCreateInstance(&CLSID_DirectPlayLobby, (IUnknown*)&dpl, CLSCTX_INPROC_SERVER, + &IID_IUnknown, (void**)&dpl); + ok(hr == CLASS_E_NOAGGREGATION || broken(hr == E_INVALIDARG), + "DirectPlayLobby create failed: %08x, expected CLASS_E_NOAGGREGATION\n", hr); + ok(!dpl || dpl == (IDirectPlayLobby*)0xdeadbeef, "dp4 = %p\n", dpl); + + /* Invalid RIID */ + hr = CoCreateInstance(&CLSID_DirectPlayLobby, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectPlay, + (void**)&dpl); + ok(hr == E_NOINTERFACE, "DirectPlayLobby create failed: %08x, expected E_NOINTERFACE\n", hr); + + /* Different refcount for all DirectPlayLobby Interfaces */ + hr = CoCreateInstance(&CLSID_DirectPlayLobby, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectPlayLobby, + (void**)&dpl); + ok(hr == S_OK, "DirectPlayLobby create failed: %08x, expected S_OK\n", hr); + refcount = IDirectPlayLobby_AddRef(dpl); + ok(refcount == 2, "refcount == %u, expected 2\n", refcount); + + hr = IDirectPlayLobby_QueryInterface(dpl, &IID_IDirectPlayLobbyA, (void**)&dplA); + ok(hr == S_OK, "QueryInterface for IID_IDirectPlayLobbyA failed: %08x\n", hr); + refcount = IDirectPlayLobby_AddRef(dplA); + ok(refcount == 2, "refcount == %u, expected 2\n", refcount); + IDirectPlayLobby_Release(dplA); + + hr = IDirectPlayLobby_QueryInterface(dpl, &IID_IDirectPlayLobby2, (void**)&dpl2); + ok(hr == S_OK, "QueryInterface for IID_IDirectPlayLobby2 failed: %08x\n", hr); + refcount = IDirectPlayLobby_AddRef(dpl2); + ok(refcount == 2, "refcount == %u, expected 2\n", refcount); + IDirectPlayLobby_Release(dpl2); + + hr = IDirectPlayLobby_QueryInterface(dpl, &IID_IDirectPlayLobby2A, (void**)&dpl2A); + ok(hr == S_OK, "QueryInterface for IID_IDirectPlayLobby2A failed: %08x\n", hr); + refcount = IDirectPlayLobby_AddRef(dpl2A); + ok(refcount == 2, "refcount == %u, expected 2\n", refcount); + IDirectPlayLobby_Release(dpl2A); + + hr = IDirectPlayLobby_QueryInterface(dpl, &IID_IDirectPlayLobby3, (void**)&dpl3); + ok(hr == S_OK, "QueryInterface for IID_IDirectPlayLobby3 failed: %08x\n", hr); + refcount = IDirectPlayLobby_AddRef(dpl3); + ok(refcount == 2, "refcount == %u, expected 2\n", refcount); + IDirectPlayLobby_Release(dpl3); + + hr = IDirectPlayLobby_QueryInterface(dpl, &IID_IDirectPlayLobby3A, (void**)&dpl3A); + ok(hr == S_OK, "QueryInterface for IID_IDirectPlayLobby3A failed: %08x\n", hr); + refcount = IDirectPlayLobby_AddRef(dpl3A); + ok(refcount == 2, "refcount == %u, expected 2\n", refcount); + IDirectPlayLobby_Release(dpl3A); + + /* IDirectPlayLobby and IUnknown share a refcount */ + hr = IDirectPlayX_QueryInterface(dpl, &IID_IUnknown, (void**)&unk); + ok(hr == S_OK, "QueryInterface for IID_IUnknown failed: %08x\n", hr); + refcount = IUnknown_AddRef(unk); + ok(refcount == 4, "refcount == %u, expected 4\n", refcount); + IDirectPlayLobby_Release(unk); + + IUnknown_Release(unk); + IDirectPlayLobby_Release(dpl3); + IDirectPlayLobby_Release(dpl3A); + IDirectPlayLobby_Release(dpl2); + IDirectPlayLobby_Release(dpl2A); + IDirectPlayLobby_Release(dplA); + IDirectPlayLobby_Release(dpl); + refcount = IDirectPlayLobby_Release(dpl); + ok(refcount == 0, "refcount == %u, expected 0\n", refcount); +} + + +START_TEST(dplayx) +{ + CoInitialize( NULL ); + + test_COM(); + test_COM_dplobby(); + + if (!winetest_interactive) + { + skip("Run in interactive mode to run dplayx tests.\n"); + return; + } + + trace("Running in interactive mode, tests will take a while\n"); + + test_DirectPlayCreate(); + test_EnumConnections(); + test_InitializeConnection(); + + test_GetCaps(); + /* test_Open() takes almost a minute, */ + test_Open(); + /* test_EnumSession takes three minutes */ + test_EnumSessions(); + test_SessionDesc(); + + /* test_CreatePlayer() takes over a minute */ + test_CreatePlayer(); + test_GetPlayerCaps(); + test_PlayerData(); + test_PlayerName(); + + /* test_GetPlayerAccount() takes over 30s */ + test_GetPlayerAccount(); + test_GetPlayerAddress(); + test_GetPlayerFlags(); + + test_CreateGroup(); + test_GroupOwner(); + + test_EnumPlayers(); + test_EnumGroups(); + test_EnumGroupsInGroup(); + + test_groups_p2p(); + test_groups_cs(); + + test_Send(); + test_Receive(); + test_GetMessageCount(); + test_GetMessageQueue(); + + test_remote_data_replication(); + test_host_migration(); + + CoUninitialize(); +} diff --git a/rostests/winetests/dplayx/testlist.c b/rostests/winetests/dplayx/testlist.c new file mode 100644 index 00000000000..c13dcaf3bb8 --- /dev/null +++ b/rostests/winetests/dplayx/testlist.c @@ -0,0 +1,12 @@ +/* Automatically generated file; DO NOT EDIT!! */ + +#define STANDALONE +#include + +extern void func_dplayx(void); + +const struct test winetest_testlist[] = +{ + { "dplayx", func_dplayx }, + { 0, 0 } +};