📄 dplay.c
字号:
static BOOL DP_CreateDirectPlay3( LPVOID lpDP )
{
IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)lpDP;
This->dp3 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->dp3) ) );
if ( This->dp3 == NULL )
{
return FALSE;
}
return TRUE;
}
static BOOL DP_DestroyDirectPlay3( LPVOID lpDP )
{
IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)lpDP;
/* Delete the contents */
HeapFree( GetProcessHeap(), 0, This->dp3 );
return TRUE;
}
static BOOL DP_CreateDirectPlay4( LPVOID lpDP )
{
IDirectPlay4AImpl *This = (IDirectPlay4AImpl *)lpDP;
This->dp4 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->dp4) ) );
if ( This->dp4 == NULL )
{
return FALSE;
}
return TRUE;
}
static BOOL DP_DestroyDirectPlay4( LPVOID lpDP )
{
IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)lpDP;
/* Delete the contents */
HeapFree( GetProcessHeap(), 0, This->dp4 );
return TRUE;
}
/* Create a new interface */
extern
HRESULT DP_CreateInterface
( REFIID riid, LPVOID* ppvObj )
{
TRACE( " for %s\n", debugstr_guid( riid ) );
*ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof( IDirectPlay2Impl ) );
if( *ppvObj == NULL )
{
return DPERR_OUTOFMEMORY;
}
if( IsEqualGUID( &IID_IDirectPlay2, riid ) )
{
IDirectPlay2Impl *This = (IDirectPlay2Impl *)*ppvObj;
This->lpVtbl = &directPlay2WVT;
}
else if( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
{
IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)*ppvObj;
This->lpVtbl = &directPlay2AVT;
}
else if( IsEqualGUID( &IID_IDirectPlay3, riid ) )
{
IDirectPlay3Impl *This = (IDirectPlay3Impl *)*ppvObj;
This->lpVtbl = &directPlay3WVT;
}
else if( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
{
IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)*ppvObj;
This->lpVtbl = &directPlay3AVT;
}
else if( IsEqualGUID( &IID_IDirectPlay4, riid ) )
{
IDirectPlay4Impl *This = (IDirectPlay4Impl *)*ppvObj;
This->lpVtbl = &directPlay4WVT;
}
else if( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
{
IDirectPlay4AImpl *This = (IDirectPlay4AImpl *)*ppvObj;
This->lpVtbl = &directPlay4AVT;
}
else
{
/* Unsupported interface */
HeapFree( GetProcessHeap(), 0, *ppvObj );
*ppvObj = NULL;
return E_NOINTERFACE;
}
/* Initialize it */
if ( DP_CreateIUnknown( *ppvObj ) &&
DP_CreateDirectPlay2( *ppvObj ) &&
DP_CreateDirectPlay3( *ppvObj ) &&
DP_CreateDirectPlay4( *ppvObj )
)
{
IDirectPlayX_AddRef( (LPDIRECTPLAY2A)*ppvObj );
return S_OK;
}
/* Initialize failed, destroy it */
DP_DestroyDirectPlay4( *ppvObj );
DP_DestroyDirectPlay3( *ppvObj );
DP_DestroyDirectPlay2( *ppvObj );
DP_DestroyIUnknown( *ppvObj );
HeapFree( GetProcessHeap(), 0, *ppvObj );
*ppvObj = NULL;
return DPERR_NOMEMORY;
}
/* Direct Play methods */
/* Shared between all dplay types */
static HRESULT WINAPI DP_QueryInterface
( LPDIRECTPLAY2 iface, REFIID riid, LPVOID* ppvObj )
{
IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
TRACE("(%p)->(%s,%p)\n", This, debugstr_guid( riid ), ppvObj );
*ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof( *This ) );
if( *ppvObj == NULL )
{
return DPERR_OUTOFMEMORY;
}
CopyMemory( *ppvObj, This, sizeof( *This ) );
(*(IDirectPlay2Impl**)ppvObj)->ulInterfaceRef = 0;
if( IsEqualGUID( &IID_IDirectPlay2, riid ) )
{
IDirectPlay2Impl *This = (IDirectPlay2Impl *)*ppvObj;
This->lpVtbl = &directPlay2WVT;
}
else if( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
{
IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)*ppvObj;
This->lpVtbl = &directPlay2AVT;
}
else if( IsEqualGUID( &IID_IDirectPlay3, riid ) )
{
IDirectPlay3Impl *This = (IDirectPlay3Impl *)*ppvObj;
This->lpVtbl = &directPlay3WVT;
}
else if( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
{
IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)*ppvObj;
This->lpVtbl = &directPlay3AVT;
}
else if( IsEqualGUID( &IID_IDirectPlay4, riid ) )
{
IDirectPlay4Impl *This = (IDirectPlay4Impl *)*ppvObj;
This->lpVtbl = &directPlay4WVT;
}
else if( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
{
IDirectPlay4AImpl *This = (IDirectPlay4AImpl *)*ppvObj;
This->lpVtbl = &directPlay4AVT;
}
else
{
/* Unsupported interface */
HeapFree( GetProcessHeap(), 0, *ppvObj );
*ppvObj = NULL;
return E_NOINTERFACE;
}
IDirectPlayX_AddRef( (LPDIRECTPLAY2)*ppvObj );
return S_OK;
}
/* Shared between all dplay types */
static ULONG WINAPI DP_AddRef
( LPDIRECTPLAY3 iface )
{
ULONG ulInterfaceRefCount, ulObjRefCount;
IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
ulObjRefCount = InterlockedIncrement( &This->unk->ulObjRef );
ulInterfaceRefCount = InterlockedIncrement( &This->ulInterfaceRef );
TRACE( "ref count incremented to %lu:%lu for %p\n",
ulInterfaceRefCount, ulObjRefCount, This );
return ulObjRefCount;
}
static ULONG WINAPI DP_Release
( LPDIRECTPLAY3 iface )
{
ULONG ulInterfaceRefCount, ulObjRefCount;
IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
ulObjRefCount = InterlockedDecrement( &This->unk->ulObjRef );
ulInterfaceRefCount = InterlockedDecrement( &This->ulInterfaceRef );
TRACE( "ref count decremented to %lu:%lu for %p\n",
ulInterfaceRefCount, ulObjRefCount, This );
/* Deallocate if this is the last reference to the object */
if( ulObjRefCount == 0 )
{
/* If we're destroying the object, this must be the last ref
of the last interface */
DP_DestroyDirectPlay4( This );
DP_DestroyDirectPlay3( This );
DP_DestroyDirectPlay2( This );
DP_DestroyIUnknown( This );
}
/* Deallocate the interface */
if( ulInterfaceRefCount == 0 )
{
HeapFree( GetProcessHeap(), 0, This );
}
return ulObjRefCount;
}
static inline DPID DP_NextObjectId(void)
{
return (DPID)InterlockedIncrement( &kludgePlayerGroupId );
}
/* *lplpReply will be non NULL iff there is something to reply */
HRESULT DP_HandleMessage( IDirectPlay2Impl* This, LPCVOID lpcMessageBody,
DWORD dwMessageBodySize, LPCVOID lpcMessageHeader,
WORD wCommandId, WORD wVersion,
LPVOID* lplpReply, LPDWORD lpdwMsgSize )
{
TRACE( "(%p)->(%p,0x%08lx,%p,%u,%u)\n",
This, lpcMessageBody, dwMessageBodySize, lpcMessageHeader, wCommandId,
wVersion );
switch( wCommandId )
{
/* Name server needs to handle this request */
case DPMSGCMD_ENUMSESSIONSREQUEST:
{
/* Reply expected */
NS_ReplyToEnumSessionsRequest( lpcMessageBody, lplpReply, lpdwMsgSize, This );
break;
}
/* Name server needs to handle this request */
case DPMSGCMD_ENUMSESSIONSREPLY:
{
/* No reply expected */
NS_AddRemoteComputerAsNameServer( lpcMessageHeader,
This->dp2->spData.dwSPHeaderSize,
(LPDPMSG_ENUMSESSIONSREPLY)lpcMessageBody,
This->dp2->lpNameServerData );
break;
}
case DPMSGCMD_REQUESTNEWPLAYERID:
{
LPCDPMSG_REQUESTNEWPLAYERID lpcMsg =
(LPCDPMSG_REQUESTNEWPLAYERID)lpcMessageBody;
LPDPMSG_NEWPLAYERIDREPLY lpReply;
*lpdwMsgSize = This->dp2->spData.dwSPHeaderSize + sizeof( *lpReply );
*lplpReply = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, *lpdwMsgSize );
FIXME( "Ignoring dwFlags 0x%08lx in request msg\n",
lpcMsg->dwFlags );
/* Setup the reply */
lpReply = (LPDPMSG_NEWPLAYERIDREPLY)( (BYTE*)(*lplpReply) +
This->dp2->spData.dwSPHeaderSize );
lpReply->envelope.dwMagic = DPMSGMAGIC_DPLAYMSG;
lpReply->envelope.wCommandId = DPMSGCMD_NEWPLAYERIDREPLY;
lpReply->envelope.wVersion = DPMSGVER_DP6;
lpReply->dpidNewPlayerId = DP_NextObjectId();
TRACE( "Allocating new playerid 0x%08lx from remote request\n",
lpReply->dpidNewPlayerId );
break;
}
case DPMSGCMD_GETNAMETABLEREPLY:
case DPMSGCMD_NEWPLAYERIDREPLY:
{
#if 0
if( wCommandId == DPMSGCMD_NEWPLAYERIDREPLY )
DebugBreak();
#endif
DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
break;
}
#if 1
case DPMSGCMD_JUSTENVELOPE:
{
TRACE( "GOT THE SELF MESSAGE: %p -> 0x%08lx\n", lpcMessageHeader, ((LPDWORD)lpcMessageHeader)[1] );
NS_SetLocalAddr( This->dp2->lpNameServerData, lpcMessageHeader, 20 );
DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
}
#endif
case DPMSGCMD_FORWARDADDPLAYER:
{
#if 0
DebugBreak();
#endif
#if 1
TRACE( "Sending message to self to get my addr\n" );
DP_MSG_ToSelf( This, 1 ); /* This is a hack right now */
#endif
break;
}
case DPMSGCMD_FORWARDADDPLAYERNACK:
{
DP_MSG_ErrorReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
break;
}
default:
{
FIXME( "Unknown wCommandId %u. Ignoring message\n", wCommandId );
DebugBreak();
break;
}
}
/* FIXME: There is code in dplaysp.c to handle dplay commands. Move to here. */
return DP_OK;
}
static HRESULT WINAPI DP_IF_AddPlayerToGroup
( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
DPID idPlayer, BOOL bAnsi )
{
lpGroupData lpGData;
lpPlayerList lpPList;
lpPlayerList lpNewPList;
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;
}
/* Create a player list (ie "shortcut" ) */
lpNewPList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpNewPList ) );
if( lpNewPList == NULL )
{
return DPERR_CANTADDPLAYER;
}
/* Add the shortcut */
lpPList->lpPData->uRef++;
lpNewPList->lpPData = lpPList->lpPData;
/* Add the player to the list of players for this group */
DPQ_INSERT(lpGData->players,lpNewPList,players);
/* Let the SP know that we've added a player to the group */
if( This->dp2->spData.lpCB->AddPlayerToGroup )
{
DPSP_ADDPLAYERTOGROUPDATA data;
TRACE( "Calling SP AddPlayerToGroup\n" );
data.idPlayer = idPlayer;
data.idGroup = idGroup;
data.lpISP = This->dp2->spData.lpISP;
(*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
}
/* Inform all other peers of the addition of player to the group. If there are
* no peers keep this event quiet.
* Also, if this event was the result of another machine sending it to us,
* don't bother rebroadcasting it.
*/
if( ( lpMsgHdr == NULL ) &&
This->dp2->lpSessionDesc &&
( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
{
DPMSG_ADDPLAYERTOGROUP msg;
msg.dwType = DPSYS_ADDPLAYERTOGROUP;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -