- Added a little more dll level debugging and small changes

- Start on group and player interfaces
oldstable
Peter Hunnisett 2000-05-30 20:08:32 +00:00 committed by Alexandre Julliard
parent 62f32331dd
commit 3951ff24ac
4 changed files with 492 additions and 10 deletions

View File

@ -18,6 +18,7 @@
#include "dpinit.h"
#include "dplayx_global.h"
#include "name_server.h"
#include "dplayx_queue.h"
/* FIXME: This stuff shouldn't really be here. It indicates a poor architectural coupling */
#include "dplobby.h"
@ -56,13 +57,55 @@ typedef struct tagDirectPlayIUnknownData
CRITICAL_SECTION DP_lock;
} DirectPlayIUnknownData;
typedef struct _enumSessionAsyncCallbackData
typedef struct tagEnumSessionAsyncCallbackData
{
LPDPENUMSESSIONSCALLBACK2 cb;
LPVOID lpContext;
DWORD dwTimeout;
} EnumSessionAsyncCallbackData;
struct PlayerData
{
/* Individual player information */
DPID dpid;
DPNAME name;
HANDLE hEvent;
LPVOID lpData;
DWORD dwDataSize;
};
typedef struct PlayerData* lpPlayerData;
struct PlayerList
{
TAILQ_ENTRY(PlayerList) players;
struct PlayerData playerData;
};
typedef struct PlayerList* lpPlayerList;
struct GroupData
{
TAILQ_ENTRY(GroupList) groups; /* A group has [0..n] groups */
TAILQ_ENTRY(PlayerList) players; /* A group has [0..n] players */
/* Individual group information */
DPID dpid;
DPNAME name;
LPVOID lpData;
DWORD dwDataSize;
};
typedef struct GroupData* lpGroupData;
struct GroupList
{
TAILQ_ENTRY(GroupList) groups;
struct GroupData groupData;
};
typedef struct GroupList* lpGroupList;
/* Contains all dp1 and dp2 data members */
typedef struct tagDirectPlay2Data
{
@ -72,7 +115,12 @@ typedef struct tagDirectPlay2Data
EnumSessionAsyncCallbackData enumSessionAsyncCallbackData;
LPVOID lpNameServerData; /* DPlay interface doesn't know type */
LPVOID lpNameServerData; /* DPlay interface doesn't know contents */
BOOL bHostInterface; /* Did this interface create the session */
TAILQ_HEAD( ,PlayerList) players;
TAILQ_HEAD( ,GroupList) groups;
} DirectPlay2Data;
typedef struct tagDirectPlay3Data
@ -118,6 +166,30 @@ static ICOM_VTABLE(IDirectPlay2) directPlay2WVT;
static ICOM_VTABLE(IDirectPlay3) directPlay3WVT;
static ICOM_VTABLE(IDirectPlay4) directPlay4WVT;
/* Local function prototypes */
static lpPlayerData DP_FindPlayer( IDirectPlay2AImpl* This, DPID dpid );
static lpPlayerData DP_CreatePlayer( IDirectPlay2* iface, LPDPID lpid,
LPDPNAME lpName, HANDLE hEvent,
BOOL bAnsi );
static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, LPDPNAME lpSrc, BOOL bAnsi );
static void DP_SetPlayerData( lpPlayerData lpPData, LPVOID lpData,
DWORD dwDataSize );
static lpGroupData DP_FindGroup( IDirectPlay2AImpl* This, DPID dpid );
static lpGroupData DP_CreateGroup( IDirectPlay2* iface, LPDPID lpid,
LPDPNAME lpName, BOOL bAnsi );
static void DP_SetGroupData( lpGroupData lpGData, LPVOID lpData,
DWORD dwDataSize );
static DWORD kludgePlayerGroupId = 100;
/* ------------------------------------------------------------------ */
BOOL DP_CreateIUnknown( LPVOID lpDP )
{
ICOM_THIS(IDirectPlay2AImpl,lpDP);
@ -165,6 +237,11 @@ BOOL DP_CreateDirectPlay2( LPVOID lpDP )
This->dp2->enumSessionAsyncCallbackData.lpContext = NULL;
This->dp2->enumSessionAsyncCallbackData.dwTimeout = INFINITE;
This->dp2->bHostInterface = FALSE;
TAILQ_INIT(&This->dp2->players);
TAILQ_INIT(&This->dp2->groups);
if( !NS_InitializeSessionCache( &This->dp2->lpNameServerData ) )
{
return FALSE;
@ -177,12 +254,16 @@ BOOL DP_DestroyDirectPlay2( LPVOID lpDP )
{
ICOM_THIS(IDirectPlay2AImpl,lpDP);
FIXME( ": memory leak\n" );
if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
{
TerminateThread( This->dp2->hEnumSessionThread, 0 );
CloseHandle( This->dp2->hEnumSessionThread );
}
/* Delete the player and group lists */
NS_DeleteSessionCache( This->dp2->lpNameServerData );
/* Delete the contents */
@ -624,14 +705,110 @@ static HRESULT WINAPI DirectPlay2WImpl_Close
return DP_OK;
}
static
lpGroupData DP_CreateGroup( IDirectPlay2* iface, LPDPID lpid,
LPDPNAME lpName, BOOL bAnsi )
{
ICOM_THIS(IDirectPlay2Impl,iface);
lpGroupList lpGroup;
TRACE( "(%p)->(%p,%p,%u)\n", This, lpid, lpName, bAnsi );
/* Allocate the new space and add to end of interface player list */
lpGroup = (lpGroupList) HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof( *lpGroup ) );
if( lpGroup == NULL )
{
return NULL;
}
TAILQ_INSERT_TAIL(&This->dp2->groups,lpGroup,groups);
if( *lpid == DPID_UNKNOWN )
{
/* Assign the next available player ID - FIXME crap solution */
lpGroup->groupData.dpid = kludgePlayerGroupId++;
}
else
{
/* Set the desired player ID - no sanity checking to see if it exists */
lpGroup->groupData.dpid = *lpid;
}
DP_CopyDPNAMEStruct( &lpGroup->groupData.name, lpName, bAnsi );
return &lpGroup->groupData;
}
static lpGroupData DP_FindGroup( IDirectPlay2AImpl* This, DPID dpid )
{
lpGroupList lpGroups;
TRACE( "(%p)->(0x%08lx)\n", This, dpid );
TAILQ_FIND_ENTRY( &This->dp2->groups, groups, groupData.dpid, dpid, lpGroups );
if( lpGroups )
{
return &lpGroups->groupData;
}
else
{
return NULL;
}
}
static HRESULT WINAPI DirectPlay2AImpl_CreateGroup
( LPDIRECTPLAY2A iface, LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
{
lpGroupData lpGData;
ICOM_THIS(IDirectPlay2Impl,iface);
FIXME("(%p)->(%p,%p,%p,0x%08lx,0x%08lx): stub\n", This, lpidGroup, lpGroupName, lpData, dwDataSize, dwFlags );
lpGData = DP_CreateGroup( iface, lpidGroup, lpGroupName, TRUE /* Ansi */ );
if( lpGData == NULL )
{
return DPERR_CANTADDPLAYER; /* yes player not group */
}
DP_SetGroupData( lpGData, lpData, dwDataSize );
/* FIXME: Should send DPMSG_CREATEPLAYERORGROUP message to everyone,
local and remote, that belongs to this session. This will not
be done by calling SetPlayerData */
FIXME( "Should broadcast group creation to everything in session\n" );
return DP_OK;
}
static void
DP_SetGroupData( lpGroupData lpGData, LPVOID lpData, DWORD dwDataSize )
{
/* Clear out the data with this player */
if( lpGData->dwDataSize != 0 )
{
HeapFree( GetProcessHeap(), 0, lpGData->lpData );
lpGData->lpData = NULL;
lpGData->dwDataSize = 0;
}
/* Reallocate for new data */
if( lpData )
{
lpGData->lpData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof( dwDataSize ) );
memcpy( lpGData->lpData, lpData, dwDataSize );
lpGData->dwDataSize = dwDataSize;
}
}
static HRESULT WINAPI DirectPlay2WImpl_CreateGroup
( LPDIRECTPLAY2 iface, LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
{
@ -640,15 +817,218 @@ static HRESULT WINAPI DirectPlay2WImpl_CreateGroup
return DP_OK;
}
static HRESULT WINAPI DirectPlay2AImpl_CreatePlayer
( LPDIRECTPLAY2A iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName, HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
/* This function will just create the storage for the new player.
* In the future it may want to intialize, but for the time being
* that will be done seperately.
*
* If *lpid == DPID_UNKNOWN then assign the next available player
*/
static
lpPlayerData DP_CreatePlayer( IDirectPlay2* iface, LPDPID lpid,
LPDPNAME lpName, HANDLE hEvent, BOOL bAnsi )
{
ICOM_THIS(IDirectPlay2Impl,iface);
lpPlayerList lpPlayer;
FIXME("(%p)->(%p,%p,%d,%p,0x%08lx,0x%08lx): stub\n", This, lpidPlayer, lpPlayerName, hEvent, lpData, dwDataSize, dwFlags );
TRACE( "(%p)->(%p,%p,%u)\n", This, lpid, lpName, bAnsi );
/* FIXME: Should send DPMSG_CREATEPLAYERORGROUP message to everyone, local and remote, that
belongs to this session */
/* Allocate the new space and add to end of interface player list */
lpPlayer = (lpPlayerList) HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof( *lpPlayer ) );
if( lpPlayer == NULL )
{
return NULL;
}
TAILQ_INSERT_TAIL(&This->dp2->players,lpPlayer,players);
if( *lpid == DPID_UNKNOWN )
{
/* Assign the next available player ID - FIXME crap solution */
lpPlayer->playerData.dpid = kludgePlayerGroupId++;
}
else
{
/* Set the desired player ID - no sanity checking to see if it exists */
lpPlayer->playerData.dpid = *lpid;
}
DP_CopyDPNAMEStruct( &lpPlayer->playerData.name, lpName, bAnsi );
lpPlayer->playerData.hEvent = hEvent;
return &lpPlayer->playerData;
}
static lpPlayerData DP_FindPlayer( IDirectPlay2AImpl* This, DPID dpid )
{
lpPlayerList lpPlayers;
TRACE( "(%p)->(0x%08lx)\n", This, dpid );
TAILQ_FIND_ENTRY( &This->dp2->players, players, playerData.dpid, dpid, lpPlayers );
if( lpPlayers )
{
return &lpPlayers->playerData;
}
else
{
return NULL;
}
}
/* 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 */
if( lpDst->psn.lpszShortNameA )
{
HeapFree( GetProcessHeap(), 0, lpDst->psn.lpszShortNameA );
}
if( lpDst->pln.lpszLongNameA )
{
HeapFree( GetProcessHeap(), 0, lpDst->psn.lpszShortNameA );
}
/* Copy as required */
memcpy( lpDst, lpSrc, lpSrc->dwSize );
if( bAnsi )
{
if( lpSrc->psn.lpszShortNameA )
{
lpDst->psn.lpszShortNameA =
HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY,
lpSrc->psn.lpszShortNameA );
}
if( lpSrc->pln.lpszLongNameA )
{
lpDst->pln.lpszLongNameA =
HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY,
lpSrc->pln.lpszLongNameA );
}
}
else
{
if( lpSrc->psn.lpszShortNameA )
{
lpDst->psn.lpszShortName =
HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY,
lpSrc->psn.lpszShortName );
}
if( lpSrc->pln.lpszLongNameA )
{
lpDst->pln.lpszLongName =
HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY,
lpSrc->pln.lpszLongName );
}
}
return TRUE;
}
static void
DP_SetPlayerData( lpPlayerData lpPData, LPVOID lpData, DWORD dwDataSize )
{
/* Clear out the data with this player */
if( lpPData->dwDataSize != 0 )
{
HeapFree( GetProcessHeap(), 0, lpPData->lpData );
lpPData->lpData = NULL;
lpPData->dwDataSize = 0;
}
/* Reallocate for new data */
if( lpData )
{
lpPData->lpData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof( dwDataSize ) );
memcpy( lpPData->lpData, lpData, dwDataSize );
lpPData->dwDataSize = dwDataSize;
}
}
static HRESULT WINAPI DirectPlay2AImpl_CreatePlayer
( LPDIRECTPLAY2A iface,
LPDPID lpidPlayer,
LPDPNAME lpPlayerName,
HANDLE hEvent,
LPVOID lpData,
DWORD dwDataSize,
DWORD dwFlags )
{
lpPlayerData lpPData;
ICOM_THIS(IDirectPlay2Impl,iface);
TRACE("(%p)->(%p,%p,%d,%p,0x%08lx,0x%08lx)\n", This, lpidPlayer, lpPlayerName, hEvent, lpData, dwDataSize, dwFlags );
if( dwFlags == 0 )
{
dwFlags = DPPLAYER_SPECTATOR;
}
/* 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 ( dwFlags & DPPLAYER_SERVERPLAYER )
{
/* We have a request to create the "master" of the session.
* This computer needs to be the session host and the server
* player can't have been created yet.
*/
if( ( !This->dp2->bHostInterface ) ||
( DP_FindPlayer( This, DPID_SERVERPLAYER ) )
)
{
return DPERR_CANTCREATEPLAYER;
}
*lpidPlayer = DPID_SERVERPLAYER;
}
else
{
*lpidPlayer = DPID_UNKNOWN;
}
lpPData = DP_CreatePlayer( iface, lpidPlayer,
lpPlayerName, hEvent, TRUE /*Ansi*/ );
if( lpPData == NULL )
{
return DPERR_CANTADDPLAYER;
}
/* Update the information and send it to all players in the session */
DP_SetPlayerData( lpPData, lpData, dwDataSize );
/* FIXME: Should send DPMSG_CREATEPLAYERORGROUP message to everyone,
local and remote, that belongs to this session. This will not
be done by calling SetPlayerData */
FIXME( "Should broadcast player creation to everything in session\n" );
return DP_OK;
}
@ -747,7 +1127,9 @@ static HRESULT WINAPI DirectPlay2AImpl_EnumPlayers
( LPDIRECTPLAY2A iface, LPGUID lpguidInstance, LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext, DWORD dwFlags )
{
ICOM_THIS(IDirectPlay2Impl,iface);
FIXME("(%p)->(%p,%p,%p,0x%08lx): stub\n", This, lpguidInstance, lpEnumPlayersCallback2, lpContext, dwFlags );
return DP_OK;
}
@ -1098,6 +1480,7 @@ static HRESULT WINAPI DirectPlay2AImpl_Open
the name server so that others can join this session */
NS_SetLocalComputerAsNameServer( lpsd );
This->dp2->bHostInterface = TRUE;
}
if( dwFlags )
@ -1151,8 +1534,28 @@ static HRESULT WINAPI DirectPlay2WImpl_Send
static HRESULT WINAPI DirectPlay2AImpl_SetGroupData
( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
{
lpGroupData lpGData;
ICOM_THIS(IDirectPlay2Impl,iface);
FIXME("(%p)->(0x%08lx,%p,0x%08lx,0x%08lx): stub\n", This, idGroup, lpData, dwDataSize, dwFlags );
FIXME("(%p)->(0x%08lx,%p,0x%08lx,0x%08lx): dwFlags ignored\n", This, idGroup, lpData, dwDataSize, dwFlags );
/* Parameter check */
if( lpData == NULL )
{
if( dwDataSize != 0 )
{
return DPERR_INVALIDPARAMS;
}
}
/* Find the pointer to the data for this player */
if( ( lpGData = DP_FindGroup( This, idGroup ) ) == NULL )
{
return DPERR_INVALIDOBJECT;
}
DP_SetGroupData( lpGData, lpData, dwDataSize );
return DP_OK;
}
@ -1183,8 +1586,33 @@ static HRESULT WINAPI DirectPlay2WImpl_SetGroupName
static HRESULT WINAPI DirectPlay2AImpl_SetPlayerData
( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
{
lpPlayerData lpPData;
ICOM_THIS(IDirectPlay2Impl,iface);
FIXME("(%p)->(0x%08lx,%p,0x%08lx,0x%08lx): stub\n", This, idPlayer, lpData, dwDataSize, dwFlags );
TRACE("(%p)->(0x%08lx,%p,0x%08lx,0x%08lx)\n", This, idPlayer, lpData, dwDataSize, dwFlags );
/* Parameter check */
if( lpData == NULL )
{
if( dwDataSize != 0 )
{
return DPERR_INVALIDPARAMS;
}
}
/* Find the pointer to the data for this player */
if( ( lpPData = DP_FindPlayer( This, idPlayer ) ) == NULL )
{
return DPERR_INVALIDOBJECT;
}
DP_SetPlayerData( lpPData, lpData, dwDataSize );
if( !(dwFlags & DPSET_LOCAL ) ) /* Is DPSET_REMOTE? */
{
FIXME( "Change not propagated to all players in the session\n" );
}
return DP_OK;
}
@ -1200,7 +1628,9 @@ static HRESULT WINAPI DirectPlay2AImpl_SetPlayerName
( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPNAME lpPlayerName, DWORD dwFlags )
{
ICOM_THIS(IDirectPlay2Impl,iface);
FIXME("(%p)->(0x%08lx,%p,0x%08lx): stub\n", This, idPlayer, lpPlayerName, dwFlags );
return DP_OK;
}
@ -1645,7 +2075,9 @@ static HRESULT WINAPI DirectPlay3AImpl_SecureOpen
the name server so that others can join this session */
NS_SetLocalComputerAsNameServer( lpsd );
This->dp2->bHostInterface = TRUE;
}
if( dwFlags )
{
ERR( ": ignored dwFlags 0x%08lx\n", dwFlags );

View File

@ -16,6 +16,9 @@ static DWORD DPLAYX_dwProcessesAttached = 0;
BOOL WINAPI DPLAYX_LibMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved )
{
FIXME( "(%p,0x%08lx,%p) & 0x%08lx\n", hinstDLL, fdwReason, lpvReserved, DPLAYX_dwProcessesAttached );
switch ( fdwReason )
{
case DLL_PROCESS_ATTACH:
@ -24,6 +27,7 @@ BOOL WINAPI DPLAYX_LibMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReser
if ( DPLAYX_dwProcessesAttached == 0 )
{
/* First instance perform construction of global processor data */
FIXME( "DPLAYX_dwProcessesAttached = 0x%08lx\n", DPLAYX_dwProcessesAttached );
DPLAYX_ConstructData();
}

View File

@ -0,0 +1,39 @@
/* Helper functions for TAILQ functions defined in <sys/queue.h>
*
* Blame any implementation mistakes on Peter Hunnisett
* <hunnise@nortelnetworks.com>
*/
#ifndef __WINE_DPLAYX_QUEUE_H
#define __WINE_DPLAYX_QUEUE_H
#include <sys/queue.h>
/* head - pointer to TAILQ_HEAD struct
* elm - how to find the next element
* field - to be concatenated to rc to compare with fieldToEqual
* fieldToEqual - The value that we're looking for
* rc - Variable to put the return code. Same type as (head)->tqh_first
*/
#define TAILQ_FIND_ENTRY( head, elm, field, fieldToEqual, rc ) { \
(rc) = (head)->tqh_first; /* NULL head? */ \
\
while( rc ) \
{ \
/* What we're searching for? */ \
if( (rc)->field == (fieldToEqual) ) \
{ \
break; /* rc == correct element */ \
} \
\
/* End of list check */ \
if( ( (rc) = (rc)->elm.tqe_next ) == (head)->tqh_first ) \
{ \
rc = NULL; \
break; \
} \
} \
}
#endif /* __WINE_DPLAYX_QUEUE_H */

View File

@ -1986,13 +1986,20 @@ HRESULT WINAPI DirectPlayLobbyCreateW( LPGUID lpGUIDDSP,
/* Parameter Check: lpGUIDSP, lpUnk & lpData must be NULL. dwDataSize must
* equal 0. These fields are mostly for future expansion.
*/
if ( lpGUIDDSP || lpUnk || lpData || dwDataSize )
if ( lpGUIDDSP || lpData || dwDataSize )
{
*lplpDPL = NULL;
ERR("Bad parameters!\n" );
return DPERR_INVALIDPARAMS;
}
if( lpUnk )
{
*lplpDPL = NULL;
ERR("Bad parameters!\n" );
return CLASS_E_NOAGGREGATION;
}
return directPlayLobby_QueryInterface( &IID_IDirectPlayLobby, (void**)lplpDPL );
}