- Implemented loading and initialization of service providers
- Created service provider COM object - Lots of dplay/dplobby implementation/fixes - Clean up of ole/guid.c
This commit is contained in:
parent
217a682b4f
commit
ef6dca5c37
|
@ -9,6 +9,7 @@ IMPORTS = ole32 advapi32 kernel32
|
|||
C_SRCS = \
|
||||
dpclassfactory.c \
|
||||
dplay.c \
|
||||
dplaysp.c \
|
||||
dplayx_global.c \
|
||||
dplayx_main.c \
|
||||
dplayx_messages.c \
|
||||
|
|
|
@ -39,7 +39,6 @@ static ULONG WINAPI DP_and_DPL_Release(LPCLASSFACTORY iface) {
|
|||
return --(This->ref);
|
||||
}
|
||||
|
||||
/* Not the most efficient implementation, but it's simple */
|
||||
static HRESULT WINAPI DP_and_DPL_CreateInstance(
|
||||
LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
|
||||
) {
|
||||
|
@ -47,12 +46,11 @@ static HRESULT WINAPI DP_and_DPL_CreateInstance(
|
|||
|
||||
TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
|
||||
|
||||
/* FIXME: reuse already created DP/DPL object if present? */
|
||||
if ( directPlayLobby_QueryInterface( riid, ppobj ) == S_OK )
|
||||
if ( DPL_CreateInterface( riid, ppobj ) == S_OK )
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
else if ( directPlay_QueryInterface( riid, ppobj ) == S_OK )
|
||||
else if ( DP_CreateInterface( riid, ppobj ) == S_OK )
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
@ -110,13 +108,3 @@ DWORD WINAPI DPLAYX_DllGetClassObject(REFCLSID rclsid,REFIID riid,LPVOID *ppv)
|
|||
ERR("(%p,%p,%p): no interface found.\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
|
||||
return CLASS_E_CLASSNOTAVAILABLE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* DllCanUnloadNow (DPLAYX.@)
|
||||
*/
|
||||
HRESULT WINAPI DPLAYX_DllCanUnloadNow(void)
|
||||
{
|
||||
FIXME("(void): stub\n");
|
||||
|
||||
return S_FALSE;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,12 @@
|
|||
#ifndef __WINE_DPINIT_H
|
||||
#define __WINE_DPINIT_H
|
||||
|
||||
extern HRESULT directPlay_QueryInterface( REFIID riid, LPVOID* ppvObj );
|
||||
extern HRESULT directPlayLobby_QueryInterface( REFIID riid, LPVOID* ppvObj );
|
||||
#include "wtypes.h"
|
||||
#include "dplay_global.h"
|
||||
|
||||
extern HRESULT DP_CreateInterface( REFIID riid, LPVOID* ppvObj );
|
||||
extern HRESULT DPL_CreateInterface( REFIID riid, LPVOID* ppvObj );
|
||||
extern HRESULT DPSP_CreateInterface( REFIID riid, LPVOID* ppvObj,
|
||||
IDirectPlay2Impl* dp );
|
||||
|
||||
#endif
|
||||
|
|
3205
dlls/dplayx/dplay.c
3205
dlls/dplayx/dplay.c
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,185 @@
|
|||
#ifndef __WINE_DPLAY_GLOBAL_INCLUDED
|
||||
#define __WINE_DPLAY_GLOBAL_INCLUDED
|
||||
|
||||
#include "dplaysp.h"
|
||||
#include "dplayx_queue.h"
|
||||
|
||||
extern HRESULT DPL_EnumAddress( LPDPENUMADDRESSCALLBACK lpEnumAddressCallback,
|
||||
LPCVOID lpAddress, DWORD dwAddressSize,
|
||||
LPVOID lpContext );
|
||||
|
||||
extern DWORD DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc, BOOL bAnsi );
|
||||
|
||||
/*****************************************************************************
|
||||
* Predeclare the interface implementation structures
|
||||
*/
|
||||
typedef struct IDirectPlay2Impl IDirectPlay2AImpl;
|
||||
typedef struct IDirectPlay2Impl IDirectPlay2Impl;
|
||||
typedef struct IDirectPlay3Impl IDirectPlay3AImpl;
|
||||
typedef struct IDirectPlay3Impl IDirectPlay3Impl;
|
||||
typedef struct IDirectPlay4Impl IDirectPlay4AImpl;
|
||||
typedef struct IDirectPlay4Impl IDirectPlay4Impl;
|
||||
|
||||
typedef struct tagDirectPlayIUnknownData
|
||||
{
|
||||
ULONG ulObjRef;
|
||||
CRITICAL_SECTION DP_lock;
|
||||
} DirectPlayIUnknownData;
|
||||
|
||||
typedef struct tagEnumSessionAsyncCallbackData
|
||||
{
|
||||
LPSPINITDATA lpSpData;
|
||||
GUID requestGuid;
|
||||
DWORD dwEnumSessionFlags;
|
||||
DWORD dwTimeout;
|
||||
HANDLE hSuicideRequest;
|
||||
} EnumSessionAsyncCallbackData;
|
||||
|
||||
struct PlayerData
|
||||
{
|
||||
/* Individual player information */
|
||||
DPID dpid;
|
||||
|
||||
DPNAME name;
|
||||
HANDLE hEvent;
|
||||
|
||||
/* View of local data */
|
||||
LPVOID lpLocalData;
|
||||
DWORD dwLocalDataSize;
|
||||
|
||||
/* View of remote data */
|
||||
LPVOID lpRemoteData;
|
||||
DWORD dwRemoteDataSize;
|
||||
|
||||
DWORD dwFlags; /* Special remarks about the type of player */
|
||||
};
|
||||
typedef struct PlayerData* lpPlayerData;
|
||||
|
||||
struct PlayerList
|
||||
{
|
||||
DPQ_ENTRY(PlayerList) players;
|
||||
|
||||
lpPlayerData lpPData;
|
||||
};
|
||||
typedef struct PlayerList* lpPlayerList;
|
||||
|
||||
struct GroupData
|
||||
{
|
||||
/* Internal information */
|
||||
DPID parent; /* If parent == 0 it's a top level group */
|
||||
|
||||
DPQ_HEAD(GroupList) groups; /* A group has [0..n] groups */
|
||||
DPQ_HEAD(PlayerList) players; /* A group has [0..n] players */
|
||||
|
||||
DPID idGroupOwner; /* ID of player who owns the group */
|
||||
|
||||
DWORD dwFlags; /* Flags describing anything special about the group */
|
||||
|
||||
DPID dpid;
|
||||
DPNAME name;
|
||||
|
||||
/* View of local data */
|
||||
LPVOID lpLocalData;
|
||||
DWORD dwLocalDataSize;
|
||||
|
||||
/* View of remote data */
|
||||
LPVOID lpRemoteData;
|
||||
DWORD dwRemoteDataSize;
|
||||
};
|
||||
typedef struct GroupData GroupData;
|
||||
typedef struct GroupData* lpGroupData;
|
||||
|
||||
struct GroupList
|
||||
{
|
||||
DPQ_ENTRY(GroupList) groups;
|
||||
|
||||
lpGroupData lpGData;
|
||||
};
|
||||
typedef struct GroupList* lpGroupList;
|
||||
|
||||
struct DPMSG
|
||||
{
|
||||
DPQ_ENTRY( DPMSG ) msgs;
|
||||
DPMSG_GENERIC* msg;
|
||||
};
|
||||
typedef struct DPMSG* LPDPMSG;
|
||||
|
||||
/* Contains all dp1 and dp2 data members */
|
||||
typedef struct tagDirectPlay2Data
|
||||
{
|
||||
BOOL bConnectionOpen;
|
||||
|
||||
/* For async EnumSessions requests */
|
||||
HANDLE hEnumSessionThread;
|
||||
HANDLE hKillEnumSessionThreadEvent;
|
||||
|
||||
LPVOID lpNameServerData; /* DPlay interface doesn't know contents */
|
||||
|
||||
BOOL bHostInterface; /* Did this interface create the session */
|
||||
|
||||
#if 0
|
||||
DPQ_HEAD(PlayerList) players; /* All players w/ interface */
|
||||
DPQ_HEAD(GroupList) groups; /* All main groups w/ interface */
|
||||
#else
|
||||
lpGroupData lpSysGroup; /* System group with _everything_ in it */
|
||||
#endif
|
||||
|
||||
LPDPSESSIONDESC2 lpSessionDesc;
|
||||
|
||||
/* I/O Msg queues */
|
||||
DPQ_HEAD( DPMSG ) receiveMsgs; /* Msg receive queue */
|
||||
DPQ_HEAD( DPMSG ) sendMsgs; /* Msg send pending queue */
|
||||
|
||||
/* Information about the service provider active on this connection */
|
||||
SPINITDATA spData;
|
||||
|
||||
/* Our service provider */
|
||||
HMODULE hServiceProvider;
|
||||
|
||||
BOOL bConnectionInitialized;
|
||||
} DirectPlay2Data;
|
||||
|
||||
typedef struct tagDirectPlay3Data
|
||||
{
|
||||
BOOL dummy;
|
||||
} DirectPlay3Data;
|
||||
typedef struct tagDirectPlay4Data
|
||||
{
|
||||
BOOL dummy;
|
||||
} DirectPlay4Data;
|
||||
|
||||
#define DP_IMPL_FIELDS \
|
||||
ULONG ulInterfaceRef; \
|
||||
DirectPlayIUnknownData* unk; \
|
||||
DirectPlay2Data* dp2; \
|
||||
DirectPlay3Data* dp3; \
|
||||
DirectPlay4Data* dp4;
|
||||
|
||||
struct IDirectPlay2Impl
|
||||
{
|
||||
ICOM_VFIELD(IDirectPlay2);
|
||||
DP_IMPL_FIELDS
|
||||
};
|
||||
|
||||
struct IDirectPlay3Impl
|
||||
{
|
||||
ICOM_VFIELD(IDirectPlay3);
|
||||
DP_IMPL_FIELDS
|
||||
};
|
||||
|
||||
struct IDirectPlay4Impl
|
||||
{
|
||||
ICOM_VFIELD(IDirectPlay4);
|
||||
DP_IMPL_FIELDS
|
||||
};
|
||||
|
||||
/* Forward declarations of virtual tables */
|
||||
extern ICOM_VTABLE(IDirectPlay2) directPlay2AVT;
|
||||
extern ICOM_VTABLE(IDirectPlay3) directPlay3AVT;
|
||||
extern ICOM_VTABLE(IDirectPlay4) directPlay4AVT;
|
||||
|
||||
extern ICOM_VTABLE(IDirectPlay2) directPlay2WVT;
|
||||
extern ICOM_VTABLE(IDirectPlay3) directPlay3WVT;
|
||||
extern ICOM_VTABLE(IDirectPlay4) directPlay4WVT;
|
||||
|
||||
#endif /* __WINE_DPLAY_GLOBAL_INCLUDED */
|
|
@ -0,0 +1,880 @@
|
|||
/* This contains the implementation of the interface Service
|
||||
* Providers require to communicate with Direct Play
|
||||
*
|
||||
* Copyright 2000 Peter Hunnisett <hunnise@nortelnetworks.com>
|
||||
*/
|
||||
|
||||
#include "heap.h"
|
||||
#include "winerror.h"
|
||||
#include "debugtools.h"
|
||||
|
||||
#include "dpinit.h"
|
||||
#include "dplaysp.h"
|
||||
#include "dplay_global.h"
|
||||
#include "name_server.h"
|
||||
#include "dplayx_messages.h"
|
||||
|
||||
#include "dplayx_global.h" /* FIXME: For global hack */
|
||||
|
||||
/* FIXME: Need to add interface locking inside procedures */
|
||||
|
||||
DEFAULT_DEBUG_CHANNEL(dplay);
|
||||
|
||||
/* Prototypes */
|
||||
static BOOL DPSP_CreateIUnknown( LPVOID lpSP );
|
||||
static BOOL DPSP_DestroyIUnknown( LPVOID lpSP );
|
||||
static BOOL DPSP_CreateDirectPlaySP( LPVOID lpSP, IDirectPlay2Impl* dp );
|
||||
static BOOL DPSP_DestroyDirectPlaySP( LPVOID lpSP );
|
||||
|
||||
|
||||
/* Predefine the interface */
|
||||
typedef struct IDirectPlaySPImpl IDirectPlaySPImpl;
|
||||
|
||||
typedef struct tagDirectPlaySPIUnknownData
|
||||
{
|
||||
ULONG ulObjRef;
|
||||
CRITICAL_SECTION DPSP_lock;
|
||||
} DirectPlaySPIUnknownData;
|
||||
|
||||
typedef struct tagDirectPlaySPData
|
||||
{
|
||||
LPVOID lpSpRemoteData;
|
||||
DWORD dwSpRemoteDataSize; /* Size of data pointed to by lpSpRemoteData */
|
||||
|
||||
LPVOID lpSpLocalData;
|
||||
DWORD dwSpLocalDataSize; /* Size of data pointed to by lpSpLocalData */
|
||||
|
||||
IDirectPlay2Impl* dplay; /* FIXME: This should perhaps be iface not impl */
|
||||
|
||||
LPVOID lpPlayerData; /* FIXME: Need to figure out how this actually behaves */
|
||||
DWORD dwPlayerDataSize;
|
||||
} DirectPlaySPData;
|
||||
|
||||
#define DPSP_IMPL_FIELDS \
|
||||
ULONG ulInterfaceRef; \
|
||||
DirectPlaySPIUnknownData* unk; \
|
||||
DirectPlaySPData* sp;
|
||||
|
||||
struct IDirectPlaySPImpl
|
||||
{
|
||||
ICOM_VFIELD(IDirectPlaySP);
|
||||
DPSP_IMPL_FIELDS
|
||||
};
|
||||
|
||||
/* Forward declaration of virtual tables */
|
||||
static ICOM_VTABLE(IDirectPlaySP) directPlaySPVT;
|
||||
|
||||
|
||||
|
||||
/* Create the SP interface */
|
||||
extern
|
||||
HRESULT DPSP_CreateInterface( REFIID riid, LPVOID* ppvObj, IDirectPlay2Impl* dp )
|
||||
{
|
||||
TRACE( " for %s\n", debugstr_guid( riid ) );
|
||||
|
||||
*ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
|
||||
sizeof( IDirectPlaySPImpl ) );
|
||||
|
||||
if( *ppvObj == NULL )
|
||||
{
|
||||
return DPERR_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
if( IsEqualGUID( &IID_IDirectPlaySP, riid ) )
|
||||
{
|
||||
ICOM_THIS(IDirectPlaySPImpl,*ppvObj);
|
||||
ICOM_VTBL(This) = &directPlaySPVT;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Unsupported interface */
|
||||
HeapFree( GetProcessHeap(), 0, *ppvObj );
|
||||
*ppvObj = NULL;
|
||||
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
/* Initialize it */
|
||||
if( DPSP_CreateIUnknown( *ppvObj ) &&
|
||||
DPSP_CreateDirectPlaySP( *ppvObj, dp )
|
||||
)
|
||||
{
|
||||
IDirectPlaySP_AddRef( (LPDIRECTPLAYSP)*ppvObj );
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/* Initialize failed, destroy it */
|
||||
DPSP_DestroyDirectPlaySP( *ppvObj );
|
||||
DPSP_DestroyIUnknown( *ppvObj );
|
||||
|
||||
HeapFree( GetProcessHeap(), 0, *ppvObj );
|
||||
*ppvObj = NULL;
|
||||
|
||||
return DPERR_NOMEMORY;
|
||||
}
|
||||
|
||||
static BOOL DPSP_CreateIUnknown( LPVOID lpSP )
|
||||
{
|
||||
ICOM_THIS(IDirectPlaySPImpl,lpSP);
|
||||
|
||||
This->unk = (DirectPlaySPIUnknownData*)HeapAlloc( GetProcessHeap(),
|
||||
HEAP_ZERO_MEMORY,
|
||||
sizeof( *(This->unk) ) );
|
||||
|
||||
if ( This->unk == NULL )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
InitializeCriticalSection( &This->unk->DPSP_lock );
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL DPSP_DestroyIUnknown( LPVOID lpSP )
|
||||
{
|
||||
ICOM_THIS(IDirectPlaySPImpl,lpSP);
|
||||
|
||||
DeleteCriticalSection( &This->unk->DPSP_lock );
|
||||
HeapFree( GetProcessHeap(), 0, This->unk );
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static BOOL DPSP_CreateDirectPlaySP( LPVOID lpSP, IDirectPlay2Impl* dp )
|
||||
{
|
||||
ICOM_THIS(IDirectPlaySPImpl,lpSP);
|
||||
|
||||
This->sp = (DirectPlaySPData*)HeapAlloc( GetProcessHeap(),
|
||||
HEAP_ZERO_MEMORY,
|
||||
sizeof( *(This->sp) ) );
|
||||
|
||||
if ( This->sp == NULL )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
This->sp->dplay = dp;
|
||||
|
||||
/* Normally we should be keeping a reference, but since only the dplay
|
||||
* interface that created us can destroy us, we do not keep a reference
|
||||
* to it (ie we'd be stuck with always having one reference to the dplay
|
||||
* object, and hence us, around).
|
||||
* NOTE: The dp object does reference count us.
|
||||
*/
|
||||
/* IDirectPlayX_AddRef( (LPDIRECTPLAY2)dp ); */
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL DPSP_DestroyDirectPlaySP( LPVOID lpSP )
|
||||
{
|
||||
ICOM_THIS(IDirectPlaySPImpl,lpSP);
|
||||
|
||||
/* Normally we should be keeping a reference, but since only the dplay
|
||||
* interface that created us can destroy us, we do not keep a reference
|
||||
* to it (ie we'd be stuck with always having one reference to the dplay
|
||||
* object, and hence us, around).
|
||||
* NOTE: The dp object does reference count us.
|
||||
*/
|
||||
/*IDirectPlayX_Release( (LPDIRECTPLAY2)This->sp->dplay ); */
|
||||
|
||||
HeapFree( GetProcessHeap(), 0, This->sp->lpSpRemoteData );
|
||||
HeapFree( GetProcessHeap(), 0, This->sp->lpSpLocalData );
|
||||
|
||||
/* FIXME: Need to delete player queue */
|
||||
|
||||
HeapFree( GetProcessHeap(), 0, This->sp );
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Interface implementation */
|
||||
|
||||
static HRESULT WINAPI DPSP_QueryInterface
|
||||
( LPDIRECTPLAYSP iface,
|
||||
REFIID riid,
|
||||
LPVOID* ppvObj )
|
||||
{
|
||||
ICOM_THIS(IDirectPlaySPImpl,iface);
|
||||
TRACE("(%p)->(%s,%p)\n", This, debugstr_guid( riid ), ppvObj );
|
||||
|
||||
*ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
|
||||
sizeof( IDirectPlaySPImpl ) );
|
||||
|
||||
if( *ppvObj == NULL )
|
||||
{
|
||||
return DPERR_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
CopyMemory( *ppvObj, iface, sizeof( IDirectPlaySPImpl ) );
|
||||
(*(IDirectPlaySPImpl**)ppvObj)->ulInterfaceRef = 0;
|
||||
|
||||
if( IsEqualGUID( &IID_IDirectPlaySP, riid ) )
|
||||
{
|
||||
ICOM_THIS(IDirectPlaySPImpl,*ppvObj);
|
||||
ICOM_VTBL(This) = &directPlaySPVT;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Unsupported interface */
|
||||
HeapFree( GetProcessHeap(), 0, *ppvObj );
|
||||
*ppvObj = NULL;
|
||||
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
IDirectPlaySP_AddRef( (LPDIRECTPLAYSP)*ppvObj );
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static ULONG WINAPI DPSP_AddRef
|
||||
( LPDIRECTPLAYSP iface )
|
||||
{
|
||||
ULONG ulInterfaceRefCount, ulObjRefCount;
|
||||
ICOM_THIS(IDirectPlaySPImpl,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 DPSP_Release
|
||||
( LPDIRECTPLAYSP iface )
|
||||
{
|
||||
ULONG ulInterfaceRefCount, ulObjRefCount;
|
||||
ICOM_THIS(IDirectPlaySPImpl,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 )
|
||||
{
|
||||
DPSP_DestroyDirectPlaySP( This );
|
||||
DPSP_DestroyIUnknown( This );
|
||||
}
|
||||
|
||||
if( ulInterfaceRefCount == 0 )
|
||||
{
|
||||
HeapFree( GetProcessHeap(), 0, This );
|
||||
}
|
||||
|
||||
return ulInterfaceRefCount;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI IDirectPlaySPImpl_AddMRUEntry
|
||||
( LPDIRECTPLAYSP iface,
|
||||
LPCWSTR lpSection,
|
||||
LPCWSTR lpKey,
|
||||
LPCVOID lpData,
|
||||
DWORD dwDataSize,
|
||||
DWORD dwMaxEntries
|
||||
)
|
||||
{
|
||||
ICOM_THIS(IDirectPlaySPImpl,iface);
|
||||
|
||||
FIXME( "(%p)->(%p,%p%p,0x%08lx,0x%08lx): stub\n",
|
||||
This, lpSection, lpKey, lpData, dwDataSize, dwMaxEntries );
|
||||
|
||||
return DP_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI IDirectPlaySPImpl_CreateAddress
|
||||
( LPDIRECTPLAYSP iface,
|
||||
REFGUID guidSP,
|
||||
REFGUID guidDataType,
|
||||
LPCVOID lpData,
|
||||
DWORD dwDataSize,
|
||||
LPVOID lpAddress,
|
||||
LPDWORD lpdwAddressSize
|
||||
)
|
||||
{
|
||||
ICOM_THIS(IDirectPlaySPImpl,iface);
|
||||
|
||||
FIXME( "(%p)->(%s,%s,%p,0x%08lx,%p,%p): stub\n",
|
||||
This, debugstr_guid(guidSP), debugstr_guid(guidDataType),
|
||||
lpData, dwDataSize, lpAddress, lpdwAddressSize );
|
||||
|
||||
return DP_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI IDirectPlaySPImpl_EnumAddress
|
||||
( LPDIRECTPLAYSP iface,
|
||||
LPDPENUMADDRESSCALLBACK lpEnumAddressCallback,
|
||||
LPCVOID lpAddress,
|
||||
DWORD dwAddressSize,
|
||||
LPVOID lpContext
|
||||
)
|
||||
{
|
||||
ICOM_THIS(IDirectPlaySPImpl,iface);
|
||||
|
||||
TRACE( "(%p)->(%p,%p,0x%08lx,%p)\n",
|
||||
This, lpEnumAddressCallback, lpAddress, dwAddressSize, lpContext );
|
||||
|
||||
DPL_EnumAddress( lpEnumAddressCallback, lpAddress, dwAddressSize, lpContext );
|
||||
|
||||
return DP_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI IDirectPlaySPImpl_EnumMRUEntries
|
||||
( LPDIRECTPLAYSP iface,
|
||||
LPCWSTR lpSection,
|
||||
LPCWSTR lpKey,
|
||||
LPENUMMRUCALLBACK lpEnumMRUCallback,
|
||||
LPVOID lpContext
|
||||
)
|
||||
{
|
||||
ICOM_THIS(IDirectPlaySPImpl,iface);
|
||||
|
||||
FIXME( "(%p)->(%p,%p,%p,%p,): stub\n",
|
||||
This, lpSection, lpKey, lpEnumMRUCallback, lpContext );
|
||||
|
||||
return DP_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI IDirectPlaySPImpl_GetPlayerFlags
|
||||
( LPDIRECTPLAYSP iface,
|
||||
DPID idPlayer,
|
||||
LPDWORD lpdwPlayerFlags
|
||||
)
|
||||
{
|
||||
ICOM_THIS(IDirectPlaySPImpl,iface);
|
||||
|
||||
FIXME( "(%p)->(0x%08lx,%p): stub\n",
|
||||
This, idPlayer, lpdwPlayerFlags );
|
||||
|
||||
return DP_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI IDirectPlaySPImpl_GetSPPlayerData
|
||||
( LPDIRECTPLAYSP iface,
|
||||
DPID idPlayer,
|
||||
LPVOID* lplpData,
|
||||
LPDWORD lpdwDataSize,
|
||||
DWORD dwFlags
|
||||
)
|
||||
{
|
||||
ICOM_THIS(IDirectPlaySPImpl,iface);
|
||||
|
||||
TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() );
|
||||
FIXME( "(%p)->(0x%08lx,%p,%p,0x%08lx): stub\n",
|
||||
This, idPlayer, lplpData, lpdwDataSize, dwFlags );
|
||||
|
||||
*lplpData = This->sp->lpPlayerData;
|
||||
*lpdwDataSize = This->sp->dwPlayerDataSize;
|
||||
|
||||
return DP_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI IDirectPlaySPImpl_HandleMessage
|
||||
( LPDIRECTPLAYSP iface,
|
||||
LPVOID lpMessageBody,
|
||||
DWORD dwMessageBodySize,
|
||||
LPVOID lpMessageHeader
|
||||
)
|
||||
{
|
||||
LPDPMSG_SENDENVELOPE lpMsg = (LPDPMSG_SENDENVELOPE)lpMessageBody;
|
||||
HRESULT hr = DPERR_GENERIC;
|
||||
|
||||
ICOM_THIS(IDirectPlaySPImpl,iface);
|
||||
|
||||
TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() );
|
||||
FIXME( "(%p)->(%p,0x%08lx,%p): mostly stub\n",
|
||||
This, lpMessageBody, dwMessageBodySize, lpMessageHeader );
|
||||
|
||||
TRACE( "Incomming message has envelope of 0x%08lx, %u, %u\n",
|
||||
lpMsg->dwMagic, lpMsg->wCommandId, lpMsg->wVersion );
|
||||
|
||||
if( lpMsg->dwMagic != DPMSGMAGIC_DPLAYMSG )
|
||||
{
|
||||
FIXME( "Unknown magic 0x%08lx!\n", lpMsg->dwMagic );
|
||||
}
|
||||
|
||||
switch( lpMsg->wCommandId )
|
||||
{
|
||||
case DPMSGCMD_ENUMSESSIONSREQUEST:
|
||||
{
|
||||
DPSP_REPLYDATA data;
|
||||
|
||||
data.lpSPMessageHeader = lpMessageHeader;
|
||||
data.idNameServer = 0;
|
||||
data.lpISP = iface;
|
||||
|
||||
NS_ReplyToEnumSessionsRequest( lpMessageBody, &data, This->sp->dplay );
|
||||
|
||||
hr = (This->sp->dplay->dp2->spData.lpCB->Reply)( &data );
|
||||
|
||||
if( FAILED(hr) )
|
||||
{
|
||||
ERR( "Reply failed 0x%08lx\n", hr );
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case DPMSGCMD_ENUMSESSIONSREPLY:
|
||||
{
|
||||
NS_SetRemoteComputerAsNameServer( lpMessageHeader,
|
||||
This->sp->dplay->dp2->spData.dwSPHeaderSize,
|
||||
(LPDPMSG_ENUMSESSIONSREPLY)lpMessageBody,
|
||||
This->sp->dplay->dp2->lpNameServerData );
|
||||
|
||||
/* No reply expected */
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
FIXME( "Unknown Command of %u\n", lpMsg->wCommandId );
|
||||
}
|
||||
|
||||
#if 0
|
||||
HRESULT hr = DP_OK;
|
||||
HANDLE hReceiveEvent = 0;
|
||||
/* FIXME: Aquire some sort of interface lock */
|
||||
/* FIXME: Need some sort of context for this callback. Need to determine
|
||||
* how this is actually done with the SP
|
||||
*/
|
||||
/* FIXME: Add in size checks for all messages to determine corrupt messages */ /* FIXME: Who needs to delete the message when done? */
|
||||
/* FIXME: Does this get invoked as soon as the message arrives, or as soon
|
||||
* as it's removed from the queue (or peeked in queue?)
|
||||
*/
|
||||
switch( lpMsg->dwType )
|
||||
{
|
||||
case DPSYS_CREATEPLAYERORGROUP:
|
||||
{
|
||||
LPDPMSG_CREATEPLAYERORGROUP msg = (LPDPMSG_CREATEPLAYERORGROUP)lpMsg;
|
||||
|
||||
if( msg->dwPlayerType == DPPLAYERTYPE_PLAYER )
|
||||
{
|
||||
hr = DP_IF_CreatePlayer( This, lpMessageHeader, msg->dpId,
|
||||
&msg->dpnName, 0, msg->lpData,
|
||||
msg->dwDataSize, msg->dwFlags, ... );
|
||||
}
|
||||
else if( msg->dwPlayerType == DPPLAYERTYPE_GROUP )
|
||||
{
|
||||
/* Group in group situation? */
|
||||
if( msg->dpIdParent == DPID_NOPARENT_GROUP )
|
||||
{
|
||||
hr = DP_IF_CreateGroup( This, lpMessageHeader, msg->dpId,
|
||||
&msg->dpnName, 0, msg->lpData,
|
||||
msg->dwDataSize, msg->dwFlags, ... );
|
||||
}
|
||||
else /* Group in Group */
|
||||
{
|
||||
hr = DP_IF_CreateGroupInGroup( This, lpMessageHeader, msg->dpIdParent,
|
||||
&msg->dpnName, 0, msg->lpData,
|
||||
msg->dwDataSize, msg->dwFlags, ... );
|
||||
}
|
||||
}
|
||||
else /* Hmmm? */
|
||||
{
|
||||
ERR( "Corrupt msg->dwPlayerType for DPSYS_CREATEPLAYERORGROUP\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case DPSYS_DESTROYPLAYERORGROUP:
|
||||
{
|
||||
LPDPMSG_DESTROYPLAYERORGROUP msg = (LPDPMSG_DESTROYPLAYERORGROUP)lpMsg;
|
||||
|
||||
if( msg->dwPlayerType == DPPLAYERTYPE_PLAYER )
|
||||
{
|
||||
hr = DP_IF_DestroyPlayer( This, msg->dpId, ... );
|
||||
}
|
||||
else if( msg->dwPlayerType == DPPLAYERTYPE_GROUP )
|
||||
{
|
||||
hr = DP_IF_DestroyGroup( This, msg->dpId, ... );
|
||||
}
|
||||
else /* Hmmm? */
|
||||
{
|
||||
ERR( "Corrupt msg->dwPlayerType for DPSYS_DESTROYPLAYERORGROUP\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case DPSYS_ADDPLAYERTOGROUP:
|
||||
{
|
||||
LPDPMSG_ADDPLAYERTOGROUP msg = (LPDPMSG_ADDPLAYERTOGROUP)lpMsg;
|
||||
|
||||
hr = DP_IF_AddPlayerToGroup( This, msg->dpIdGroup, msg->dpIdPlayer, ... );
|
||||
break;
|
||||
}
|
||||
|
||||
case DPSYS_DELETEPLAYERFROMGROUP:
|
||||
{
|
||||
LPDPMSG_DELETEPLAYERFROMGROUP msg = (LPDPMSG_DELETEPLAYERFROMGROUP)lpMsg;
|
||||
|
||||
hr = DP_IF_DeletePlayerFromGroup( This, msg->dpIdGroup, msg->dpIdPlayer,
|
||||
... );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case DPSYS_SESSIONLOST:
|
||||
{
|
||||
LPDPMSG_SESSIONLOST msg = (LPDPMSG_SESSIONLOST)lpMsg;
|
||||
|
||||
FIXME( "DPSYS_SESSIONLOST not handled\n" );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case DPSYS_HOST:
|
||||
{
|
||||
LPDPMSG_HOST msg = (LPDPMSG_HOST)lpMsg;
|
||||
|
||||
FIXME( "DPSYS_HOST not handled\n" );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case DPSYS_SETPLAYERORGROUPDATA:
|
||||
{
|
||||
LPDPMSG_SETPLAYERORGROUPDATA msg = (LPDPMSG_SETPLAYERORGROUPDATA)lpMsg;
|
||||
|
||||
if( msg->dwPlayerType == DPPLAYERTYPE_PLAYER )
|
||||
{
|
||||
hr = DP_IF_SetPlayerData( This, msg->dpId, msg->lpData, msg->dwDataSize, DPSET_REMOTE, ... );
|
||||
}
|
||||
else if( msg->dwPlayerType == DPPLAYERTYPE_GROUP )
|
||||
{
|
||||
hr = DP_IF_SetGroupData( This, msg->dpId, msg->lpData, msg->dwDataSize,
|
||||
DPSET_REMOTE, ... );
|
||||
}
|
||||
else /* Hmmm? */
|
||||
{
|
||||
ERR( "Corrupt msg->dwPlayerType for LPDPMSG_SETPLAYERORGROUPDATA\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case DPSYS_SETPLAYERORGROUPNAME:
|
||||
{
|
||||
LPDPMSG_SETPLAYERORGROUPNAME msg = (LPDPMSG_SETPLAYERORGROUPNAME)lpMsg;
|
||||
|
||||
if( msg->dwPlayerType == DPPLAYERTYPE_PLAYER )
|
||||
{
|
||||
hr = DP_IF_SetPlayerName( This, msg->dpId, msg->dpnName, ... );
|
||||
}
|
||||
else if( msg->dwPlayerType == DPPLAYERTYPE_GROUP )
|
||||
{
|
||||
hr = DP_IF_SetGroupName( This, msg->dpId, msg->dpnName, ... );
|
||||
}
|
||||
else /* Hmmm? */
|
||||
{
|
||||
ERR( "Corrupt msg->dwPlayerType for LPDPMSG_SETPLAYERORGROUPDATA\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case DPSYS_SETSESSIONDESC;
|
||||
{
|
||||
LPDPMSG_SETSESSIONDESC msg = (LPDPMSG_SETSESSIONDESC)lpMsg;
|
||||
|
||||
hr = DP_IF_SetSessionDesc( This, &msg->dpDesc );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case DPSYS_ADDGROUPTOGROUP:
|
||||
{
|
||||
LPDPMSG_ADDGROUPTOGROUP msg = (LPDPMSG_ADDGROUPTOGROUP)lpMsg;
|
||||
|
||||
hr = DP_IF_AddGroupToGroup( This, msg->dpIdParentGroup, msg->dpIdGroup,
|
||||
... );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case DPSYS_DELETEGROUPFROMGROUP:
|
||||
{
|
||||
LPDPMSG_DELETEGROUPFROMGROUP msg = (LPDPMSG_DELETEGROUPFROMGROUP)lpMsg;
|
||||
|
||||
hr = DP_IF_DeleteGroupFromGroup( This, msg->dpIdParentGroup,
|
||||
msg->dpIdGroup, ... );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case DPSYS_SECUREMESSAGE:
|
||||
{
|
||||
LPDPMSG_SECUREMESSAGE msg = (LPDPMSG_SECUREMESSAGE)lpMsg;
|
||||
|
||||
FIXME( "DPSYS_SECUREMESSAGE not implemented\n" );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case DPSYS_STARTSESSION:
|
||||
{
|
||||
LPDPMSG_STARTSESSION msg = (LPDPMSG_STARTSESSION)lpMsg;
|
||||
|
||||
FIXME( "DPSYS_STARTSESSION not implemented\n" );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case DPSYS_CHAT:
|
||||
{
|
||||
LPDPMSG_CHAT msg = (LPDPMSG_CHAT)lpMsg;
|
||||
|
||||
FIXME( "DPSYS_CHAT not implemeneted\n" );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case DPSYS_SETGROUPOWNER:
|
||||
{
|
||||
LPDPMSG_SETGROUPOWNER msg = (LPDPMSG_SETGROUPOWNER)lpMsg;
|
||||
|
||||
FIXME( "DPSYS_SETGROUPOWNER not implemented\n" );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case DPSYS_SENDCOMPLETE:
|
||||
{
|
||||
LPDPMSG_SENDCOMPLETE msg = (LPDPMSG_SENDCOMPLETE)lpMsg;
|
||||
|
||||
FIXME( "DPSYS_SENDCOMPLETE not implemented\n" );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
/* NOTE: This should be a user defined type. There is nothing that we
|
||||
* need to do with it except queue it.
|
||||
*/
|
||||
TRACE( "Received user message type(?) 0x%08lx through SP.\n",
|
||||
lpMsg->dwType );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
FIXME( "Queue message in the receive queue. Need some context data!\n" );
|
||||
|
||||
if( FAILED(hr) )
|
||||
{
|
||||
ERR( "Unable to perform action for msg type 0x%08lx\n", lpMsg->dwType );
|
||||
}
|
||||
/* If a receieve event was registered for this player, invoke it */
|
||||
if( hReceiveEvent )
|
||||
{
|
||||
SetEvent( hReceiveEvent );
|
||||
}
|
||||
#endif
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI IDirectPlaySPImpl_SetSPPlayerData
|
||||
( LPDIRECTPLAYSP iface,
|
||||
DPID idPlayer,
|
||||
LPVOID lpData,
|
||||
DWORD dwDataSize,
|
||||
DWORD dwFlags
|
||||
)
|
||||
{
|
||||
ICOM_THIS(IDirectPlaySPImpl,iface);
|
||||
|
||||
/* FIXME: I'm not sure if this stuff should be associated with the DPlay
|
||||
* player lists. How else would this stuff get deleted?
|
||||
*/
|
||||
|
||||
TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() );
|
||||
FIXME( "(%p)->(0x%08lx,%p,0x%08lx,0x%08lx): stub\n",
|
||||
This, idPlayer, lpData, dwDataSize, dwFlags );
|
||||
|
||||
This->sp->lpPlayerData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize );
|
||||
|
||||
This->sp->dwPlayerDataSize = dwDataSize;
|
||||
CopyMemory( This->sp->lpPlayerData, lpData, dwDataSize );
|
||||
|
||||
return DP_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI IDirectPlaySPImpl_CreateCompoundAddress
|
||||
( LPDIRECTPLAYSP iface,
|
||||
LPCDPCOMPOUNDADDRESSELEMENT lpElements,
|
||||
DWORD dwElementCount,
|
||||
LPVOID lpAddress,
|
||||
LPDWORD lpdwAddressSize
|
||||
)
|
||||
{
|
||||
ICOM_THIS(IDirectPlaySPImpl,iface);
|
||||
|
||||
FIXME( "(%p)->(%p,0x%08lx,%p,%p): stub\n",
|
||||
This, lpElements, dwElementCount, lpAddress, lpdwAddressSize );
|
||||
|
||||
return DP_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI IDirectPlaySPImpl_GetSPData
|
||||
( LPDIRECTPLAYSP iface,
|
||||
LPVOID* lplpData,
|
||||
LPDWORD lpdwDataSize,
|
||||
DWORD dwFlags
|
||||
)
|
||||
{
|
||||
ICOM_THIS(IDirectPlaySPImpl,iface);
|
||||
|
||||
TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() );
|
||||
TRACE( "(%p)->(%p,%p,0x%08lx)\n",
|
||||
This, lplpData, lpdwDataSize, dwFlags );
|
||||
|
||||
#if 0
|
||||
/* This is what the documentation says... */
|
||||
if( dwFlags != 0 )
|
||||
{
|
||||
return DPERR_INVALIDPARAMS;
|
||||
}
|
||||
#else
|
||||
/* ... but most service providers call this with 1 */
|
||||
/* Guess that this is using a DPSET_LOCAL or DPSET_REMOTE type of
|
||||
* thing?
|
||||
*/
|
||||
if( dwFlags != 0 )
|
||||
{
|
||||
FIXME( "Undocumented dwFlags 0x%08lx used\n", dwFlags );
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Yes, we're supposed to return a pointer to the memory we have stored! */
|
||||
if( dwFlags == DPSET_REMOTE )
|
||||
{
|
||||
*lpdwDataSize = This->sp->dwSpRemoteDataSize;
|
||||
*lplpData = This->sp->lpSpRemoteData;
|
||||
}
|
||||
else if( dwFlags == DPSET_LOCAL )
|
||||
{
|
||||
*lpdwDataSize = This->sp->dwSpLocalDataSize;
|
||||
*lplpData = This->sp->lpSpLocalData;
|
||||
}
|
||||
|
||||
return DP_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI IDirectPlaySPImpl_SetSPData
|
||||
( LPDIRECTPLAYSP iface,
|
||||
LPVOID lpData,
|
||||
DWORD dwDataSize,
|
||||
DWORD dwFlags
|
||||
)
|
||||
{
|
||||
LPVOID lpSpData;
|
||||
|
||||
ICOM_THIS(IDirectPlaySPImpl,iface);
|
||||
|
||||
TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() );
|
||||
TRACE( "(%p)->(%p,0x%08lx,0x%08lx)\n",
|
||||
This, lpData, dwDataSize, dwFlags );
|
||||
|
||||
#if 0
|
||||
/* This is what the documentation says... */
|
||||
if( dwFlags != 0 )
|
||||
{
|
||||
return DPERR_INVALIDPARAMS;
|
||||
}
|
||||
#else
|
||||
/* ... but most service providers call this with 1 */
|
||||
/* Guess that this is using a DPSET_LOCAL or DPSET_REMOTE type of
|
||||
* thing?
|
||||
*/
|
||||
if( dwFlags != 0 )
|
||||
{
|
||||
FIXME( "Undocumented dwFlags 0x%08lx used\n", dwFlags );
|
||||
}
|
||||
#endif
|
||||
|
||||
if( dwFlags == DPSET_REMOTE )
|
||||
{
|
||||
lpSpData = DPLAYX_PrivHeapAlloc( HEAP_ZERO_MEMORY, dwDataSize );
|
||||
}
|
||||
else
|
||||
{
|
||||
lpSpData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize );
|
||||
}
|
||||
|
||||
CopyMemory( lpSpData, lpData, dwDataSize );
|
||||
|
||||
/* If we have data already allocated, free it and replace it */
|
||||
if( dwFlags == DPSET_REMOTE )
|
||||
{
|
||||
/* FIXME: This doesn't strictly make sense as there is no means to share
|
||||
* this shared data. Must be misinterpreting something...
|
||||
*/
|
||||
if( This->sp->lpSpRemoteData )
|
||||
{
|
||||
DPLAYX_PrivHeapFree( This->sp->lpSpRemoteData );
|
||||
}
|
||||
|
||||
/* NOTE: dwDataSize is also stored in the heap structure */
|
||||
This->sp->dwSpRemoteDataSize = dwDataSize;
|
||||
This->sp->lpSpRemoteData = lpSpData;
|
||||
}
|
||||
else if ( dwFlags == DPSET_LOCAL )
|
||||
{
|
||||
if( This->sp->lpSpLocalData )
|
||||
{
|
||||
HeapFree( GetProcessHeap(), 0, This->sp->lpSpLocalData );
|
||||
}
|
||||
|
||||
This->sp->lpSpLocalData = lpSpData;
|
||||
This->sp->dwSpLocalDataSize = dwDataSize;
|
||||
}
|
||||
|
||||
return DP_OK;
|
||||
}
|
||||
|
||||
static VOID WINAPI IDirectPlaySPImpl_SendComplete
|
||||
( LPDIRECTPLAYSP iface,
|
||||
LPVOID unknownA,
|
||||
DWORD unknownB
|
||||
)
|
||||
{
|
||||
ICOM_THIS(IDirectPlaySPImpl,iface);
|
||||
|
||||
FIXME( "(%p)->(%p,0x%08lx): stub\n",
|
||||
This, unknownA, unknownB );
|
||||
}
|
||||
|
||||
|
||||
static struct ICOM_VTABLE(IDirectPlaySP) directPlaySPVT =
|
||||
{
|
||||
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
|
||||
|
||||
DPSP_QueryInterface,
|
||||
DPSP_AddRef,
|
||||
DPSP_Release,
|
||||
|
||||
IDirectPlaySPImpl_AddMRUEntry,
|
||||
IDirectPlaySPImpl_CreateAddress,
|
||||
IDirectPlaySPImpl_EnumAddress,
|
||||
IDirectPlaySPImpl_EnumMRUEntries,
|
||||
IDirectPlaySPImpl_GetPlayerFlags,
|
||||
IDirectPlaySPImpl_GetSPPlayerData,
|
||||
IDirectPlaySPImpl_HandleMessage,
|
||||
IDirectPlaySPImpl_SetSPPlayerData,
|
||||
IDirectPlaySPImpl_CreateCompoundAddress,
|
||||
IDirectPlaySPImpl_GetSPData,
|
||||
IDirectPlaySPImpl_SetSPData,
|
||||
IDirectPlaySPImpl_SendComplete
|
||||
};
|
|
@ -0,0 +1,337 @@
|
|||
#ifndef __WINE_DIRECT_PLAY_SP_H
|
||||
#define __WINE_DIRECT_PLAY_SP_H
|
||||
|
||||
#include "dplay.h"
|
||||
#include "dplobby.h"
|
||||
|
||||
/* GUID for IDirectPlaySP {0C9F6360-CC61-11cf-ACEC-00AA006886E3} */
|
||||
DEFINE_GUID(IID_IDirectPlaySP, 0xc9f6360, 0xcc61, 0x11cf, 0xac, 0xec, 0x0, 0xaa, 0x0, 0x68, 0x86, 0xe3);
|
||||
typedef struct IDirectPlaySP IDirectPlaySP, *LPDIRECTPLAYSP;
|
||||
|
||||
|
||||
typedef BOOL (CALLBACK* LPENUMMRUCALLBACK)( LPCVOID lpData,
|
||||
DWORD dwDataSize,
|
||||
LPVOID lpContext );
|
||||
|
||||
/* For SP. Top 16 bits is dplay, bottom 16 is SP */
|
||||
#define DPSP_MAJORVERSION 0x00060000
|
||||
#define DPSP_DX5VERSION 0x00050000
|
||||
#define DPSP_DX3VERSION 0x00040000
|
||||
|
||||
#define DPSP_MAJORVERSIONMASK 0xFFFF0000
|
||||
#define DPSP_MINORVERSIONMASK 0x0000FFFF
|
||||
|
||||
|
||||
/* Some flags */
|
||||
#define DPLAYI_PLAYER_SYSPLAYER 0x00000001
|
||||
#define DPLAYI_PLAYER_NAMESRVR 0x00000002
|
||||
#define DPLAYI_PLAYER_PLAYERINGROUP 0x00000004
|
||||
#define DPLAYI_PLAYER_PLAYERLOCAL 0x00000008
|
||||
#define DPLAYI_GROUP_SYSGROUP 0x00000020
|
||||
#define DPLAYI_GROUP_DPLAYOWNS 0x00000040
|
||||
#define DPLAYI_PLAYER_APPSERVER 0x00000080
|
||||
#define DPLAYI_GROUP_HIDDEN 0x00000400
|
||||
|
||||
/* Define the COM interface */
|
||||
#define ICOM_INTERFACE IDirectPlaySP
|
||||
#define IDirectPlaySP_METHODS \
|
||||
ICOM_METHOD5(HRESULT,AddMRUEntry, LPCWSTR,lpSection, LPCWSTR,lpKey, LPCVOID,lpData, DWORD,dwDataSize, DWORD,dwMaxEntries ) \
|
||||
ICOM_METHOD6(HRESULT,CreateAddress, REFGUID,guidSP, REFGUID,guidDataType, LPCVOID,lpData, DWORD,dwDataSize, LPVOID,lpAddress,LPDWORD,lpdwAddressSize) \
|
||||
ICOM_METHOD4(HRESULT,EnumAddress, LPDPENUMADDRESSCALLBACK,lpEnumAddressCallback, LPCVOID,lpAddress, DWORD,dwAddressSize, LPVOID,lpContext ) \
|
||||
ICOM_METHOD4(HRESULT,EnumMRUEntries, LPCWSTR,lpSection, LPCWSTR,lpKey, LPENUMMRUCALLBACK,lpEnumMRUCallback, LPVOID,lpContext ) \
|
||||
ICOM_METHOD2(HRESULT,GetPlayerFlags, DPID,idPlayer, LPDWORD,lpdwPlayerFlags ) \
|
||||
ICOM_METHOD4(HRESULT,GetSPPlayerData, DPID,idPlayer, LPVOID*,lplpData, LPDWORD,lpdwDataSize, DWORD,dwFlags ) \
|
||||
ICOM_METHOD3(HRESULT,HandleMessage, LPVOID,lpMessageBody, DWORD,dwMessageBodySize, LPVOID,lpMessageHeader ) \
|
||||
ICOM_METHOD4(HRESULT,SetSPPlayerData, DPID,idPlayer, LPVOID,lpData, DWORD,dwDataSize, DWORD,dwFlags ) \
|
||||
ICOM_METHOD4(HRESULT,CreateCompoundAddress, LPCDPCOMPOUNDADDRESSELEMENT,lpElements, DWORD,dwElementCount, LPVOID,lpAddress, LPDWORD,lpdwAddressSize ) \
|
||||
ICOM_METHOD3(HRESULT,GetSPData, LPVOID*,lplpData, LPDWORD,dwDataSize, DWORD,dwFlags ) \
|
||||
ICOM_METHOD3(HRESULT,SetSPData, LPVOID,lpData, DWORD,dwDataSize, DWORD,dwFlags ) \
|
||||
ICOM_METHOD2(VOID,SendComplete, LPVOID,, DWORD, )
|
||||
|
||||
#define IDirectPlaySP_IMETHODS \
|
||||
IUnknown_IMETHODS \
|
||||
IDirectPlaySP_METHODS
|
||||
|
||||
ICOM_DEFINE(IDirectPlaySP,IUnknown)
|
||||
#undef ICOM_INTERFACE
|
||||
|
||||
/*** IUnknown methods ***/
|
||||
#define IDirectPlaySP_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b)
|
||||
#define IDirectPlaySP_AddRef(p) ICOM_CALL (AddRef,p)
|
||||
#define IDirectPlaySP_Release(p) ICOM_CALL (Release,p)
|
||||
/*** IDirectPlaySP methods ***/
|
||||
#define IDirectPlaySP_AddMRUEntry ICOM_CALL5(AddMRUEntry,p,a,b,c,d,e)
|
||||
#define IDirectPlaySP_CreateAddress ICOM_CALL6(CreateAddress,p,a,b,c,d,e,f)
|
||||
#define IDirectPlaySP_EnumAddress ICOM_CALL4(EnumAddress,p,a,b,c,d)
|
||||
#define IDirectPlaySP_EnumMRUEntries ICOM_CALL4(EnumMRUEntries,p,a,b,c,d)
|
||||
#define IDirectPlaySP_GetPlayerFlags ICOM_CALL2(GetPlayerFlags,p,a,b)
|
||||
#define IDirectPlaySP_GetSPPlayerData ICOM_CALL4(GetSPPlayerData,p,a,b,c,d)
|
||||
#define IDirectPlaySP_HandleMessage ICOM_CALL3(HandleMessage,p,a,b,c)
|
||||
#define IDirectPlaySP_SetSPPlayerData ICOM_CALL4(SetSPPlayerData,p,a,b,c,d)
|
||||
#define IDirectPlaySP_CreateCompoundAddress ICOM_CALL4(CreateCompoundAddress,p,a,b,c,d)
|
||||
#define IDirectPlaySP_GetSPData ICOM_CALL3(GetSPData,p,a,b,c)
|
||||
#define IDirectPlaySP_SetSPData ICOM_CALL3(SetSPData,p,a,b,c)
|
||||
#define IDirectPlaySP_SendComplete ICOM_CALL2(SendComplete,p,a,b)
|
||||
|
||||
/* SP Callback stuff */
|
||||
|
||||
typedef struct tagDPSP_ADDPLAYERTOGROUPDATA
|
||||
{
|
||||
DPID idPlayer;
|
||||
DPID idGroup;
|
||||
IDirectPlaySP* lpISP;
|
||||
} DPSP_ADDPLAYERTOGROUPDATA, *LPDPSP_ADDPLAYERTOGROUPDATA;
|
||||
|
||||
typedef struct tagDPSP_CLOSEDATA
|
||||
{
|
||||
IDirectPlaySP* lpISP;
|
||||
} DPSP_CLOSEDATA, *LPDPSP_CLOSEDATA;
|
||||
|
||||
typedef struct tagDPSP_CREATEGROUPDATA
|
||||
{
|
||||
DPID idGroup;
|
||||
DWORD dwFlags;
|
||||
LPVOID lpSPMessageHeader;
|
||||
IDirectPlaySP* lpISP;
|
||||
} DPSP_CREATEGROUPDATA, *LPDPSP_CREATEGROUPDATA;
|
||||
|
||||
typedef struct tagDPSP_CREATEPLAYERDATA
|
||||
{
|
||||
DPID idPlayer;
|
||||
DWORD dwFlags;
|
||||
LPVOID lpSPMessageHeader;
|
||||
IDirectPlaySP* lpISP;
|
||||
} DPSP_CREATEPLAYERDATA, *LPDPSP_CREATEPLAYERDATA;
|
||||
|
||||
typedef struct tagDPSP_DELETEGROUPDATA
|
||||
{
|
||||
DPID idGroup;
|
||||
DWORD dwFlags;
|
||||
IDirectPlaySP* lpISP;
|
||||
} DPSP_DELETEGROUPDATA, *LPDPSP_DELETEGROUPDATA;
|
||||
|
||||
typedef struct tagDPSP_DELETEPLAYERDATA
|
||||
{
|
||||
DPID idPlayer;
|
||||
DWORD dwFlags;
|
||||
IDirectPlaySP* lpISP;
|
||||
} DPSP_DELETEPLAYERDATA, *LPDPSP_DELETEPLAYERDATA;
|
||||
|
||||
typedef struct tagDPSP_ENUMSESSIONSDATA
|
||||
{
|
||||
LPVOID lpMessage;
|
||||
DWORD dwMessageSize;
|
||||
IDirectPlaySP* lpISP;
|
||||
BOOL bReturnStatus;
|
||||
} DPSP_ENUMSESSIONSDATA, *LPDPSP_ENUMSESSIONSDATA;
|
||||
|
||||
typedef struct _DPSP_GETADDRESSDATA
|
||||
{
|
||||
DPID idPlayer;
|
||||
DWORD dwFlags;
|
||||
LPDPADDRESS lpAddress;
|
||||
LPDWORD lpdwAddressSize;
|
||||
IDirectPlaySP* lpISP;
|
||||
} DPSP_GETADDRESSDATA, *LPDPSP_GETADDRESSDATA;
|
||||
|
||||
typedef struct tagDPSP_GETADDRESSCHOICESDATA
|
||||
{
|
||||
LPDPADDRESS lpAddress;
|
||||
LPDWORD lpdwAddressSize;
|
||||
IDirectPlaySP* lpISP;
|
||||
} DPSP_GETADDRESSCHOICESDATA, *LPDPSP_GETADDRESSCHOICESDATA;
|
||||
|
||||
typedef struct tagDPSP_GETCAPSDATA
|
||||
{
|
||||
DPID idPlayer;
|
||||
LPDPCAPS lpCaps;
|
||||
DWORD dwFlags;
|
||||
IDirectPlaySP* lpISP;
|
||||
} DPSP_GETCAPSDATA, *LPDPSP_GETCAPSDATA;
|
||||
|
||||
typedef struct tagDPSP_OPENDATA
|
||||
{
|
||||
BOOL bCreate;
|
||||
LPVOID lpSPMessageHeader;
|
||||
IDirectPlaySP* lpISP;
|
||||
BOOL bReturnStatus;
|
||||
DWORD dwOpenFlags;
|
||||
DWORD dwSessionFlags;
|
||||
} DPSP_OPENDATA, *LPDPSP_OPENDATA;
|
||||
|
||||
typedef struct tagDPSP_REMOVEPLAYERFROMGROUPDATA
|
||||
{
|
||||
DPID idPlayer;
|
||||
DPID idGroup;
|
||||
IDirectPlaySP* lpISP;
|
||||
} DPSP_REMOVEPLAYERFROMGROUPDATA, *LPDPSP_REMOVEPLAYERFROMGROUPDATA;
|
||||
|
||||
typedef struct tagDPSP_REPLYDATA
|
||||
{
|
||||
LPVOID lpSPMessageHeader;
|
||||
LPVOID lpMessage;
|
||||
DWORD dwMessageSize;
|
||||
DPID idNameServer;
|
||||
IDirectPlaySP* lpISP;
|
||||
} DPSP_REPLYDATA, *LPDPSP_REPLYDATA;
|
||||
|
||||
typedef struct tagDPSP_SENDDATA
|
||||
{
|
||||
DWORD dwFlags;
|
||||
DPID idPlayerTo;
|
||||
DPID idPlayerFrom;
|
||||
LPVOID lpMessage;
|
||||
DWORD dwMessageSize;
|
||||
BOOL bSystemMessage;
|
||||
IDirectPlaySP* lpISP;
|
||||
} DPSP_SENDDATA, *LPDPSP_SENDDATA;
|
||||
|
||||
typedef struct tagDPSP_SENDTOGROUPDATA
|
||||
{
|
||||
DWORD dwFlags;
|
||||
DPID idGroupTo;
|
||||
DPID idPlayerFrom;
|
||||
LPVOID lpMessage;
|
||||
DWORD dwMessageSize;
|
||||
IDirectPlaySP* lpISP;
|
||||
} DPSP_SENDTOGROUPDATA, *LPDPSP_SENDTOGROUPDATA;
|
||||
|
||||
typedef struct tagDPSP_SENDEXDATA
|
||||
{
|
||||
IDirectPlaySP* lpISP;
|
||||
DWORD dwFlags;
|
||||
DPID idPlayerTo;
|
||||
DPID idPlayerFrom;
|
||||
LPSGBUFFER lpSendBuffers;
|
||||
DWORD cBuffers;
|
||||
DWORD dwMessageSize;
|
||||
DWORD dwPriority;
|
||||
DWORD dwTimeout;
|
||||
LPVOID lpDPContext;
|
||||
LPDWORD lpdwSPMsgID;
|
||||
BOOL bSystemMessage;
|
||||
} DPSP_SENDEXDATA, *LPDPSP_SENDEXDATA;
|
||||
|
||||
typedef struct tagDPSP_SENDTOGROUPEXDATA
|
||||
{
|
||||
IDirectPlaySP* lpISP;
|
||||
DWORD dwFlags;
|
||||
DPID idGroupTo;
|
||||
DPID idPlayerFrom;
|
||||
LPSGBUFFER lpSendBuffers;
|
||||
DWORD cBuffers;
|
||||
DWORD dwMessageSize;
|
||||
DWORD dwPriority;
|
||||
DWORD dwTimeout;
|
||||
LPVOID lpDPContext;
|
||||
LPDWORD lpdwSPMsgID;
|
||||
} DPSP_SENDTOGROUPEXDATA, *LPDPSP_SENDTOGROUPEXDATA;
|
||||
|
||||
typedef struct tagDPSP_GETMESSAGEQUEUEDATA
|
||||
{
|
||||
IDirectPlaySP* lpISP;
|
||||
DWORD dwFlags;
|
||||
DPID idFrom;
|
||||
DPID idTo;
|
||||
LPDWORD lpdwNumMsgs;
|
||||
LPDWORD lpdwNumBytes;
|
||||
} DPSP_GETMESSAGEQUEUEDATA, *LPDPSP_GETMESSAGEQUEUEDATA;
|
||||
|
||||
#define DPCANCELSEND_PRIORITY 0x00000001
|
||||
#define DPCANCELSEND_ALL 0x00000002
|
||||
|
||||
typedef struct tagDPSP_CANCELDATA
|
||||
{
|
||||
IDirectPlaySP* lpISP;
|
||||
DWORD dwFlags;
|
||||
LPRGLPVOID lprglpvSPMsgID;
|
||||
DWORD cSPMsgID;
|
||||
DWORD dwMinPriority;
|
||||
DWORD dwMaxPriority;
|
||||
} DPSP_CANCELDATA, *LPDPSP_CANCELDATA;
|
||||
|
||||
typedef struct tagDPSP_SHUTDOWNDATA
|
||||
{
|
||||
IDirectPlaySP* lpISP;
|
||||
} DPSP_SHUTDOWNDATA, *LPDPSP_SHUTDOWNDATA;
|
||||
|
||||
|
||||
/* Prototypes returned by SPInit */
|
||||
typedef HRESULT (WINAPI *LPDPSP_CREATEPLAYER)(LPDPSP_CREATEPLAYERDATA);
|
||||
typedef HRESULT (WINAPI *LPDPSP_DELETEPLAYER)(LPDPSP_DELETEPLAYERDATA);
|
||||
typedef HRESULT (WINAPI *LPDPSP_SEND)(LPDPSP_SENDDATA);
|
||||
typedef HRESULT (WINAPI *LPDPSP_ENUMSESSIONS)(LPDPSP_ENUMSESSIONSDATA);
|
||||
typedef HRESULT (WINAPI *LPDPSP_REPLY)(LPDPSP_REPLYDATA);
|
||||
typedef HRESULT (WINAPI *LPDPSP_SHUTDOWN)(void);
|
||||
typedef HRESULT (WINAPI *LPDPSP_CREATEGROUP)(LPDPSP_CREATEGROUPDATA);
|
||||
typedef HRESULT (WINAPI *LPDPSP_DELETEGROUP)(LPDPSP_DELETEGROUPDATA);
|
||||
typedef HRESULT (WINAPI *LPDPSP_ADDPLAYERTOGROUP)(LPDPSP_ADDPLAYERTOGROUPDATA);
|
||||
typedef HRESULT (WINAPI *LPDPSP_REMOVEPLAYERFROMGROUP)(LPDPSP_REMOVEPLAYERFROMGROUPDATA);
|
||||
typedef HRESULT (WINAPI *LPDPSP_GETCAPS)(LPDPSP_GETCAPSDATA);
|
||||
typedef HRESULT (WINAPI *LPDPSP_GETADDRESS)(LPDPSP_GETADDRESSDATA);
|
||||
typedef HRESULT (WINAPI *LPDPSP_GETADDRESSCHOICES)(LPDPSP_GETADDRESSCHOICESDATA);
|
||||
typedef HRESULT (WINAPI *LPDPSP_OPEN)(LPDPSP_OPENDATA);
|
||||
typedef HRESULT (WINAPI *LPDPSP_CLOSE)(void);
|
||||
typedef HRESULT (WINAPI *LPDPSP_SENDTOGROUP)(LPDPSP_SENDTOGROUPDATA);
|
||||
typedef HRESULT (WINAPI *LPDPSP_SHUTDOWNEX)(LPDPSP_SHUTDOWNDATA);
|
||||
typedef HRESULT (WINAPI *LPDPSP_CLOSEEX)(LPDPSP_CLOSEDATA);
|
||||
typedef HRESULT (WINAPI *LPDPSP_SENDEX)(LPDPSP_SENDEXDATA);
|
||||
typedef HRESULT (WINAPI *LPDPSP_SENDTOGROUPEX)(LPDPSP_SENDTOGROUPEXDATA);
|
||||
typedef HRESULT (WINAPI *LPDPSP_CANCEL)(LPDPSP_CANCELDATA);
|
||||
typedef HRESULT (WINAPI *LPDPSP_GETMESSAGEQUEUE)(LPDPSP_GETMESSAGEQUEUEDATA);
|
||||
|
||||
|
||||
typedef struct tagDPSP_SPCALLBACKS
|
||||
{
|
||||
DWORD dwSize;
|
||||
DWORD dwVersion;
|
||||
|
||||
LPDPSP_ENUMSESSIONS EnumSessions; /* Must be provided */
|
||||
LPDPSP_REPLY Reply; /* Must be provided */
|
||||
LPDPSP_SEND Send; /* Must be provided */
|
||||
LPDPSP_ADDPLAYERTOGROUP AddPlayerToGroup; /* Optional */
|
||||
LPDPSP_CLOSE Close; /* Optional */
|
||||
LPDPSP_CREATEGROUP CreateGroup; /* Optional */
|
||||
LPDPSP_CREATEPLAYER CreatePlayer; /* Optional */
|
||||
LPDPSP_DELETEGROUP DeleteGroup; /* Optional */
|
||||
LPDPSP_DELETEPLAYER DeletePlayer; /* Optional */
|
||||
LPDPSP_GETADDRESS GetAddress; /* Optional */
|
||||
LPDPSP_GETCAPS GetCaps; /* Optional */
|
||||
LPDPSP_OPEN Open; /* Optional */
|
||||
LPDPSP_REMOVEPLAYERFROMGROUP RemovePlayerFromGroup; /* Optional */
|
||||
LPDPSP_SENDTOGROUP SendToGroup; /* Optional */
|
||||
LPDPSP_SHUTDOWN Shutdown; /* Optional */
|
||||
|
||||
LPDPSP_CLOSEEX CloseEx; /* Optional */
|
||||
LPDPSP_SHUTDOWNEX ShutdownEx; /* Optional */
|
||||
LPDPSP_GETADDRESSCHOICES GetAddressChoices; /* Optional */
|
||||
|
||||
LPDPSP_SENDEX SendEx; /* Optional */
|
||||
LPDPSP_SENDTOGROUPEX SendToGroupEx; /* Optional */
|
||||
LPDPSP_CANCEL Cancel; /* Optional */
|
||||
LPDPSP_GETMESSAGEQUEUE GetMessageQueue; /* Optional */
|
||||
} DPSP_SPCALLBACKS, *LPDPSP_SPCALLBACKS;
|
||||
|
||||
typedef struct tagSPINITDATA
|
||||
{
|
||||
LPDPSP_SPCALLBACKS lpCB;
|
||||
IDirectPlaySP* lpISP;
|
||||
LPWSTR lpszName;
|
||||
LPGUID lpGuid;
|
||||
DWORD dwReserved1;
|
||||
DWORD dwReserved2;
|
||||
DWORD dwSPHeaderSize;
|
||||
LPDPADDRESS lpAddress;
|
||||
DWORD dwAddressSize;
|
||||
DWORD dwSPVersion;
|
||||
} SPINITDATA, *LPSPINITDATA;
|
||||
|
||||
typedef HRESULT (WINAPI *LPDPSP_SPINIT)(LPSPINITDATA);
|
||||
|
||||
/* This variable is exported from the DLL at ordinal 6 to be accessed by the
|
||||
* SP directly
|
||||
*/
|
||||
extern DWORD gdwDPlaySPRefCount;
|
||||
|
||||
#endif
|
||||
|
|
@ -10,11 +10,14 @@
|
|||
* dplayx.dll data which is accessible from all processes.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "debugtools.h"
|
||||
#include "winbase.h"
|
||||
#include "winerror.h"
|
||||
#include "wine/unicode.h"
|
||||
#include "heap.h"
|
||||
|
||||
#include "wingdi.h"
|
||||
#include "winuser.h"
|
||||
|
||||
#include "dplayx_global.h"
|
||||
#include "dplayx_messages.h" /* For CreateMessageReceptionThread only */
|
||||
|
@ -42,9 +45,9 @@ static LPVOID lpSharedStaticData = NULL;
|
|||
|
||||
|
||||
/* HACK for simple global data right now */
|
||||
#define dwStaticSharedSize (128 * 1024) /* FIXME: Way too much */
|
||||
#define dwDynamicSharedSize (128 * 1024) /* FIXME: Enough? */
|
||||
#define dwTotalSharedSize (dwStaticSharedSize + dwDynamicSharedSize)
|
||||
#define dwStaticSharedSize (128 * 1024) /* 128 KBytes */
|
||||
#define dwDynamicSharedSize (512 * 1024) /* 512 KBytes */
|
||||
#define dwTotalSharedSize ( dwStaticSharedSize + dwDynamicSharedSize )
|
||||
|
||||
|
||||
/* FIXME: Is there no easier way? */
|
||||
|
@ -53,7 +56,6 @@ static LPVOID lpSharedStaticData = NULL;
|
|||
* Each block has 4 bytes which are 0 unless used */
|
||||
#define dwBlockSize 512
|
||||
#define dwMaxBlock (dwDynamicSharedSize/dwBlockSize)
|
||||
DWORD dwBlockOn = 0;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
@ -61,7 +63,7 @@ typedef struct
|
|||
DWORD data[dwBlockSize-sizeof(DWORD)];
|
||||
} DPLAYX_MEM_SLICE;
|
||||
|
||||
DPLAYX_MEM_SLICE* lpMemArea;
|
||||
static DPLAYX_MEM_SLICE* lpMemArea;
|
||||
|
||||
void DPLAYX_PrivHeapFree( LPVOID addr );
|
||||
void DPLAYX_PrivHeapFree( LPVOID addr )
|
||||
|
@ -81,6 +83,7 @@ void DPLAYX_PrivHeapFree( LPVOID addr )
|
|||
lpMemArea[ dwBlockUsed ].used = 0;
|
||||
}
|
||||
|
||||
/* FIXME: This should be static, but is being used for a hack right now */
|
||||
LPVOID DPLAYX_PrivHeapAlloc( DWORD flags, DWORD size );
|
||||
LPVOID DPLAYX_PrivHeapAlloc( DWORD flags, DWORD size )
|
||||
{
|
||||
|
@ -149,17 +152,19 @@ typedef struct tagDPLAYX_LOBBYDATA
|
|||
|
||||
/* Information for dplobby interfaces */
|
||||
DWORD dwAppID;
|
||||
HANDLE hReceiveEvent;
|
||||
DWORD dwAppLaunchedFromID;
|
||||
|
||||
/* Should this lobby app send messages to creator at important life
|
||||
* stages
|
||||
*/
|
||||
BOOL bInformOnConnect; /* FIXME: Not used yet */
|
||||
BOOL bInformOnSettingRead;
|
||||
BOOL bInformOnAppDeath; /* FIXME: Not used yet */
|
||||
HANDLE hInformOnAppStart;
|
||||
HANDLE hInformOnAppDeath;
|
||||
HANDLE hInformOnSettingRead;
|
||||
|
||||
/* Sundries */
|
||||
BOOL bWaitForConnectionSettings;
|
||||
DWORD dwLobbyMsgThreadId;
|
||||
|
||||
|
||||
} DPLAYX_LOBBYDATA, *LPDPLAYX_LOBBYDATA;
|
||||
|
||||
|
@ -190,6 +195,7 @@ BOOL DPLAYX_ConstructData(void)
|
|||
SECURITY_ATTRIBUTES s_attrib;
|
||||
BOOL bInitializeSharedMemory = FALSE;
|
||||
LPVOID lpDesiredMemoryMapStart = (LPVOID)0x50000000;
|
||||
HANDLE hInformOnStart;
|
||||
|
||||
TRACE( "DPLAYX dll loaded - construct called\n" );
|
||||
|
||||
|
@ -309,6 +315,22 @@ BOOL DPLAYX_ConstructData(void)
|
|||
|
||||
DPLAYX_ReleaseSemaphore();
|
||||
|
||||
/* Everything was created correctly. Signal the lobby client that
|
||||
* we started up correctly
|
||||
*/
|
||||
if( DPLAYX_GetThisLobbyHandles( &hInformOnStart, NULL, NULL, FALSE ) &&
|
||||
hInformOnStart
|
||||
)
|
||||
{
|
||||
BOOL bSuccess;
|
||||
bSuccess = SetEvent( hInformOnStart );
|
||||
TRACE( "Signalling lobby app start event %u %s\n",
|
||||
hInformOnStart, bSuccess ? "succeed" : "failed" );
|
||||
|
||||
/* Close out handle */
|
||||
DPLAYX_GetThisLobbyHandles( &hInformOnStart, NULL, NULL, TRUE );
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -318,8 +340,26 @@ BOOL DPLAYX_ConstructData(void)
|
|||
***************************************************************************/
|
||||
BOOL DPLAYX_DestructData(void)
|
||||
{
|
||||
HANDLE hInformOnDeath;
|
||||
|
||||
TRACE( "DPLAYX dll unloaded - destruct called\n" );
|
||||
|
||||
/* If required, inform that this app is dying */
|
||||
if( DPLAYX_GetThisLobbyHandles( NULL, &hInformOnDeath, NULL, FALSE ) &&
|
||||
hInformOnDeath
|
||||
)
|
||||
{
|
||||
BOOL bSuccess;
|
||||
bSuccess = SetEvent( hInformOnDeath );
|
||||
TRACE( "Signalling lobby app death event %u %s\n",
|
||||
hInformOnDeath, bSuccess ? "succeed" : "failed" );
|
||||
|
||||
/* Close out handle */
|
||||
DPLAYX_GetThisLobbyHandles( NULL, &hInformOnDeath, NULL, TRUE );
|
||||
}
|
||||
|
||||
/* DO CLEAN UP (LAST) */
|
||||
|
||||
/* Delete the semaphore */
|
||||
CloseHandle( hDplayxSema );
|
||||
|
||||
|
@ -334,9 +374,6 @@ BOOL DPLAYX_DestructData(void)
|
|||
void DPLAYX_InitializeLobbyDataEntry( LPDPLAYX_LOBBYDATA lpData )
|
||||
{
|
||||
ZeroMemory( lpData, sizeof( *lpData ) );
|
||||
|
||||
/* Set the handle to a better invalid value */
|
||||
lpData->hReceiveEvent = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
/* NOTE: This must be called with the semaphore aquired.
|
||||
|
@ -370,7 +407,7 @@ BOOL DPLAYX_IsAppIdLobbied( DWORD dwAppID, LPDPLAYX_LOBBYDATA* lplpDplData )
|
|||
}
|
||||
|
||||
/* Reserve a spot for the new appliction. TRUE means success and FALSE failure. */
|
||||
BOOL DPLAYX_CreateLobbyApplication( DWORD dwAppID, HANDLE hReceiveEvent )
|
||||
BOOL DPLAYX_CreateLobbyApplication( DWORD dwAppID )
|
||||
{
|
||||
UINT i;
|
||||
|
||||
|
@ -388,16 +425,16 @@ BOOL DPLAYX_CreateLobbyApplication( DWORD dwAppID, HANDLE hReceiveEvent )
|
|||
if( lobbyData[ i ].dwAppID == 0 )
|
||||
{
|
||||
/* This process is now lobbied */
|
||||
TRACE( "Setting lobbyData[%u] for (0x%08lx,%u,0x%08lx)\n",
|
||||
i, dwAppID, hReceiveEvent, GetCurrentProcessId() );
|
||||
TRACE( "Setting lobbyData[%u] for (0x%08lx,0x%08lx)\n",
|
||||
i, dwAppID, GetCurrentProcessId() );
|
||||
|
||||
lobbyData[ i ].dwAppID = dwAppID;
|
||||
lobbyData[ i ].hReceiveEvent = hReceiveEvent;
|
||||
lobbyData[ i ].dwAppLaunchedFromID = GetCurrentProcessId();
|
||||
|
||||
lobbyData[ i ].bInformOnConnect = TRUE;
|
||||
lobbyData[ i ].bInformOnSettingRead = TRUE;
|
||||
lobbyData[ i ].bInformOnAppDeath = TRUE;
|
||||
/* FIXME: Where is the best place for this? In interface or here? */
|
||||
lobbyData[ i ].hInformOnAppStart = 0;
|
||||
lobbyData[ i ].hInformOnAppDeath = 0;
|
||||
lobbyData[ i ].hInformOnSettingRead = 0;
|
||||
|
||||
DPLAYX_ReleaseSemaphore();
|
||||
return TRUE;
|
||||
|
@ -437,14 +474,114 @@ BOOL DPLAYX_DestroyLobbyApplication( DWORD dwAppID )
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL DPLAYX_SetLobbyHandles( DWORD dwAppID,
|
||||
HANDLE hStart, HANDLE hDeath, HANDLE hConnRead )
|
||||
{
|
||||
LPDPLAYX_LOBBYDATA lpLData;
|
||||
|
||||
/* Need to explictly give lobby application. Can't set for yourself */
|
||||
if( dwAppID == 0 )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
DPLAYX_AquireSemaphore();
|
||||
|
||||
if( !DPLAYX_IsAppIdLobbied( dwAppID, &lpLData ) )
|
||||
{
|
||||
DPLAYX_ReleaseSemaphore();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
lpLData->hInformOnAppStart = hStart;
|
||||
lpLData->hInformOnAppDeath = hDeath;
|
||||
lpLData->hInformOnSettingRead = hConnRead;
|
||||
|
||||
DPLAYX_ReleaseSemaphore();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL DPLAYX_GetThisLobbyHandles( LPHANDLE lphStart,
|
||||
LPHANDLE lphDeath,
|
||||
LPHANDLE lphConnRead,
|
||||
BOOL bClearSetHandles )
|
||||
{
|
||||
LPDPLAYX_LOBBYDATA lpLData;
|
||||
|
||||
DPLAYX_AquireSemaphore();
|
||||
|
||||
if( !DPLAYX_IsAppIdLobbied( 0, &lpLData ) )
|
||||
{
|
||||
DPLAYX_ReleaseSemaphore();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if( lphStart != NULL )
|
||||
{
|
||||
if( lpLData->hInformOnAppStart == 0 )
|
||||
{
|
||||
DPLAYX_ReleaseSemaphore();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*lphStart = lpLData->hInformOnAppStart;
|
||||
|
||||
if( bClearSetHandles )
|
||||
{
|
||||
CloseHandle( lpLData->hInformOnAppStart );
|
||||
lpLData->hInformOnAppStart = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if( lphDeath != NULL )
|
||||
{
|
||||
if( lpLData->hInformOnAppDeath == 0 )
|
||||
{
|
||||
DPLAYX_ReleaseSemaphore();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*lphDeath = lpLData->hInformOnAppDeath;
|
||||
|
||||
if( bClearSetHandles )
|
||||
{
|
||||
CloseHandle( lpLData->hInformOnAppDeath );
|
||||
lpLData->hInformOnAppDeath = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if( lphConnRead != NULL )
|
||||
{
|
||||
if( lpLData->hInformOnSettingRead == 0 )
|
||||
{
|
||||
DPLAYX_ReleaseSemaphore();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*lphConnRead = lpLData->hInformOnSettingRead;
|
||||
|
||||
if( bClearSetHandles )
|
||||
{
|
||||
CloseHandle( lpLData->hInformOnSettingRead );
|
||||
lpLData->hInformOnSettingRead = 0;
|
||||
}
|
||||
}
|
||||
|
||||
DPLAYX_ReleaseSemaphore();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
HRESULT DPLAYX_GetConnectionSettingsA
|
||||
( DWORD dwAppID,
|
||||
LPVOID lpData,
|
||||
LPDWORD lpdwDataSize,
|
||||
LPBOOL lpbSendHaveReadMessage )
|
||||
LPDWORD lpdwDataSize )
|
||||
{
|
||||
LPDPLAYX_LOBBYDATA lpDplData;
|
||||
DWORD dwRequiredDataSize = 0;
|
||||
HANDLE hInformOnSettingRead;
|
||||
|
||||
DPLAYX_AquireSemaphore();
|
||||
|
||||
|
@ -472,14 +609,24 @@ HRESULT DPLAYX_GetConnectionSettingsA
|
|||
return DPERR_BUFFERTOOSMALL;
|
||||
}
|
||||
|
||||
/* They have gotten the information */
|
||||
*lpbSendHaveReadMessage = lpDplData->bInformOnSettingRead;
|
||||
lpDplData->bInformOnSettingRead = FALSE;
|
||||
|
||||
DPLAYX_CopyConnStructA( (LPDPLCONNECTION)lpData, lpDplData->lpConn );
|
||||
|
||||
DPLAYX_ReleaseSemaphore();
|
||||
|
||||
/* They have gotten the information - signal the event if required */
|
||||
if( DPLAYX_GetThisLobbyHandles( NULL, NULL, &hInformOnSettingRead, FALSE ) &&
|
||||
hInformOnSettingRead
|
||||
)
|
||||
{
|
||||
BOOL bSuccess;
|
||||
bSuccess = SetEvent( hInformOnSettingRead );
|
||||
TRACE( "Signalling setting read event %u %s\n",
|
||||
hInformOnSettingRead, bSuccess ? "succeed" : "failed" );
|
||||
|
||||
/* Close out handle */
|
||||
DPLAYX_GetThisLobbyHandles( NULL, NULL, &hInformOnSettingRead, TRUE );
|
||||
}
|
||||
|
||||
return DP_OK;
|
||||
}
|
||||
|
||||
|
@ -488,7 +635,7 @@ void DPLAYX_CopyConnStructA( LPDPLCONNECTION dest, LPDPLCONNECTION src )
|
|||
{
|
||||
BYTE* lpStartOfFreeSpace;
|
||||
|
||||
memcpy( dest, src, sizeof( DPLCONNECTION ) );
|
||||
CopyMemory( dest, src, sizeof( DPLCONNECTION ) );
|
||||
|
||||
lpStartOfFreeSpace = ((BYTE*)dest) + sizeof( DPLCONNECTION );
|
||||
|
||||
|
@ -497,7 +644,7 @@ void DPLAYX_CopyConnStructA( LPDPLCONNECTION dest, LPDPLCONNECTION src )
|
|||
{
|
||||
dest->lpSessionDesc = (LPDPSESSIONDESC2)lpStartOfFreeSpace;
|
||||
lpStartOfFreeSpace += sizeof( DPSESSIONDESC2 );
|
||||
memcpy( dest->lpSessionDesc, src->lpSessionDesc, sizeof( DPSESSIONDESC2 ) );
|
||||
CopyMemory( dest->lpSessionDesc, src->lpSessionDesc, sizeof( DPSESSIONDESC2 ) );
|
||||
|
||||
/* Session names may or may not exist */
|
||||
if( src->lpSessionDesc->sess.lpszSessionNameA )
|
||||
|
@ -505,7 +652,7 @@ void DPLAYX_CopyConnStructA( LPDPLCONNECTION dest, LPDPLCONNECTION src )
|
|||
strcpy( (LPSTR)lpStartOfFreeSpace, src->lpSessionDesc->sess.lpszSessionNameA );
|
||||
dest->lpSessionDesc->sess.lpszSessionNameA = (LPSTR)lpStartOfFreeSpace;
|
||||
lpStartOfFreeSpace +=
|
||||
strlen( (LPSTR)dest->lpSessionDesc->sess.lpszSessionName ) + 1;
|
||||
strlen( (LPSTR)dest->lpSessionDesc->sess.lpszSessionNameA ) + 1;
|
||||
}
|
||||
|
||||
if( src->lpSessionDesc->pass.lpszPasswordA )
|
||||
|
@ -522,7 +669,7 @@ void DPLAYX_CopyConnStructA( LPDPLCONNECTION dest, LPDPLCONNECTION src )
|
|||
{
|
||||
dest->lpPlayerName = (LPDPNAME)lpStartOfFreeSpace;
|
||||
lpStartOfFreeSpace += sizeof( DPNAME );
|
||||
memcpy( dest->lpPlayerName, src->lpPlayerName, sizeof( DPNAME ) );
|
||||
CopyMemory( dest->lpPlayerName, src->lpPlayerName, sizeof( DPNAME ) );
|
||||
|
||||
if( src->lpPlayerName->psn.lpszShortNameA )
|
||||
{
|
||||
|
@ -546,7 +693,7 @@ void DPLAYX_CopyConnStructA( LPDPLCONNECTION dest, LPDPLCONNECTION src )
|
|||
if( src->lpAddress )
|
||||
{
|
||||
dest->lpAddress = (LPVOID)lpStartOfFreeSpace;
|
||||
memcpy( lpStartOfFreeSpace, src->lpAddress, src->dwAddressSize );
|
||||
CopyMemory( lpStartOfFreeSpace, src->lpAddress, src->dwAddressSize );
|
||||
/* No need to advance lpStartOfFreeSpace as there is no more "dynamic" data */
|
||||
}
|
||||
}
|
||||
|
@ -554,11 +701,11 @@ void DPLAYX_CopyConnStructA( LPDPLCONNECTION dest, LPDPLCONNECTION src )
|
|||
HRESULT DPLAYX_GetConnectionSettingsW
|
||||
( DWORD dwAppID,
|
||||
LPVOID lpData,
|
||||
LPDWORD lpdwDataSize,
|
||||
LPBOOL lpbSendHaveReadMessage )
|
||||
LPDWORD lpdwDataSize )
|
||||
{
|
||||
LPDPLAYX_LOBBYDATA lpDplData;
|
||||
DWORD dwRequiredDataSize = 0;
|
||||
HANDLE hInformOnSettingRead;
|
||||
|
||||
DPLAYX_AquireSemaphore();
|
||||
|
||||
|
@ -584,14 +731,24 @@ HRESULT DPLAYX_GetConnectionSettingsW
|
|||
return DPERR_BUFFERTOOSMALL;
|
||||
}
|
||||
|
||||
/* They have gotten the information */
|
||||
*lpbSendHaveReadMessage = lpDplData->bInformOnSettingRead;
|
||||
lpDplData->bInformOnSettingRead = FALSE;
|
||||
|
||||
DPLAYX_CopyConnStructW( (LPDPLCONNECTION)lpData, lpDplData->lpConn );
|
||||
|
||||
DPLAYX_ReleaseSemaphore();
|
||||
|
||||
/* They have gotten the information - signal the event if required */
|
||||
if( DPLAYX_GetThisLobbyHandles( NULL, NULL, &hInformOnSettingRead, FALSE ) &&
|
||||
hInformOnSettingRead
|
||||
)
|
||||
{
|
||||
BOOL bSuccess;
|
||||
bSuccess = SetEvent( hInformOnSettingRead );
|
||||
TRACE( "Signalling setting read event %u %s\n",
|
||||
hInformOnSettingRead, bSuccess ? "succeed" : "failed" );
|
||||
|
||||
/* Close out handle */
|
||||
DPLAYX_GetThisLobbyHandles( NULL, NULL, &hInformOnSettingRead, TRUE );
|
||||
}
|
||||
|
||||
return DP_OK;
|
||||
}
|
||||
|
||||
|
@ -600,7 +757,7 @@ void DPLAYX_CopyConnStructW( LPDPLCONNECTION dest, LPDPLCONNECTION src )
|
|||
{
|
||||
BYTE* lpStartOfFreeSpace;
|
||||
|
||||
memcpy( dest, src, sizeof( DPLCONNECTION ) );
|
||||
CopyMemory( dest, src, sizeof( DPLCONNECTION ) );
|
||||
|
||||
lpStartOfFreeSpace = ( (BYTE*)dest) + sizeof( DPLCONNECTION );
|
||||
|
||||
|
@ -609,7 +766,7 @@ void DPLAYX_CopyConnStructW( LPDPLCONNECTION dest, LPDPLCONNECTION src )
|
|||
{
|
||||
dest->lpSessionDesc = (LPDPSESSIONDESC2)lpStartOfFreeSpace;
|
||||
lpStartOfFreeSpace += sizeof( DPSESSIONDESC2 );
|
||||
memcpy( dest->lpSessionDesc, src->lpSessionDesc, sizeof( DPSESSIONDESC2 ) );
|
||||
CopyMemory( dest->lpSessionDesc, src->lpSessionDesc, sizeof( DPSESSIONDESC2 ) );
|
||||
|
||||
/* Session names may or may not exist */
|
||||
if( src->lpSessionDesc->sess.lpszSessionName )
|
||||
|
@ -634,7 +791,7 @@ void DPLAYX_CopyConnStructW( LPDPLCONNECTION dest, LPDPLCONNECTION src )
|
|||
{
|
||||
dest->lpPlayerName = (LPDPNAME)lpStartOfFreeSpace;
|
||||
lpStartOfFreeSpace += sizeof( DPNAME );
|
||||
memcpy( dest->lpPlayerName, src->lpPlayerName, sizeof( DPNAME ) );
|
||||
CopyMemory( dest->lpPlayerName, src->lpPlayerName, sizeof( DPNAME ) );
|
||||
|
||||
if( src->lpPlayerName->psn.lpszShortName )
|
||||
{
|
||||
|
@ -658,7 +815,7 @@ void DPLAYX_CopyConnStructW( LPDPLCONNECTION dest, LPDPLCONNECTION src )
|
|||
if( src->lpAddress )
|
||||
{
|
||||
dest->lpAddress = (LPVOID)lpStartOfFreeSpace;
|
||||
memcpy( lpStartOfFreeSpace, src->lpAddress, src->dwAddressSize );
|
||||
CopyMemory( lpStartOfFreeSpace, src->lpAddress, src->dwAddressSize );
|
||||
/* No need to advance lpStartOfFreeSpace as there is no more "dynamic" data */
|
||||
}
|
||||
|
||||
|
@ -883,7 +1040,8 @@ DWORD DPLAYX_SizeOfLobbyDataW( LPDPLCONNECTION lpConn )
|
|||
LPDPSESSIONDESC2 DPLAYX_CopyAndAllocateSessionDesc2A( LPCDPSESSIONDESC2 lpSessionSrc )
|
||||
{
|
||||
LPDPSESSIONDESC2 lpSessionDest =
|
||||
(LPDPSESSIONDESC2)DPLAYX_PrivHeapAlloc( HEAP_ZERO_MEMORY, sizeof( *lpSessionSrc ) );
|
||||
(LPDPSESSIONDESC2)HeapAlloc( GetProcessHeap(),
|
||||
HEAP_ZERO_MEMORY, sizeof( *lpSessionSrc ) );
|
||||
DPLAYX_CopyIntoSessionDesc2A( lpSessionDest, lpSessionSrc );
|
||||
|
||||
return lpSessionDest;
|
||||
|
@ -893,17 +1051,19 @@ LPDPSESSIONDESC2 DPLAYX_CopyAndAllocateSessionDesc2A( LPCDPSESSIONDESC2 lpSessio
|
|||
BOOL DPLAYX_CopyIntoSessionDesc2A( LPDPSESSIONDESC2 lpSessionDest,
|
||||
LPCDPSESSIONDESC2 lpSessionSrc )
|
||||
{
|
||||
memcpy( lpSessionDest, lpSessionSrc, sizeof( *lpSessionSrc ) );
|
||||
CopyMemory( lpSessionDest, lpSessionSrc, sizeof( *lpSessionSrc ) );
|
||||
|
||||
if( lpSessionSrc->sess.lpszSessionNameA )
|
||||
{
|
||||
lpSessionDest->sess.lpszSessionNameA =
|
||||
DPLAYX_strdupA( HEAP_ZERO_MEMORY, lpSessionSrc->sess.lpszSessionNameA );
|
||||
HEAP_strdupA( GetProcessHeap(),
|
||||
HEAP_ZERO_MEMORY, lpSessionSrc->sess.lpszSessionNameA );
|
||||
}
|
||||
if( lpSessionSrc->pass.lpszPasswordA )
|
||||
{
|
||||
lpSessionDest->pass.lpszPasswordA =
|
||||
DPLAYX_strdupA( HEAP_ZERO_MEMORY, lpSessionSrc->pass.lpszPasswordA );
|
||||
HEAP_strdupA( GetProcessHeap(),
|
||||
HEAP_ZERO_MEMORY, lpSessionSrc->pass.lpszPasswordA );
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
@ -1002,6 +1162,24 @@ BOOL DPLAYX_AnyLobbiesWaitingForConnSettings(void)
|
|||
return bFound;
|
||||
}
|
||||
|
||||
BOOL DPLAYX_SetLobbyMsgThreadId( DWORD dwAppId, DWORD dwThreadId )
|
||||
{
|
||||
LPDPLAYX_LOBBYDATA lpLobbyData;
|
||||
|
||||
DPLAYX_AquireSemaphore();
|
||||
|
||||
if( !DPLAYX_IsAppIdLobbied( dwAppId, &lpLobbyData ) )
|
||||
{
|
||||
DPLAYX_ReleaseSemaphore();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
lpLobbyData->dwLobbyMsgThreadId = dwThreadId;
|
||||
|
||||
DPLAYX_ReleaseSemaphore();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* NOTE: This is potentially not thread safe. You are not guaranteed to end up
|
||||
with the correct string printed in the case where the HRESULT is not
|
||||
|
@ -1149,7 +1327,7 @@ LPCSTR DPLAYX_HresultToString(HRESULT hr)
|
|||
/* For errors not in the list, return HRESULT as a string
|
||||
This part is not thread safe */
|
||||
WARN( "Unknown error 0x%08lx\n", hr );
|
||||
sprintf( szTempStr, "0x%08lx", hr );
|
||||
wsprintfA( szTempStr, "0x%08lx", hr );
|
||||
return szTempStr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,12 +9,10 @@ BOOL DPLAYX_DestructData(void);
|
|||
|
||||
HRESULT DPLAYX_GetConnectionSettingsA ( DWORD dwAppID,
|
||||
LPVOID lpData,
|
||||
LPDWORD lpdwDataSize,
|
||||
LPBOOL lpbSendHaveReadMessage );
|
||||
LPDWORD lpdwDataSize );
|
||||
HRESULT DPLAYX_GetConnectionSettingsW ( DWORD dwAppID,
|
||||
LPVOID lpData,
|
||||
LPDWORD lpdwDataSize,
|
||||
LPBOOL lpbSendHaveReadMessage );
|
||||
LPDWORD lpdwDataSize );
|
||||
|
||||
HRESULT DPLAYX_SetConnectionSettingsA ( DWORD dwFlags,
|
||||
DWORD dwAppID,
|
||||
|
@ -23,16 +21,33 @@ HRESULT DPLAYX_SetConnectionSettingsW ( DWORD dwFlags,
|
|||
DWORD dwAppID,
|
||||
LPDPLCONNECTION lpConn );
|
||||
|
||||
BOOL DPLAYX_CreateLobbyApplication( DWORD dwAppID, HANDLE hReceiveEvent );
|
||||
BOOL DPLAYX_CreateLobbyApplication( DWORD dwAppID );
|
||||
BOOL DPLAYX_DestroyLobbyApplication( DWORD dwAppID );
|
||||
|
||||
BOOL DPLAYX_WaitForConnectionSettings( BOOL bWait );
|
||||
BOOL DPLAYX_AnyLobbiesWaitingForConnSettings(void);
|
||||
|
||||
BOOL DPLAYX_SetLobbyHandles( DWORD dwAppID,
|
||||
HANDLE hStart, HANDLE hDeath, HANDLE hConnRead );
|
||||
BOOL DPLAYX_GetThisLobbyHandles( LPHANDLE lphStart,
|
||||
LPHANDLE lphDeath,
|
||||
LPHANDLE lphConnRead, BOOL bClearSetHandles );
|
||||
|
||||
LPDPSESSIONDESC2 DPLAYX_CopyAndAllocateLocalSession( UINT* index );
|
||||
BOOL DPLAYX_CopyLocalSession( UINT* index, LPDPSESSIONDESC2 lpsd );
|
||||
void DPLAYX_SetLocalSession( LPCDPSESSIONDESC2 lpsd );
|
||||
|
||||
BOOL DPLAYX_SetLobbyMsgThreadId( DWORD dwAppId, DWORD dwThreadId );
|
||||
|
||||
/* FIXME: This should not be here */
|
||||
LPVOID DPLAYX_PrivHeapAlloc( DWORD flags, DWORD size );
|
||||
void DPLAYX_PrivHeapFree( LPVOID addr );
|
||||
|
||||
LPSTR DPLAYX_strdupA( DWORD flags, LPCSTR str );
|
||||
LPWSTR DPLAYX_strdupW( DWORD flags, LPCWSTR str );
|
||||
/* FIXME: End shared data alloc which should be local */
|
||||
|
||||
|
||||
/* Convert a DP or DPL HRESULT code into a string for human consumption */
|
||||
LPCSTR DPLAYX_HresultToString( HRESULT hr );
|
||||
|
||||
|
|
|
@ -5,19 +5,24 @@
|
|||
*
|
||||
* contact <hunnise@nortelnetworks.com>
|
||||
*/
|
||||
|
||||
#include "winerror.h"
|
||||
#include "winbase.h"
|
||||
#include "debugtools.h"
|
||||
|
||||
#include "initguid.h"
|
||||
#include "dplay.h"
|
||||
#include "dplobby.h"
|
||||
#include "initguid.h" /* To define the GUIDs */
|
||||
#include "dplaysp.h"
|
||||
#include "dplayx_global.h"
|
||||
|
||||
DEFAULT_DEBUG_CHANNEL(dplay);
|
||||
|
||||
DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
|
||||
|
||||
static DWORD DPLAYX_dwProcessesAttached = 0;
|
||||
|
||||
/* This is a globally exported variable at ordinal 6 of DPLAYX.DLL */
|
||||
DWORD gdwDPlaySPRefCount = 0; /* FIXME: Should it be initialized here? */
|
||||
|
||||
|
||||
BOOL WINAPI DPLAYX_LibMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved )
|
||||
{
|
||||
|
||||
|
@ -59,3 +64,20 @@ BOOL WINAPI DPLAYX_LibMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReser
|
|||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* DllCanUnloadNow (DPLAYX.10)
|
||||
*/
|
||||
HRESULT WINAPI DPLAYX_DllCanUnloadNow(void)
|
||||
{
|
||||
HRESULT hr = ( gdwDPlaySPRefCount > 0 ) ? S_FALSE : S_OK;
|
||||
|
||||
/* FIXME: Should I be putting a check in for class factory objects
|
||||
* as well
|
||||
*/
|
||||
|
||||
TRACE( ": returning 0x%08lx\n", hr );
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,48 +9,130 @@
|
|||
#include "winbase.h"
|
||||
#include "debugtools.h"
|
||||
|
||||
#include "wingdi.h"
|
||||
#include "winuser.h"
|
||||
|
||||
#include "dplayx_messages.h"
|
||||
|
||||
DEFAULT_DEBUG_CHANNEL(dplay)
|
||||
|
||||
typedef struct tagMSGTHREADINFO
|
||||
{
|
||||
HANDLE hStart;
|
||||
HANDLE hDeath;
|
||||
HANDLE hSettingRead;
|
||||
HANDLE hNotifyEvent;
|
||||
} MSGTHREADINFO, *LPMSGTHREADINFO;
|
||||
|
||||
static DWORD CALLBACK DPLAYX_MSG_ThreadMain( LPVOID lpContext );
|
||||
|
||||
static DWORD CALLBACK DPL_MSG_ThreadMain( LPVOID lpContext );
|
||||
|
||||
/* Create the message reception thread to allow the application to receive
|
||||
* asynchronous message reception
|
||||
*/
|
||||
DWORD CreateMessageReceptionThread( HANDLE hNotifyEvent )
|
||||
DWORD CreateLobbyMessageReceptionThread( HANDLE hNotifyEvent, HANDLE hStart,
|
||||
HANDLE hDeath, HANDLE hConnRead )
|
||||
{
|
||||
DWORD dwMsgThreadId;
|
||||
LPMSGTHREADINFO lpThreadInfo;
|
||||
|
||||
if( !DuplicateHandle( 0, hNotifyEvent, 0, NULL, 0, FALSE, 0 ) )
|
||||
lpThreadInfo = HeapAlloc( GetProcessHeap(), 0, sizeof( *lpThreadInfo ) );
|
||||
if( lpThreadInfo == NULL )
|
||||
{
|
||||
ERR( "Unable to duplicate event handle\n" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* FIXME: Should most likely store that thread handle */
|
||||
CreateThread( NULL, /* Security attribs */
|
||||
/* The notify event may or may not exist. Depends if async comm or not */
|
||||
if( hNotifyEvent &&
|
||||
!DuplicateHandle( GetCurrentProcess(), hNotifyEvent,
|
||||
GetCurrentProcess(), &lpThreadInfo->hNotifyEvent,
|
||||
0, FALSE, DUPLICATE_SAME_ACCESS ) )
|
||||
{
|
||||
ERR( "Unable to duplicate event handle\n" );
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* These 3 handles don't need to be duplicated because we don't keep a
|
||||
* reference to them where they're created. They're created specifically
|
||||
* for the message thread
|
||||
*/
|
||||
lpThreadInfo->hStart = hStart;
|
||||
lpThreadInfo->hDeath = hDeath;
|
||||
lpThreadInfo->hSettingRead = hConnRead;
|
||||
|
||||
if( !CreateThread( NULL, /* Security attribs */
|
||||
0, /* Stack */
|
||||
DPLAYX_MSG_ThreadMain, /* Msg reception function */
|
||||
(LPVOID)hNotifyEvent, /* Msg reception function parameter */
|
||||
DPL_MSG_ThreadMain, /* Msg reception function */
|
||||
lpThreadInfo, /* Msg reception func parameter */
|
||||
0, /* Flags */
|
||||
&dwMsgThreadId /* Updated with thread id */
|
||||
);
|
||||
)
|
||||
)
|
||||
{
|
||||
ERR( "Unable to create msg thread\n" );
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* FIXME: Should I be closing the handle to the thread or does that
|
||||
terminate the thread? */
|
||||
|
||||
return dwMsgThreadId;
|
||||
|
||||
error:
|
||||
|
||||
HeapFree( GetProcessHeap(), 0, lpThreadInfo );
|
||||
|
||||
return 0;
|
||||
}
|
||||
static DWORD CALLBACK DPLAYX_MSG_ThreadMain( LPVOID lpContext )
|
||||
|
||||
static DWORD CALLBACK DPL_MSG_ThreadMain( LPVOID lpContext )
|
||||
{
|
||||
HANDLE hMsgEvent = (HANDLE)lpContext;
|
||||
LPMSGTHREADINFO lpThreadInfo = (LPMSGTHREADINFO)lpContext;
|
||||
DWORD dwWaitResult;
|
||||
|
||||
TRACE( "Msg thread created. Waiting on app startup\n" );
|
||||
|
||||
/* Wait to ensure that the lobby application is started w/ 1 min timeout */
|
||||
dwWaitResult = WaitForSingleObject( lpThreadInfo->hStart, 10000 /* 10 sec */ );
|
||||
if( dwWaitResult == WAIT_TIMEOUT )
|
||||
{
|
||||
FIXME( "Should signal app/wait creation failure (0x%08lx)\n", dwWaitResult );
|
||||
goto end_of_thread;
|
||||
}
|
||||
|
||||
/* Close this handle as it's not needed anymore */
|
||||
CloseHandle( lpThreadInfo->hStart );
|
||||
lpThreadInfo->hStart = 0;
|
||||
|
||||
/* Wait until the lobby knows what it is */
|
||||
dwWaitResult = WaitForSingleObject( lpThreadInfo->hSettingRead, INFINITE );
|
||||
if( dwWaitResult == WAIT_TIMEOUT )
|
||||
{
|
||||
ERR( "App Read connection setting timeout fail (0x%08lx)\n", dwWaitResult );
|
||||
}
|
||||
|
||||
/* Close this handle as it's not needed anymore */
|
||||
CloseHandle( lpThreadInfo->hSettingRead );
|
||||
lpThreadInfo->hSettingRead = 0;
|
||||
|
||||
TRACE( "App created && intialized starting main message reception loop\n" );
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
FIXME( "Ho Hum. Msg thread with nothing to do on handle %u\n", hMsgEvent );
|
||||
MSG lobbyMsg;
|
||||
#ifdef STRICT
|
||||
HANDLE hNullHandle = NULL;
|
||||
#else
|
||||
HANDLE hNullHandle = 0;
|
||||
#endif
|
||||
|
||||
SleepEx( 10000, FALSE ); /* 10 secs */
|
||||
GetMessageW( &lobbyMsg, hNullHandle, 0, 0 );
|
||||
}
|
||||
|
||||
CloseHandle( hMsgEvent );
|
||||
end_of_thread:
|
||||
TRACE( "Msg thread exiting!\n" );
|
||||
HeapFree( GetProcessHeap(), 0, lpThreadInfo );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,136 @@
|
|||
|
||||
#ifndef __WINE_DPLAYX_MESSAGES
|
||||
#define __WINE_DPLAYX_MESSAGES
|
||||
#ifndef __WINE_DPLAYX_MESSAGES__
|
||||
#define __WINE_DPLAYX_MESSAGES__
|
||||
|
||||
#include "windef.h"
|
||||
#include "dplay.h"
|
||||
#include "rpc.h" /* For GUID */
|
||||
|
||||
DWORD CreateMessageReceptionThread( HANDLE hNotifyEvent );
|
||||
DWORD CreateLobbyMessageReceptionThread( HANDLE hNotifyEvent, HANDLE hStart,
|
||||
HANDLE hDeath, HANDLE hConnRead );
|
||||
|
||||
|
||||
/* Message types etc. */
|
||||
#include "pshpack1.h"
|
||||
|
||||
/* Non provided messages for DPLAY - guess work which may be wrong :( */
|
||||
#define DPMSGCMD_ENUMSESSIONSREPLY 1
|
||||
#define DPMSGCMD_ENUMSESSIONSREQUEST 2
|
||||
|
||||
#define DPMSGCMD_GETSETNAMETABLE 3 /* Request info from NS about
|
||||
existing players/groups etc. Is
|
||||
also used for reply */
|
||||
|
||||
#define DPMSGCMD_REQUESTNEWPLAYERID 5
|
||||
|
||||
#define DPMSGCMD_NEWPLAYERIDREPLY 7
|
||||
#define DPMSGCMD_CREATESESSION 8
|
||||
#define DPMSGCMD_CREATENEWPLAYER 9
|
||||
#define DPMSGCMD_SYSTEMMESSAGE 10
|
||||
|
||||
#define DPMSGCMD_DELETEGROUP 12
|
||||
|
||||
#define DPMSGCMD_ENUMGROUPS 17
|
||||
|
||||
/* This is what DP 6 defines it as. Don't know what it means. All messages
|
||||
* defined below are DPMSGVER_DP6.
|
||||
*/
|
||||
#define DPMSGVER_DP6 11
|
||||
|
||||
/* MAGIC number at the start of all dplay packets ("play" in ASCII) */
|
||||
#define DPMSGMAGIC_DPLAYMSG 0x79616c70
|
||||
|
||||
/* All messages sent from the system are sent with this at the beginning of
|
||||
* the message.
|
||||
*/
|
||||
|
||||
/* Size is 4 bytes */
|
||||
typedef struct tagDPMSG_SENDENVELOPE
|
||||
{
|
||||
DWORD dwMagic;
|
||||
WORD wCommandId;
|
||||
WORD wVersion;
|
||||
} DPMSG_SENDENVELOPE, *LPDPMSG_SENDENVELOPE;
|
||||
typedef const DPMSG_SENDENVELOPE* LPCDPMSG_SENDENVELOPE;
|
||||
|
||||
typedef struct tagDPMSG_SYSMSGENVELOPE
|
||||
{
|
||||
DWORD dwPlayerFrom;
|
||||
DWORD dwPlayerTo;
|
||||
} DPMSG_SYSMSGENVELOPE, *LPDPMSG_SYSMSGENVELOPE;
|
||||
typedef const DPMSG_SYSMSGENVELOPE* LPCDPMSG_SYSMSGENVELOPE;
|
||||
|
||||
|
||||
typedef struct tagDPMSG_ENUMSESSIONSREPLY
|
||||
{
|
||||
DPMSG_SENDENVELOPE envelope;
|
||||
|
||||
#if 0
|
||||
DWORD dwSize; /* Size of DPSESSIONDESC2 struct */
|
||||
DWORD dwFlags; /* Sessions flags */
|
||||
|
||||
GUID guidInstance; /* Not 100% sure this is what it is... */
|
||||
|
||||
GUID guidApplication;
|
||||
|
||||
DWORD dwMaxPlayers;
|
||||
DWORD dwCurrentPlayers;
|
||||
|
||||
BYTE unknown[36];
|
||||
#else
|
||||
DPSESSIONDESC2 sd;
|
||||
#endif
|
||||
|
||||
DWORD dwUnknown; /* Seems to be equal to 0x5c which is a "\\" */
|
||||
/* Encryption package string? */
|
||||
|
||||
/* At the end we have ... */
|
||||
/* WCHAR wszSessionName[1]; Var length with NULL terminal */
|
||||
|
||||
} DPMSG_ENUMSESSIONSREPLY, *LPDPMSG_ENUMSESSIONSREPLY;
|
||||
typedef const DPMSG_ENUMSESSIONSREPLY* LPCDPMSG_ENUMSESSIONSREPLY;
|
||||
|
||||
typedef struct tagDPMSG_ENUMSESSIONSREQUEST
|
||||
{
|
||||
DPMSG_SENDENVELOPE envelope;
|
||||
|
||||
GUID guidApplication;
|
||||
|
||||
DWORD dwPasswordSize; /* A Guess. This is normally 0x00000000. */
|
||||
/* This might be the name server DPID which
|
||||
is needed for the reply */
|
||||
|
||||
DWORD dwFlags; /* dwFlags from EnumSessions */
|
||||
|
||||
} DPMSG_ENUMSESSIONSREQUEST, *LPDPMSG_ENUMSESSIONSREQUEST;
|
||||
typedef const DPMSG_ENUMSESSIONSREQUEST* LPCDPMSG_ENUMSESSIONSREQUEST;
|
||||
|
||||
/* Size is 146 received - with 18 or 20 bytes header = ~128 bytes */
|
||||
typedef struct tagDPMSG_CREATESESSION
|
||||
{
|
||||
DPMSG_SENDENVELOPE envelope;
|
||||
} DPMSG_CREATESESSION, *LPDPMSG_CREATESESSION;
|
||||
typedef const DPMSG_CREATESESSION* LPCDPMSG_CREATESESSION;
|
||||
|
||||
/* 28 bytes - ~18 header ~= 10 bytes msg */
|
||||
typedef struct tagDPMSG_REQUESTNEWPLAYERID
|
||||
{
|
||||
DPMSG_SENDENVELOPE envelope;
|
||||
|
||||
|
||||
|
||||
} DPMSG_REQUESTNEWPLAYERID, *LPDPMSG_REQUESTNEWPLAYERID;
|
||||
typedef const DPMSG_REQUESTNEWPLAYERID* LPCDPMSG_REQUESTNEWPLAYERID;
|
||||
|
||||
/* 64 byte - ~18 header ~= 46 bytes msg */
|
||||
typedef struct tagDPMSG_NEWPLAYERIDREPLY
|
||||
{
|
||||
DPMSG_SENDENVELOPE envelope;
|
||||
|
||||
} DPMSG_NEWPLAYERIDREPLY, *LPDPMSG_NEWPLAYERIDREPLY;
|
||||
typedef const DPMSG_NEWPLAYERIDREPLY* LPCDPMSG_NEWPLAYERIDREPLY;
|
||||
|
||||
|
||||
#include "poppack.h"
|
||||
|
||||
#endif
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
#ifndef __WINE_DPLAYX_QUEUE_H
|
||||
#define __WINE_DPLAYX_QUEUE_H
|
||||
|
||||
#include "winbase.h"
|
||||
|
||||
#define DPQ_INSERT(a,b,c) DPQ_INSERT_IN_TAIL(a,b,c)
|
||||
|
||||
/*
|
||||
|
@ -33,6 +35,19 @@ do{ \
|
|||
(head).lpQHLast = &(head).lpQHFirst; \
|
||||
} while(0)
|
||||
|
||||
/* Front of the queue */
|
||||
#define DPQ_FIRST( head ) ( (head).lpQHFirst )
|
||||
|
||||
/* Check if the queue has any elements */
|
||||
#define DPQ_IS_EMPTY( head ) ( DPQ_FIRST(head) == NULL )
|
||||
|
||||
/* Next entry -- FIXME: Convert everything over to this macro ... */
|
||||
#define DPQ_NEXT( elem ) (elem).lpQNext
|
||||
|
||||
#define DPQ_IS_ENDOFLIST( elem ) \
|
||||
( DPQ_NEXT(elem) == NULL )
|
||||
|
||||
/* Insert element at end of queue */
|
||||
#define DPQ_INSERT_IN_TAIL(head, elm, field) \
|
||||
do { \
|
||||
(elm)->field.lpQNext = NULL; \
|
||||
|
@ -41,6 +56,7 @@ do { \
|
|||
(head).lpQHLast = &(elm)->field.lpQNext; \
|
||||
} while(0)
|
||||
|
||||
/* Remove element from the queue */
|
||||
#define DPQ_REMOVE(head, elm, field) \
|
||||
do { \
|
||||
if (((elm)->field.lpQNext) != NULL) \
|
||||
|
@ -53,18 +69,20 @@ do { \
|
|||
|
||||
/* 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
|
||||
* field - to be concatenated to rc to compare with fieldToCompare
|
||||
* fieldToCompare - The value that we're comparing against
|
||||
* fieldCompareOperator - The logical operator to compare field and
|
||||
* fieldToCompare.
|
||||
* rc - Variable to put the return code. Same type as (head).lpQHFirst
|
||||
*/
|
||||
#define DPQ_FIND_ENTRY( head, elm, field, fieldToEqual, rc ) \
|
||||
#define DPQ_FIND_ENTRY( head, elm, field, fieldCompareOperator, fieldToCompare, rc )\
|
||||
do { \
|
||||
(rc) = (head).lpQHFirst; /* NULL head? */ \
|
||||
\
|
||||
while( rc ) \
|
||||
{ \
|
||||
/* What we're searching for? */ \
|
||||
if( (rc)->field == (fieldToEqual) ) \
|
||||
if( (rc)->field fieldCompareOperator (fieldToCompare) ) \
|
||||
{ \
|
||||
break; /* rc == correct element */ \
|
||||
} \
|
||||
|
@ -81,12 +99,14 @@ do { \
|
|||
/* 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
|
||||
* fieldToCompare - The value that we're comparing against
|
||||
* fieldCompareOperator - The logical operator to compare field and
|
||||
* fieldToCompare.
|
||||
* rc - Variable to put the return code. Same type as (head).lpQHFirst
|
||||
*/
|
||||
#define DPQ_REMOVE_ENTRY( head, elm, field, fieldToEqual, rc ) \
|
||||
#define DPQ_REMOVE_ENTRY( head, elm, field, fieldCompareOperator, fieldToCompare, rc )\
|
||||
do { \
|
||||
DPQ_FIND_ENTRY( head, elm, field, fieldToEqual, rc ); \
|
||||
DPQ_FIND_ENTRY( head, elm, field, fieldCompareOperator, fieldToCompare, rc );\
|
||||
\
|
||||
/* Was the element found? */ \
|
||||
if( rc ) \
|
||||
|
@ -95,4 +115,24 @@ do { \
|
|||
} \
|
||||
} while(0)
|
||||
|
||||
/* Delete the entire queue
|
||||
* head - pointer to the head of the queue
|
||||
* field - field to access the next elements of the queue
|
||||
* type - type of the pointer to the element element
|
||||
* df - a delete function to be called. Declared with DPQ_DECL_DELETECB.
|
||||
*/
|
||||
#define DPQ_DELETEQ( head, field, type, df ) \
|
||||
while( !DPQ_IS_EMPTY(head) ) \
|
||||
{ \
|
||||
type holder = (head).lpQHFirst; \
|
||||
DPQ_REMOVE( head, holder, field ); \
|
||||
df( holder ); \
|
||||
}
|
||||
|
||||
/* How to define the method to be passed to DPQ_DELETEQ */
|
||||
#define DPQ_DECL_DELETECB( name, type ) void name( type elem )
|
||||
|
||||
/* Prototype of a method which just performs a HeapFree on the elem */
|
||||
DPQ_DECL_DELETECB( cbDeleteElemFromHeap, LPVOID );
|
||||
|
||||
#endif /* __WINE_DPLAYX_QUEUE_H */
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -10,101 +10,190 @@
|
|||
|
||||
#include "winbase.h"
|
||||
#include "debugtools.h"
|
||||
#include "heap.h"
|
||||
|
||||
#include "dplayx_global.h"
|
||||
#include "name_server.h"
|
||||
#include "dplaysp.h"
|
||||
#include "dplayx_messages.h"
|
||||
#include "dplayx_queue.h"
|
||||
|
||||
/* FIXME: Need to aquire the interface semaphore before didlling data */
|
||||
/* Can't seem to solve unresolved reference even with import */
|
||||
#define HACK_TIMEGETTIME
|
||||
|
||||
#if defined( HACK_TIMEGETTIME )
|
||||
static DWORD timeGetTime(void);
|
||||
#else
|
||||
#include "mmsystem.h"
|
||||
#endif
|
||||
|
||||
/* FIXME: Need to create a crit section, store and use it */
|
||||
|
||||
DEFAULT_DEBUG_CHANNEL(dplay);
|
||||
|
||||
/* NS specific structures */
|
||||
typedef struct tagNSCacheData
|
||||
struct NSCacheData
|
||||
{
|
||||
struct tagNSCacheData* next;
|
||||
DPQ_ENTRY(NSCacheData) next;
|
||||
|
||||
DWORD dwTime; /* Time at which data was last known valid */
|
||||
LPDPSESSIONDESC2 data;
|
||||
|
||||
} NSCacheData, *lpNSCacheData;
|
||||
LPVOID lpNSAddrHdr;
|
||||
|
||||
typedef struct tagNSCache
|
||||
};
|
||||
typedef struct NSCacheData NSCacheData, *lpNSCacheData;
|
||||
|
||||
struct NSCache
|
||||
{
|
||||
lpNSCacheData present; /* keep track of what is to be looked at */
|
||||
lpNSCacheData first;
|
||||
} NSCache, *lpNSCache;
|
||||
|
||||
/* Local Prototypes */
|
||||
static void NS_InvalidateSessionCache( lpNSCache lpCache );
|
||||
lpNSCacheData present; /* keep track of what is to be looked at when walking */
|
||||
|
||||
DPQ_HEAD(NSCacheData) first;
|
||||
};
|
||||
typedef struct NSCache NSCache, *lpNSCache;
|
||||
|
||||
/* Name Server functions
|
||||
* ---------------------
|
||||
*/
|
||||
void NS_SetLocalComputerAsNameServer( LPCDPSESSIONDESC2 lpsd )
|
||||
{
|
||||
#if 0
|
||||
DPLAYX_SetLocalSession( lpsd );
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Store the given NS remote address for future reference */
|
||||
void NS_SetRemoteComputerAsNameServer( LPVOID lpNSAddrHdr,
|
||||
DWORD dwHdrSize,
|
||||
LPDPMSG_ENUMSESSIONSREPLY lpMsg,
|
||||
LPVOID lpNSInfo )
|
||||
{
|
||||
lpNSCache lpCache = (lpNSCache)lpNSInfo;
|
||||
lpNSCacheData lpCacheNode;
|
||||
|
||||
TRACE( "%p, %p, %p\n", lpNSAddrHdr, lpMsg, lpNSInfo );
|
||||
|
||||
/* FIXME: Should check to see if the reply is for an existing session. If
|
||||
* so we just update the contents and update the timestamp.
|
||||
*/
|
||||
lpCacheNode = (lpNSCacheData)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
|
||||
sizeof( *lpCacheNode ) );
|
||||
|
||||
if( lpCacheNode == NULL )
|
||||
{
|
||||
ERR( "no memory for NS node\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
lpCacheNode->lpNSAddrHdr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
|
||||
dwHdrSize );
|
||||
CopyMemory( lpCacheNode->lpNSAddrHdr, lpNSAddrHdr, dwHdrSize );
|
||||
|
||||
|
||||
lpCacheNode->data = (LPDPSESSIONDESC2)HeapAlloc( GetProcessHeap(),
|
||||
HEAP_ZERO_MEMORY,
|
||||
sizeof( *lpCacheNode->data ) );
|
||||
|
||||
if( lpCacheNode->data == NULL )
|
||||
{
|
||||
ERR( "no memory for SESSIONDESC2\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
CopyMemory( lpCacheNode->data, &lpMsg->sd, sizeof( *lpCacheNode->data ) );
|
||||
lpCacheNode->data->sess.lpszSessionNameA = HEAP_strdupWtoA( GetProcessHeap(),
|
||||
HEAP_ZERO_MEMORY,
|
||||
(LPWSTR)(lpMsg+1) );
|
||||
|
||||
lpCacheNode->dwTime = timeGetTime();
|
||||
|
||||
DPQ_INSERT(lpCache->first, lpCacheNode, next );
|
||||
|
||||
lpCache->present = lpCacheNode;
|
||||
|
||||
/* Use this message as an oportunity to weed out any old sessions so
|
||||
* that we don't enum them again
|
||||
*/
|
||||
NS_PruneSessionCache( lpNSInfo );
|
||||
}
|
||||
|
||||
LPVOID NS_GetNSAddr( LPVOID lpNSInfo )
|
||||
{
|
||||
lpNSCache lpCache = (lpNSCache)lpNSInfo;
|
||||
|
||||
FIXME( ":quick stub\n" );
|
||||
|
||||
/* Ok. Cheat and don't search for the correct stuff just take the first.
|
||||
* FIXME: In the future how are we to know what is _THE_ enum we used?
|
||||
*/
|
||||
|
||||
return lpCache->first.lpQHFirst->lpNSAddrHdr;
|
||||
}
|
||||
|
||||
/* This function is responsible for sending a request for all other known
|
||||
nameservers to send us what sessions they have registered locally
|
||||
*/
|
||||
void NS_SendSessionRequestBroadcast( LPVOID lpNSInfo )
|
||||
HRESULT NS_SendSessionRequestBroadcast( LPCGUID lpcGuid,
|
||||
DWORD dwFlags,
|
||||
LPSPINITDATA lpSpData )
|
||||
|
||||
{
|
||||
UINT index = 0;
|
||||
lpNSCache lpCache = (lpNSCache)lpNSInfo;
|
||||
LPDPSESSIONDESC2 lpTmp = NULL;
|
||||
DPSP_ENUMSESSIONSDATA data;
|
||||
LPDPMSG_ENUMSESSIONSREQUEST lpMsg;
|
||||
|
||||
/* Invalidate the session cache for the interface */
|
||||
NS_InvalidateSessionCache( lpCache );
|
||||
TRACE( "enumerating for guid %s\n", debugstr_guid( lpcGuid ) );
|
||||
|
||||
/* Add the local known sessions to the cache */
|
||||
if( ( lpTmp = DPLAYX_CopyAndAllocateLocalSession( &index ) ) != NULL )
|
||||
{
|
||||
lpCache->first = (lpNSCacheData)HeapAlloc( GetProcessHeap(),
|
||||
HEAP_ZERO_MEMORY,
|
||||
sizeof( *(lpCache->first) ) );
|
||||
lpCache->first->data = lpTmp;
|
||||
lpCache->first->next = NULL;
|
||||
lpCache->present = lpCache->first;
|
||||
/* Get the SP to deal with sending the EnumSessions request */
|
||||
FIXME( ": not all data fields are correct\n" );
|
||||
|
||||
while( ( lpTmp = DPLAYX_CopyAndAllocateLocalSession( &index ) ) != NULL )
|
||||
{
|
||||
lpCache->present->next = (lpNSCacheData)HeapAlloc( GetProcessHeap(),
|
||||
HEAP_ZERO_MEMORY,
|
||||
sizeof( *(lpCache->present) ) );
|
||||
lpCache->present = lpCache->present->next;
|
||||
lpCache->present->data = lpTmp;
|
||||
lpCache->present->next = NULL;
|
||||
}
|
||||
data.dwMessageSize = lpSpData->dwSPHeaderSize + sizeof( *lpMsg ); /*FIXME!*/
|
||||
data.lpMessage = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
|
||||
data.dwMessageSize );
|
||||
data.lpISP = lpSpData->lpISP;
|
||||
data.bReturnStatus = (dwFlags & DPENUMSESSIONS_RETURNSTATUS) ? TRUE : FALSE;
|
||||
|
||||
lpCache->present = lpCache->first;
|
||||
}
|
||||
|
||||
/* Send out requests for matching sessions to all other known computers */
|
||||
FIXME( ": no remote requests sent\n" );
|
||||
/* FIXME - how to handle responses to messages anyways? */
|
||||
lpMsg = (LPDPMSG_ENUMSESSIONSREQUEST)(((BYTE*)data.lpMessage)+lpSpData->dwSPHeaderSize);
|
||||
|
||||
/* Setup EnumSession reqest message */
|
||||
lpMsg->envelope.dwMagic = DPMSGMAGIC_DPLAYMSG;
|
||||
lpMsg->envelope.wCommandId = DPMSGCMD_ENUMSESSIONSREQUEST;
|
||||
lpMsg->envelope.wVersion = DPMSGVER_DP6;
|
||||
|
||||
lpMsg->dwPasswordSize = 0; /* FIXME: If enumerating passwords..? */
|
||||
lpMsg->dwFlags = dwFlags;
|
||||
|
||||
CopyMemory( &lpMsg->guidApplication, lpcGuid, sizeof( *lpcGuid ) );
|
||||
|
||||
return (lpSpData->lpCB->EnumSessions)( &data );
|
||||
}
|
||||
|
||||
/* Render all data in a session cache invalid */
|
||||
static void NS_InvalidateSessionCache( lpNSCache lpCache )
|
||||
DPQ_DECL_DELETECB( cbDeleteNSNodeFromHeap, lpNSCacheData );
|
||||
DPQ_DECL_DELETECB( cbDeleteNSNodeFromHeap, lpNSCacheData )
|
||||
{
|
||||
/* FIXME: Memory leak on data (contained ptrs) */
|
||||
HeapFree( GetProcessHeap(), 0, elem->data );
|
||||
HeapFree( GetProcessHeap(), 0, elem->lpNSAddrHdr );
|
||||
HeapFree( GetProcessHeap(), 0, elem );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Render all data in a session cache invalid */
|
||||
void NS_InvalidateSessionCache( LPVOID lpNSInfo )
|
||||
{
|
||||
lpNSCache lpCache = (lpNSCache)lpNSInfo;
|
||||
|
||||
if( lpCache == NULL )
|
||||
{
|
||||
ERR( ": invalidate non existant cache\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
/* Remove everything from the cache */
|
||||
while( lpCache->first )
|
||||
{
|
||||
lpCache->present = lpCache->first;
|
||||
lpCache->first = lpCache->first->next;
|
||||
HeapFree( GetProcessHeap(), 0, lpCache->present );
|
||||
}
|
||||
DPQ_DELETEQ( lpCache->first, next, lpNSCacheData, cbDeleteNSNodeFromHeap );
|
||||
|
||||
/* NULL out the cache pointers */
|
||||
/* NULL out the walking pointer */
|
||||
lpCache->present = NULL;
|
||||
lpCache->first = NULL;
|
||||
}
|
||||
|
||||
/* Create and initialize a session cache */
|
||||
|
@ -121,7 +210,8 @@ BOOL NS_InitializeSessionCache( LPVOID* lplpNSInfo )
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
lpCache->first = lpCache->present = NULL;
|
||||
DPQ_INIT(lpCache->first);
|
||||
lpCache->present = NULL;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -136,7 +226,7 @@ void NS_DeleteSessionCache( LPVOID lpNSInfo )
|
|||
void NS_ResetSessionEnumeration( LPVOID lpNSInfo )
|
||||
{
|
||||
|
||||
((lpNSCache)lpNSInfo)->present = ((lpNSCache)lpNSInfo)->first;
|
||||
((lpNSCache)lpNSInfo)->present = ((lpNSCache)lpNSInfo)->first.lpQHFirst;
|
||||
}
|
||||
|
||||
LPDPSESSIONDESC2 NS_WalkSessions( LPVOID lpNSInfo )
|
||||
|
@ -144,6 +234,8 @@ LPDPSESSIONDESC2 NS_WalkSessions( LPVOID lpNSInfo )
|
|||
LPDPSESSIONDESC2 lpSessionDesc;
|
||||
lpNSCache lpCache = (lpNSCache)lpNSInfo;
|
||||
|
||||
/* FIXME: The pointers could disappear when walking if a prune happens */
|
||||
|
||||
/* Test for end of the list */
|
||||
if( lpCache->present == NULL )
|
||||
{
|
||||
|
@ -153,7 +245,93 @@ LPDPSESSIONDESC2 NS_WalkSessions( LPVOID lpNSInfo )
|
|||
lpSessionDesc = lpCache->present->data;
|
||||
|
||||
/* Advance tracking pointer */
|
||||
lpCache->present = lpCache->present->next;
|
||||
lpCache->present = lpCache->present->next.lpQNext;
|
||||
|
||||
return lpSessionDesc;
|
||||
}
|
||||
|
||||
/* This method should check to see if there are any sessions which are
|
||||
* older than the criteria. If so, just delete that information.
|
||||
*/
|
||||
void NS_PruneSessionCache( LPVOID lpNSInfo )
|
||||
{
|
||||
lpNSCache lpCache = lpNSInfo;
|
||||
lpNSCacheData lpCacheEntry;
|
||||
|
||||
DWORD dwPresentTime = timeGetTime();
|
||||
#if defined( HACK_TIMEGETTIME )
|
||||
DWORD dwPruneTime = dwPresentTime - 2; /* One iteration with safety */
|
||||
#else
|
||||
DWORD dwPruneTime = dwPresentTime - 10000 /* 10 secs? */;
|
||||
#endif
|
||||
|
||||
FIXME( ": semi stub\n" );
|
||||
|
||||
/* FIXME: This doesn't handle time roll over correctly */
|
||||
/* FIXME: Session memory leak on delete */
|
||||
do
|
||||
{
|
||||
DPQ_FIND_ENTRY( lpCache->first, next, dwTime, <=, dwPruneTime, lpCacheEntry );
|
||||
}
|
||||
while( lpCacheEntry != NULL );
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Message stuff */
|
||||
void NS_ReplyToEnumSessionsRequest( LPVOID lpMsg,
|
||||
LPDPSP_REPLYDATA lpReplyData,
|
||||
IDirectPlay2Impl* lpDP )
|
||||
{
|
||||
LPDPMSG_ENUMSESSIONSREPLY rmsg;
|
||||
DWORD dwVariableSize;
|
||||
DWORD dwVariableLen;
|
||||
LPWSTR string;
|
||||
/* LPDPMSG_ENUMSESSIONSREQUEST msg = (LPDPMSG_ENUMSESSIONSREQUEST)lpMsg; */
|
||||
BOOL bAnsi = TRUE; /* FIXME: This needs to be in the DPLAY interface */
|
||||
|
||||
FIXME( ": few fixed + need to check request for response\n" );
|
||||
|
||||
dwVariableLen = bAnsi ? lstrlenA( lpDP->dp2->lpSessionDesc->sess.lpszSessionNameA ) + 1
|
||||
: lstrlenW( lpDP->dp2->lpSessionDesc->sess.lpszSessionName ) + 1;
|
||||
|
||||
dwVariableSize = dwVariableLen * sizeof( WCHAR );
|
||||
|
||||
lpReplyData->dwMessageSize = lpDP->dp2->spData.dwSPHeaderSize +
|
||||
sizeof( *rmsg ) + dwVariableSize;
|
||||
lpReplyData->lpMessage = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
|
||||
lpReplyData->dwMessageSize );
|
||||
|
||||
rmsg = (LPDPMSG_ENUMSESSIONSREPLY)lpReplyData->lpMessage;
|
||||
|
||||
rmsg->envelope.dwMagic = DPMSGMAGIC_DPLAYMSG;
|
||||
rmsg->envelope.wCommandId = DPMSGCMD_ENUMSESSIONSREPLY;
|
||||
rmsg->envelope.wVersion = DPMSGVER_DP6;
|
||||
|
||||
CopyMemory( &rmsg->sd, lpDP->dp2->lpSessionDesc,
|
||||
sizeof( lpDP->dp2->lpSessionDesc->dwSize ) );
|
||||
rmsg->dwUnknown = 0x0000005c;
|
||||
if( bAnsi )
|
||||
{
|
||||
string = HEAP_strdupAtoW( GetProcessHeap(), 0,
|
||||
lpDP->dp2->lpSessionDesc->sess.lpszSessionNameA );
|
||||
/* FIXME: Memory leak */
|
||||
}
|
||||
else
|
||||
{
|
||||
string = lpDP->dp2->lpSessionDesc->sess.lpszSessionName;
|
||||
}
|
||||
|
||||
lstrcpyW( (LPWSTR)rmsg+1, string );
|
||||
|
||||
}
|
||||
|
||||
#if defined( HACK_TIMEGETTIME )
|
||||
DWORD timeGetTime(void)
|
||||
{
|
||||
static DWORD time = 0;
|
||||
|
||||
return time++;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -3,14 +3,33 @@
|
|||
#define __WINE_DPLAYX_NAMESERVER
|
||||
|
||||
#include "dplay.h"
|
||||
#include "dplaysp.h"
|
||||
#include "dplayx_messages.h"
|
||||
#include "dplay_global.h"
|
||||
|
||||
void NS_SetLocalComputerAsNameServer( LPCDPSESSIONDESC2 lpsd );
|
||||
void NS_SendSessionRequestBroadcast( LPVOID lpNSInfo );
|
||||
void NS_SetRemoteComputerAsNameServer( LPVOID lpNSAddrHdr,
|
||||
DWORD dwHdrSize,
|
||||
LPDPMSG_ENUMSESSIONSREPLY lpMsg,
|
||||
LPVOID lpNSInfo );
|
||||
LPVOID NS_GetNSAddr( LPVOID lpNSInfo );
|
||||
|
||||
void NS_ReplyToEnumSessionsRequest( LPVOID lpMsg,
|
||||
LPDPSP_REPLYDATA lpReplyData,
|
||||
IDirectPlay2Impl* lpDP );
|
||||
|
||||
HRESULT NS_SendSessionRequestBroadcast( LPCGUID lpcGuid,
|
||||
DWORD dwFlags,
|
||||
LPSPINITDATA lpSpData );
|
||||
|
||||
|
||||
BOOL NS_InitializeSessionCache( LPVOID* lplpNSInfo );
|
||||
void NS_DeleteSessionCache( LPVOID lpNSInfo );
|
||||
void NS_InvalidateSessionCache( LPVOID lpNSInfo );
|
||||
|
||||
|
||||
void NS_ResetSessionEnumeration( LPVOID lpNSInfo );
|
||||
LPDPSESSIONDESC2 NS_WalkSessions( LPVOID lpNSInfo );
|
||||
void NS_PruneSessionCache( LPVOID lpNSInfo );
|
||||
|
||||
#endif /* __WINE_DPLAYX_NAMESERVER */
|
||||
|
|
|
@ -13,6 +13,13 @@ extern "C" {
|
|||
|
||||
#include "pshpack1.h"
|
||||
|
||||
typedef LPVOID (*LPRGLPVOID)[];
|
||||
typedef LPRGLPVOID PRGPVOID, LPRGPVOID, PRGLPVOID, PAPVOID, LPAPVOID, PALPVOID, LPALPVOID;
|
||||
|
||||
#define VOL volatile
|
||||
typedef VOID *VOL LPVOIDV;
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* Predeclare the interfaces
|
||||
*/
|
||||
|
@ -283,6 +290,13 @@ typedef struct tagDPCHAT
|
|||
}msgstr;
|
||||
} DPCHAT, *LPDPCHAT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT len;
|
||||
PUCHAR pData;
|
||||
} SGBUFFER, *PSGBUFFER, *LPSGBUFFER;
|
||||
|
||||
|
||||
typedef struct tagDPSECURITYDESC
|
||||
{
|
||||
DWORD dwSize; /* Size of structure */
|
||||
|
@ -342,14 +356,7 @@ typedef BOOL CALLBACK (*LPDPENUMDPCALLBACKA)(
|
|||
DWORD dwMinorVersion, /* Minor # of driver spec in lpguidSP */
|
||||
LPVOID lpContext); /* User given */
|
||||
|
||||
/* NOTE: This isn't in the dplay.h header file, but this shouldn't be
|
||||
* a problem. We require this because we include all these header files
|
||||
* which declare GUIDs in guid.c
|
||||
*/
|
||||
#ifndef __LPCGUID_DEFINED__
|
||||
#define __LPCGUID_DEFINED__
|
||||
typedef const GUID *LPCGUID;
|
||||
#endif
|
||||
|
||||
typedef const DPNAME *LPCDPNAME;
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@ VPATH = @srcdir@
|
|||
MODULE = ole
|
||||
|
||||
C_SRCS = \
|
||||
guid.c \
|
||||
ole2nls.c
|
||||
|
||||
EXTRASUBDIRS = nls
|
||||
|
|
32
ole/guid.c
32
ole/guid.c
|
@ -1,32 +0,0 @@
|
|||
#define INITGUID
|
||||
|
||||
/* FIXME: we include all the header files containing GUIDs
|
||||
* so that the corresponding variables get defined. But they
|
||||
* don't even all belong to the same DLL !!!
|
||||
*
|
||||
* Therefore, as the builtin DLL's get teased apart (e.g. for elf-dlls)
|
||||
* then this file will have to be partitioned into per dll files.
|
||||
*/
|
||||
#include "initguid.h"
|
||||
|
||||
#if 0
|
||||
#include "shlguid.h"
|
||||
#include "docobj.h"
|
||||
#include "olectl.h"
|
||||
#include "oleidl.h"
|
||||
#include "oaidl.h"
|
||||
#include "ocidl.h"
|
||||
#include "objbase.h"
|
||||
#include "servprov.h"
|
||||
#include "ddraw.h"
|
||||
#include "d3d.h"
|
||||
#include "dinput.h"
|
||||
#include "dsound.h"
|
||||
#include "dplay.h"
|
||||
#include "dplobby.h"
|
||||
#include "vfw.h"
|
||||
#include "shlobj.h"
|
||||
#endif
|
||||
|
||||
/* and now for the one assumed GUID... */
|
||||
DEFINE_GUID(GUID_NULL, 0,0,0,0,0,0,0,0,0,0,0);
|
Loading…
Reference in New Issue