- 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
oldstable
Peter Hunnisett 2000-07-10 13:19:28 +00:00 committed by Alexandre Julliard
parent 961053fd2f
commit 4da59ea6dd
11 changed files with 1450 additions and 680 deletions

View File

@ -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

View File

@ -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 );

View File

@ -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;

View File

@ -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 );
}

View File

@ -0,0 +1,10 @@
#ifndef __WINE_DPLAYX_MESSAGES
#define __WINE_DPLAYX_MESSAGES
#include "windef.h"
DWORD CreateMessageReceptionThread( HANDLE hNotifyEvent );
#endif

View File

@ -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 */

View File

@ -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;
}

View File

@ -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

View File

@ -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) */