📄 dplay.c
字号:
/* Delete Player List object */
HeapFree( GetProcessHeap(), 0, lpPList );
}
static lpPlayerList DP_FindPlayer( IDirectPlay2AImpl* This, DPID dpid )
{
lpPlayerList lpPlayers;
TRACE( "(%p)->(0x%08lx)\n", This, dpid );
DPQ_FIND_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPlayers );
return lpPlayers;
}
/* Basic area for Dst must already be allocated */
static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, LPDPNAME lpSrc, BOOL bAnsi )
{
if( lpSrc == NULL )
{
ZeroMemory( lpDst, sizeof( *lpDst ) );
lpDst->dwSize = sizeof( *lpDst );
return TRUE;
}
if( lpSrc->dwSize != sizeof( *lpSrc) )
{
return FALSE;
}
/* Delete any existing pointers */
HeapFree( GetProcessHeap(), 0, lpDst->lpszShortNameA );
HeapFree( GetProcessHeap(), 0, lpDst->lpszLongNameA );
/* Copy as required */
CopyMemory( lpDst, lpSrc, lpSrc->dwSize );
if( bAnsi )
{
if( lpSrc->lpszShortNameA )
{
lpDst->lpszShortNameA = HeapAlloc( GetProcessHeap(), 0,
strlen(lpSrc->lpszShortNameA)+1 );
strcpy( lpDst->lpszShortNameA, lpSrc->lpszShortNameA );
}
if( lpSrc->lpszLongNameA )
{
lpDst->lpszLongNameA = HeapAlloc( GetProcessHeap(), 0,
strlen(lpSrc->lpszLongNameA)+1 );
strcpy( lpDst->lpszLongNameA, lpSrc->lpszLongNameA );
}
}
else
{
if( lpSrc->lpszShortNameA )
{
lpDst->lpszShortName = HeapAlloc( GetProcessHeap(), 0,
(strlenW(lpSrc->lpszShortName)+1)*sizeof(WCHAR) );
strcpyW( lpDst->lpszShortName, lpSrc->lpszShortName );
}
if( lpSrc->lpszLongNameA )
{
lpDst->lpszLongName = HeapAlloc( GetProcessHeap(), 0,
(strlenW(lpSrc->lpszLongName)+1)*sizeof(WCHAR) );
strcpyW( lpDst->lpszLongName, lpSrc->lpszLongName );
}
}
return TRUE;
}
static void
DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
LPVOID lpData, DWORD dwDataSize )
{
/* Clear out the data with this player */
if( dwFlags & DPSET_LOCAL )
{
if ( lpPData->dwLocalDataSize != 0 )
{
HeapFree( GetProcessHeap(), 0, lpPData->lpLocalData );
lpPData->lpLocalData = NULL;
lpPData->dwLocalDataSize = 0;
}
}
else
{
if( lpPData->dwRemoteDataSize != 0 )
{
HeapFree( GetProcessHeap(), 0, lpPData->lpRemoteData );
lpPData->lpRemoteData = NULL;
lpPData->dwRemoteDataSize = 0;
}
}
/* Reallocate for new data */
if( lpData != NULL )
{
LPVOID lpNewData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof( dwDataSize ) );
CopyMemory( lpNewData, lpData, dwDataSize );
if( dwFlags & DPSET_LOCAL )
{
lpPData->lpLocalData = lpData;
lpPData->dwLocalDataSize = dwDataSize;
}
else
{
lpPData->lpRemoteData = lpNewData;
lpPData->dwRemoteDataSize = dwDataSize;
}
}
}
static HRESULT WINAPI DP_IF_CreatePlayer
( IDirectPlay2Impl* This,
LPVOID lpMsgHdr, /* NULL for local creation, non NULL for remote creation */
LPDPID lpidPlayer,
LPDPNAME lpPlayerName,
HANDLE hEvent,
LPVOID lpData,
DWORD dwDataSize,
DWORD dwFlags,
BOOL bAnsi )
{
HRESULT hr = DP_OK;
lpPlayerData lpPData;
lpPlayerList lpPList;
DWORD dwCreateFlags = 0;
TRACE( "(%p)->(%p,%p,%p,%p,0x%08lx,0x%08lx,%u)\n",
This, lpidPlayer, lpPlayerName, hEvent, lpData,
dwDataSize, dwFlags, bAnsi );
if( dwFlags == 0 )
{
dwFlags = DPPLAYER_SPECTATOR;
}
if( lpidPlayer == NULL )
{
return DPERR_INVALIDPARAMS;
}
/* Determine the creation flags for the player. These will be passed
* to the name server if requesting a player id and to the SP when
* informing it of the player creation
*/
{
if( dwFlags & DPPLAYER_SERVERPLAYER )
{
if( *lpidPlayer == DPID_SERVERPLAYER )
{
/* Server player for the host interface */
dwCreateFlags |= DPLAYI_PLAYER_APPSERVER;
}
else if( *lpidPlayer == DPID_NAME_SERVER )
{
/* Name server - master of everything */
dwCreateFlags |= (DPLAYI_PLAYER_NAMESRVR|DPLAYI_PLAYER_SYSPLAYER);
}
else
{
/* Server player for a non host interface */
dwCreateFlags |= DPLAYI_PLAYER_SYSPLAYER;
}
}
if( lpMsgHdr == NULL )
dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
}
/* Verify we know how to handle all the flags */
if( !( ( dwFlags & DPPLAYER_SERVERPLAYER ) ||
( dwFlags & DPPLAYER_SPECTATOR )
)
)
{
/* Assume non fatal failure */
ERR( "unknown dwFlags = 0x%08lx\n", dwFlags );
}
/* If the name is not specified, we must provide one */
if( *lpidPlayer == DPID_UNKNOWN )
{
/* If we are the session master, we dish out the group/player ids */
if( This->dp2->bHostInterface )
{
*lpidPlayer = DP_NextObjectId();
}
else
{
hr = DP_MSG_SendRequestPlayerId( This, dwCreateFlags, lpidPlayer );
if( FAILED(hr) )
{
ERR( "Request for ID failed: %s\n", DPLAYX_HresultToString( hr ) );
return hr;
}
}
}
else
{
/* FIXME: Would be nice to perhaps verify that we don't already have
* this player.
*/
}
/* FIXME: Should we be storing these dwFlags or the creation ones? */
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 )
{
FIXME( "Memory leak\n" );
return DPERR_CANTADDPLAYER;
}
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 )
{
DPSP_CREATEPLAYERDATA data;
data.idPlayer = *lpidPlayer;
data.dwFlags = dwCreateFlags;
data.lpSPMessageHeader = lpMsgHdr;
data.lpISP = This->dp2->spData.lpISP;
TRACE( "Calling SP CreatePlayer 0x%08lx: dwFlags: 0x%08lx lpMsgHdr: %p\n",
*lpidPlayer, data.dwFlags, data.lpSPMessageHeader );
hr = (*This->dp2->spData.lpCB->CreatePlayer)( &data );
}
if( FAILED(hr) )
{
ERR( "Failed to create player with sp: %s\n", DPLAYX_HresultToString(hr) );
return hr;
}
/* Now let the SP know that this player is a member of the system group */
if( This->dp2->spData.lpCB->AddPlayerToGroup )
{
DPSP_ADDPLAYERTOGROUPDATA data;
data.idPlayer = *lpidPlayer;
data.idGroup = DPID_SYSTEM_GROUP;
data.lpISP = This->dp2->spData.lpISP;
TRACE( "Calling SP AddPlayerToGroup (sys group)\n" );
hr = (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
}
if( FAILED(hr) )
{
ERR( "Failed to add player to sys group with sp: %s\n",
DPLAYX_HresultToString(hr) );
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(...);
*/
#if 0
TRACE( "Sending message to self to get my addr\n" );
DP_MSG_ToSelf( This, *lpidPlayer ); /* This is a hack right now */
#endif
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 ) )
{
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 );
}
#endif
return hr;
}
static HRESULT WINAPI DirectPlay2AImpl_CreatePlayer
( LPDIRECTPLAY2A iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName,
HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
{
IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
if( dwFlags & DPPLAYER_SERVERPLAYER )
{
*lpidPlayer = DPID_SERVERPLAYER;
}
else
{
*lpidPlayer = DPID_UNKNOWN;
}
return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
lpData, dwDataSize, dwFlags, TRUE );
}
static HRESULT WINAPI DirectPlay2WImpl_CreatePlayer
( LPDIRECTPLAY2 iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName,
HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
{
IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
if( dwFlags & DPPLAYER_SERVERPLAYER )
{
*lpidPlayer = DPID_SERVERPLAYER;
}
else
{
*lpidPlayer = DPID_UNKNOWN;
}
return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
lpData, dwDataSize, dwFlags, FALSE );
}
static DPID DP_GetRemoteNextObjectId(void)
{
FIXME( ":stub\n" );
/* Hack solution */
return DP_NextObjectId();
}
static HRESULT WINAPI DP_IF_DeletePlayerFromGroup
( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
DPID idPlayer, BOOL bAnsi )
{
HRESULT hr = DP_OK;
lpGroupData lpGData;
lpPlayerList lpPList;
TRACE( "(%p)->(%p,0x%08lx,0x%08lx,%u)\n",
This, lpMsgHdr, idGroup, idPlayer, bAnsi );
/* Find the group */
if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
{
return DPERR_INVALIDGROUP;
}
/* Find the player */
if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
{
return DPERR_INVALIDPLAYER;
}
/* Remove the player shortcut from the group */
DPQ_REMOVE_ENTRY( lpGData->players, players, lpPData->dpid, ==, idPlayer, lpPList );
if( lpPList == NULL )
{
return DPERR_INVALIDPLAYER;
}
/* One less reference */
lpPList->lpPData->uRef--;
/* Delete the Player List element */
HeapFree( GetProcessHeap(), 0, lpPList );
/* Inform the SP if they care */
if( This->dp2->spData.lpCB->RemovePlayerFromGroup )
{
DPSP_REMOVEPLAYERFROMGROUPDATA data;
TRACE( "Calling SP RemovePlayerFromGroup\n" );
data.idPlayer = idPlayer;
data.idGroup = idGroup;
data.lpISP = This->dp2->spData.lpISP;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -