- Make ref counting a little more efficient
- Correct suspended process resumption - Don't use sys/queue.h anymore - Properly initialize the global semaphore across processes - Create a mapped file for shared data structures - Change some trace messages - Allocate dynamic shared data from the mapped file - Rework setting and retrieving lobby settings from shared memory - Add infrastructure for syncronization after app launch - Small documentation update - Include some stuff missing from header - Start on dp and dpl message infrastructure - Unicode versions of player/group commands added - Combined Connect/ConnectEx and Open/SecureOpen - More implementation
This commit is contained in:
parent
961053fd2f
commit
4da59ea6dd
|
@ -6,12 +6,14 @@ MODULE = dplayx
|
|||
SOVERSION = 1.0
|
||||
IMPORTS = ole32
|
||||
|
||||
C_SRCS = dplay.c \
|
||||
dplobby.c \
|
||||
dpclassfactory.c \
|
||||
dplayx_main.c \
|
||||
dplayx_global.c \
|
||||
name_server.c
|
||||
C_SRCS = \
|
||||
dpclassfactory.c \
|
||||
dplay.c \
|
||||
dplayx_global.c \
|
||||
dplayx_main.c \
|
||||
dplayx_messages.c \
|
||||
dplobby.c \
|
||||
name_server.c
|
||||
|
||||
@MAKE_DLL_RULES@
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -4,18 +4,31 @@
|
|||
|
||||
#include "dplay.h"
|
||||
|
||||
void DPLAYX_ConstructData(void);
|
||||
void DPLAYX_DestructData(void);
|
||||
BOOL DPLAYX_ConstructData(void);
|
||||
BOOL DPLAYX_DestructData(void);
|
||||
|
||||
HRESULT DPLAYX_GetConnectionSettingsA ( DWORD dwAppID, LPVOID lpData, LPDWORD lpdwDataSize );
|
||||
HRESULT DPLAYX_GetConnectionSettingsW ( DWORD dwAppID, LPVOID lpData, LPDWORD lpdwDataSize );
|
||||
HRESULT DPLAYX_GetConnectionSettingsA ( DWORD dwAppID,
|
||||
LPVOID lpData,
|
||||
LPDWORD lpdwDataSize,
|
||||
LPBOOL lpbSendHaveReadMessage );
|
||||
HRESULT DPLAYX_GetConnectionSettingsW ( DWORD dwAppID,
|
||||
LPVOID lpData,
|
||||
LPDWORD lpdwDataSize,
|
||||
LPBOOL lpbSendHaveReadMessage );
|
||||
|
||||
HRESULT DPLAYX_SetConnectionSettingsA ( DWORD dwFlags, DWORD dwAppID, LPDPLCONNECTION lpConn );
|
||||
HRESULT DPLAYX_SetConnectionSettingsW ( DWORD dwFlags, DWORD dwAppID, LPDPLCONNECTION lpConn );
|
||||
HRESULT DPLAYX_SetConnectionSettingsA ( DWORD dwFlags,
|
||||
DWORD dwAppID,
|
||||
LPDPLCONNECTION lpConn );
|
||||
HRESULT DPLAYX_SetConnectionSettingsW ( DWORD dwFlags,
|
||||
DWORD dwAppID,
|
||||
LPDPLCONNECTION lpConn );
|
||||
|
||||
BOOL DPLAYX_CreateLobbyApplication( DWORD dwAppID, HANDLE hReceiveEvent );
|
||||
BOOL DPLAYX_DestroyLobbyApplication( DWORD dwAppID );
|
||||
|
||||
BOOL DPLAYX_WaitForConnectionSettings( BOOL bWait );
|
||||
BOOL DPLAYX_AnyLobbiesWaitingForConnSettings(void);
|
||||
|
||||
LPDPSESSIONDESC2 DPLAYX_CopyAndAllocateLocalSession( UINT* index );
|
||||
BOOL DPLAYX_CopyLocalSession( UINT* index, LPDPSESSIONDESC2 lpsd );
|
||||
void DPLAYX_SetLocalSession( LPCDPSESSIONDESC2 lpsd );
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* DPLAYX.DLL LibMain
|
||||
*
|
||||
* Copyright 1999 - Peter Hunnisett
|
||||
* Copyright 1999,2000 - Peter Hunnisett
|
||||
*
|
||||
* contact <hunnise@nortelnetworks.com>
|
||||
*/
|
||||
|
@ -17,34 +17,29 @@ static DWORD DPLAYX_dwProcessesAttached = 0;
|
|||
BOOL WINAPI DPLAYX_LibMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved )
|
||||
{
|
||||
|
||||
TRACE( "(%p,0x%08lx,%p) & 0x%08lx\n", hinstDLL, fdwReason, lpvReserved, DPLAYX_dwProcessesAttached );
|
||||
TRACE( "(%u,0x%08lx,%p) & 0x%08lx\n", hinstDLL, fdwReason, lpvReserved, DPLAYX_dwProcessesAttached );
|
||||
|
||||
switch ( fdwReason )
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
{
|
||||
|
||||
if ( DPLAYX_dwProcessesAttached == 0 )
|
||||
if ( DPLAYX_dwProcessesAttached++ == 0 )
|
||||
{
|
||||
/* First instance perform construction of global processor data */
|
||||
TRACE( "DPLAYX_dwProcessesAttached = 0x%08lx\n", DPLAYX_dwProcessesAttached );
|
||||
DPLAYX_ConstructData();
|
||||
return DPLAYX_ConstructData();
|
||||
}
|
||||
|
||||
DPLAYX_dwProcessesAttached++;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case DLL_PROCESS_DETACH:
|
||||
{
|
||||
|
||||
DPLAYX_dwProcessesAttached--;
|
||||
|
||||
if ( DPLAYX_dwProcessesAttached == 0 )
|
||||
if ( --DPLAYX_dwProcessesAttached == 0 )
|
||||
{
|
||||
/* Last instance perform destruction of global processor data */
|
||||
DPLAYX_DestructData();
|
||||
/* Last instance performs destruction of global processor data */
|
||||
return DPLAYX_DestructData();
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
/* DirectPlay & DirectPlayLobby messaging implementation
|
||||
*
|
||||
* Copyright 2000 - Peter Hunnisett
|
||||
*
|
||||
* <presently under construction - contact hunnise@nortelnetworks.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "winbase.h"
|
||||
#include "debugtools.h"
|
||||
|
||||
#include "dplayx_messages.h"
|
||||
|
||||
DEFAULT_DEBUG_CHANNEL(dplay)
|
||||
|
||||
|
||||
static DWORD CALLBACK DPLAYX_MSG_ThreadMain( LPVOID lpContext );
|
||||
|
||||
/* Create the message reception thread to allow the application to receive
|
||||
* asynchronous message reception
|
||||
*/
|
||||
DWORD CreateMessageReceptionThread( HANDLE hNotifyEvent )
|
||||
{
|
||||
DWORD dwMsgThreadId;
|
||||
|
||||
if( !DuplicateHandle( 0, hNotifyEvent, 0, NULL, 0, FALSE, 0 ) )
|
||||
{
|
||||
ERR( "Unable to duplicate event handle\n" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* FIXME: Should most likely store that thread handle */
|
||||
CreateThread( NULL, /* Security attribs */
|
||||
0, /* Stack */
|
||||
DPLAYX_MSG_ThreadMain, /* Msg reception function */
|
||||
(LPVOID)hNotifyEvent, /* Msg reception function parameter */
|
||||
0, /* Flags */
|
||||
&dwMsgThreadId /* Updated with thread id */
|
||||
);
|
||||
|
||||
return dwMsgThreadId;
|
||||
}
|
||||
static DWORD CALLBACK DPLAYX_MSG_ThreadMain( LPVOID lpContext )
|
||||
{
|
||||
HANDLE hMsgEvent = (HANDLE)lpContext;
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
FIXME( "Ho Hum. Msg thread with nothing to do on handle %u\n", hMsgEvent );
|
||||
|
||||
SleepEx( 10000, FALSE ); /* 10 secs */
|
||||
}
|
||||
|
||||
CloseHandle( hMsgEvent );
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
|
||||
#ifndef __WINE_DPLAYX_MESSAGES
|
||||
#define __WINE_DPLAYX_MESSAGES
|
||||
|
||||
#include "windef.h"
|
||||
|
||||
DWORD CreateMessageReceptionThread( HANDLE hNotifyEvent );
|
||||
|
||||
|
||||
#endif
|
|
@ -1,5 +1,4 @@
|
|||
|
||||
/* Helper functions for TAILQ functions defined in <sys/queue.h>
|
||||
/* A queue definition based on sys/queue.h TAILQ definitions
|
||||
*
|
||||
* Blame any implementation mistakes on Peter Hunnisett
|
||||
* <hunnise@nortelnetworks.com>
|
||||
|
@ -8,50 +7,92 @@
|
|||
#ifndef __WINE_DPLAYX_QUEUE_H
|
||||
#define __WINE_DPLAYX_QUEUE_H
|
||||
|
||||
#include <sys/queue.h>
|
||||
#define DPQ_INSERT(a,b,c) DPQ_INSERT_IN_TAIL(a,b,c)
|
||||
|
||||
/* 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
|
||||
/*
|
||||
* Tail queue definitions.
|
||||
*/
|
||||
#define TAILQ_FIND_ENTRY( head, elm, field, fieldToEqual, rc ) \
|
||||
do { \
|
||||
(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; \
|
||||
} \
|
||||
} \
|
||||
#define DPQ_HEAD(type) \
|
||||
struct { \
|
||||
struct type *lpQHFirst; /* first element */ \
|
||||
struct type **lpQHLast; /* addr of last next element */ \
|
||||
}
|
||||
|
||||
#define DPQ_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *lpQNext; /* next element */ \
|
||||
struct type **lpQPrev; /* address of previous next element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* Tail queue functions.
|
||||
*/
|
||||
#define DPQ_INIT(head) \
|
||||
do{ \
|
||||
(head).lpQHFirst = NULL; \
|
||||
(head).lpQHLast = &(head).lpQHFirst; \
|
||||
} while(0)
|
||||
|
||||
/* head - pointer to TAILQ_HEAD struct
|
||||
#define DPQ_INSERT_IN_TAIL(head, elm, field) \
|
||||
do { \
|
||||
(elm)->field.lpQNext = NULL; \
|
||||
(elm)->field.lpQPrev = (head).lpQHLast; \
|
||||
*(head).lpQHLast = (elm); \
|
||||
(head).lpQHLast = &(elm)->field.lpQNext; \
|
||||
} while(0)
|
||||
|
||||
#define DPQ_REMOVE(head, elm, field) \
|
||||
do { \
|
||||
if (((elm)->field.lpQNext) != NULL) \
|
||||
(elm)->field.lpQNext->field.lpQPrev = \
|
||||
(elm)->field.lpQPrev; \
|
||||
else \
|
||||
(head).lpQHLast = (elm)->field.lpQPrev; \
|
||||
*(elm)->field.lpQPrev = (elm)->field.lpQNext; \
|
||||
} while(0)
|
||||
|
||||
/* head - pointer to DPQ_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
|
||||
* rc - Variable to put the return code. Same type as (head).lpQHFirst
|
||||
*/
|
||||
#define TAILQ_REMOVE_ENTRY( head, elm, field, fieldToEqual, rc ) \
|
||||
do { \
|
||||
TAILQ_FIND_ENTRY( head, elm, field, fieldToEqual, rc ); \
|
||||
\
|
||||
/* Was the element found? */ \
|
||||
if( rc ) \
|
||||
{ \
|
||||
TAILQ_REMOVE( head, rc, elm ); \
|
||||
} \
|
||||
#define DPQ_FIND_ENTRY( head, elm, field, fieldToEqual, rc ) \
|
||||
do { \
|
||||
(rc) = (head).lpQHFirst; /* 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.lpQNext ) == (head).lpQHFirst ) \
|
||||
{ \
|
||||
rc = NULL; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
/* head - pointer to DPQ_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).lpQHFirst
|
||||
*/
|
||||
#define DPQ_REMOVE_ENTRY( head, elm, field, fieldToEqual, rc ) \
|
||||
do { \
|
||||
DPQ_FIND_ENTRY( head, elm, field, fieldToEqual, rc ); \
|
||||
\
|
||||
/* Was the element found? */ \
|
||||
if( rc ) \
|
||||
{ \
|
||||
DPQ_REMOVE( head, rc, elm ); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#endif /* __WINE_DPLAYX_QUEUE_H */
|
||||
|
|
|
@ -16,9 +16,19 @@
|
|||
#include "dplobby.h"
|
||||
#include "dpinit.h"
|
||||
#include "dplayx_global.h"
|
||||
#include "dplayx_messages.h"
|
||||
|
||||
DEFAULT_DEBUG_CHANNEL(dplay)
|
||||
|
||||
/*****************************************************************************
|
||||
* Predeclare the interface implementation structures
|
||||
*/
|
||||
typedef struct IDirectPlayLobbyImpl IDirectPlayLobbyAImpl;
|
||||
typedef struct IDirectPlayLobbyImpl IDirectPlayLobbyWImpl;
|
||||
typedef struct IDirectPlayLobby2Impl IDirectPlayLobby2AImpl;
|
||||
typedef struct IDirectPlayLobby2Impl IDirectPlayLobby2WImpl;
|
||||
typedef struct IDirectPlayLobby3Impl IDirectPlayLobby3AImpl;
|
||||
typedef struct IDirectPlayLobby3Impl IDirectPlayLobby3WImpl;
|
||||
|
||||
/* Forward declarations for this module helper methods */
|
||||
HRESULT DPL_CreateCompoundAddress ( LPCDPCOMPOUNDADDRESSELEMENT lpElements, DWORD dwElementCount,
|
||||
|
@ -32,16 +42,11 @@ HRESULT DPL_CreateAddress( REFGUID guidSP, REFGUID guidDataType, LPCVOID lpData,
|
|||
static HRESULT DPL_EnumAddress( LPDPENUMADDRESSCALLBACK lpEnumAddressCallback, LPCVOID lpAddress,
|
||||
DWORD dwAddressSize, LPVOID lpContext );
|
||||
|
||||
static HRESULT WINAPI DPL_ConnectEx( IDirectPlayLobbyAImpl* This,
|
||||
DWORD dwFlags, REFIID riid,
|
||||
LPVOID* lplpDP, IUnknown* pUnk );
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* Predeclare the interface implementation structures
|
||||
*/
|
||||
typedef struct IDirectPlayLobbyImpl IDirectPlayLobbyAImpl;
|
||||
typedef struct IDirectPlayLobbyImpl IDirectPlayLobbyWImpl;
|
||||
typedef struct IDirectPlayLobby2Impl IDirectPlayLobby2AImpl;
|
||||
typedef struct IDirectPlayLobby2Impl IDirectPlayLobby2WImpl;
|
||||
typedef struct IDirectPlayLobby3Impl IDirectPlayLobby3AImpl;
|
||||
typedef struct IDirectPlayLobby3Impl IDirectPlayLobby3WImpl;
|
||||
|
||||
/*****************************************************************************
|
||||
* IDirectPlayLobby {1,2,3} implementation structure
|
||||
|
@ -65,7 +70,7 @@ typedef struct tagDirectPlayLobbyIUnknownData
|
|||
|
||||
typedef struct tagDirectPlayLobbyData
|
||||
{
|
||||
HKEY hkCallbackKeyHack;
|
||||
HKEY hkCallbackKeyHack;
|
||||
} DirectPlayLobbyData;
|
||||
|
||||
typedef struct tagDirectPlayLobby2Data
|
||||
|
@ -565,11 +570,7 @@ static ULONG WINAPI IDirectPlayLobbyImpl_AddRef
|
|||
ULONG refCount;
|
||||
ICOM_THIS(IDirectPlayLobbyWImpl,iface);
|
||||
|
||||
EnterCriticalSection( &This->unk->DPL_lock );
|
||||
{
|
||||
refCount = ++(This->unk->ref);
|
||||
}
|
||||
LeaveCriticalSection( &This->unk->DPL_lock );
|
||||
refCount = InterlockedIncrement( &This->unk->ref );
|
||||
|
||||
TRACE("ref count incremented to %lu for %p\n", refCount, This );
|
||||
|
||||
|
@ -585,14 +586,9 @@ static ULONG WINAPI IDirectPlayLobbyAImpl_Release
|
|||
( LPDIRECTPLAYLOBBYA iface )
|
||||
{
|
||||
ULONG refCount;
|
||||
|
||||
ICOM_THIS(IDirectPlayLobbyAImpl,iface);
|
||||
|
||||
EnterCriticalSection( &This->unk->DPL_lock );
|
||||
{
|
||||
refCount = --(This->unk->ref);
|
||||
}
|
||||
LeaveCriticalSection( &This->unk->DPL_lock );
|
||||
refCount = InterlockedDecrement( &This->unk->ref );
|
||||
|
||||
TRACE("ref count decremeneted to %lu for %p\n", refCount, This );
|
||||
|
||||
|
@ -618,20 +614,19 @@ static ULONG WINAPI IDirectPlayLobbyAImpl_Release
|
|||
* Returns a IDirectPlay interface.
|
||||
*
|
||||
*/
|
||||
static HRESULT WINAPI IDirectPlayLobbyAImpl_Connect
|
||||
( LPDIRECTPLAYLOBBYA iface,
|
||||
DWORD dwFlags,
|
||||
LPDIRECTPLAY2A* lplpDP,
|
||||
static HRESULT WINAPI DPL_ConnectEx
|
||||
( IDirectPlayLobbyAImpl* This,
|
||||
DWORD dwFlags,
|
||||
REFIID riid,
|
||||
LPVOID* lplpDP,
|
||||
IUnknown* pUnk)
|
||||
{
|
||||
ICOM_THIS(IDirectPlayLobbyAImpl,iface);
|
||||
HRESULT hr;
|
||||
DWORD dwOpenFlags = 0;
|
||||
DWORD dwConnSize = 0;
|
||||
LPDPLCONNECTION lpConn;
|
||||
|
||||
LPDIRECTPLAY2A lpDirectPlay2A;
|
||||
/* LPDIRECTPLAY3A lpDirectPlay3A; */
|
||||
/* LPDIRECTPLAYLOBBY2A lpDirectPlayLobby2A; */
|
||||
HRESULT rc;
|
||||
|
||||
FIXME("(%p)->(0x%08lx,%p,%p): stub\n", This, dwFlags, lplpDP, pUnk );
|
||||
FIXME("(%p)->(0x%08lx,%p,%p): semi stub\n", This, dwFlags, lplpDP, pUnk );
|
||||
|
||||
if( dwFlags || pUnk )
|
||||
{
|
||||
|
@ -639,27 +634,66 @@ static HRESULT WINAPI IDirectPlayLobbyAImpl_Connect
|
|||
}
|
||||
|
||||
/* Create the DirectPlay interface */
|
||||
if( ( rc = directPlay_QueryInterface( &IID_IDirectPlay2A, (LPVOID*)lplpDP ) ) != DP_OK )
|
||||
if( ( hr = directPlay_QueryInterface( riid, lplpDP ) ) != DP_OK )
|
||||
{
|
||||
ERR("error creating Direct Play 2A interface. Return Code = 0x%lx.\n", rc );
|
||||
return rc;
|
||||
ERR( "error creating interface for %s:%s.\n",
|
||||
debugstr_guid( riid ), DPLAYX_HresultToString( hr ) );
|
||||
return hr;
|
||||
}
|
||||
|
||||
lpDirectPlay2A = *lplpDP;
|
||||
|
||||
/* - Need to call IDirectPlay::EnumConnections with the service provider to get that good information
|
||||
* - Need to call CreateAddress to create the lpConnection param for IDirectPlay::InitializeConnection
|
||||
* - Call IDirectPlay::InitializeConnection
|
||||
* - Call IDirectPlay::Open
|
||||
*/
|
||||
#if 0
|
||||
IDirectPlayLobby_EnumAddress( iface, RunApplicationA_Callback,
|
||||
lpConn->lpAddress, lpConn->dwAddressSize, NULL );
|
||||
#endif
|
||||
|
||||
/* FIXME: Is it safe/correct to use appID of 0? */
|
||||
hr = IDirectPlayLobby_GetConnectionSettings( (LPDIRECTPLAYLOBBY)This,
|
||||
0, NULL, &dwConnSize );
|
||||
if( hr != DPERR_BUFFERTOOSMALL )
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
|
||||
lpConn = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwConnSize );
|
||||
|
||||
return DP_OK;
|
||||
if( lpConn == NULL )
|
||||
{
|
||||
return DPERR_NOMEMORY;
|
||||
}
|
||||
|
||||
/* FIXME: Is it safe/correct to use appID of 0? */
|
||||
hr = IDirectPlayLobby_GetConnectionSettings( (LPDIRECTPLAYLOBBY)This,
|
||||
0, lpConn, &dwConnSize );
|
||||
if( FAILED( hr ) )
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
|
||||
/* Setup flags to pass into DirectPlay::Open */
|
||||
if( dwFlags & DPCONNECT_RETURNSTATUS )
|
||||
{
|
||||
dwOpenFlags |= DPOPEN_RETURNSTATUS;
|
||||
}
|
||||
dwOpenFlags |= lpConn->dwFlags;
|
||||
|
||||
hr = IDirectPlayX_Open( (*(LPDIRECTPLAY2*)lplpDP), lpConn->lpSessionDesc,
|
||||
dwOpenFlags );
|
||||
|
||||
HeapFree( GetProcessHeap(), 0, lpConn );
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI IDirectPlayLobbyAImpl_Connect
|
||||
( LPDIRECTPLAYLOBBYA iface,
|
||||
DWORD dwFlags,
|
||||
LPDIRECTPLAY2A* lplpDP,
|
||||
IUnknown* pUnk)
|
||||
{
|
||||
ICOM_THIS(IDirectPlayLobbyAImpl,iface);
|
||||
return DPL_ConnectEx( This, dwFlags, &IID_IDirectPlay2A,
|
||||
(LPVOID)lplpDP, pUnk );
|
||||
}
|
||||
|
||||
static HRESULT WINAPI IDirectPlayLobbyWImpl_Connect
|
||||
|
@ -668,29 +702,9 @@ static HRESULT WINAPI IDirectPlayLobbyWImpl_Connect
|
|||
LPDIRECTPLAY2* lplpDP,
|
||||
IUnknown* pUnk)
|
||||
{
|
||||
ICOM_THIS(IDirectPlayLobbyWImpl,iface);
|
||||
LPDIRECTPLAY2* directPlay2W;
|
||||
HRESULT createRC;
|
||||
|
||||
FIXME("(%p)->(0x%08lx,%p,%p): stub\n", This, dwFlags, lplpDP, pUnk );
|
||||
|
||||
if( dwFlags || pUnk )
|
||||
{
|
||||
return DPERR_INVALIDPARAMS;
|
||||
}
|
||||
|
||||
/* Create the DirectPlay interface */
|
||||
if( ( createRC = directPlay_QueryInterface( &IID_IDirectPlay2, (LPVOID*)lplpDP ) ) != DP_OK )
|
||||
{
|
||||
ERR("error creating Direct Play 2W interface. Return Code = 0x%lx.\n", createRC );
|
||||
return createRC;
|
||||
}
|
||||
|
||||
/* This should invoke IDirectPlay3::InitializeConnection IDirectPlay3::Open */
|
||||
directPlay2W = lplpDP;
|
||||
|
||||
return DP_OK;
|
||||
|
||||
ICOM_THIS(IDirectPlayLobbyAImpl,iface); /* Yes cast to A */
|
||||
return DPL_ConnectEx( This, dwFlags, &IID_IDirectPlay2,
|
||||
(LPVOID)lplpDP, pUnk );
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
|
@ -1099,15 +1113,25 @@ static HRESULT WINAPI IDirectPlayLobbyAImpl_GetConnectionSettings
|
|||
{
|
||||
ICOM_THIS(IDirectPlayLobbyAImpl,iface);
|
||||
HRESULT hr;
|
||||
BOOL bSendHaveReadSettingsMessage = FALSE;
|
||||
|
||||
TRACE("(%p)->(0x%08lx,%p,%p)\n", This, dwAppID, lpData, lpdwDataSize );
|
||||
|
||||
EnterCriticalSection( &This->unk->DPL_lock );
|
||||
|
||||
hr = DPLAYX_GetConnectionSettingsA( dwAppID, lpData, lpdwDataSize );
|
||||
hr = DPLAYX_GetConnectionSettingsA( dwAppID,
|
||||
lpData,
|
||||
lpdwDataSize,
|
||||
&bSendHaveReadSettingsMessage
|
||||
);
|
||||
|
||||
LeaveCriticalSection( &This->unk->DPL_lock );
|
||||
|
||||
if( bSendHaveReadSettingsMessage )
|
||||
{
|
||||
FIXME( "Send a DPSYS_CONNECTIONSETTINGSREAD message\n" );
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
|
@ -1119,15 +1143,25 @@ static HRESULT WINAPI IDirectPlayLobbyWImpl_GetConnectionSettings
|
|||
{
|
||||
ICOM_THIS(IDirectPlayLobbyWImpl,iface);
|
||||
HRESULT hr;
|
||||
BOOL bSendHaveReadSettingsMessage = FALSE;
|
||||
|
||||
TRACE("(%p)->(0x%08lx,%p,%p)\n", This, dwAppID, lpData, lpdwDataSize );
|
||||
|
||||
EnterCriticalSection( &This->unk->DPL_lock );
|
||||
|
||||
hr = DPLAYX_GetConnectionSettingsW( dwAppID, lpData, lpdwDataSize );
|
||||
hr = DPLAYX_GetConnectionSettingsW( dwAppID,
|
||||
lpData,
|
||||
lpdwDataSize,
|
||||
&bSendHaveReadSettingsMessage
|
||||
);
|
||||
|
||||
LeaveCriticalSection( &This->unk->DPL_lock );
|
||||
|
||||
if( bSendHaveReadSettingsMessage )
|
||||
{
|
||||
FIXME( "Send a DPSYS_CONNECTIONSETTINGSREAD message\n" );
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
|
@ -1274,6 +1308,7 @@ static HRESULT WINAPI IDirectPlayLobbyAImpl_RunApplication
|
|||
STARTUPINFOA startupInfo;
|
||||
PROCESS_INFORMATION newProcessInfo;
|
||||
LPSTR appName;
|
||||
DWORD dwSuspendCount;
|
||||
|
||||
TRACE( "(%p)->(0x%08lx,%p,%p,%x)\n", This, dwFlags, lpdwAppID, lpConn, hReceiveEvent );
|
||||
|
||||
|
@ -1282,6 +1317,11 @@ static HRESULT WINAPI IDirectPlayLobbyAImpl_RunApplication
|
|||
return DPERR_INVALIDPARAMS;
|
||||
}
|
||||
|
||||
if( DPLAYX_AnyLobbiesWaitingForConnSettings() )
|
||||
{
|
||||
FIXME( "Waiting lobby not being handled correctly\n" );
|
||||
}
|
||||
|
||||
EnterCriticalSection( &This->unk->DPL_lock );
|
||||
|
||||
ZeroMemory( &enumData, sizeof( enumData ) );
|
||||
|
@ -1326,7 +1366,7 @@ static HRESULT WINAPI IDirectPlayLobbyAImpl_RunApplication
|
|||
)
|
||||
)
|
||||
{
|
||||
FIXME( "Failed to create process for app %s\n", appName );
|
||||
ERR( "Failed to create process for app %s\n", appName );
|
||||
|
||||
HeapFree( GetProcessHeap(), 0, appName );
|
||||
HeapFree( GetProcessHeap(), 0, enumData.lpszCommandLine );
|
||||
|
@ -1342,25 +1382,35 @@ static HRESULT WINAPI IDirectPlayLobbyAImpl_RunApplication
|
|||
/* Reserve this global application id! */
|
||||
if( !DPLAYX_CreateLobbyApplication( newProcessInfo.dwProcessId, hReceiveEvent ) )
|
||||
{
|
||||
ERR( "Unable to create global application data\n" );
|
||||
ERR( "Unable to create global application data for 0x%08lx\n",
|
||||
newProcessInfo.dwProcessId );
|
||||
}
|
||||
|
||||
hr = IDirectPlayLobby_SetConnectionSettings( iface, 0, newProcessInfo.dwProcessId, lpConn );
|
||||
|
||||
if( hr != DP_OK )
|
||||
{
|
||||
FIXME( "SetConnectionSettings failure %s\n", DPLAYX_HresultToString( hr ) );
|
||||
ERR( "SetConnectionSettings failure %s\n", DPLAYX_HresultToString( hr ) );
|
||||
return hr;
|
||||
}
|
||||
|
||||
/* Everything seems to have been set correctly, update the dwAppID */
|
||||
*lpdwAppID = newProcessInfo.dwProcessId;
|
||||
|
||||
/* Unsuspend the process */
|
||||
ResumeThread( newProcessInfo.dwThreadId );
|
||||
if( hReceiveEvent )
|
||||
{
|
||||
FIXME( "Need to store msg thread id\n" );
|
||||
CreateMessageReceptionThread( hReceiveEvent );
|
||||
}
|
||||
|
||||
LeaveCriticalSection( &This->unk->DPL_lock );
|
||||
|
||||
/* Unsuspend the process - should return the prev suspension count */
|
||||
if( ( dwSuspendCount = ResumeThread( newProcessInfo.hThread ) ) != 1 )
|
||||
{
|
||||
ERR( "ResumeThread failed with 0x%08lx\n", dwSuspendCount );
|
||||
}
|
||||
|
||||
return DP_OK;
|
||||
}
|
||||
|
||||
|
@ -1425,6 +1475,17 @@ static HRESULT WINAPI IDirectPlayLobbyWImpl_SetConnectionSettings
|
|||
|
||||
hr = DPLAYX_SetConnectionSettingsW( dwFlags, dwAppID, lpConn );
|
||||
|
||||
/* FIXME: Don't think that this is supposed to fail, but the docuementation
|
||||
is somewhat sketchy. I'll try creating a lobby application
|
||||
for this... */
|
||||
if( hr == DPERR_NOTLOBBIED )
|
||||
{
|
||||
FIXME( "Unlobbied app setting connections. Is this correct behavior?\n" );
|
||||
dwAppID = GetCurrentProcessId();
|
||||
DPLAYX_CreateLobbyApplication( dwAppID, 0 );
|
||||
hr = DPLAYX_SetConnectionSettingsW( dwFlags, dwAppID, lpConn );
|
||||
}
|
||||
|
||||
LeaveCriticalSection( &This->unk->DPL_lock );
|
||||
|
||||
return hr;
|
||||
|
@ -1445,6 +1506,17 @@ static HRESULT WINAPI IDirectPlayLobbyAImpl_SetConnectionSettings
|
|||
|
||||
hr = DPLAYX_SetConnectionSettingsA( dwFlags, dwAppID, lpConn );
|
||||
|
||||
/* FIXME: Don't think that this is supposed to fail, but the docuementation
|
||||
is somewhat sketchy. I'll try creating a lobby application
|
||||
for this... */
|
||||
if( hr == DPERR_NOTLOBBIED )
|
||||
{
|
||||
FIXME( "Unlobbied app setting connections. Is this correct behavior?\n" );
|
||||
dwAppID = GetCurrentProcessId();
|
||||
DPLAYX_CreateLobbyApplication( dwAppID, 0 );
|
||||
hr = DPLAYX_SetConnectionSettingsA( dwFlags, dwAppID, lpConn );
|
||||
}
|
||||
|
||||
LeaveCriticalSection( &This->unk->DPL_lock );
|
||||
|
||||
return hr;
|
||||
|
@ -1477,12 +1549,6 @@ static HRESULT WINAPI IDirectPlayLobbyWImpl_SetLobbyMessageEvent
|
|||
|
||||
|
||||
/* DPL 2 methods */
|
||||
|
||||
/********************************************************************
|
||||
*
|
||||
* Registers an event that will be set when a lobby message is received.
|
||||
*
|
||||
*/
|
||||
static HRESULT WINAPI IDirectPlayLobby2WImpl_CreateCompoundAddress
|
||||
( LPDIRECTPLAYLOBBY2 iface,
|
||||
LPCDPCOMPOUNDADDRESSELEMENT lpElements,
|
||||
|
@ -1680,17 +1746,19 @@ HRESULT DPL_CreateCompoundAddress
|
|||
/* DPL 3 methods */
|
||||
|
||||
static HRESULT WINAPI IDirectPlayLobby3WImpl_ConnectEx
|
||||
( LPDIRECTPLAYLOBBY3 iface, DWORD dwFlags, REFIID riid, LPVOID* lplpDP, IUnknown* pUnk )
|
||||
( LPDIRECTPLAYLOBBY3 iface, DWORD dwFlags, REFIID riid,
|
||||
LPVOID* lplpDP, IUnknown* pUnk )
|
||||
{
|
||||
FIXME(":stub\n");
|
||||
return DP_OK;
|
||||
ICOM_THIS( IDirectPlayLobbyAImpl, iface );
|
||||
return DPL_ConnectEx( This, dwFlags, riid, lplpDP, pUnk );
|
||||
}
|
||||
|
||||
static HRESULT WINAPI IDirectPlayLobby3AImpl_ConnectEx
|
||||
( LPDIRECTPLAYLOBBY3A iface, DWORD dwFlags, REFIID riid, LPVOID* lplpDP, IUnknown* pUnk )
|
||||
( LPDIRECTPLAYLOBBY3A iface, DWORD dwFlags, REFIID riid,
|
||||
LPVOID* lplpDP, IUnknown* pUnk )
|
||||
{
|
||||
FIXME(":stub\n");
|
||||
return DP_OK;
|
||||
ICOM_THIS( IDirectPlayLobbyAImpl, iface );
|
||||
return DPL_ConnectEx( This, dwFlags, riid, lplpDP, pUnk );
|
||||
}
|
||||
|
||||
static HRESULT WINAPI IDirectPlayLobby3WImpl_RegisterApplication
|
||||
|
@ -1724,15 +1792,35 @@ static HRESULT WINAPI IDirectPlayLobby3AImpl_UnregisterApplication
|
|||
static HRESULT WINAPI IDirectPlayLobby3WImpl_WaitForConnectionSettings
|
||||
( LPDIRECTPLAYLOBBY3 iface, DWORD dwFlags )
|
||||
{
|
||||
FIXME(":stub\n");
|
||||
return DP_OK;
|
||||
HRESULT hr = DP_OK;
|
||||
BOOL bStartWait = (dwFlags & DPLWAIT_CANCEL) ? FALSE : TRUE;
|
||||
|
||||
TRACE( "(%p)->(0x%08lx)\n", iface, dwFlags );
|
||||
|
||||
if( DPLAYX_WaitForConnectionSettings( bStartWait ) )
|
||||
{
|
||||
/* FIXME: What is the correct error return code? */
|
||||
hr = DPERR_NOTLOBBIED;
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI IDirectPlayLobby3AImpl_WaitForConnectionSettings
|
||||
( LPDIRECTPLAYLOBBY3A iface, DWORD dwFlags )
|
||||
{
|
||||
FIXME(":stub\n");
|
||||
return DP_OK;
|
||||
HRESULT hr = DP_OK;
|
||||
BOOL bStartWait = (dwFlags & DPLWAIT_CANCEL) ? FALSE : TRUE;
|
||||
|
||||
TRACE( "(%p)->(0x%08lx)\n", iface, dwFlags );
|
||||
|
||||
if( DPLAYX_WaitForConnectionSettings( bStartWait ) )
|
||||
{
|
||||
/* FIXME: What is the correct error return code? */
|
||||
hr = DPERR_NOTLOBBIED;
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -9,21 +9,41 @@ reasonably thourough description of what's going on.
|
|||
Associated DirectX user header files are include/dplay.h, include/dplobby.h.
|
||||
|
||||
Implementation of the DPLAY and DPLAYX dlls are both in the dlls/dplayx
|
||||
directory.
|
||||
directory. Here's a brief description of the function of each of the files in that
|
||||
directory:
|
||||
|
||||
dplay.c: Implementation of all the direct play object interfaces.
|
||||
|
||||
dplobby.c: Implementation of all the direct play lobby interfaces.
|
||||
|
||||
dpclassfactory.c: Implementation of the COM class factory which can create either
|
||||
direct play lobby or direct play lobby interfaces.
|
||||
|
||||
dpinit.h: Header file so that dpclassfactory.c can access dplay and dplobby query
|
||||
functions. Shouldn't be included by anything else.
|
||||
|
||||
dplayx_global.h,
|
||||
dplayx_global.c: Implementation of all things which are associated with dplay on
|
||||
the computer - ie shared resources and such. Methods in this
|
||||
compilation unit should not call anything out side this unit.
|
||||
compilation unit should not call anything out side this unit
|
||||
excepting base windows services and an interface to start the
|
||||
messaging thread.
|
||||
|
||||
name_server.h,
|
||||
name_server.c: Implementation of all things which are associated with the name
|
||||
server functionality
|
||||
|
||||
dplayx_main.c: LibMain executed for loading and unloading the dll. This will make
|
||||
the call to dplayx_global.c to request initialization and destruction
|
||||
of any global data.
|
||||
|
||||
dplayx_queue.h: Linked list implementation for dplay/dplobby. Based off of the BSD
|
||||
version found in <sys/queue.h>
|
||||
|
||||
dplayx_messages.h,
|
||||
dplayx_messages.c: Messaging interface required for both DirectPlay and
|
||||
DirectPlayLobby.
|
||||
|
||||
Presently the architectural relationship between this files is a little shakey, but
|
||||
isn't so sufficiently bad that it needs fixing yet.
|
||||
|
||||
|
@ -32,6 +52,12 @@ or direct play lobby will not work at this point. Priority will be to get
|
|||
examples from the sdk running. Once they're at least partially working, I can
|
||||
get down to trying to get some of the games working.
|
||||
|
||||
However, now that address separation is a reality, all binary samples provided
|
||||
in the sdk can be used. I have had success spawning processes and one
|
||||
directx7 example will allow creation of an app and allow another to join it.
|
||||
Unfortunately, there isn't much for it to be able to do give the state of
|
||||
inter lobby messaging.
|
||||
|
||||
A small issue will be the fact that DirectX 6.1(ie. DirectPlay4) introduces a layer of functionality
|
||||
inside the DP objects which provide guaranteed protocol delivery. This is
|
||||
even if the native protocol, IPX or modem for instance, doesn't guarantee it. I'm going to leave
|
||||
|
@ -59,7 +85,7 @@ TODO:
|
|||
- (done) Fix wine dplay.h and dplobby.h header files to allow apps to create the ansi versions
|
||||
- (started) Port some WineLib test programs using sdk programs (both C and C++ progs)
|
||||
- (done) Implement a lib main for the dplayx dll (required for RunApplication, etc.)
|
||||
- Figure out how to share the global memory correctly
|
||||
- (done)Figure out how to share the global memory correctly
|
||||
- Ensure that all dll stubs are present and the ordinals are correct
|
||||
- (started) Implementation of functionality
|
||||
- Addition of DirectX 7.0 functionality for direct play (try to catch that moving train)
|
||||
|
@ -75,6 +101,19 @@ TODO:
|
|||
- Handles need to be correctly reference counted
|
||||
- Need to check if we need to deallocate any list objects when destroying
|
||||
dplay interface
|
||||
- RunApplication process spawning needs to have correct syncronization.
|
||||
- Need to get inter lobby messages working.
|
||||
|
||||
ENHANCEMENTS:
|
||||
- Improve footprint and realtime blocking by setting up a seperate data share
|
||||
between lobby application and client since there can be multiple apps per
|
||||
client.
|
||||
- Handle everything in UNICODE (as server does) and do conversions for ANSI
|
||||
interfaces. Should cut down on dplayx code base and maintanability (marginally)
|
||||
and could be used to improve efficiency of dialog with the server (it wouldn't
|
||||
have to do ANSI<->UNICODE transformations).
|
||||
|
||||
|
||||
|
||||
Programs to make work:
|
||||
- lserver.exe (from sdk)
|
||||
|
@ -91,8 +130,7 @@ Next API to implement on a per SDK program basis:
|
|||
- ?
|
||||
|
||||
dplaunch.exe
|
||||
- IDirectPlayLobbyAImpl_RunApplication
|
||||
(need address space separation or else rebuild all sdk examples)
|
||||
- Just needs final process startup messages to be exchanged correctly!
|
||||
|
||||
lserver.exe
|
||||
- IDirectPlayLobby2WImpl_Connect
|
||||
|
|
|
@ -424,6 +424,9 @@ ICOM_DEFINE(IDirectPlayLobby3,IDirectPlayLobby2)
|
|||
#define IDirectPlayLobby_UnregisterApplication(p,a,b) ICOM_CALL2(UnregisterApplication,p,a,b)
|
||||
#define IDirectPlayLobby_WaitForConnectionSettings(p,a) ICOM_CALL1(WaitForConnectionSettings,p,a)
|
||||
|
||||
/* Used for WaitForConnectionSettings */
|
||||
#define DPLWAIT_CANCEL 0x00000001
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif /* defined(__cplusplus) */
|
||||
|
|
Loading…
Reference in New Issue