- 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:
Peter Hunnisett 2000-08-25 21:58:05 +00:00 committed by Alexandre Julliard
parent 217a682b4f
commit ef6dca5c37
19 changed files with 4909 additions and 1671 deletions

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

185
dlls/dplayx/dplay_global.h Normal file
View File

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

880
dlls/dplayx/dplaysp.c Normal file
View File

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

337
dlls/dplayx/dplaysp.h Normal file
View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -6,7 +6,6 @@ VPATH = @srcdir@
MODULE = ole
C_SRCS = \
guid.c \
ole2nls.c
EXTRASUBDIRS = nls

View File

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