📄 dplay.c
字号:
/* Direct Play 2,3,4 Implementation
*
* Copyright 1998,1999,2000,2001 - Peter Hunnisett
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include "wine/port.h"
#include <stdarg.h>
#include <string.h>
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
#include "windef.h"
#include "winerror.h"
#include "winbase.h"
#include "winnt.h"
#include "winreg.h"
#include "winnls.h"
#include "wine/unicode.h"
#include "wine/debug.h"
#include "dpinit.h"
#include "dplayx_global.h"
#include "name_server.h"
#include "dplayx_queue.h"
#include "dplaysp.h"
#include "dplay_global.h"
WINE_DEFAULT_DEBUG_CHANNEL(dplay);
/* FIXME: Should this be externed? */
extern HRESULT DPL_CreateCompoundAddress
( LPCDPCOMPOUNDADDRESSELEMENT lpElements, DWORD dwElementCount,
LPVOID lpAddress, LPDWORD lpdwAddressSize, BOOL bAnsiInterface );
/* Local function prototypes */
static lpPlayerList DP_FindPlayer( IDirectPlay2AImpl* This, DPID dpid );
static lpPlayerData DP_CreatePlayer( IDirectPlay2Impl* iface, LPDPID lpid,
LPDPNAME lpName, DWORD dwFlags,
HANDLE hEvent, BOOL bAnsi );
static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, LPDPNAME lpSrc, BOOL bAnsi );
static void DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
LPVOID lpData, DWORD dwDataSize );
static lpGroupData DP_CreateGroup( IDirectPlay2AImpl* iface, LPDPID lpid,
LPDPNAME lpName, DWORD dwFlags,
DPID idParent, BOOL bAnsi );
static void DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
LPVOID lpData, DWORD dwDataSize );
static void DP_DeleteDPNameStruct( LPDPNAME lpDPName );
static void DP_DeletePlayer( IDirectPlay2Impl* This, DPID dpid );
static BOOL CALLBACK cbDeletePlayerFromAllGroups( DPID dpId,
DWORD dwPlayerType,
LPCDPNAME lpName,
DWORD dwFlags,
LPVOID lpContext );
static lpGroupData DP_FindAnyGroup( IDirectPlay2AImpl* This, DPID dpid );
static BOOL CALLBACK cbRemoveGroupOrPlayer( DPID dpId, DWORD dwPlayerType,
LPCDPNAME lpName, DWORD dwFlags,
LPVOID lpContext );
static void DP_DeleteGroup( IDirectPlay2Impl* This, DPID dpid );
/* Forward declarations of virtual tables */
static const IDirectPlay2Vtbl directPlay2AVT;
static const IDirectPlay3Vtbl directPlay3AVT;
static const IDirectPlay4Vtbl directPlay4AVT;
static const IDirectPlay2Vtbl directPlay2WVT;
static const IDirectPlay3Vtbl directPlay3WVT;
static const IDirectPlay4Vtbl directPlay4WVT;
/* Helper methods for player/group interfaces */
static HRESULT WINAPI DP_IF_DeletePlayerFromGroup
( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
DPID idPlayer, BOOL bAnsi );
static HRESULT WINAPI DP_IF_CreatePlayer
( IDirectPlay2Impl* This, LPVOID lpMsgHdr, LPDPID lpidPlayer,
LPDPNAME lpPlayerName, HANDLE hEvent, LPVOID lpData,
DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
static HRESULT WINAPI DP_IF_DestroyGroup
( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, BOOL bAnsi );
static HRESULT WINAPI DP_IF_DestroyPlayer
( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idPlayer, BOOL bAnsi );
static HRESULT WINAPI DP_IF_EnumGroupPlayers
( IDirectPlay2Impl* This, DPID idGroup, LPGUID lpguidInstance,
LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
static HRESULT WINAPI DP_IF_EnumGroups
( IDirectPlay2Impl* This, LPGUID lpguidInstance,
LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
static HRESULT WINAPI DP_IF_EnumPlayers
( IDirectPlay2Impl* This, LPGUID lpguidInstance,
LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
static HRESULT WINAPI DP_IF_GetGroupData
( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi );
static HRESULT WINAPI DP_IF_GetGroupName
( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
LPDWORD lpdwDataSize, BOOL bAnsi );
static HRESULT WINAPI DP_IF_GetPlayerData
( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi );
static HRESULT WINAPI DP_IF_GetPlayerName
( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
LPDWORD lpdwDataSize, BOOL bAnsi );
static HRESULT WINAPI DP_IF_SetGroupName
( IDirectPlay2Impl* This, DPID idGroup, LPDPNAME lpGroupName,
DWORD dwFlags, BOOL bAnsi );
static HRESULT WINAPI DP_IF_SetPlayerData
( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
static HRESULT WINAPI DP_IF_SetPlayerName
( IDirectPlay2Impl* This, DPID idPlayer, LPDPNAME lpPlayerName,
DWORD dwFlags, BOOL bAnsi );
static HRESULT WINAPI DP_IF_AddGroupToGroup
( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup );
static HRESULT WINAPI DP_IF_CreateGroup
( IDirectPlay2AImpl* This, LPVOID lpMsgHdr, LPDPID lpidGroup,
LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
DWORD dwFlags, BOOL bAnsi );
static HRESULT WINAPI DP_IF_CreateGroupInGroup
( IDirectPlay3Impl* This, LPVOID lpMsgHdr, DPID idParentGroup,
LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData,
DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
static HRESULT WINAPI DP_IF_AddPlayerToGroup
( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
DPID idPlayer, BOOL bAnsi );
static HRESULT WINAPI DP_IF_DeleteGroupFromGroup
( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup );
static HRESULT WINAPI DP_SetSessionDesc
( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpSessDesc,
DWORD dwFlags, BOOL bInitial, BOOL bAnsi );
static HRESULT WINAPI DP_SecureOpen
( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials,
BOOL bAnsi );
static HRESULT WINAPI DP_SendEx
( IDirectPlay2Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
LPVOID lpContext, LPDWORD lpdwMsgID, BOOL bAnsi );
static HRESULT WINAPI DP_IF_Receive
( IDirectPlay2Impl* This, LPDPID lpidFrom, LPDPID lpidTo,
DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize, BOOL bAnsi );
static HRESULT WINAPI DP_IF_GetMessageQueue
( IDirectPlay4Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes, BOOL bAnsi );
static HRESULT WINAPI DP_SP_SendEx
( IDirectPlay2Impl* This, DWORD dwFlags,
LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
LPVOID lpContext, LPDWORD lpdwMsgID );
static HRESULT WINAPI DP_IF_SetGroupData
( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
static HRESULT WINAPI DP_IF_GetPlayerCaps
( IDirectPlay2Impl* This, DPID idPlayer, LPDPCAPS lpDPCaps,
DWORD dwFlags );
static HRESULT WINAPI DP_IF_Close( IDirectPlay2Impl* This, BOOL bAnsi );
static HRESULT WINAPI DP_IF_CancelMessage
( IDirectPlay4Impl* This, DWORD dwMsgID, DWORD dwFlags,
DWORD dwMinPriority, DWORD dwMaxPriority, BOOL bAnsi );
static HRESULT WINAPI DP_IF_EnumGroupsInGroup
( IDirectPlay3AImpl* This, DPID idGroup, LPGUID lpguidInstance,
LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
static HRESULT WINAPI DP_IF_GetGroupParent
( IDirectPlay3AImpl* This, DPID idGroup, LPDPID lpidGroup,
BOOL bAnsi );
static HRESULT WINAPI DP_IF_GetCaps
( IDirectPlay2Impl* This, LPDPCAPS lpDPCaps, DWORD dwFlags );
static HRESULT WINAPI DP_IF_EnumSessions
( IDirectPlay2Impl* This, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
static HRESULT WINAPI DP_IF_InitializeConnection
( IDirectPlay3Impl* This, LPVOID lpConnection, DWORD dwFlags, BOOL bAnsi );
static BOOL CALLBACK cbDPCreateEnumConnections( LPCGUID lpguidSP,
LPVOID lpConnection, DWORD dwConnectionSize, LPCDPNAME lpName,
DWORD dwFlags, LPVOID lpContext );
static BOOL WINAPI DP_BuildSPCompoundAddr( LPGUID lpcSpGuid, LPVOID* lplpAddrBuf,
LPDWORD lpdwBufSize );
static inline DPID DP_NextObjectId(void);
static DPID DP_GetRemoteNextObjectId(void);
static void DP_CopySessionDesc( LPDPSESSIONDESC2 destSessionDesc,
LPCDPSESSIONDESC2 srcSessDesc, BOOL bAnsi );
static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp );
static HRESULT DP_InitializeDPSP( IDirectPlay3Impl* This, HMODULE hServiceProvider );
static HRESULT DP_InitializeDPLSP( IDirectPlay3Impl* This, HMODULE hServiceProvider );
#define DPID_NOPARENT_GROUP 0 /* Magic number to indicate no parent of group */
#define DPID_SYSTEM_GROUP DPID_NOPARENT_GROUP /* If system group is supported
we don't have to change much */
#define DPID_NAME_SERVER 0x19a9d65b /* Don't ask me why */
/* Strip out dwFlag values which cannot be sent in the CREATEGROUP msg */
#define DPMSG_CREATEGROUP_DWFLAGS(x) ( (x) & DPGROUP_HIDDEN )
/* Strip out all dwFlags values for CREATEPLAYER msg */
#define DPMSG_CREATEPLAYER_DWFLAGS(x) 0
static LONG kludgePlayerGroupId = 1000;
/* ------------------------------------------------------------------ */
static BOOL DP_CreateIUnknown( LPVOID lpDP )
{
IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)lpDP;
This->unk = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->unk) ) );
if ( This->unk == NULL )
{
return FALSE;
}
InitializeCriticalSection( &This->unk->DP_lock );
return TRUE;
}
static BOOL DP_DestroyIUnknown( LPVOID lpDP )
{
IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)lpDP;
DeleteCriticalSection( &This->unk->DP_lock );
HeapFree( GetProcessHeap(), 0, This->unk );
return TRUE;
}
static BOOL DP_CreateDirectPlay2( LPVOID lpDP )
{
IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)lpDP;
This->dp2 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->dp2) ) );
if ( This->dp2 == NULL )
{
return FALSE;
}
This->dp2->bConnectionOpen = FALSE;
This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
This->dp2->bHostInterface = FALSE;
DPQ_INIT(This->dp2->receiveMsgs);
DPQ_INIT(This->dp2->sendMsgs);
DPQ_INIT(This->dp2->replysExpected);
if( !NS_InitializeSessionCache( &This->dp2->lpNameServerData ) )
{
/* FIXME: Memory leak */
return FALSE;
}
/* Provide an initial session desc with nothing in it */
This->dp2->lpSessionDesc = HeapAlloc( GetProcessHeap(),
HEAP_ZERO_MEMORY,
sizeof( *This->dp2->lpSessionDesc ) );
if( This->dp2->lpSessionDesc == NULL )
{
/* FIXME: Memory leak */
return FALSE;
}
This->dp2->lpSessionDesc->dwSize = sizeof( *This->dp2->lpSessionDesc );
/* We are emulating a dp 6 implementation */
This->dp2->spData.dwSPVersion = DPSP_MAJORVERSION;
This->dp2->spData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof( *This->dp2->spData.lpCB ) );
This->dp2->spData.lpCB->dwSize = sizeof( *This->dp2->spData.lpCB );
This->dp2->spData.lpCB->dwVersion = DPSP_MAJORVERSION;
/* This is the pointer to the service provider */
if( FAILED( DPSP_CreateInterface( &IID_IDirectPlaySP,
(LPVOID*)&This->dp2->spData.lpISP, This ) )
)
{
/* FIXME: Memory leak */
return FALSE;
}
/* Setup lobby provider information */
This->dp2->dplspData.dwSPVersion = DPSP_MAJORVERSION;
This->dp2->dplspData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof( *This->dp2->dplspData.lpCB ) );
This->dp2->dplspData.lpCB->dwSize = sizeof( *This->dp2->dplspData.lpCB );
if( FAILED( DPLSP_CreateInterface( &IID_IDPLobbySP,
(LPVOID*)&This->dp2->dplspData.lpISP, This ) )
)
{
/* FIXME: Memory leak */
return FALSE;
}
return TRUE;
}
/* Definition of the global function in dplayx_queue.h. #
* FIXME: Would it be better to have a dplayx_queue.c for this function? */
DPQ_DECL_DELETECB( cbDeleteElemFromHeap, LPVOID )
{
HeapFree( GetProcessHeap(), 0, elem );
}
/* Function to delete the list of groups with this interface. Needs to
* delete the group and player lists associated with this group as well
* as the group data associated with this group. It should not delete
* player data as that is shared with the top player list and will be
* deleted with that.
*/
DPQ_DECL_DELETECB( cbDeleteGroupsElem, lpGroupList );
DPQ_DECL_DELETECB( cbDeleteGroupsElem, lpGroupList )
{
DPQ_DELETEQ( elem->lpGData->groups, groups,
lpGroupList, cbDeleteElemFromHeap );
DPQ_DELETEQ( elem->lpGData->players, players,
lpPlayerList, cbDeleteElemFromHeap );
HeapFree( GetProcessHeap(), 0, elem->lpGData );
HeapFree( GetProcessHeap(), 0, elem );
}
/* Function to delete the list of players with this interface. Needs to
* delete the player data for all players as well.
*/
DPQ_DECL_DELETECB( cbDeletePlayerElem, lpPlayerList );
DPQ_DECL_DELETECB( cbDeletePlayerElem, lpPlayerList )
{
HeapFree( GetProcessHeap(), 0, elem->lpPData );
HeapFree( GetProcessHeap(), 0, elem );
}
static BOOL DP_DestroyDirectPlay2( LPVOID lpDP )
{
IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)lpDP;
if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
{
TerminateThread( This->dp2->hEnumSessionThread, 0 );
CloseHandle( This->dp2->hEnumSessionThread );
}
/* Finish with the SP - have it shutdown */
if( This->dp2->spData.lpCB->ShutdownEx )
{
DPSP_SHUTDOWNDATA data;
TRACE( "Calling SP ShutdownEx\n" );
data.lpISP = This->dp2->spData.lpISP;
(*This->dp2->spData.lpCB->ShutdownEx)( &data );
}
else if (This->dp2->spData.lpCB->Shutdown ) /* obsolete interface */
{
TRACE( "Calling obsolete SP Shutdown\n" );
(*This->dp2->spData.lpCB->Shutdown)();
}
/* Unload the SP (if it exists) */
if( This->dp2->hServiceProvider != 0 )
{
FreeLibrary( This->dp2->hServiceProvider );
}
/* Unload the Lobby Provider (if it exists) */
if( This->dp2->hDPLobbyProvider != 0 )
{
FreeLibrary( This->dp2->hDPLobbyProvider );
}
#if 0
DPQ_DELETEQ( This->dp2->players, players, lpPlayerList, cbDeletePlayerElem );
DPQ_DELETEQ( This->dp2->groups, groups, lpGroupList, cbDeleteGroupsElem );
#endif
/* FIXME: Need to delete receive and send msgs queue contents */
NS_DeleteSessionCache( This->dp2->lpNameServerData );
HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
IDirectPlaySP_Release( This->dp2->spData.lpISP );
/* Delete the contents */
HeapFree( GetProcessHeap(), 0, This->dp2 );
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -