From 0e41a8680902604efef2099ee1560aecf5fe908c Mon Sep 17 00:00:00 2001 From: Ismael Barros Date: Mon, 11 Aug 2008 04:23:38 +0200 Subject: [PATCH] dplayx: Code to send CreatePlayer messages --- dlls/dplayx/dplay.c | 223 +++++++++++++++++++++++------------------- dlls/dplayx/dplay_global.h | 5 + dlls/dplayx/dplayx_messages.c | 118 ++++++++++++++++++++++ dlls/dplayx/dplayx_messages.h | 1 + 4 files changed, 249 insertions(+), 98 deletions(-) diff --git a/dlls/dplayx/dplay.c b/dlls/dplayx/dplay.c index ef52b29826d..09fb759e7dd 100644 --- a/dlls/dplayx/dplay.c +++ b/dlls/dplayx/dplay.c @@ -50,9 +50,6 @@ extern HRESULT DPL_CreateCompoundAddress /* Local function prototypes */ -static lpPlayerData DP_CreatePlayer( IDirectPlay2Impl* iface, LPDPID lpid, - LPDPNAME lpName, DWORD dwFlags, - HANDLE hEvent, BOOL bAnsi ); static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, const DPNAME *lpSrc, BOOL bAnsi ); static void DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize ); @@ -1264,52 +1261,137 @@ DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags, } -/* This function will just create the storage for the new player. */ -static -lpPlayerData DP_CreatePlayer( IDirectPlay2Impl* This, LPDPID lpid, - LPDPNAME lpName, DWORD dwFlags, - HANDLE hEvent, BOOL bAnsi ) + +HRESULT DP_CreatePlayer( IDirectPlay2Impl* This, DPID idPlayer, + LPDPNAME lpName, DWORD dwFlags, + LPVOID lpData, DWORD dwDataSize, + HANDLE hEvent, BOOL bAnsi, + lpPlayerData* lplpPlayer ) { - lpPlayerData lpPData; + /* Create the storage for a new player and insert + * it in the list of players. */ + + lpPlayerList lpPList = NULL; + lpPlayerData lpPlayer; + HRESULT hr; + + TRACE( "(%p)->(0x%08x,%p,0x%08x,%p,%d,%p,%u,%p)\n", + This, idPlayer, lpName, dwFlags, lpData, + dwDataSize, hEvent, bAnsi, lplpPlayer ); - TRACE( "(%p)->(%p,%p,%u)\n", This, lpid, lpName, bAnsi ); + /* Verify that we don't already have this player */ + DPQ_FIND_ENTRY( This->dp2->lpSysGroup->players, players, + lpPData->dpid, ==, idPlayer, lpPList ); + if ( lpPList != NULL ) + { + hr = DPERR_CANTCREATEPLAYER; + goto end; + } /* Allocate the storage for the player and associate it with list element */ - lpPData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpPData ) ); - if( lpPData == NULL ) + lpPlayer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpPlayer ) ); + if( lpPlayer == NULL ) { - return NULL; + hr = DPERR_CANTCREATEPLAYER; + goto end; } - /* Set the desired player ID */ - lpPData->dpid = *lpid; + if ( lplpPlayer != NULL ) + { + *lplpPlayer = lpPlayer; + } - DP_CopyDPNAMEStruct( &lpPData->name, lpName, bAnsi ); + lpPlayer->dpid = idPlayer; + lpPlayer->dwFlags = dwFlags; - lpPData->dwFlags = dwFlags; + DP_CopyDPNAMEStruct( &lpPlayer->name, lpName, bAnsi ); /* If we were given an event handle, duplicate it */ if( hEvent != 0 ) { if( !DuplicateHandle( GetCurrentProcess(), hEvent, - GetCurrentProcess(), &lpPData->hEvent, - 0, FALSE, DUPLICATE_SAME_ACCESS ) - ) + GetCurrentProcess(), &lpPlayer->hEvent, + 0, FALSE, DUPLICATE_SAME_ACCESS ) ) { - /* FIXME: Memory leak */ ERR( "Can't duplicate player msg handle %p\n", hEvent ); + hr = DPERR_CANTCREATEPLAYER; + goto end; } } - /* Initialize the SP data section */ - lpPData->lpSPPlayerData = DPSP_CreateSPPlayerData(); + /* Set player data */ + if ( lpData != NULL ) + { + DP_SetPlayerData( lpPlayer, DPSET_REMOTE, lpData, dwDataSize ); + } - TRACE( "Created player id 0x%08x\n", *lpid ); + /* Initialize the SP data section */ + lpPlayer->lpSPPlayerData = DPSP_CreateSPPlayerData(); if( ~dwFlags & DPLAYI_PLAYER_SYSPLAYER ) + { This->dp2->lpSessionDesc->dwCurrentPlayers++; + } + + /* Create the list object and link it in */ + lpPList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpPList ) ); + if( lpPList == NULL ) + { + hr = DPERR_CANTADDPLAYER; + goto end; + } + + lpPlayer->uRef = 1; + lpPList->lpPData = lpPlayer; + + /* Add the player to the system group */ + DPQ_INSERT( This->dp2->lpSysGroup->players, lpPList, players ); + + /* Quick hack */ + if ( ~dwFlags & DPLAYI_PLAYER_PLAYERLOCAL ) { + lpPlayerList lpPList; + LPDPMSG lpMsg = + HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct DPMSG) ); + LPDPMSG_CREATEPLAYERORGROUP msg = + HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DPMSG_CREATEPLAYERORGROUP) ); + + msg->dwType = DPSYS_CREATEPLAYERORGROUP; + msg->dwPlayerType = DPPLAYERTYPE_PLAYER; + msg->dpId = idPlayer; + msg->dwCurrentPlayers = This->dp2->lpSessionDesc->dwCurrentPlayers; + msg->lpData = NULL;/*TODO*/ + msg->dwDataSize = 0;/*TODO*/ + msg->dpIdParent = DPID_NOPARENT_GROUP; + msg->dwFlags = DPMSG_CREATEPLAYER_DWFLAGS( dwFlags ); + if ( lpName ) + { + msg->dpnName = *lpName; + } + + lpMsg->msg = (LPDPMSG_GENERIC) msg; + lpMsg->dwMsgSize = sizeof(LPDPMSG_CREATEPLAYERORGROUP); + DPQ_INSERT( This->dp2->receiveMsgs, lpMsg, msgs ); + + if ( (lpPList = DPQ_FIRST( This->dp2->lpSysGroup->players )) ) + { + do + { + if ( ( lpPList->lpPData->dwFlags & DPLAYI_PLAYER_PLAYERLOCAL ) && + lpPList->lpPData->hEvent ) + { + SetEvent( lpPList->lpPData->hEvent ); + } + } + while( (lpPList = DPQ_NEXT( lpPList->players )) ); + } + } - return lpPData; +end: + if ( FAILED(hr) ) + { + DP_DeletePlayer( This, idPlayer ); + } + return hr; } /* Delete the contents of the DPNAME struct */ @@ -1497,7 +1579,6 @@ static HRESULT DP_IF_CreatePlayer { HRESULT hr = DP_OK; lpPlayerData lpPData; - lpPlayerList lpPList; TRACE( "(%p)->(%p,%p,%p,%p,0x%08x,0x%08x,%u)\n", This, lpidPlayer, lpPlayerName, hEvent, lpData, @@ -1571,46 +1652,15 @@ static HRESULT DP_IF_CreatePlayer } } } - else - { - /* Verify that we don't already have this player */ - - lpPlayerList lpPlayers = NULL; - DPQ_FIND_ENTRY( This->dp2->lpSysGroup->players, players, - lpPData->dpid, ==, *lpidPlayer, lpPlayers ); - - if (lpPlayers != NULL) - { - return DPERR_CANTCREATEPLAYER; - } - - } - lpPData = DP_CreatePlayer( This, lpidPlayer, lpPlayerName, dwFlags, - hEvent, bAnsi ); - - if( lpPData == NULL ) - { - return DPERR_CANTADDPLAYER; - } - - /* Create the list object and link it in */ - lpPList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpPList ) ); - if( lpPList == NULL ) + hr = DP_CreatePlayer( This, *lpidPlayer, lpPlayerName, dwFlags, + lpData, dwDataSize, hEvent, bAnsi, + &lpPData ); + if( FAILED(hr) ) { - FIXME( "Memory leak\n" ); - return DPERR_CANTADDPLAYER; + return hr; } - lpPData->uRef = 1; - lpPList->lpPData = lpPData; - - /* Add the player to the system group */ - DPQ_INSERT( This->dp2->lpSysGroup->players, lpPList, players ); - - /* Update the information and send it to all players in the session */ - DP_SetPlayerData( lpPData, DPSET_REMOTE, lpData, dwDataSize ); - /* Let the SP know that we've created this player */ if( This->dp2->spData.lpCB->CreatePlayer ) { @@ -1654,45 +1704,22 @@ static HRESULT DP_IF_CreatePlayer return hr; } -#if 1 - if( This->dp2->bHostInterface == FALSE ) - { - /* Let the name server know about the creation of this player */ - /* FIXME: Is this only to be done for the creation of a server player or - * is this used for regular players? If only for server players, move - * this call to DP_SecureOpen(...); - */ - hr = DP_MSG_ForwardPlayerCreation( This, *lpidPlayer); - } -#else - /* Inform all other peers of the creation of a new player. If there are - * no peers keep this quiet. - * Also, if this was a remote event, no need to rebroadcast it. - */ - if( ( lpMsgHdr == NULL ) && - This->dp2->lpSessionDesc && - ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) ) + if ( ( ! This->dp2->bHostInterface ) && ( lpMsgHdr == NULL ) ) { - DPMSG_CREATEPLAYERORGROUP msg; - msg.dwType = DPSYS_CREATEPLAYERORGROUP; - - msg.dwPlayerType = DPPLAYERTYPE_PLAYER; - msg.dpId = *lpidPlayer; - msg.dwCurrentPlayers = 0; /* FIXME: Incorrect */ - msg.lpData = lpData; - msg.dwDataSize = dwDataSize; - msg.dpnName = *lpPlayerName; - msg.dpIdParent = DPID_NOPARENT_GROUP; - msg.dwFlags = DPMSG_CREATEPLAYER_DWFLAGS( dwFlags ); - - /* FIXME: Correct to just use send effectively? */ - /* FIXME: Should size include data w/ message or just message "header" */ - /* FIXME: Check return code */ - hr = DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, - sizeof( msg ), 0, 0, NULL, NULL, bAnsi ); + if ( dwFlags & DPLAYI_PLAYER_SYSPLAYER ) + { + /* Let the name server know about the creation of this player, + * and reeceive the name table */ + hr = DP_MSG_ForwardPlayerCreation( This, *lpidPlayer); + } + else + { + /* Inform all other peers of the creation of a new player. + * Also, if this was a remote event, no need to rebroadcast it. */ + hr = DP_MSG_SendCreatePlayer( This, lpPData ); + } } -#endif return hr; } diff --git a/dlls/dplayx/dplay_global.h b/dlls/dplayx/dplay_global.h index 279520e778d..3481335ab75 100644 --- a/dlls/dplayx/dplay_global.h +++ b/dlls/dplayx/dplay_global.h @@ -242,6 +242,11 @@ HRESULT DP_SetSessionDesc( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpSessDesc, DWORD dwFlags, BOOL bInitial, BOOL bAnsi ); +HRESULT DP_CreatePlayer( IDirectPlay2Impl* This, DPID idPlayer, + LPDPNAME lpName, DWORD dwFlags, + LPVOID lpData, DWORD dwDataSize, + HANDLE hEvent, BOOL bAnsi, + lpPlayerData* lplpPlayer ); /* DP SP external interfaces into DirectPlay */ extern HRESULT DP_GetSPPlayerData( IDirectPlay2Impl* lpDP, DPID idPlayer, LPVOID* lplpData ); diff --git a/dlls/dplayx/dplayx_messages.c b/dlls/dplayx/dplayx_messages.c index 02b74b36814..c4c998d3efb 100644 --- a/dlls/dplayx/dplayx_messages.c +++ b/dlls/dplayx/dplayx_messages.c @@ -364,6 +364,124 @@ HRESULT DP_MSG_ForwardPlayerCreation( IDirectPlay2AImpl* This, DPID dpidServer ) return hr; } +HRESULT DP_MSG_SendCreatePlayer( IDirectPlay2AImpl* This, lpPlayerData lpData ) +{ + LPBYTE lpMsg; + LPDPSP_MSG_CREATEPLAYER lpMsgBody; + DWORD dwMsgSize, dwWrapperSize; + HRESULT hr; + + TRACE( "(%p)->(0x%08x)\n", This, lpData->dpid ); + + + /* If the session supports multicast, wrap the message up into + * a DPSP_MSG_ASK4MULTICAST */ + if ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) + { + dwWrapperSize = sizeof(DPSP_MSG_ASK4MULTICAST); + } + else + { + dwWrapperSize = 0; + } + + + dwMsgSize = This->dp2->spData.dwSPHeaderSize + + dwWrapperSize + + sizeof(DPSP_MSG_CREATEPLAYER) + + 256; /* Estimated max size for player data */ + + lpMsg = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwMsgSize ); + lpMsgBody = (LPDPSP_MSG_CREATEPLAYER)( lpMsg + + This->dp2->spData.dwSPHeaderSize + + dwWrapperSize ); + + + /* Fill wrapper if needed */ + if ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) + { + LPDPSP_MSG_ASK4MULTICAST lpWrapper = (LPDPSP_MSG_ASK4MULTICAST) lpMsg; + + lpWrapper->envelope.dwMagic = DPMSG_SIGNATURE; + lpWrapper->envelope.wCommandId = DPMSGCMD_CREATEPLAYER; + lpWrapper->envelope.wVersion = DX61AVERSION; + + lpWrapper->GroupTo = 0; /*TODO*/ + lpWrapper->PlayerFrom = lpData->dpid; + lpWrapper->MessageOffset = sizeof(DPSP_MSG_ASK4MULTICAST); + } + + + /* Compose dplay message envelope */ + lpMsgBody->envelope.dwMagic = DPMSG_SIGNATURE; + lpMsgBody->envelope.wCommandId = DPMSGCMD_CREATEPLAYER; + lpMsgBody->envelope.wVersion = DX61AVERSION; + + /* Compose body of message */ + lpMsgBody->IDTo = 0; /* Name server */ + lpMsgBody->PlayerID = lpData->dpid; + lpMsgBody->GroupID = 0; /* Ignored */ + lpMsgBody->CreateOffset = sizeof(DPSP_MSG_CREATEPLAYER); + lpMsgBody->PasswordOffset = 0; /* Ignored */ + + /* Add PlayerInfo and recalculation of exact message size */ + dwMsgSize -= 256; /* We estimated 256 */ + dwMsgSize += DP_MSG_FillPackedPlayer( + This, + (LPDPLAYI_PACKEDPLAYER)(((LPBYTE) lpMsgBody) + lpMsgBody->CreateOffset ), + lpData, FALSE, TRUE ); + + + /* If the session supports multicast, send message to the game host */ + if ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) + { + DPSP_SENDDATA sendData; + sendData.dwFlags = DPSEND_GUARANTEED; + sendData.idPlayerTo = 0; /* Name server */ + sendData.idPlayerFrom = lpData->dpid; + sendData.lpMessage = lpMsg; + sendData.dwMessageSize = dwMsgSize; + sendData.bSystemMessage = TRUE; /* Allow reply to be sent */ + sendData.lpISP = This->dp2->spData.lpISP; + + hr = (*This->dp2->spData.lpCB->Send)( &sendData ); + } + /* Otherwise, send the message to each player in the session */ + else + { + lpPlayerList lpPList; + DPSP_SENDDATA sendData; + sendData.dwFlags = DPSEND_GUARANTEED; + sendData.idPlayerFrom = lpData->dpid; + sendData.lpMessage = lpMsg; + sendData.dwMessageSize = dwMsgSize; + sendData.bSystemMessage = TRUE; + sendData.lpISP = This->dp2->spData.lpISP; + + if ( (lpPList = DPQ_FIRST( This->dp2->lpSysGroup->players )) ) + { + do + { + if ( ( lpPList->lpPData->dwFlags & DPLAYI_PLAYER_SYSPLAYER ) && + ( ~lpPList->lpPData->dwFlags & DPLAYI_PLAYER_PLAYERLOCAL ) ) + { + sendData.idPlayerTo = lpPList->lpPData->dpid; + hr = (*This->dp2->spData.lpCB->Send)( &sendData ); + if ( FAILED(hr) ) + { + ERR( "Failed to send message to 0x%08x\n", sendData.idPlayerTo ); + } + } + } + while( (lpPList = DPQ_NEXT( lpPList->players )) ); + } + + } + + HeapFree( GetProcessHeap(), 0, lpMsg ); + return hr; +} + /* Queue up a structure indicating that we want a reply of type wReplyCommandId. DPlay does * not seem to offer any way of uniquely differentiating between replies of the same type * relative to the request sent. There is an implicit assumption that there will be no diff --git a/dlls/dplayx/dplayx_messages.h b/dlls/dplayx/dplayx_messages.h index 014c8074892..a3c73fda7ed 100644 --- a/dlls/dplayx/dplayx_messages.h +++ b/dlls/dplayx/dplayx_messages.h @@ -34,6 +34,7 @@ DWORD CreateLobbyMessageReceptionThread( HANDLE hNotifyEvent, HANDLE hStart, HRESULT DP_MSG_SendRequestPlayerId( IDirectPlay2AImpl* This, DWORD dwFlags, LPDPID lpdipidAllocatedId ); +HRESULT DP_MSG_SendCreatePlayer( IDirectPlay2AImpl* This, lpPlayerData lpData ); HRESULT DP_MSG_ForwardPlayerCreation( IDirectPlay2AImpl* This, DPID dpidServer ); void DP_MSG_ReplyToEnumPlayersRequest( IDirectPlay2Impl* lpDP, LPVOID* lplpReply, LPDWORD lpdwMsgSize ); -- 2.11.4.GIT