📄 dplay.c
字号:
msg.dpIdGroup = idGroup;
msg.dpIdPlayer = idPlayer;
/* FIXME: Correct to just use send effectively? */
/* FIXME: Should size include data w/ message or just message "header" */
/* FIXME: Check return code */
DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ), 0, 0, NULL, NULL, bAnsi );
}
return DP_OK;
}
static HRESULT WINAPI DirectPlay2AImpl_AddPlayerToGroup
( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer )
{
IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
return DP_IF_AddPlayerToGroup( This, NULL, idGroup, idPlayer, TRUE );
}
static HRESULT WINAPI DirectPlay2WImpl_AddPlayerToGroup
( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer )
{
IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
return DP_IF_AddPlayerToGroup( This, NULL, idGroup, idPlayer, FALSE );
}
static HRESULT WINAPI DP_IF_Close( IDirectPlay2Impl* This, BOOL bAnsi )
{
HRESULT hr = DP_OK;
TRACE("(%p)->(%u)\n", This, bAnsi );
/* FIXME: Need to find a new host I assume (how?) */
/* FIXME: Need to destroy all local groups */
/* FIXME: Need to migrate all remotely visible players to the new host */
/* Invoke the SP callback to inform of session close */
if( This->dp2->spData.lpCB->CloseEx )
{
DPSP_CLOSEDATA data;
TRACE( "Calling SP CloseEx\n" );
data.lpISP = This->dp2->spData.lpISP;
hr = (*This->dp2->spData.lpCB->CloseEx)( &data );
}
else if ( This->dp2->spData.lpCB->Close ) /* Try obsolete version */
{
TRACE( "Calling SP Close (obsolete interface)\n" );
hr = (*This->dp2->spData.lpCB->Close)();
}
return hr;
}
static HRESULT WINAPI DirectPlay2AImpl_Close
( LPDIRECTPLAY2A iface )
{
IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
return DP_IF_Close( This, TRUE );
}
static HRESULT WINAPI DirectPlay2WImpl_Close
( LPDIRECTPLAY2 iface )
{
IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
return DP_IF_Close( This, FALSE );
}
static
lpGroupData DP_CreateGroup( IDirectPlay2AImpl* This, LPDPID lpid,
LPDPNAME lpName, DWORD dwFlags,
DPID idParent, BOOL bAnsi )
{
lpGroupData lpGData;
/* Allocate the new space and add to end of high level group list */
lpGData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGData ) );
if( lpGData == NULL )
{
return NULL;
}
DPQ_INIT(lpGData->groups);
DPQ_INIT(lpGData->players);
/* Set the desired player ID - no sanity checking to see if it exists */
lpGData->dpid = *lpid;
DP_CopyDPNAMEStruct( &lpGData->name, lpName, bAnsi );
/* FIXME: Should we check that the parent exists? */
lpGData->parent = idParent;
/* FIXME: Should we validate the dwFlags? */
lpGData->dwFlags = dwFlags;
TRACE( "Created group id 0x%08lx\n", *lpid );
return lpGData;
}
/* This method assumes that all links to it are already deleted */
static void
DP_DeleteGroup( IDirectPlay2Impl* This, DPID dpid )
{
lpGroupList lpGList;
TRACE( "(%p)->(0x%08lx)\n", This, dpid );
DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGList );
if( lpGList == NULL )
{
ERR( "DPID 0x%08lx not found\n", dpid );
return;
}
if( --(lpGList->lpGData->uRef) )
{
FIXME( "Why is this not the last reference to group?\n" );
DebugBreak();
}
/* Delete player */
DP_DeleteDPNameStruct( &lpGList->lpGData->name );
HeapFree( GetProcessHeap(), 0, lpGList->lpGData );
/* Remove and Delete Player List object */
HeapFree( GetProcessHeap(), 0, lpGList );
}
static lpGroupData DP_FindAnyGroup( IDirectPlay2AImpl* This, DPID dpid )
{
lpGroupList lpGroups;
TRACE( "(%p)->(0x%08lx)\n", This, dpid );
if( dpid == DPID_SYSTEM_GROUP )
{
return This->dp2->lpSysGroup;
}
else
{
DPQ_FIND_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGroups );
}
if( lpGroups == NULL )
{
return NULL;
}
return lpGroups->lpGData;
}
static HRESULT WINAPI DP_IF_CreateGroup
( IDirectPlay2AImpl* This, LPVOID lpMsgHdr, LPDPID lpidGroup,
LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
DWORD dwFlags, BOOL bAnsi )
{
lpGroupData lpGData;
TRACE( "(%p)->(%p,%p,%p,%p,0x%08lx,0x%08lx,%u)\n",
This, lpMsgHdr, lpidGroup, lpGroupName, lpData, dwDataSize,
dwFlags, bAnsi );
/* If the name is not specified, we must provide one */
if( DPID_UNKNOWN == *lpidGroup )
{
/* If we are the name server, we decide on the group ids. If not, we
* must ask for one before attempting a creation.
*/
if( This->dp2->bHostInterface )
{
*lpidGroup = DP_NextObjectId();
}
else
{
*lpidGroup = DP_GetRemoteNextObjectId();
}
}
lpGData = DP_CreateGroup( This, lpidGroup, lpGroupName, dwFlags,
DPID_NOPARENT_GROUP, bAnsi );
if( lpGData == NULL )
{
return DPERR_CANTADDPLAYER; /* yes player not group */
}
if( DPID_SYSTEM_GROUP == *lpidGroup )
{
This->dp2->lpSysGroup = lpGData;
TRACE( "Inserting system group\n" );
}
else
{
/* Insert into the system group */
lpGroupList lpGroup = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGroup ) );
lpGroup->lpGData = lpGData;
DPQ_INSERT( This->dp2->lpSysGroup->groups, lpGroup, groups );
}
/* Something is now referencing this data */
lpGData->uRef++;
/* Set all the important stuff for the group */
DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
/* FIXME: We should only create the system group if GetCaps returns
* DPCAPS_GROUPOPTIMIZED.
*/
/* Let the SP know that we've created this group */
if( This->dp2->spData.lpCB->CreateGroup )
{
DPSP_CREATEGROUPDATA data;
DWORD dwCreateFlags = 0;
TRACE( "Calling SP CreateGroup\n" );
if( *lpidGroup == DPID_NOPARENT_GROUP )
dwCreateFlags |= DPLAYI_GROUP_SYSGROUP;
if( lpMsgHdr == NULL )
dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
if( dwFlags & DPGROUP_HIDDEN )
dwCreateFlags |= DPLAYI_GROUP_HIDDEN;
data.idGroup = *lpidGroup;
data.dwFlags = dwCreateFlags;
data.lpSPMessageHeader = lpMsgHdr;
data.lpISP = This->dp2->spData.lpISP;
(*This->dp2->spData.lpCB->CreateGroup)( &data );
}
/* Inform all other peers of the creation of a new group. If there are
* no peers keep this event quiet.
* Also if this message was sent to us, don't rebroadcast.
*/
if( ( lpMsgHdr == NULL ) &&
This->dp2->lpSessionDesc &&
( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
{
DPMSG_CREATEPLAYERORGROUP msg;
msg.dwType = DPSYS_CREATEPLAYERORGROUP;
msg.dwPlayerType = DPPLAYERTYPE_GROUP;
msg.dpId = *lpidGroup;
msg.dwCurrentPlayers = 0; /* FIXME: Incorrect? */
msg.lpData = lpData;
msg.dwDataSize = dwDataSize;
msg.dpnName = *lpGroupName;
msg.dpIdParent = DPID_NOPARENT_GROUP;
msg.dwFlags = DPMSG_CREATEGROUP_DWFLAGS( dwFlags );
/* FIXME: Correct to just use send effectively? */
/* FIXME: Should size include data w/ message or just message "header" */
/* FIXME: Check return code */
DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
0, 0, NULL, NULL, bAnsi );
}
return DP_OK;
}
static HRESULT WINAPI DirectPlay2AImpl_CreateGroup
( LPDIRECTPLAY2A iface, LPDPID lpidGroup, LPDPNAME lpGroupName,
LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
{
*lpidGroup = DPID_UNKNOWN;
return DP_IF_CreateGroup( (IDirectPlay2AImpl*)iface, NULL, lpidGroup,
lpGroupName, lpData, dwDataSize, dwFlags, TRUE );
}
static HRESULT WINAPI DirectPlay2WImpl_CreateGroup
( LPDIRECTPLAY2 iface, LPDPID lpidGroup, LPDPNAME lpGroupName,
LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
{
*lpidGroup = DPID_UNKNOWN;
return DP_IF_CreateGroup( (IDirectPlay2AImpl*)iface, NULL, lpidGroup,
lpGroupName, lpData, dwDataSize, dwFlags, FALSE );
}
static void
DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
LPVOID lpData, DWORD dwDataSize )
{
/* Clear out the data with this player */
if( dwFlags & DPSET_LOCAL )
{
if ( lpGData->dwLocalDataSize != 0 )
{
HeapFree( GetProcessHeap(), 0, lpGData->lpLocalData );
lpGData->lpLocalData = NULL;
lpGData->dwLocalDataSize = 0;
}
}
else
{
if( lpGData->dwRemoteDataSize != 0 )
{
HeapFree( GetProcessHeap(), 0, lpGData->lpRemoteData );
lpGData->lpRemoteData = NULL;
lpGData->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 )
{
lpGData->lpLocalData = lpData;
lpGData->dwLocalDataSize = dwDataSize;
}
else
{
lpGData->lpRemoteData = lpNewData;
lpGData->dwRemoteDataSize = dwDataSize;
}
}
}
/* 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 )
{
lpPlayerData lpPData;
TRACE( "(%p)->(%p,%p,%u)\n", This, lpid, lpName, bAnsi );
/* Allocate the storage for the player and associate it with list element */
lpPData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpPData ) );
if( lpPData == NULL )
{
return NULL;
}
/* Set the desired player ID */
lpPData->dpid = *lpid;
DP_CopyDPNAMEStruct( &lpPData->name, lpName, bAnsi );
lpPData->dwFlags = dwFlags;
/* If we were given an event handle, duplicate it */
if( hEvent != 0 )
{
if( !DuplicateHandle( GetCurrentProcess(), hEvent,
GetCurrentProcess(), &lpPData->hEvent,
0, FALSE, DUPLICATE_SAME_ACCESS )
)
{
/* FIXME: Memory leak */
ERR( "Can't duplicate player msg handle %p\n", hEvent );
}
}
/* Initialize the SP data section */
lpPData->lpSPPlayerData = DPSP_CreateSPPlayerData();
TRACE( "Created player id 0x%08lx\n", *lpid );
return lpPData;
}
/* Delete the contents of the DPNAME struct */
static void
DP_DeleteDPNameStruct( LPDPNAME lpDPName )
{
HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->lpszShortNameA );
HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->lpszLongNameA );
}
/* This method assumes that all links to it are already deleted */
static void
DP_DeletePlayer( IDirectPlay2Impl* This, DPID dpid )
{
lpPlayerList lpPList;
TRACE( "(%p)->(0x%08lx)\n", This, dpid );
DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPList );
if( lpPList == NULL )
{
ERR( "DPID 0x%08lx not found\n", dpid );
return;
}
/* Verify that this is the last reference to the data */
if( --(lpPList->lpPData->uRef) )
{
FIXME( "Why is this not the last reference to player?\n" );
DebugBreak();
}
/* Delete player */
DP_DeleteDPNameStruct( &lpPList->lpPData->name );
CloseHandle( lpPList->lpPData->hEvent );
HeapFree( GetProcessHeap(), 0, lpPList->lpPData );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -