Addin wine 0.9 dplay and dplayx it is directx core for network and tested in windows and not in reactos.

it is working in windows. 

svn path=/trunk/; revision=18811
This commit is contained in:
Magnus Olsen 2005-10-27 22:10:33 +00:00
parent da8e63268f
commit 5bd48cf0fa
26 changed files with 13851 additions and 0 deletions

View file

@ -62,6 +62,12 @@
<directory name="dnsapi">
<xi:include href="dnsapi/dnsapi.xml" />
</directory>
<directory name="dplay">
<xi:include href="dplay/dplay.xml" />
</directory>
<directory name="dplayx">
<xi:include href="dplayx/dplayx.xml" />
</directory>
<directory name="dsound">
<xi:include href="dsound/dsound.xml" />
</directory>

View file

@ -0,0 +1,4 @@
# First DirectPlay dll. Replaced by dplayx.dll.
@ stdcall DirectPlayCreate(ptr ptr ptr) dplayx.DirectPlayCreate
@ stdcall DirectPlayEnumerate(ptr ptr) dplayx.DirectPlayEnumerate

View file

@ -0,0 +1,25 @@
<module name="dplay" type="win32dll" baseaddress="${BASEADDRESS_DPLAY}" installbase="system32" installname="dplay.dll">
<importlibrary definition="dplay.spec.def" />
<include base="dinput8">.</include>
<include base="ReactOS">include/wine</include>
<define name="UNICODE" />
<define name="_UNICODE" />
<define name="__REACTOS__" />
<define name="__USE_W32API" />
<define name="_WIN32_IE">0x600</define>
<define name="_WIN32_WINNT">0x501</define>
<define name="WINVER">0x501</define>
<library>wine</library>
<library>uuid</library>
<library>ntdll</library>
<library>kernel32</library>
<library>user32</library>
<library>advapi32</library>
<library>ole32</library>
<library>winmm</library>
<library>dxguid</library>
<library>dinput</library>
<file>version.rc</file>
<file>dplay_main.c</file>
<file>dplay.spec</file>
</module>

View file

@ -0,0 +1 @@
/* nothing here yet */

View file

@ -0,0 +1,27 @@
/*
* Copyright 2004 Tom Wickline
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#define WINE_OLESELFREGISTER
#define WINE_FILEDESCRIPTION_STR "Wine DirectPlay"
#define WINE_FILENAME_STR "dplay.dll"
#define WINE_FILEVERSION 5,3,0,900
#define WINE_FILEVERSION_STR "5.3.0.900"
#define WINE_PRODUCTVERSION 5,3,0,900
#define WINE_PRODUCTVERSION_STR "5.3"
#include "wine/wine_common_ver.rc"

View file

@ -0,0 +1,134 @@
/* COM class factory for direct play lobby interfaces.
*
* Copyright 1999, 2000 Peter Hunnisett
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdarg.h>
#include <string.h>
#define COBJMACROS
#include "windef.h"
#include "winbase.h"
#include "objbase.h"
#include "winerror.h"
#include "wine/debug.h"
#include "dpinit.h"
WINE_DEFAULT_DEBUG_CHANNEL(dplay);
/*******************************************************************************
* DirectPlayLobby ClassFactory
*/
typedef struct
{
/* IUnknown fields */
const IClassFactoryVtbl *lpVtbl;
LONG ref;
} IClassFactoryImpl;
static HRESULT WINAPI
DP_and_DPL_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
return E_NOINTERFACE;
}
static ULONG WINAPI
DP_and_DPL_AddRef(LPCLASSFACTORY iface) {
IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
return InterlockedIncrement(&This->ref);
}
static ULONG WINAPI DP_and_DPL_Release(LPCLASSFACTORY iface) {
IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
/* static class (reference starts @ 1), won't ever be freed */
return InterlockedDecrement(&This->ref);
}
static HRESULT WINAPI DP_and_DPL_CreateInstance(
LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
) {
IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
if ( DPL_CreateInterface( riid, ppobj ) == S_OK )
{
return S_OK;
}
else if ( DP_CreateInterface( riid, ppobj ) == S_OK )
{
return S_OK;
}
return E_NOINTERFACE;
}
static HRESULT WINAPI DP_and_DPL_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
FIXME("(%p)->(%d),stub!\n",This,dolock);
return S_OK;
}
static const IClassFactoryVtbl DP_and_DPL_Vtbl = {
DP_and_DPL_QueryInterface,
DP_and_DPL_AddRef,
DP_and_DPL_Release,
DP_and_DPL_CreateInstance,
DP_and_DPL_LockServer
};
static IClassFactoryImpl DP_and_DPL_CF = {&DP_and_DPL_Vtbl, 1 };
/*******************************************************************************
* DllGetClassObject [DPLAYX.@]
* Retrieves DP or DPL class object from a DLL object
*
* NOTES
* Docs say returns STDAPI
*
* PARAMS
* rclsid [I] CLSID for the class object
* riid [I] Reference to identifier of interface for class object
* ppv [O] Address of variable to receive interface pointer for riid
*
* RETURNS
* Success: S_OK
* Failure: CLASS_E_CLASSNOTAVAILABLE, E_OUTOFMEMORY, E_INVALIDARG,
* E_UNEXPECTED
*/
HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
{
TRACE("(%p,%p,%p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
if ( IsEqualCLSID( riid, &IID_IClassFactory ) )
{
*ppv = (LPVOID)&DP_and_DPL_CF;
IClassFactory_AddRef( (IClassFactory*)*ppv );
return S_OK;
}
ERR("(%p,%p,%p): no interface found.\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
return CLASS_E_CLASSNOTAVAILABLE;
}

View file

@ -0,0 +1,37 @@
/*
* Copyright 1999, 2000 Peter Hunnisett
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __WINE_DPINIT_H
#define __WINE_DPINIT_H
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#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 );
extern HRESULT DPLSP_CreateInterface( REFIID riid, LPVOID* ppvObj,
IDirectPlay2Impl* dp );
#endif

5451
reactos/lib/dplayx/dplay.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,246 @@
/*
* Copyright 2000 Peter Hunnisett
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __WINE_DPLAY_GLOBAL_INCLUDED
#define __WINE_DPLAY_GLOBAL_INCLUDED
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "dplaysp.h"
#include "lobbysp.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
{
LONG ulObjRef;
CRITICAL_SECTION DP_lock;
} DirectPlayIUnknownData;
typedef struct tagEnumSessionAsyncCallbackData
{
LPSPINITDATA lpSpData;
GUID requestGuid;
DWORD dwEnumSessionFlags;
DWORD dwTimeout;
HANDLE hSuicideRequest;
} EnumSessionAsyncCallbackData;
typedef struct tagDP_MSG_REPLY_STRUCT
{
HANDLE hReceipt;
WORD wExpectedReply;
LPVOID lpReplyMsg;
DWORD dwMsgBodySize;
/* FIXME: Is the message header required as well? */
} DP_MSG_REPLY_STRUCT, *LPDP_MSG_REPLY_STRUCT;
typedef struct tagDP_MSG_REPLY_STRUCT_LIST
{
DPQ_ENTRY(tagDP_MSG_REPLY_STRUCT_LIST) replysExpected;
DP_MSG_REPLY_STRUCT replyExpected;
} DP_MSG_REPLY_STRUCT_LIST, *LPDP_MSG_REPLY_STRUCT_LIST;
struct PlayerData
{
/* Individual player information */
DPID dpid;
DPNAME name;
HANDLE hEvent;
ULONG uRef; /* What is the reference count on this data? */
/* View of local data */
LPVOID lpLocalData;
DWORD dwLocalDataSize;
/* View of remote data */
LPVOID lpRemoteData;
DWORD dwRemoteDataSize;
/* SP data on a per player basis */
LPVOID lpSPPlayerData;
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 */
ULONG uRef; /* Reference count */
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;
enum SPSTATE
{
NO_PROVIDER = 0,
DP_SERVICE_PROVIDER = 1,
DP_LOBBY_PROVIDER = 2
};
/* Contains all data members. FIXME: Rename me */
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 */
lpGroupData lpSysGroup; /* System group with _everything_ in it */
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;
BOOL bSPInitialized;
/* Information about the lobby server that's attached to this DP object */
SPDATA_INIT dplspData;
BOOL bDPLSPInitialized;
/* Our service provider */
HMODULE hServiceProvider;
/* Our DP lobby provider */
HMODULE hDPLobbyProvider;
enum SPSTATE connectionInitialized;
/* Expected messages queue */
DPQ_HEAD( tagDP_MSG_REPLY_STRUCT_LIST ) replysExpected;
} DirectPlay2Data;
typedef struct tagDirectPlay3Data
{
BOOL dummy;
} DirectPlay3Data;
typedef struct tagDirectPlay4Data
{
BOOL dummy;
} DirectPlay4Data;
#define DP_IMPL_FIELDS \
LONG ulInterfaceRef; \
DirectPlayIUnknownData* unk; \
DirectPlay2Data* dp2; \
DirectPlay3Data* dp3; \
DirectPlay4Data* dp4;
struct IDirectPlay2Impl
{
const IDirectPlay2Vtbl *lpVtbl;
DP_IMPL_FIELDS
};
struct IDirectPlay3Impl
{
const IDirectPlay3Vtbl *lpVtbl;
DP_IMPL_FIELDS
};
struct IDirectPlay4Impl
{
const IDirectPlay4Vtbl *lpVtbl;
DP_IMPL_FIELDS
};
HRESULT DP_HandleMessage( IDirectPlay2Impl* This, LPCVOID lpMessageBody,
DWORD dwMessageBodySize, LPCVOID lpMessageHeader,
WORD wCommandId, WORD wVersion,
LPVOID* lplpReply, LPDWORD lpdwMsgSize );
/* DP SP external interfaces into DirectPlay */
extern HRESULT DP_GetSPPlayerData( IDirectPlay2Impl* lpDP, DPID idPlayer, LPVOID* lplpData );
extern HRESULT DP_SetSPPlayerData( IDirectPlay2Impl* lpDP, DPID idPlayer, LPVOID lpData );
/* DP external interfaces to call into DPSP interface */
extern LPVOID DPSP_CreateSPPlayerData(void);
#endif /* __WINE_DPLAY_GLOBAL_INCLUDED */

View file

@ -0,0 +1,955 @@
/* This contains the implementation of the interface Service
* Providers require to communicate with Direct Play
*
* Copyright 2000 Peter Hunnisett
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <string.h>
#include "winerror.h"
#include "wine/debug.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 */
WINE_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
{
LONG 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 */
} DirectPlaySPData;
#define DPSP_IMPL_FIELDS \
LONG ulInterfaceRef; \
DirectPlaySPIUnknownData* unk; \
DirectPlaySPData* sp;
struct IDirectPlaySPImpl
{
const IDirectPlaySPVtbl *lpVtbl;
DPSP_IMPL_FIELDS
};
/* Forward declaration of virtual tables */
static const IDirectPlaySPVtbl directPlaySPVT;
/* This structure is passed to the DP object for safe keeping */
typedef struct tagDP_SPPLAYERDATA
{
LPVOID lpPlayerLocalData;
DWORD dwPlayerLocalDataSize;
LPVOID lpPlayerRemoteData;
DWORD dwPlayerRemoteDataSize;
} DP_SPPLAYERDATA, *LPDP_SPPLAYERDATA;
/* 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 ) )
{
IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)*ppvObj;
This->lpVtbl = &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 )
{
IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)lpSP;
This->unk = 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 )
{
IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)lpSP;
DeleteCriticalSection( &This->unk->DPSP_lock );
HeapFree( GetProcessHeap(), 0, This->unk );
return TRUE;
}
static BOOL DPSP_CreateDirectPlaySP( LPVOID lpSP, IDirectPlay2Impl* dp )
{
IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)lpSP;
This->sp = 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.
*
* FIXME: This is a kludge to get around a problem where a queryinterface
* is used to get a new interface and then is closed. We will then
* reference garbage. However, with this we will never deallocate
* the interface we store. The correct fix is to require all
* DP internal interfaces to use the This->dp2 interface which
* should be changed to This->dp
*/
IDirectPlayX_AddRef( (LPDIRECTPLAY2)dp );
return TRUE;
}
static BOOL DPSP_DestroyDirectPlaySP( LPVOID lpSP )
{
IDirectPlaySPImpl *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 )
{
IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
TRACE("(%p)->(%s,%p)\n", This, debugstr_guid( riid ), ppvObj );
*ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof( *This ) );
if( *ppvObj == NULL )
{
return DPERR_OUTOFMEMORY;
}
CopyMemory( *ppvObj, This, sizeof( *This ) );
(*(IDirectPlaySPImpl**)ppvObj)->ulInterfaceRef = 0;
if( IsEqualGUID( &IID_IDirectPlaySP, riid ) )
{
IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)*ppvObj;
This->lpVtbl = &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;
IDirectPlaySPImpl *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;
IDirectPlaySPImpl *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
)
{
IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
/* Should be able to call the comctl32 undocumented MRU routines.
I suspect that the interface works appropriately */
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
)
{
IDirectPlaySPImpl *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
)
{
IDirectPlaySPImpl *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
)
{
IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
/* Should be able to call the comctl32 undocumented MRU routines.
I suspect that the interface works appropriately */
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
)
{
IDirectPlaySPImpl *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
)
{
HRESULT hr;
LPDP_SPPLAYERDATA lpPlayerData;
IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
TRACE( "(%p)->(0x%08lx,%p,%p,0x%08lx)\n",
This, idPlayer, lplpData, lpdwDataSize, dwFlags );
hr = DP_GetSPPlayerData( This->sp->dplay, idPlayer, (LPVOID*)&lpPlayerData );
if( FAILED(hr) )
{
TRACE( "Couldn't get player data: %s\n", DPLAYX_HresultToString(hr) );
return DPERR_INVALIDPLAYER;
}
/* What to do in the case where there is nothing set yet? */
if( dwFlags == DPSET_LOCAL )
{
HeapFree( GetProcessHeap(), 0, lpPlayerData->lpPlayerLocalData );
*lplpData = lpPlayerData->lpPlayerLocalData;
*lpdwDataSize = lpPlayerData->dwPlayerLocalDataSize;
}
else if( dwFlags == DPSET_REMOTE )
{
HeapFree( GetProcessHeap(), 0, lpPlayerData->lpPlayerRemoteData );
*lplpData = lpPlayerData->lpPlayerRemoteData;
*lpdwDataSize = lpPlayerData->dwPlayerRemoteDataSize;
}
if( *lplpData == NULL )
{
hr = DPERR_GENERIC;
}
return hr;
}
static HRESULT WINAPI IDirectPlaySPImpl_HandleMessage
( LPDIRECTPLAYSP iface,
LPVOID lpMessageBody,
DWORD dwMessageBodySize,
LPVOID lpMessageHeader
)
{
LPDPMSG_SENDENVELOPE lpMsg = (LPDPMSG_SENDENVELOPE)lpMessageBody;
HRESULT hr = DPERR_GENERIC;
WORD wCommandId;
WORD wVersion;
DPSP_REPLYDATA data;
IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
FIXME( "(%p)->(%p,0x%08lx,%p): mostly stub\n",
This, lpMessageBody, dwMessageBodySize, lpMessageHeader );
wCommandId = lpMsg->wCommandId;
wVersion = lpMsg->wVersion;
TRACE( "Incoming message has envelope of 0x%08lx, %u, %u\n",
lpMsg->dwMagic, wCommandId, wVersion );
if( lpMsg->dwMagic != DPMSGMAGIC_DPLAYMSG )
{
ERR( "Unknown magic 0x%08lx!\n", lpMsg->dwMagic );
return DPERR_GENERIC;
}
#if 0
{
const LPDWORD lpcHeader = (LPDWORD)lpMessageHeader;
TRACE( "lpMessageHeader = [0x%08lx] [0x%08lx] [0x%08lx] [0x%08lx] [0x%08lx]\n",
lpcHeader[0], lpcHeader[1], lpcHeader[2], lpcHeader[3], lpcHeader[4] );
}
#endif
/* Pass everything else to Direct Play */
data.lpMessage = NULL;
data.dwMessageSize = 0;
/* Pass this message to the dplay interface to handle */
hr = DP_HandleMessage( This->sp->dplay, lpMessageBody, dwMessageBodySize,
lpMessageHeader, wCommandId, wVersion,
&data.lpMessage, &data.dwMessageSize );
if( FAILED(hr) )
{
ERR( "Command processing failed %s\n", DPLAYX_HresultToString(hr) );
}
/* Do we want a reply? */
if( data.lpMessage != NULL )
{
data.lpSPMessageHeader = lpMessageHeader;
data.idNameServer = 0;
data.lpISP = iface;
hr = (This->sp->dplay->dp2->spData.lpCB->Reply)( &data );
if( FAILED(hr) )
{
ERR( "Reply failed %s\n", DPLAYX_HresultToString(hr) );
}
}
return hr;
#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: Who needs to delete the message when done? */
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 receive event was registered for this player, invoke it */
if( hReceiveEvent )
{
SetEvent( hReceiveEvent );
}
#endif
}
static HRESULT WINAPI IDirectPlaySPImpl_SetSPPlayerData
( LPDIRECTPLAYSP iface,
DPID idPlayer,
LPVOID lpData,
DWORD dwDataSize,
DWORD dwFlags
)
{
HRESULT hr;
LPDP_SPPLAYERDATA lpPlayerEntry;
LPVOID lpPlayerData;
IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
/* TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() ); */
TRACE( "(%p)->(0x%08lx,%p,0x%08lx,0x%08lx)\n",
This, idPlayer, lpData, dwDataSize, dwFlags );
hr = DP_GetSPPlayerData( This->sp->dplay, idPlayer, (LPVOID*)&lpPlayerEntry );
if( FAILED(hr) )
{
/* Player must not exist */
return DPERR_INVALIDPLAYER;
}
lpPlayerData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize );
CopyMemory( lpPlayerData, lpData, dwDataSize );
if( dwFlags == DPSET_LOCAL )
{
lpPlayerEntry->lpPlayerLocalData = lpPlayerData;
lpPlayerEntry->dwPlayerLocalDataSize = dwDataSize;
}
else if( dwFlags == DPSET_REMOTE )
{
lpPlayerEntry->lpPlayerRemoteData = lpPlayerData;
lpPlayerEntry->dwPlayerRemoteDataSize = dwDataSize;
}
hr = DP_SetSPPlayerData( This->sp->dplay, idPlayer, lpPlayerEntry );
return hr;
}
static HRESULT WINAPI IDirectPlaySPImpl_CreateCompoundAddress
( LPDIRECTPLAYSP iface,
LPCDPCOMPOUNDADDRESSELEMENT lpElements,
DWORD dwElementCount,
LPVOID lpAddress,
LPDWORD lpdwAddressSize
)
{
IDirectPlaySPImpl *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
)
{
HRESULT hr = DP_OK;
IDirectPlaySPImpl *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 != DPSET_REMOTE )
{
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 != DPSET_REMOTE )
{
TRACE( "Undocumented dwFlags 0x%08lx used\n", dwFlags );
}
#endif
/* FIXME: What to do in the case where this isn't initialized yet? */
/* 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;
if( This->sp->lpSpRemoteData == NULL )
{
hr = DPERR_GENERIC;
}
}
else if( dwFlags == DPSET_LOCAL )
{
*lpdwDataSize = This->sp->dwSpLocalDataSize;
*lplpData = This->sp->lpSpLocalData;
if( This->sp->lpSpLocalData == NULL )
{
hr = DPERR_GENERIC;
}
}
return hr;
}
static HRESULT WINAPI IDirectPlaySPImpl_SetSPData
( LPDIRECTPLAYSP iface,
LPVOID lpData,
DWORD dwDataSize,
DWORD dwFlags
)
{
LPVOID lpSpData;
IDirectPlaySPImpl *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 != DPSET_REMOTE )
{
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 != DPSET_REMOTE )
{
TRACE( "Undocumented dwFlags 0x%08lx used\n", dwFlags );
}
#endif
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 )
{
HeapFree( GetProcessHeap(), 0, This->sp->lpSpRemoteData );
This->sp->dwSpRemoteDataSize = dwDataSize;
This->sp->lpSpRemoteData = lpSpData;
}
else if ( dwFlags == DPSET_LOCAL )
{
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
)
{
IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
FIXME( "(%p)->(%p,0x%08lx): stub\n",
This, unknownA, unknownB );
}
static const IDirectPlaySPVtbl directPlaySPVT =
{
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
};
/* DP external interfaces to call into DPSP interface */
/* Allocate the structure */
extern LPVOID DPSP_CreateSPPlayerData(void)
{
TRACE( "Creating SPPlayer data struct\n" );
return HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof( DP_SPPLAYERDATA ) );
}

View file

@ -0,0 +1,366 @@
/*
* Copyright 2000 Peter Hunnisett
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __WINE_DIRECT_PLAY_SP_H
#define __WINE_DIRECT_PLAY_SP_H
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "winuser.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 *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 INTERFACE IDirectPlaySP
DECLARE_INTERFACE_(IDirectPlaySP,IUnknown)
{
/*** IUnknown methods ***/
STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE;
STDMETHOD_(ULONG,AddRef)(THIS) PURE;
STDMETHOD_(ULONG,Release)(THIS) PURE;
/*** IDirectPlaySP methods ***/
STDMETHOD(AddMRUEntry)(THIS_ LPCWSTR lpSection, LPCWSTR lpKey, LPCVOID lpData, DWORD dwDataSize, DWORD dwMaxEntries ) PURE;
STDMETHOD(CreateAddress)(THIS_ REFGUID guidSP, REFGUID guidDataType, LPCVOID lpData, DWORD dwDataSize, LPVOID lpAddress,LPDWORD lpdwAddressSize) PURE;
STDMETHOD(EnumAddress)(THIS_ LPDPENUMADDRESSCALLBACK lpEnumAddressCallback, LPCVOID lpAddress, DWORD dwAddressSize, LPVOID lpContext ) PURE;
STDMETHOD(EnumMRUEntries)(THIS_ LPCWSTR lpSection, LPCWSTR lpKey, LPENUMMRUCALLBACK lpEnumMRUCallback, LPVOID lpContext ) PURE;
STDMETHOD(GetPlayerFlags)(THIS_ DPID idPlayer, LPDWORD lpdwPlayerFlags ) PURE;
STDMETHOD(GetSPPlayerData)(THIS_ DPID idPlayer, LPVOID *lplpData, LPDWORD lpdwDataSize, DWORD dwFlags ) PURE;
STDMETHOD(HandleMessage)(THIS_ LPVOID lpMessageBody, DWORD dwMessageBodySize, LPVOID lpMessageHeader ) PURE;
STDMETHOD(SetSPPlayerData)(THIS_ DPID idPlayer, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags ) PURE;
STDMETHOD(CreateCompoundAddress)(THIS_ LPCDPCOMPOUNDADDRESSELEMENT lpElements, DWORD dwElementCount, LPVOID lpAddress, LPDWORD lpdwAddressSize ) PURE;
STDMETHOD(GetSPData)(THIS_ LPVOID *lplpData, LPDWORD dwDataSize, DWORD dwFlags ) PURE;
STDMETHOD(SetSPData)(THIS_ LPVOID lpData, DWORD dwDataSize, DWORD dwFlags ) PURE;
STDMETHOD_(VOID,SendComplete)(THIS_ LPVOID , DWORD ) PURE;
};
#undef INTERFACE
/* NOTE: The microsoft provided header file doesn't have these access
* functions
*/
#if !defined (__cplusplus) || defined(CINTERFACE)
/*** IUnknown methods ***/
#define IDirectPlaySP_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
#define IDirectPlaySP_AddRef(p) (p)->lpVtbl->AddRef(p)
#define IDirectPlaySP_Release(p) (p)->lpVtbl->Release(p)
/*** IDirectPlaySP methods ***/
#define IDirectPlaySP_AddMRUEntry(p,a,b,c,d,e) (p)->lpVtbl->AddMRUEntry(p,a,b,c,d,e)
#define IDirectPlaySP_CreateAddress(p,a,b,c,d,e,f) (p)->lpVtbl->CreateAddress(p,a,b,c,d,e,f)
#define IDirectPlaySP_EnumAddress(p,a,b,c,d) (p)->lpVtbl->EnumAddress(p,a,b,c,d)
#define IDirectPlaySP_EnumMRUEntries(p,a,b,c,d) (p)->lpVtbl->EnumMRUEntries(p,a,b,c,d)
#define IDirectPlaySP_GetPlayerFlags(p,a,b) (p)->lpVtbl->GetPlayerFlags(p,a,b)
#define IDirectPlaySP_GetSPPlayerData(p,a,b,c,d) (p)->lpVtbl->GetSPPlayerData(p,a,b,c,d)
#define IDirectPlaySP_HandleMessage(p,a,b,c) (p)->lpVtbl->HandleMessage(p,a,b,c)
#define IDirectPlaySP_SetSPPlayerData(p,a,b,c,d) (p)->lpVtbl->SetSPPlayerData(p,a,b,c,d)
#define IDirectPlaySP_CreateCompoundAddress(p,a,b,c,d) (p)->lpVtbl->CreateCompoundAddress(p,a,b,c,d)
#define IDirectPlaySP_GetSPData(p,a,b,c) (p)->lpVtbl->GetSPData(p,a,b,c)
#define IDirectPlaySP_SetSPData(p,a,b,c) (p)->lpVtbl->SetSPData(p,a,b,c)
#define IDirectPlaySP_SendComplete(p,a,b) (p)->lpVtbl->SendComplete(p,a,b)
#endif
/* 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

@ -0,0 +1,12 @@
1 stdcall DirectPlayCreate(ptr ptr ptr)
2 stdcall DirectPlayEnumerateA(ptr ptr)
3 stdcall DirectPlayEnumerateW(ptr ptr)
4 stdcall DirectPlayLobbyCreateA(ptr ptr ptr ptr long)
5 stdcall DirectPlayLobbyCreateW(ptr ptr ptr ptr long)
6 extern gdwDPlaySPRefCount
9 stdcall DirectPlayEnumerate(ptr ptr) DirectPlayEnumerateA
@ stdcall -private DllCanUnloadNow()
@ stdcall -private DllGetClassObject(ptr ptr ptr)
@ stdcall -private DllRegisterServer()
@ stdcall -private DllUnregisterServer()

View file

@ -0,0 +1,33 @@
<module name="dplayx" type="win32dll" baseaddress="${BASEADDRESS_DPLAYX}" installbase="system32" installname="dplayx.dll" allowwarnings ="true">
<importlibrary definition="dplayx.spec.def" />
<include base="dplayx">.</include>
<include base="ReactOS">include/wine</include>
<define name="UNICODE" />
<define name="_UNICODE" />
<define name="__REACTOS__" />
<define name="__USE_W32API" />
<define name="_WIN32_IE">0x600</define>
<define name="_WIN32_WINNT">0x501</define>
<define name="WINVER">0x501</define>
<library>wine</library>
<library>uuid</library>
<library>ntdll</library>
<library>kernel32</library>
<library>user32</library>
<library>advapi32</library>
<library>ole32</library>
<library>winmm</library>
<library>dxguid</library>
<file>version.rc</file>
<file>dpclassfactory.c</file>
<file>dplay.c</file>
<file>dplaysp.c</file>
<file>dplayx_global.c</file>
<file>dplayx_main.c</file>
<file>dplayx_messages.c</file>
<file>dplobby.c</file>
<file>lobbysp.c</file>
<file>name_server.c</file>
<file>regsvr.c</file>
<file>dplayx.spec</file>
</module>

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,76 @@
/*
* Copyright 1999, 2000 Peter Hunnisett
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __WINE_DPLAYX_GLOBAL
#define __WINE_DPLAYX_GLOBAL
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "winuser.h"
#include "dplay.h"
BOOL DPLAYX_ConstructData(void);
BOOL DPLAYX_DestructData(void);
HRESULT DPLAYX_GetConnectionSettingsA ( DWORD dwAppID,
LPVOID lpData,
LPDWORD lpdwDataSize );
HRESULT DPLAYX_GetConnectionSettingsW ( DWORD dwAppID,
LPVOID lpData,
LPDWORD lpdwDataSize );
HRESULT DPLAYX_SetConnectionSettingsA ( DWORD dwFlags,
DWORD dwAppID,
LPDPLCONNECTION lpConn );
HRESULT DPLAYX_SetConnectionSettingsW ( DWORD dwFlags,
DWORD dwAppID,
LPDPLCONNECTION lpConn );
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 );
#endif /* __WINE_DPLAYX_GLOBAL */

View file

@ -0,0 +1,111 @@
/*
* DPLAYX.DLL LibMain
*
* Copyright 1999,2000 - Peter Hunnisett
*
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* NOTES
* o DPMSGCMD_ENUMSESSIONSREPLY & DPMSGCMD_ENUMSESSIONSREQUEST
* Have most fields understood, but not all. Everything seems to work.
* o DPMSGCMD_REQUESTNEWPLAYERID & DPMSGCMD_NEWPLAYERIDREPLY
* Barely work. This needs to be completed for sessions to start.
* o A small issue will be the fact that DirectX 6.1(ie. DirectPlay4)
* introduces a layer of functionality inside the DP objects which
* provide guaranteed protocol delivery. This is even if the native
* protocol, IPX or modem for instance, doesn't guarantee it. I'm going
* to leave this kind of implementation to as close to the end as
* possible. However, I will implement an abstraction layer, where
* possible, for this functionality. It will do nothing to start, but
* will require only the implementation of the guaranteness to give
* final implementation.
*
* TODO:
* - Implement mutual exclusion on object data for existing functions
* - Ensure that all dll stubs are present and the ordinals are correct
* - Addition of DirectX 7.0 functionality for direct play
* - Implement some WineLib test programs using sdk programs as a skeleton
* - Change RegEnumKeyEx enumeration pattern to allow error handling and to
* share registry implementation (or at least simplify).
* - Add in appropriate RegCloseKey calls for all the opening we're doing...
* - Fix all the buffer sizes for registry calls. They're off by one -
* but in a safe direction.
* - Fix race condition on interface destruction
* - Handles need to be correctly reference counted
* - Check if we need to deallocate any list objects when destroying
* a dplay interface
* - RunApplication process spawning needs to have correct syncronization.
* - Need to get inter lobby messages working.
* - Decypher dplay messages between applications and implement...
* - Need to implement lobby session spawning.
* - Improve footprint and realtime blocking by setting up a separate data share
* between lobby application and client since there can be multiple apps per
* client. Also get rid of offset dependency by making data offset independent
* somehow.
*/
#include <stdarg.h>
#include "winerror.h"
#include "windef.h"
#include "winbase.h"
#include "wine/debug.h"
#include "dplayx_global.h"
WINE_DEFAULT_DEBUG_CHANNEL(dplay);
/* This is a globally exported variable at ordinal 6 of DPLAYX.DLL */
DWORD gdwDPlaySPRefCount = 0; /* FIXME: Should it be initialized here? */
BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved )
{
TRACE( "(%p,%ld,%p)\n", hinstDLL, fdwReason, lpvReserved );
switch ( fdwReason )
{
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(hinstDLL);
/* First instance perform construction of global processor data */
return DPLAYX_ConstructData();
case DLL_PROCESS_DETACH:
/* Last instance performs destruction of global processor data */
return DPLAYX_DestructData();
default:
break;
}
return TRUE;
}
/***********************************************************************
* DllCanUnloadNow (DPLAYX.@)
*/
HRESULT WINAPI 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

@ -0,0 +1,511 @@
/* DirectPlay & DirectPlayLobby messaging implementation
*
* Copyright 2000,2001 - Peter Hunnisett
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* NOTES
* o Messaging interface required for both DirectPlay and DirectPlayLobby.
*/
#include <stdarg.h>
#include <string.h>
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "winerror.h"
#include "ntstatus.h"
#include "dplayx_messages.h"
#include "dplay_global.h"
#include "dplayx_global.h"
#include "name_server.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(dplay);
typedef struct tagMSGTHREADINFO
{
HANDLE hStart;
HANDLE hDeath;
HANDLE hSettingRead;
HANDLE hNotifyEvent;
} MSGTHREADINFO, *LPMSGTHREADINFO;
static DWORD CALLBACK DPL_MSG_ThreadMain( LPVOID lpContext );
static LPVOID DP_MSG_ExpectReply( IDirectPlay2AImpl* This, LPDPSP_SENDDATA data,
DWORD dwWaitTime, WORD wReplyCommandId,
LPVOID* lplpReplyMsg, LPDWORD lpdwMsgBodySize );
/* Create the message reception thread to allow the application to receive
* asynchronous message reception
*/
DWORD CreateLobbyMessageReceptionThread( HANDLE hNotifyEvent, HANDLE hStart,
HANDLE hDeath, HANDLE hConnRead )
{
DWORD dwMsgThreadId;
LPMSGTHREADINFO lpThreadInfo;
lpThreadInfo = HeapAlloc( GetProcessHeap(), 0, sizeof( *lpThreadInfo ) );
if( lpThreadInfo == NULL )
{
return 0;
}
/* 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 */
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 DPL_MSG_ThreadMain( LPVOID 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 ( ;; )
{
MSG lobbyMsg;
GetMessageW( &lobbyMsg, 0, 0, 0 );
}
end_of_thread:
TRACE( "Msg thread exiting!\n" );
HeapFree( GetProcessHeap(), 0, lpThreadInfo );
return 0;
}
/* DP messageing stuff */
static HANDLE DP_MSG_BuildAndLinkReplyStruct( IDirectPlay2Impl* This,
LPDP_MSG_REPLY_STRUCT_LIST lpReplyStructList,
WORD wReplyCommandId );
static LPVOID DP_MSG_CleanReplyStruct( LPDP_MSG_REPLY_STRUCT_LIST lpReplyStructList,
LPVOID* lplpReplyMsg, LPDWORD lpdwMsgBodySize );
static
HANDLE DP_MSG_BuildAndLinkReplyStruct( IDirectPlay2Impl* This,
LPDP_MSG_REPLY_STRUCT_LIST lpReplyStructList, WORD wReplyCommandId )
{
lpReplyStructList->replyExpected.hReceipt = CreateEventW( NULL, FALSE, FALSE, NULL );
lpReplyStructList->replyExpected.wExpectedReply = wReplyCommandId;
lpReplyStructList->replyExpected.lpReplyMsg = NULL;
lpReplyStructList->replyExpected.dwMsgBodySize = 0;
/* Insert into the message queue while locked */
EnterCriticalSection( &This->unk->DP_lock );
DPQ_INSERT( This->dp2->replysExpected, lpReplyStructList, replysExpected );
LeaveCriticalSection( &This->unk->DP_lock );
return lpReplyStructList->replyExpected.hReceipt;
}
static
LPVOID DP_MSG_CleanReplyStruct( LPDP_MSG_REPLY_STRUCT_LIST lpReplyStructList,
LPVOID* lplpReplyMsg, LPDWORD lpdwMsgBodySize )
{
CloseHandle( lpReplyStructList->replyExpected.hReceipt );
*lplpReplyMsg = lpReplyStructList->replyExpected.lpReplyMsg;
*lpdwMsgBodySize = lpReplyStructList->replyExpected.dwMsgBodySize;
return lpReplyStructList->replyExpected.lpReplyMsg;
}
HRESULT DP_MSG_SendRequestPlayerId( IDirectPlay2AImpl* This, DWORD dwFlags,
LPDPID lpdpidAllocatedId )
{
LPVOID lpMsg;
LPDPMSG_REQUESTNEWPLAYERID lpMsgBody;
DWORD dwMsgSize;
HRESULT hr = DP_OK;
dwMsgSize = This->dp2->spData.dwSPHeaderSize + sizeof( *lpMsgBody );
lpMsg = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwMsgSize );
lpMsgBody = (LPDPMSG_REQUESTNEWPLAYERID)( (BYTE*)lpMsg +
This->dp2->spData.dwSPHeaderSize );
/* Compose dplay message envelope */
lpMsgBody->envelope.dwMagic = DPMSGMAGIC_DPLAYMSG;
lpMsgBody->envelope.wCommandId = DPMSGCMD_REQUESTNEWPLAYERID;
lpMsgBody->envelope.wVersion = DPMSGVER_DP6;
/* Compose the body of the message */
lpMsgBody->dwFlags = dwFlags;
/* Send the message */
{
DPSP_SENDDATA data;
data.dwFlags = DPSEND_GUARANTEED;
data.idPlayerTo = 0; /* Name server */
data.idPlayerFrom = 0; /* Sending from DP */
data.lpMessage = lpMsg;
data.dwMessageSize = dwMsgSize;
data.bSystemMessage = TRUE; /* Allow reply to be sent */
data.lpISP = This->dp2->spData.lpISP;
TRACE( "Asking for player id w/ dwFlags 0x%08lx\n",
lpMsgBody->dwFlags );
DP_MSG_ExpectReply( This, &data, DPMSG_DEFAULT_WAIT_TIME, DPMSGCMD_NEWPLAYERIDREPLY,
&lpMsg, &dwMsgSize );
}
/* Need to examine the data and extract the new player id */
if( !FAILED(hr) )
{
LPCDPMSG_NEWPLAYERIDREPLY lpcReply;
lpcReply = (LPCDPMSG_NEWPLAYERIDREPLY)lpMsg;
*lpdpidAllocatedId = lpcReply->dpidNewPlayerId;
TRACE( "Received reply for id = 0x%08lx\n", lpcReply->dpidNewPlayerId );
/* FIXME: I think that the rest of the message has something to do
* with remote data for the player that perhaps I need to setup.
* However, with the information that is passed, all that it could
* be used for is a standardized intialization value, which I'm
* guessing we can do without. Unless the message content is the same
* for several different messages?
*/
HeapFree( GetProcessHeap(), 0, lpMsg );
}
return hr;
}
HRESULT DP_MSG_ForwardPlayerCreation( IDirectPlay2AImpl* This, DPID dpidServer )
{
LPVOID lpMsg;
LPDPMSG_FORWARDADDPLAYER lpMsgBody;
DWORD dwMsgSize;
HRESULT hr = DP_OK;
dwMsgSize = This->dp2->spData.dwSPHeaderSize + sizeof( *lpMsgBody );
lpMsg = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwMsgSize );
lpMsgBody = (LPDPMSG_FORWARDADDPLAYER)( (BYTE*)lpMsg +
This->dp2->spData.dwSPHeaderSize );
/* Compose dplay message envelope */
lpMsgBody->envelope.dwMagic = DPMSGMAGIC_DPLAYMSG;
lpMsgBody->envelope.wCommandId = DPMSGCMD_FORWARDADDPLAYER;
lpMsgBody->envelope.wVersion = DPMSGVER_DP6;
#if 0
{
LPBYTE lpPData;
DWORD dwDataSize;
/* SP Player remote data needs to be propagated at some point - is this the point? */
IDirectPlaySP_GetSPPlayerData( This->dp2->spData.lpISP, 0, (LPVOID*)&lpPData, &dwDataSize, DPSET_REMOTE );
ERR( "Player Data size is 0x%08lx\n"
"[%02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x]\n"
"[%02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x]\n",
dwDataSize,
lpPData[0], lpPData[1], lpPData[2], lpPData[3], lpPData[4],
lpPData[5], lpPData[6], lpPData[7], lpPData[8], lpPData[9],
lpPData[10], lpPData[11], lpPData[12], lpPData[13], lpPData[14],
lpPData[15], lpPData[16], lpPData[17], lpPData[18], lpPData[19],
lpPData[20], lpPData[21], lpPData[22], lpPData[23], lpPData[24],
lpPData[25], lpPData[26], lpPData[27], lpPData[28], lpPData[29],
lpPData[30], lpPData[31]
);
DebugBreak();
}
#endif
/* Compose body of message */
lpMsgBody->dpidAppServer = dpidServer;
lpMsgBody->unknown2[0] = 0x0;
lpMsgBody->unknown2[1] = 0x1c;
lpMsgBody->unknown2[2] = 0x6c;
lpMsgBody->unknown2[3] = 0x50;
lpMsgBody->unknown2[4] = 0x9;
lpMsgBody->dpidAppServer2 = dpidServer;
lpMsgBody->unknown3[0] = 0x0;
lpMsgBody->unknown3[0] = 0x0;
lpMsgBody->unknown3[0] = 0x20;
lpMsgBody->unknown3[0] = 0x0;
lpMsgBody->unknown3[0] = 0x0;
lpMsgBody->dpidAppServer3 = dpidServer;
lpMsgBody->unknown4[0] = 0x30;
lpMsgBody->unknown4[1] = 0xb;
lpMsgBody->unknown4[2] = 0x0;
lpMsgBody->unknown4[3] = NS_GetNsMagic( This->dp2->lpNameServerData ) -
0x02000000;
TRACE( "Setting first magic to 0x%08lx\n", lpMsgBody->unknown4[3] );
lpMsgBody->unknown4[4] = 0x0;
lpMsgBody->unknown4[5] = 0x0;
lpMsgBody->unknown4[6] = 0x0;
#if 0
lpMsgBody->unknown4[7] = NS_GetOtherMagic( This->dp2->lpNameServerData )
#else
lpMsgBody->unknown4[7] = NS_GetNsMagic( This->dp2->lpNameServerData );
#endif
TRACE( "Setting second magic to 0x%08lx\n", lpMsgBody->unknown4[7] );
lpMsgBody->unknown4[8] = 0x0;
lpMsgBody->unknown4[9] = 0x0;
lpMsgBody->unknown4[10] = 0x0;
lpMsgBody->unknown4[11] = 0x0;
lpMsgBody->unknown5[0] = 0x0;
lpMsgBody->unknown5[1] = 0x0;
/* Send the message */
{
DPSP_SENDDATA data;
data.dwFlags = DPSEND_GUARANTEED;
data.idPlayerTo = 0; /* Name server */
data.idPlayerFrom = dpidServer; /* Sending from session server */
data.lpMessage = lpMsg;
data.dwMessageSize = dwMsgSize;
data.bSystemMessage = TRUE; /* Allow reply to be sent */
data.lpISP = This->dp2->spData.lpISP;
TRACE( "Sending forward player request with 0x%08lx\n", dpidServer );
lpMsg = DP_MSG_ExpectReply( This, &data,
DPMSG_WAIT_60_SECS,
DPMSGCMD_GETNAMETABLEREPLY,
&lpMsg, &dwMsgSize );
}
/* Need to examine the data and extract the new player id */
if( lpMsg != NULL )
{
FIXME( "Name Table reply received: stub\n" );
}
return hr;
}
/* Queue up a structure indicating that we want a reply of type wReplyCommandId. DPlay does
* not seem to offer any way of uniquely differentiating between replies of the same type
* relative to the request sent. There is an implicit assumption that there will be no
* ordering issues on sends and receives from the opposite machine. No wonder MS is not
* a networking company.
*/
static
LPVOID DP_MSG_ExpectReply( IDirectPlay2AImpl* This, LPDPSP_SENDDATA lpData,
DWORD dwWaitTime, WORD wReplyCommandId,
LPVOID* lplpReplyMsg, LPDWORD lpdwMsgBodySize )
{
HRESULT hr;
HANDLE hMsgReceipt;
DP_MSG_REPLY_STRUCT_LIST replyStructList;
DWORD dwWaitReturn;
/* Setup for receipt */
hMsgReceipt = DP_MSG_BuildAndLinkReplyStruct( This, &replyStructList,
wReplyCommandId );
TRACE( "Sending msg and expecting cmd %u in reply within %lu ticks\n",
wReplyCommandId, dwWaitTime );
hr = (*This->dp2->spData.lpCB->Send)( lpData );
if( FAILED(hr) )
{
ERR( "Send failed: %s\n", DPLAYX_HresultToString( hr ) );
return NULL;
}
/* The reply message will trigger the hMsgReceipt event effectively switching
* control back to this thread. See DP_MSG_ReplyReceived.
*/
dwWaitReturn = WaitForSingleObject( hMsgReceipt, dwWaitTime );
if( dwWaitReturn != WAIT_OBJECT_0 )
{
ERR( "Wait failed 0x%08lx\n", dwWaitReturn );
return NULL;
}
/* Clean Up */
return DP_MSG_CleanReplyStruct( &replyStructList, lplpReplyMsg, lpdwMsgBodySize );
}
/* Determine if there is a matching request for this incoming message and then copy
* all important data. It is quite silly to have to copy the message, but the documents
* indicate that a copy is taken. Silly really.
*/
void DP_MSG_ReplyReceived( IDirectPlay2AImpl* This, WORD wCommandId,
LPCVOID lpcMsgBody, DWORD dwMsgBodySize )
{
LPDP_MSG_REPLY_STRUCT_LIST lpReplyList;
#if 0
if( wCommandId == DPMSGCMD_FORWARDADDPLAYER )
{
DebugBreak();
}
#endif
/* Find, and immediately remove (to avoid double triggering), the appropriate entry. Call locked to
* avoid problems.
*/
EnterCriticalSection( &This->unk->DP_lock );
DPQ_REMOVE_ENTRY( This->dp2->replysExpected, replysExpected, replyExpected.wExpectedReply,\
==, wCommandId, lpReplyList );
LeaveCriticalSection( &This->unk->DP_lock );
if( lpReplyList != NULL )
{
lpReplyList->replyExpected.dwMsgBodySize = dwMsgBodySize;
lpReplyList->replyExpected.lpReplyMsg = HeapAlloc( GetProcessHeap(),
HEAP_ZERO_MEMORY,
dwMsgBodySize );
CopyMemory( lpReplyList->replyExpected.lpReplyMsg,
lpcMsgBody, dwMsgBodySize );
/* Signal the thread which sent the message that it has a reply */
SetEvent( lpReplyList->replyExpected.hReceipt );
}
else
{
ERR( "No receipt event set - only expecting in reply mode\n" );
DebugBreak();
}
}
void DP_MSG_ToSelf( IDirectPlay2AImpl* This, DPID dpidSelf )
{
LPVOID lpMsg;
LPDPMSG_SENDENVELOPE lpMsgBody;
DWORD dwMsgSize;
dwMsgSize = This->dp2->spData.dwSPHeaderSize + sizeof( *lpMsgBody );
lpMsg = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwMsgSize );
lpMsgBody = (LPDPMSG_SENDENVELOPE)( (BYTE*)lpMsg +
This->dp2->spData.dwSPHeaderSize );
/* Compose dplay message envelope */
lpMsgBody->dwMagic = DPMSGMAGIC_DPLAYMSG;
lpMsgBody->wCommandId = DPMSGCMD_JUSTENVELOPE;
lpMsgBody->wVersion = DPMSGVER_DP6;
/* Send the message to ourselves */
{
DPSP_SENDDATA data;
data.dwFlags = 0;
data.idPlayerTo = dpidSelf; /* Sending to session server */
data.idPlayerFrom = 0; /* Sending from session server */
data.lpMessage = lpMsg;
data.dwMessageSize = dwMsgSize;
data.bSystemMessage = TRUE; /* Allow reply to be sent */
data.lpISP = This->dp2->spData.lpISP;
lpMsg = DP_MSG_ExpectReply( This, &data,
DPMSG_WAIT_5_SECS,
DPMSGCMD_JUSTENVELOPE,
&lpMsg, &dwMsgSize );
}
}
void DP_MSG_ErrorReceived( IDirectPlay2AImpl* This, WORD wCommandId,
LPCVOID lpMsgBody, DWORD dwMsgBodySize )
{
LPCDPMSG_FORWARDADDPLAYERNACK lpcErrorMsg;
lpcErrorMsg = (LPCDPMSG_FORWARDADDPLAYERNACK)lpMsgBody;
ERR( "Received error message %u. Error is %s\n",
wCommandId, DPLAYX_HresultToString( lpcErrorMsg->errorCode) );
DebugBreak();
}

View file

@ -0,0 +1,223 @@
/*
* Copyright 2000 Peter Hunnisett
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __WINE_DPLAYX_MESSAGES__
#define __WINE_DPLAYX_MESSAGES__
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "dplay.h"
#include "rpc.h" /* For GUID */
#include "dplay_global.h"
DWORD CreateLobbyMessageReceptionThread( HANDLE hNotifyEvent, HANDLE hStart,
HANDLE hDeath, HANDLE hConnRead );
HRESULT DP_MSG_SendRequestPlayerId( IDirectPlay2AImpl* This, DWORD dwFlags,
LPDPID lpdipidAllocatedId );
HRESULT DP_MSG_ForwardPlayerCreation( IDirectPlay2AImpl* This, DPID dpidServer );
void DP_MSG_ReplyReceived( IDirectPlay2AImpl* This, WORD wCommandId,
LPCVOID lpMsgBody, DWORD dwMsgBodySize );
void DP_MSG_ErrorReceived( IDirectPlay2AImpl* This, WORD wCommandId,
LPCVOID lpMsgBody, DWORD dwMsgBodySize );
void DP_MSG_ToSelf( IDirectPlay2AImpl* This, DPID dpidSelf );
/* Timings -> 1000 ticks/sec */
#define DPMSG_WAIT_5_SECS 5000
#define DPMSG_WAIT_30_SECS 30000
#define DPMSG_WAIT_60_SECS 60000
#define DPMSG_DEFAULT_WAIT_TIME DPMSG_WAIT_30_SECS
/* 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_GETNAMETABLEREPLY 3 /* Contains all existing players in session */
#define DPMSGCMD_REQUESTNEWPLAYERID 5
#define DPMSGCMD_NEWPLAYERIDREPLY 7
#define DPMSGCMD_CREATESESSION 8 /* Might be a create nameserver or new player msg */
#define DPMSGCMD_CREATENEWPLAYER 9
#define DPMSGCMD_SYSTEMMESSAGE 10
#define DPMSGCMD_DELETEPLAYER 11
#define DPMSGCMD_DELETEGROUP 12
#define DPMSGCMD_ENUMGROUPS 17
#define DPMSGCMD_FORWARDADDPLAYER 19
#define DPMSGCMD_PLAYERCHAT 22
#define DPMSGCMD_FORWARDADDPLAYERNACK 36
#define DPMSGCMD_JUSTENVELOPE 1000
#define DPMSGCMD_JUSTENVELOPEREPLY 1001
/* 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 8 bytes
*/
typedef struct tagDPMSG_SENDENVELOPE
{
DWORD dwMagic;
WORD wCommandId;
WORD wVersion;
} DPMSG_SENDENVELOPE, *LPDPMSG_SENDENVELOPE;
typedef const DPMSG_SENDENVELOPE* LPCDPMSG_SENDENVELOPE;
/* System messages exchanged between players seems to have this
* payload envelope on top of the basic envelope
*/
typedef struct tagDPMSG_SYSMSGENVELOPE
{
DWORD dwPlayerFrom;
DWORD dwPlayerTo;
} DPMSG_SYSMSGENVELOPE, *LPDPMSG_SYSMSGENVELOPE;
typedef const DPMSG_SYSMSGENVELOPE* LPCDPMSG_SYSMSGENVELOPE;
/* Reply sent in response to an enumsession request */
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;
/* Msg sent to find out what sessions are available */
typedef struct tagDPMSG_ENUMSESSIONSREQUEST
{
DPMSG_SENDENVELOPE envelope;
GUID guidApplication;
DWORD dwPasswordSize; /* A Guess. This is 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;
/* 12 bytes msg */
typedef struct tagDPMSG_REQUESTNEWPLAYERID
{
DPMSG_SENDENVELOPE envelope;
DWORD dwFlags; /* dwFlags used for CreatePlayer */
} DPMSG_REQUESTNEWPLAYERID, *LPDPMSG_REQUESTNEWPLAYERID;
typedef const DPMSG_REQUESTNEWPLAYERID* LPCDPMSG_REQUESTNEWPLAYERID;
/* 48 bytes msg */
typedef struct tagDPMSG_NEWPLAYERIDREPLY
{
DPMSG_SENDENVELOPE envelope;
DPID dpidNewPlayerId;
/* Assume that this is data that is tacked on to the end of the message
* that comes from the SP remote data stored that needs to be propagated.
*/
BYTE unknown[36]; /* This appears to always be 0 - not sure though */
} DPMSG_NEWPLAYERIDREPLY, *LPDPMSG_NEWPLAYERIDREPLY;
typedef const DPMSG_NEWPLAYERIDREPLY* LPCDPMSG_NEWPLAYERIDREPLY;
typedef struct tagDPMSG_FORWARDADDPLAYER
{
DPMSG_SENDENVELOPE envelope;
DWORD unknown; /* 0 */
DPID dpidAppServer; /* Remote application server id */
DWORD unknown2[5]; /* 0x0, 0x1c, 0x6c, 0x50, 0x9 */
DPID dpidAppServer2; /* Remote application server id again !? */
DWORD unknown3[5]; /* 0x0, 0x0, 0x20, 0x0, 0x0 */
DPID dpidAppServer3; /* Remote application server id again !? */
DWORD unknown4[12]; /* ??? - Is this a clump of 5 and then 8? */
/* NOTE: 1 byte in front of the two 0x??090002 entries changes!
* Is it a timestamp of some sort? 1st always smaller than
* other...
*/
#define FORWARDADDPLAYER_UNKNOWN4_INIT { 0x30, 0xb, 0x0, 0x1e090002, 0x0, 0x0, 0x0, 0x32090002, 0x0, 0x0, 0x0, 0x0 }
BYTE unknown5[2]; /* 2 bytes at the end. This may be a part of something! ( 0x0, 0x0) */
} DPMSG_FORWARDADDPLAYER, *LPDPMSG_FORWARDADDPLAYER;
typedef const DPMSG_FORWARDADDPLAYER* LPCDPMSG_FORWARDADDPLAYER;
/* This is an error message that can be received. Not sure if this is
* specifically for a forward add player or for all errors
*/
typedef struct tagDPMSG_FORWARDADDPLAYERNACK
{
DPMSG_SENDENVELOPE envelope;
HRESULT errorCode;
} DPMSG_FORWARDADDPLAYERNACK, *LPDPMSG_FORWARDADDPLAYERNACK;
typedef const DPMSG_FORWARDADDPLAYERNACK* LPCDPMSG_FORWARDADDPLAYERNACK;
#include "poppack.h"
#endif

View file

@ -0,0 +1,216 @@
/* A queue definition based on sys/queue.h TAILQ definitions
*
* Copyright 2000 Peter Hunnisett
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* NOTES
* o Linked list implementation for dplay/dplobby. Based off of the BSD
* version found in <sys/queue.h>
* o Port it to <wine/list.h> ?
*
*/
#ifndef __WINE_DPLAYX_QUEUE_H
#define __WINE_DPLAYX_QUEUE_H
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#define DPQ_INSERT(a,b,c) DPQ_INSERT_IN_TAIL(a,b,c)
/*
* Tail queue definitions.
*/
#define DPQ_HEAD(type) \
struct { \
struct type *lpQHFirst; /* first element */ \
struct type **lpQHLast; /* addr of last next element */ \
}
#define DPQ_ENTRY(type) \
struct { \
struct type *lpQNext; /* next element */ \
struct type **lpQPrev; /* address of previous next element */ \
}
/*
* Tail queue functions.
*/
#define DPQ_INIT(head) \
do{ \
(head).lpQHFirst = NULL; \
(head).lpQHLast = &(head).lpQHFirst; \
} while(0)
/* 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; \
(elm)->field.lpQPrev = (head).lpQHLast; \
*(head).lpQHLast = (elm); \
(head).lpQHLast = &(elm)->field.lpQNext; \
} while(0)
/* Remove element from the queue */
#define DPQ_REMOVE(head, elm, field) \
do { \
if (((elm)->field.lpQNext) != NULL) \
(elm)->field.lpQNext->field.lpQPrev = \
(elm)->field.lpQPrev; \
else \
(head).lpQHLast = (elm)->field.lpQPrev; \
*(elm)->field.lpQPrev = (elm)->field.lpQNext; \
} while(0)
/* head - pointer to DPQ_HEAD struct
* elm - how to find the next element
* field - to be concatenated to rc to compare with 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, fieldCompareOperator, fieldToCompare, rc )\
do { \
(rc) = DPQ_FIRST(head); /* NULL head? */ \
\
while( rc ) \
{ \
/* What we're searching for? */ \
if( (rc)->field fieldCompareOperator (fieldToCompare) ) \
{ \
break; /* rc == correct element */ \
} \
\
/* End of list check */ \
if( ( (rc) = (rc)->elm.lpQNext ) == (head).lpQHFirst ) \
{ \
rc = NULL; \
break; \
} \
} \
} while(0)
/* head - pointer to DPQ_HEAD struct
* elm - how to find the next element
* field - to be concatenated to rc to compare with fieldToCompare
* fieldToCompare - The value that we're comparing against
* compare_cb - Callback to invoke to determine if comparision should continue.
* Callback must be defined with DPQ_DECL_COMPARECB.
* rc - Variable to put the return code. Same type as (head).lpQHFirst
*/
#define DPQ_FIND_ENTRY_CB( head, elm, field, compare_cb, fieldToCompare, rc )\
do { \
(rc) = DPQ_FIRST(head); /* NULL head? */ \
\
while( rc ) \
{ \
/* What we're searching for? */ \
if( compare_cb( &((rc)->field), &(fieldToCompare) ) ) \
{ \
break; /* no more */ \
} \
\
/* End of list check */ \
if( ( (rc) = (rc)->elm.lpQNext ) == (head).lpQHFirst ) \
{ \
rc = NULL; \
break; \
} \
} \
} while(0)
/* How to define the method to be passed to DPQ_DELETEQ */
#define DPQ_DECL_COMPARECB( name, type ) BOOL name( const type* elem1, const type* elem2 )
/* head - pointer to DPQ_HEAD struct
* elm - how to find the next element
* field - to be concatenated to rc to compare with fieldToEqual
* 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, fieldCompareOperator, fieldToCompare, rc )\
do { \
DPQ_FIND_ENTRY( head, elm, field, fieldCompareOperator, fieldToCompare, rc );\
\
/* Was the element found? */ \
if( rc ) \
{ \
DPQ_REMOVE( head, rc, elm ); \
} \
} while(0)
/* head - pointer to DPQ_HEAD struct
* elm - how to find the next element
* field - to be concatenated to rc to compare with fieldToCompare
* fieldToCompare - The value that we're comparing against
* compare_cb - Callback to invoke to determine if comparision should continue.
* Callback must be defined with DPQ_DECL_COMPARECB.
* rc - Variable to put the return code. Same type as (head).lpQHFirst
*/
#define DPQ_REMOVE_ENTRY_CB( head, elm, field, compare_cb, fieldToCompare, rc )\
do { \
DPQ_FIND_ENTRY_CB( head, elm, field, compare_cb, fieldToCompare, rc );\
\
/* Was the element found? */ \
if( rc ) \
{ \
DPQ_REMOVE( head, rc, elm ); \
} \
} 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 ) \
do \
{ \
while( !DPQ_IS_EMPTY(head) ) \
{ \
type holder = DPQ_FIRST(head); \
DPQ_REMOVE( head, holder, field ); \
df( holder ); \
} \
} while(0)
/* 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 */

2012
reactos/lib/dplayx/dplobby.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,462 @@
/* This contains the implementation of the Lobby Service
* Providers interface required to communicate with Direct Play
*
* Copyright 2001 Peter Hunnisett
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "winerror.h"
#include "wine/debug.h"
#include "lobbysp.h"
#include "dplay_global.h"
#include "dpinit.h"
WINE_DEFAULT_DEBUG_CHANNEL(dplay);
/* Prototypes */
static BOOL DPLSP_CreateIUnknown( LPVOID lpSP );
static BOOL DPLSP_DestroyIUnknown( LPVOID lpSP );
static BOOL DPLSP_CreateDPLobbySP( LPVOID lpSP, IDirectPlay2Impl* dp );
static BOOL DPLSP_DestroyDPLobbySP( LPVOID lpSP );
/* Predefine the interface */
typedef struct IDPLobbySPImpl IDPLobbySPImpl;
typedef struct tagDPLobbySPIUnknownData
{
LONG ulObjRef;
CRITICAL_SECTION DPLSP_lock;
} DPLobbySPIUnknownData;
typedef struct tagDPLobbySPData
{
IDirectPlay2Impl* dplay;
} DPLobbySPData;
#define DPLSP_IMPL_FIELDS \
LONG ulInterfaceRef; \
DPLobbySPIUnknownData* unk; \
DPLobbySPData* sp;
struct IDPLobbySPImpl
{
const IDPLobbySPVtbl *lpVtbl;
DPLSP_IMPL_FIELDS
};
/* Forward declaration of virtual tables */
static const IDPLobbySPVtbl dpLobbySPVT;
HRESULT DPLSP_CreateInterface( REFIID riid, LPVOID* ppvObj, IDirectPlay2Impl* dp )
{
TRACE( " for %s\n", debugstr_guid( riid ) );
*ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof( IDPLobbySPImpl ) );
if( *ppvObj == NULL )
{
return DPERR_OUTOFMEMORY;
}
if( IsEqualGUID( &IID_IDPLobbySP, riid ) )
{
IDPLobbySPImpl *This = (IDPLobbySPImpl *)*ppvObj;
This->lpVtbl = &dpLobbySPVT;
}
else
{
/* Unsupported interface */
HeapFree( GetProcessHeap(), 0, *ppvObj );
*ppvObj = NULL;
return E_NOINTERFACE;
}
/* Initialize it */
if( DPLSP_CreateIUnknown( *ppvObj ) &&
DPLSP_CreateDPLobbySP( *ppvObj, dp )
)
{
IDPLobbySP_AddRef( (LPDPLOBBYSP)*ppvObj );
return S_OK;
}
/* Initialize failed, destroy it */
DPLSP_DestroyDPLobbySP( *ppvObj );
DPLSP_DestroyIUnknown( *ppvObj );
HeapFree( GetProcessHeap(), 0, *ppvObj );
*ppvObj = NULL;
return DPERR_NOMEMORY;
}
static BOOL DPLSP_CreateIUnknown( LPVOID lpSP )
{
IDPLobbySPImpl *This = (IDPLobbySPImpl *)lpSP;
This->unk = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->unk) ) );
if ( This->unk == NULL )
{
return FALSE;
}
InitializeCriticalSection( &This->unk->DPLSP_lock );
return TRUE;
}
static BOOL DPLSP_DestroyIUnknown( LPVOID lpSP )
{
IDPLobbySPImpl *This = (IDPLobbySPImpl *)lpSP;
DeleteCriticalSection( &This->unk->DPLSP_lock );
HeapFree( GetProcessHeap(), 0, This->unk );
return TRUE;
}
static BOOL DPLSP_CreateDPLobbySP( LPVOID lpSP, IDirectPlay2Impl* dp )
{
IDPLobbySPImpl *This = (IDPLobbySPImpl *)lpSP;
This->sp = 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.
*
* FIXME: This is a kludge to get around a problem where a queryinterface
* is used to get a new interface and then is closed. We will then
* reference garbage. However, with this we will never deallocate
* the interface we store. The correct fix is to require all
* DP internal interfaces to use the This->dp2 interface which
* should be changed to This->dp
*/
IDirectPlayX_AddRef( (LPDIRECTPLAY2)dp );
return TRUE;
}
static BOOL DPLSP_DestroyDPLobbySP( LPVOID lpSP )
{
IDPLobbySPImpl *This = (IDPLobbySPImpl *)lpSP;
HeapFree( GetProcessHeap(), 0, This->sp );
return TRUE;
}
static
HRESULT WINAPI DPLSP_QueryInterface
( LPDPLOBBYSP iface,
REFIID riid,
LPVOID* ppvObj
)
{
IDPLobbySPImpl *This = (IDPLobbySPImpl *)iface;
TRACE("(%p)->(%s,%p)\n", This, debugstr_guid( riid ), ppvObj );
*ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof( *This ) );
if( *ppvObj == NULL )
{
return DPERR_OUTOFMEMORY;
}
CopyMemory( *ppvObj, This, sizeof( *This ) );
(*(IDPLobbySPImpl**)ppvObj)->ulInterfaceRef = 0;
if( IsEqualGUID( &IID_IDPLobbySP, riid ) )
{
IDPLobbySPImpl *This = (IDPLobbySPImpl *)*ppvObj;
This->lpVtbl = &dpLobbySPVT;
}
else
{
/* Unsupported interface */
HeapFree( GetProcessHeap(), 0, *ppvObj );
*ppvObj = NULL;
return E_NOINTERFACE;
}
IDPLobbySP_AddRef( (LPDPLOBBYSP)*ppvObj );
return S_OK;
}
static
ULONG WINAPI DPLSP_AddRef
( LPDPLOBBYSP iface )
{
ULONG ulInterfaceRefCount, ulObjRefCount;
IDPLobbySPImpl *This = (IDPLobbySPImpl *)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 DPLSP_Release
( LPDPLOBBYSP iface )
{
ULONG ulInterfaceRefCount, ulObjRefCount;
IDPLobbySPImpl *This = (IDPLobbySPImpl *)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 )
{
DPLSP_DestroyDPLobbySP( This );
DPLSP_DestroyIUnknown( This );
}
if( ulInterfaceRefCount == 0 )
{
HeapFree( GetProcessHeap(), 0, This );
}
return ulInterfaceRefCount;
}
static
HRESULT WINAPI IDPLobbySPImpl_AddGroupToGroup
( LPDPLOBBYSP iface,
LPSPDATA_ADDREMOTEGROUPTOGROUP argtg
)
{
IDPLobbySPImpl *This = (IDPLobbySPImpl *)iface;
FIXME( "(%p)->(%p):stub\n", This, argtg );
return DP_OK;
}
static
HRESULT WINAPI IDPLobbySPImpl_AddPlayerToGroup
( LPDPLOBBYSP iface,
LPSPDATA_ADDREMOTEPLAYERTOGROUP arptg
)
{
IDPLobbySPImpl *This = (IDPLobbySPImpl *)iface;
FIXME( "(%p)->(%p):stub\n", This, arptg );
return DP_OK;
}
static
HRESULT WINAPI IDPLobbySPImpl_CreateGroup
( LPDPLOBBYSP iface,
LPSPDATA_CREATEREMOTEGROUP crg
)
{
IDPLobbySPImpl *This = (IDPLobbySPImpl *)iface;
FIXME( "(%p)->(%p):stub\n", This, crg );
return DP_OK;
}
static
HRESULT WINAPI IDPLobbySPImpl_CreateGroupInGroup
( LPDPLOBBYSP iface,
LPSPDATA_CREATEREMOTEGROUPINGROUP crgig
)
{
IDPLobbySPImpl *This = (IDPLobbySPImpl *)iface;
FIXME( "(%p)->(%p):stub\n", This, crgig );
return DP_OK;
}
static
HRESULT WINAPI IDPLobbySPImpl_DeleteGroupFromGroup
( LPDPLOBBYSP iface,
LPSPDATA_DELETEREMOTEGROUPFROMGROUP drgfg
)
{
IDPLobbySPImpl *This = (IDPLobbySPImpl *)iface;
FIXME( "(%p)->(%p):stub\n", This, drgfg );
return DP_OK;
}
static
HRESULT WINAPI IDPLobbySPImpl_DeletePlayerFromGroup
( LPDPLOBBYSP iface,
LPSPDATA_DELETEREMOTEPLAYERFROMGROUP drpfg
)
{
IDPLobbySPImpl *This = (IDPLobbySPImpl *)iface;
FIXME( "(%p)->(%p):stub\n", This, drpfg );
return DP_OK;
}
static
HRESULT WINAPI IDPLobbySPImpl_DestroyGroup
( LPDPLOBBYSP iface,
LPSPDATA_DESTROYREMOTEGROUP drg
)
{
IDPLobbySPImpl *This = (IDPLobbySPImpl *)iface;
FIXME( "(%p)->(%p):stub\n", This, drg );
return DP_OK;
}
static
HRESULT WINAPI IDPLobbySPImpl_EnumSessionsResponse
( LPDPLOBBYSP iface,
LPSPDATA_ENUMSESSIONSRESPONSE er
)
{
IDPLobbySPImpl *This = (IDPLobbySPImpl *)iface;
FIXME( "(%p)->(%p):stub\n", This, er );
return DP_OK;
}
static
HRESULT WINAPI IDPLobbySPImpl_GetSPDataPointer
( LPDPLOBBYSP iface,
LPVOID* lplpData
)
{
IDPLobbySPImpl *This = (IDPLobbySPImpl *)iface;
FIXME( "(%p)->(%p):stub\n", This, lplpData );
return DP_OK;
}
static
HRESULT WINAPI IDPLobbySPImpl_HandleMessage
( LPDPLOBBYSP iface,
LPSPDATA_HANDLEMESSAGE hm
)
{
IDPLobbySPImpl *This = (IDPLobbySPImpl *)iface;
FIXME( "(%p)->(%p):stub\n", This, hm );
return DP_OK;
}
static
HRESULT WINAPI IDPLobbySPImpl_SendChatMessage
( LPDPLOBBYSP iface,
LPSPDATA_CHATMESSAGE cm
)
{
IDPLobbySPImpl *This = (IDPLobbySPImpl *)iface;
FIXME( "(%p)->(%p):stub\n", This, cm );
return DP_OK;
}
static
HRESULT WINAPI IDPLobbySPImpl_SetGroupName
( LPDPLOBBYSP iface,
LPSPDATA_SETREMOTEGROUPNAME srgn
)
{
IDPLobbySPImpl *This = (IDPLobbySPImpl *)iface;
FIXME( "(%p)->(%p):stub\n", This, srgn );
return DP_OK;
}
static
HRESULT WINAPI IDPLobbySPImpl_SetPlayerName
( LPDPLOBBYSP iface,
LPSPDATA_SETREMOTEPLAYERNAME srpn
)
{
IDPLobbySPImpl *This = (IDPLobbySPImpl *)iface;
FIXME( "(%p)->(%p):stub\n", This, srpn );
return DP_OK;
}
static
HRESULT WINAPI IDPLobbySPImpl_SetSessionDesc
( LPDPLOBBYSP iface,
LPSPDATA_SETSESSIONDESC ssd
)
{
IDPLobbySPImpl *This = (IDPLobbySPImpl *)iface;
FIXME( "(%p)->(%p):stub\n", This, ssd );
return DP_OK;
}
static
HRESULT WINAPI IDPLobbySPImpl_SetSPDataPointer
( LPDPLOBBYSP iface,
LPVOID lpData
)
{
IDPLobbySPImpl *This = (IDPLobbySPImpl *)iface;
FIXME( "(%p)->(%p):stub\n", This, lpData );
return DP_OK;
}
static
HRESULT WINAPI IDPLobbySPImpl_StartSession
( LPDPLOBBYSP iface,
LPSPDATA_STARTSESSIONCOMMAND ssc
)
{
IDPLobbySPImpl *This = (IDPLobbySPImpl *)iface;
FIXME( "(%p)->(%p):stub\n", This, ssc );
return DP_OK;
}
static const IDPLobbySPVtbl dpLobbySPVT =
{
DPLSP_QueryInterface,
DPLSP_AddRef,
DPLSP_Release,
IDPLobbySPImpl_AddGroupToGroup,
IDPLobbySPImpl_AddPlayerToGroup,
IDPLobbySPImpl_CreateGroup,
IDPLobbySPImpl_CreateGroupInGroup,
IDPLobbySPImpl_DeleteGroupFromGroup,
IDPLobbySPImpl_DeletePlayerFromGroup,
IDPLobbySPImpl_DestroyGroup,
IDPLobbySPImpl_EnumSessionsResponse,
IDPLobbySPImpl_GetSPDataPointer,
IDPLobbySPImpl_HandleMessage,
IDPLobbySPImpl_SendChatMessage,
IDPLobbySPImpl_SetGroupName,
IDPLobbySPImpl_SetPlayerName,
IDPLobbySPImpl_SetSessionDesc,
IDPLobbySPImpl_SetSPDataPointer,
IDPLobbySPImpl_StartSession
};

View file

@ -0,0 +1,520 @@
/*
* Copyright 2001 Peter Hunnisett
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __WINE_LOBBY_SP_H
#define __WINE_LOBBY_SP_H
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "winuser.h"
#include "dplobby.h"
/* GUID for IDPLobbySP {5A4E5A20-2CED-11d0-A889-00A0C905433C} */
DEFINE_GUID(IID_IDPLobbySP, 0x5a4e5a20, 0x2ced, 0x11d0, 0xa8, 0x89, 0x0, 0xa0, 0xc9, 0x5, 0x43, 0x3c);
typedef struct IDPLobbySP *LPDPLOBBYSP;
/* For SP. Top 16 bits is dplay, bottom 16 is SP */
#define DPLSP_MAJORVERSION 0x00050000
typedef struct SPDATA_ADDGROUPTOGROUP
{
DWORD dwSize;
LPDPLOBBYSP lpISP;
DWORD dwParentID;
DWORD dwGroupID;
} SPDATA_ADDGROUPTOGROUP, *LPSPDATA_ADDGROUPTOGROUP;
typedef struct SPDATA_ADDPLAYERTOGROUP
{
DWORD dwSize;
LPDPLOBBYSP lpISP;
DWORD dwGroupID;
DWORD dwPlayerID;
} SPDATA_ADDPLAYERTOGROUP, *LPSPDATA_ADDPLAYERTOGROUP;
typedef struct SPDATA_ADDREMOTEGROUPTOGROUP
{
DWORD dwSize;
LPDPLOBBYSP lpISP;
DWORD dwAnchorID;
DWORD dwGroupID;
DWORD dwParentID;
LPDPNAME lpName;
DWORD dwGroupFlags;
} SPDATA_ADDREMOTEGROUPTOGROUP, *LPSPDATA_ADDREMOTEGROUPTOGROUP;
typedef struct SPDATA_ADDREMOTEPLAYERTOGROUP
{
DWORD dwSize;
LPDPLOBBYSP lpISP;
DWORD dwGroupID;
DWORD dwPlayerID;
DWORD dwPlayerFlags;
LPDPNAME lpName;
} SPDATA_ADDREMOTEPLAYERTOGROUP, *LPSPDATA_ADDREMOTEPLAYERTOGROUP;
typedef struct SPDATA_BUILDPARENTALHEIRARCHY
{
DWORD dwSize;
LPDPLOBBYSP lpISP;
DWORD dwGroupID;
DWORD dwMessage;
DWORD dwParentID;
} SPDATA_BUILDPARENTALHEIRARCHY, *LPSPDATA_BUILDPARENTALHEIRARCHY;
typedef struct SPDATA_CLOSE
{
DWORD dwSize;
LPDPLOBBYSP lpISP;
} SPDATA_CLOSE, *LPSPDATA_CLOSE;
typedef struct SPDATA_CREATEGROUP
{
DWORD dwSize;
LPDPLOBBYSP lpISP;
DWORD dwGroupID;
LPDPNAME lpName;
LPVOID lpData;
DWORD dwDataSize;
DWORD dwFlags;
} SPDATA_CREATEGROUP, *LPSPDATA_CREATEGROUP;
typedef struct SPDATA_CREATEGROUPINGROUP
{
DWORD dwSize;
LPDPLOBBYSP lpISP;
DWORD dwParentID;
DWORD dwGroupID;
LPDPNAME lpName;
LPVOID lpData;
DWORD dwDataSize;
DWORD dwFlags;
} SPDATA_CREATEGROUPINGROUP, *LPSPDATA_CREATEGROUPINGROUP;
typedef struct SPDATA_CREATEREMOTEGROUP
{
DWORD dwSize;
LPDPLOBBYSP lpISP;
DWORD dwGroupID;
LPDPNAME lpName;
LPVOID lpData;
DWORD dwDataSize;
DWORD dwFlags;
} SPDATA_CREATEREMOTEGROUP, *LPSPDATA_CREATEREMOTEGROUP;
typedef struct SPDATA_CREATEREMOTEGROUPINGROUP
{
DWORD dwSize;
LPDPLOBBYSP lpISP;
DWORD dwParentID;
DWORD dwGroupID;
LPDPNAME lpName;
DWORD dwFlags;
} SPDATA_CREATEREMOTEGROUPINGROUP, *LPSPDATA_CREATEREMOTEGROUPINGROUP;
typedef struct SPDATA_CREATEPLAYER
{
DWORD dwSize;
LPDPLOBBYSP lpISP;
DWORD dwPlayerID;
LPDPNAME lpName;
LPVOID lpData;
DWORD dwDataSize;
DWORD dwFlags;
} SPDATA_CREATEPLAYER, *LPSPDATA_CREATEPLAYER;
typedef struct SPDATA_DELETEGROUPFROMGROUP
{
DWORD dwSize;
LPDPLOBBYSP lpISP;
DWORD dwParentID;
DWORD dwGroupID;
} SPDATA_DELETEGROUPFROMGROUP, *LPSPDATA_DELETEGROUPFROMGROUP;
typedef struct SPDATA_DELETEPLAYERFROMGROUP
{
DWORD dwSize;
LPDPLOBBYSP lpISP;
DWORD dwGroupID;
DWORD dwPlayerID;
} SPDATA_DELETEPLAYERFROMGROUP, *LPSPDATA_DELETEPLAYERFROMGROUP;
typedef struct SPDATA_DELETEREMOTEGROUPFROMGROUP
{
DWORD dwSize;
LPDPLOBBYSP lpISP;
DWORD dwParentID;
DWORD dwGroupID;
} SPDATA_DELETEREMOTEGROUPFROMGROUP, *LPSPDATA_DELETEREMOTEGROUPFROMGROUP;
typedef struct SPDATA_DELETEREMOTEPLAYERFROMGROUP
{
DWORD dwSize;
LPDPLOBBYSP lpISP;
DWORD dwGroupID;
DWORD dwPlayerID;
} SPDATA_DELETEREMOTEPLAYERFROMGROUP, *LPSPDATA_DELETEREMOTEPLAYERFROMGROUP;
typedef struct SPDATA_DESTROYGROUP
{
DWORD dwSize;
LPDPLOBBYSP lpISP;
DWORD dwGroupID;
} SPDATA_DESTROYGROUP, *LPSPDATA_DESTROYGROUP;
typedef struct SPDATA_DESTROYREMOTEGROUP
{
DWORD dwSize;
LPDPLOBBYSP lpISP;
DWORD dwGroupID;
} SPDATA_DESTROYREMOTEGROUP, *LPSPDATA_DESTROYREMOTEGROUP;
typedef struct SPDATA_DESTROYPLAYER
{
DWORD dwSize;
LPDPLOBBYSP lpISP;
DWORD dwPlayerID;
} SPDATA_DESTROYPLAYER, *LPSPDATA_DESTROYPLAYER;
typedef struct SPDATA_ENUMSESSIONS
{
DWORD dwSize;
LPDPLOBBYSP lpISP;
LPDPSESSIONDESC2 lpsd;
DWORD dwTimeout;
DWORD dwFlags;
} SPDATA_ENUMSESSIONS, *LPSPDATA_ENUMSESSIONS;
typedef struct SPDATA_ENUMSESSIONSRESPONSE
{
DWORD dwSize;
LPDPSESSIONDESC2 lpsd;
} SPDATA_ENUMSESSIONSRESPONSE, *LPSPDATA_ENUMSESSIONSRESPONSE;
typedef struct SPDATA_GETCAPS
{
DWORD dwSize;
LPDPLOBBYSP lpISP;
DWORD dwFlags;
LPDPCAPS lpcaps;
} SPDATA_GETCAPS, *LPSPDATA_GETCAPS;
typedef struct SPDATA_GETGROUPCONNECTIONSETTINGS
{
DWORD dwSize;
DWORD dwFlags;
LPDPLOBBYSP lpISP;
DWORD dwGroupID;
LPDWORD lpdwBufferSize;
LPVOID lpBuffer;
} SPDATA_GETGROUPCONNECTIONSETTINGS, *LPSPDATA_GETGROUPCONNECTIONSETTINGS;
typedef struct SPDATA_GETGROUPDATA
{
DWORD dwSize;
LPDPLOBBYSP lpISP;
DWORD dwGroupID;
LPDWORD lpdwDataSize;
LPVOID lpData;
} SPDATA_GETGROUPDATA, *LPSPDATA_GETGROUPDATA;
typedef struct SPDATA_GETPLAYERCAPS
{
DWORD dwSize;
LPDPLOBBYSP lpISP;
DWORD dwFlags;
DWORD dwPlayerID;
LPDPCAPS lpcaps;
} SPDATA_GETPLAYERCAPS, *LPSPDATA_GETPLAYERCAPS;
typedef struct SPDATA_GETPLAYERDATA
{
DWORD dwSize;
LPDPLOBBYSP lpISP;
DWORD dwPlayerID;
LPDWORD lpdwDataSize;
LPVOID lpData;
} SPDATA_GETPLAYERDATA, *LPSPDATA_GETPLAYERDATA;
typedef struct SPDATA_HANDLEMESSAGE
{
DWORD dwSize;
DWORD dwFromID;
DWORD dwToID;
LPVOID lpBuffer;
DWORD dwBufSize;
} SPDATA_HANDLEMESSAGE, *LPSPDATA_HANDLEMESSAGE;
typedef struct SPDATA_OPEN
{
DWORD dwSize;
LPDPLOBBYSP lpISP;
LPDPSESSIONDESC2 lpsd;
DWORD dwFlags;
LPCDPCREDENTIALS lpCredentials;
} SPDATA_OPEN, *LPSPDATA_OPEN;
typedef struct SPDATA_SEND
{
DWORD dwSize;
LPDPLOBBYSP lpISP;
DWORD dwFromID;
DWORD dwToID;
DWORD dwFlags;
LPVOID lpBuffer;
DWORD dwBufSize;
} SPDATA_SEND, *LPSPDATA_SEND;
typedef struct SPDATA_CHATMESSAGE
{
DWORD dwSize;
LPDPLOBBYSP lpISP;
DWORD dwFromID;
DWORD dwToID;
DWORD dwFlags;
LPDPCHAT lpChat;
} SPDATA_CHATMESSAGE, *LPSPDATA_CHATMESSAGE;
typedef struct SPDATA_SETGROUPCONNECTIONSETTINGS
{
DWORD dwSize;
DWORD dwFlags;
LPDPLOBBYSP lpISP;
DWORD dwGroupID;
LPDPLCONNECTION lpConn;
} SPDATA_SETGROUPCONNECTIONSETTINGS, *LPSPDATA_SETGROUPCONNECTIONSETTINGS;
typedef struct SPDATA_SETGROUPDATA
{
DWORD dwSize;
LPDPLOBBYSP lpISP;
DWORD dwGroupID;
LPVOID lpData;
DWORD dwDataSize;
DWORD dwFlags;
} SPDATA_SETGROUPDATA, *LPSPDATA_SETGROUPDATA;
typedef struct SPDATA_SETGROUPNAME
{
DWORD dwSize;
LPDPLOBBYSP lpISP;
DWORD dwGroupID;
LPDPNAME lpName;
DWORD dwFlags;
} SPDATA_SETGROUPNAME, *LPSPDATA_SETGROUPNAME;
typedef struct SPDATA_SETREMOTEGROUPNAME
{
DWORD dwSize;
LPDPLOBBYSP lpISP;
DWORD dwGroupID;
LPDPNAME lpName;
DWORD dwFlags;
} SPDATA_SETREMOTEGROUPNAME, *LPSPDATA_SETREMOTEGROUPNAME;
typedef struct SPDATA_SETPLAYERDATA
{
DWORD dwSize;
LPDPLOBBYSP lpISP;
DWORD dwPlayerID;
LPVOID lpData;
DWORD dwDataSize;
DWORD dwFlags;
} SPDATA_SETPLAYERDATA, *LPSPDATA_SETPLAYERDATA;
typedef struct SPDATA_SETPLAYERNAME
{
DWORD dwSize;
LPDPLOBBYSP lpISP;
DWORD dwPlayerID;
LPDPNAME lpName;
DWORD dwFlags;
} SPDATA_SETPLAYERNAME, *LPSPDATA_SETPLAYERNAME;
typedef struct SPDATA_SETREMOTEPLAYERNAME
{
DWORD dwSize;
LPDPLOBBYSP lpISP;
DWORD dwPlayerID;
LPDPNAME lpName;
DWORD dwFlags;
} SPDATA_SETREMOTEPLAYERNAME, *LPSPDATA_SETREMOTEPLAYERNAME;
typedef struct SPDATA_SETSESSIONDESC
{
DWORD dwSize;
LPDPSESSIONDESC2 lpsd;
} SPDATA_SETSESSIONDESC, *LPSPDATA_SETSESSIONDESC;
typedef struct SPDATA_SHUTDOWN
{
DWORD dwSize;
LPDPLOBBYSP lpISP;
} SPDATA_SHUTDOWN, *LPSPDATA_SHUTDOWN;
typedef struct SPDATA_STARTSESSION
{
DWORD dwSize;
LPDPLOBBYSP lpISP;
DWORD dwFlags;
DWORD dwGroupID;
} SPDATA_STARTSESSION, *LPSPDATA_STARTSESSION;
typedef struct SPDATA_STARTSESSIONCOMMAND
{
DWORD dwFlags;
DWORD dwGroupID;
DWORD dwHostID;
LPDPLCONNECTION lpConn;
} SPDATA_STARTSESSIONCOMMAND, *LPSPDATA_STARTSESSIONCOMMAND;
/* Prototypes for callbacks returned by DPLSPInit */
typedef HRESULT (WINAPI *LPSP_ADDGROUPTOGROUP)(LPSPDATA_ADDGROUPTOGROUP);
typedef HRESULT (WINAPI *LPSP_ADDPLAYERTOGROUP)(LPSPDATA_ADDPLAYERTOGROUP);
typedef HRESULT (WINAPI *LPSP_BUILDPARENTALHEIRARCHY)(LPSPDATA_BUILDPARENTALHEIRARCHY);
typedef HRESULT (WINAPI *LPSP_CLOSE)(LPSPDATA_CLOSE);
typedef HRESULT (WINAPI *LPSP_CREATEGROUP)(LPSPDATA_CREATEGROUP);
typedef HRESULT (WINAPI *LPSP_CREATEGROUPINGROUP)(LPSPDATA_CREATEGROUPINGROUP);
typedef HRESULT (WINAPI *LPSP_CREATEPLAYER)(LPSPDATA_CREATEPLAYER);
typedef HRESULT (WINAPI *LPSP_DELETEGROUPFROMGROUP)(LPSPDATA_DELETEGROUPFROMGROUP);
typedef HRESULT (WINAPI *LPSP_DELETEPLAYERFROMGROUP)(LPSPDATA_DELETEPLAYERFROMGROUP);
typedef HRESULT (WINAPI *LPSP_DESTROYGROUP)(LPSPDATA_DESTROYGROUP);
typedef HRESULT (WINAPI *LPSP_DESTROYPLAYER)(LPSPDATA_DESTROYPLAYER);
typedef HRESULT (WINAPI *LPSP_ENUMSESSIONS)(LPSPDATA_ENUMSESSIONS);
typedef HRESULT (WINAPI *LPSP_GETCAPS)(LPSPDATA_GETCAPS);
typedef HRESULT (WINAPI *LPSP_GETGROUPCONNECTIONSETTINGS)(LPSPDATA_GETGROUPCONNECTIONSETTINGS);
typedef HRESULT (WINAPI *LPSP_GETGROUPDATA)(LPSPDATA_GETGROUPDATA);
typedef HRESULT (WINAPI *LPSP_GETPLAYERCAPS)(LPSPDATA_GETPLAYERCAPS);
typedef HRESULT (WINAPI *LPSP_GETPLAYERDATA)(LPSPDATA_GETPLAYERDATA);
typedef HRESULT (WINAPI *LPSP_HANDLEMESSAGE)(LPSPDATA_HANDLEMESSAGE);
typedef HRESULT (WINAPI *LPSP_OPEN)(LPSPDATA_OPEN);
typedef HRESULT (WINAPI *LPSP_SEND)(LPSPDATA_SEND);
typedef HRESULT (WINAPI *LPSP_SENDCHATMESSAGE)(LPSPDATA_CHATMESSAGE);
typedef HRESULT (WINAPI *LPSP_SETGROUPCONNECTIONSETTINGS)(LPSPDATA_SETGROUPCONNECTIONSETTINGS);
typedef HRESULT (WINAPI *LPSP_SETGROUPDATA)(LPSPDATA_SETGROUPDATA);
typedef HRESULT (WINAPI *LPSP_SETGROUPNAME)(LPSPDATA_SETGROUPNAME);
typedef HRESULT (WINAPI *LPSP_SETPLAYERDATA)(LPSPDATA_SETPLAYERDATA);
typedef HRESULT (WINAPI *LPSP_SETPLAYERNAME)(LPSPDATA_SETPLAYERNAME);
typedef HRESULT (WINAPI *LPSP_SHUTDOWN)(LPSPDATA_SHUTDOWN);
typedef HRESULT (WINAPI *LPSP_STARTSESSION)(LPSPDATA_STARTSESSION);
/* Callback table for dplay to call into service provider */
typedef struct SP_CALLBACKS
{
DWORD dwSize;
DWORD dwFlags;
LPSP_ADDGROUPTOGROUP AddGroupToGroup;
LPSP_ADDPLAYERTOGROUP AddPlayerToGroup;
LPSP_BUILDPARENTALHEIRARCHY BuildParentalHeirarchy;
LPSP_CLOSE Close;
LPSP_CREATEGROUP CreateGroup;
LPSP_CREATEGROUPINGROUP CreateGroupInGroup;
LPSP_CREATEPLAYER CreatePlayer;
LPSP_DELETEGROUPFROMGROUP DeleteGroupFromGroup;
LPSP_DELETEPLAYERFROMGROUP DeletePlayerFromGroup;
LPSP_DESTROYGROUP DestroyGroup;
LPSP_DESTROYPLAYER DestroyPlayer;
LPSP_ENUMSESSIONS EnumSessions;
LPSP_GETCAPS GetCaps;
LPSP_GETGROUPCONNECTIONSETTINGS GetGroupConnectionSettings;
LPSP_GETGROUPDATA GetGroupData;
LPSP_GETPLAYERCAPS GetPlayerCaps;
LPSP_GETPLAYERDATA GetPlayerData;
LPSP_OPEN Open;
LPSP_SEND Send;
LPSP_SENDCHATMESSAGE SendChatMessage;
LPSP_SETGROUPCONNECTIONSETTINGS SetGroupConnectionSettings;
LPSP_SETGROUPDATA SetGroupData;
LPSP_SETGROUPNAME SetGroupName;
LPSP_SETPLAYERDATA SetPlayerData;
LPSP_SETPLAYERNAME SetPlayerName;
LPSP_SHUTDOWN Shutdown;
LPSP_STARTSESSION StartSession;
} SP_CALLBACKS, *LPSP_CALLBACKS;
typedef struct SPDATA_INIT
{
LPSP_CALLBACKS lpCB;
DWORD dwSPVersion;
LPDPLOBBYSP lpISP;
LPDPADDRESS lpAddress;
} SPDATA_INIT, *LPSPDATA_INIT;
typedef HRESULT (WINAPI *LPSP_INIT)(LPSPDATA_INIT);
HRESULT WINAPI DPLSPInit(LPSPDATA_INIT);
/* Define the COM interface */
#define INTERFACE IDPLobbySP
DECLARE_INTERFACE_(IDPLobbySP,IUnknown)
{
/*** IUnknown methods ***/
STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE;
STDMETHOD_(ULONG,AddRef)(THIS) PURE;
STDMETHOD_(ULONG,Release)(THIS) PURE;
/*** IDPLobbySP methods ***/
STDMETHOD(AddGroupToGroup)(THIS_ LPSPDATA_ADDREMOTEGROUPTOGROUP argtg ) PURE;
STDMETHOD(AddPlayerToGroup)(THIS_ LPSPDATA_ADDREMOTEPLAYERTOGROUP arptg ) PURE;
STDMETHOD(CreateGroup)(THIS_ LPSPDATA_CREATEREMOTEGROUP crg ) PURE;
STDMETHOD(CreateGroupInGroup)(THIS_ LPSPDATA_CREATEREMOTEGROUPINGROUP crgig ) PURE;
STDMETHOD(DeleteGroupFromGroup)(THIS_ LPSPDATA_DELETEREMOTEGROUPFROMGROUP drgfg ) PURE;
STDMETHOD(DeletePlayerFromGroup)(THIS_ LPSPDATA_DELETEREMOTEPLAYERFROMGROUP drpfg ) PURE;
STDMETHOD(DestroyGroup)(THIS_ LPSPDATA_DESTROYREMOTEGROUP drg ) PURE;
STDMETHOD(EnumSessionsResponse)(THIS_ LPSPDATA_ENUMSESSIONSRESPONSE er ) PURE;
STDMETHOD(GetSPDataPointer)(THIS_ LPVOID * lplpData ) PURE;
STDMETHOD(HandleMessage)(THIS_ LPSPDATA_HANDLEMESSAGE hm ) PURE;
STDMETHOD(SendChatMessage)(THIS_ LPSPDATA_CHATMESSAGE cm ) PURE;
STDMETHOD(SetGroupName)(THIS_ LPSPDATA_SETREMOTEGROUPNAME srgn ) PURE;
STDMETHOD(SetPlayerName)(THIS_ LPSPDATA_SETREMOTEPLAYERNAME srpn ) PURE;
STDMETHOD(SetSessionDesc)(THIS_ LPSPDATA_SETSESSIONDESC ssd ) PURE;
STDMETHOD(SetSPDataPointer)(THIS_ LPVOID lpData ) PURE;
STDMETHOD(StartSession)(THIS_ LPSPDATA_STARTSESSIONCOMMAND ssc ) PURE;
};
#undef INTERFACE
#if !defined (__cplusplus) || defined(CINTERFACE)
/*** IUnknown methods ***/
#define IDPLobbySP_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
#define IDPLobbySP_AddRef(p) (p)->lpVtbl->AddRef(p)
#define IDPLobbySP_Release(p) (p)->lpVtbl->Release(p)
/*** IDPLobbySP methods ***/
#define IDPLobbySP_AddGroupToGroup(p,a) (p)->lpVtbl->AddGroupToGroup(p,a)
#define IDPLobbySP_AddPlayerToGroup(p,a) (p)->lpVtbl->AddPlayerToGroup(p,a)
#define IDPLobbySP_CreateGroup(p,a) (p)->lpVtbl->CreateGroup(p,a)
#define IDPLobbySP_CreateGroupInGroup(p,a) (p)->lpVtbl->CreateGroupInGroup(p,a)
#define IDPLobbySP_DeleteGroupFromGroup(p,a) (p)->lpVtbl->DeleteGroupFromGroup(p,a)
#define IDPLobbySP_DeletePlayerFromGroup(p,a) (p)->lpVtbl->DeletePlayerFromGroup(p,a)
#define IDPLobbySP_DestroyGroup(p,a) (p)->lpVtbl->DestroyGroup(p,a)
#define IDPLobbySP_EnumSessionsResponse(p,a) (p)->lpVtbl->EnumSessionsResponse(p,a)
#define IDPLobbySP_GetSPDataPointer(p,a) (p)->lpVtbl->GetSPDataPointer(p,a)
#define IDPLobbySP_HandleMessage(p,a) (p)->lpVtbl->HandleMessage(p,a)
#define IDPLobbySP_SetGroupName(p,a) (p)->lpVtbl->SetGroupName(p,a)
#define IDPLobbySP_SetPlayerName(p,a) (p)->lpVtbl->SetPlayerName(p,a)
#define IDPLobbySP_SetSessionDesc(p,a) (p)->lpVtbl->SetSessionDesc(p,a)
#define IDPLobbySP_StartSession(p,a) (p)->lpVtbl->StartSession(p,a)
#define IDPLobbySP_SetSPDataPointer(p,a) (p)->lpVtbl->SetSPDataPointer(p,a)
#endif
/* This variable is exported from the DLL at ordinal 6 to be accessed by the
* SP directly. This is the same variable that the DP SP will use.
*/
extern DWORD gdwDPlaySPRefCount;
#endif

View file

@ -0,0 +1,425 @@
/* DPLAYX.DLL name server implementation
*
* Copyright 2000-2001 - Peter Hunnisett
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* NOTE: Methods with the NS_ prefix are name server methods */
#include <stdarg.h>
#include <string.h>
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
#include "windef.h"
#include "winbase.h"
#include "winnls.h"
#include "wine/unicode.h"
#include "wine/debug.h"
#include "mmsystem.h"
#include "dplayx_global.h"
#include "name_server.h"
#include "dplaysp.h"
#include "dplayx_messages.h"
#include "dplayx_queue.h"
/* FIXME: Need to create a crit section, store and use it */
WINE_DEFAULT_DEBUG_CHANNEL(dplay);
/* NS specific structures */
struct NSCacheData
{
DPQ_ENTRY(NSCacheData) next;
DWORD dwTime; /* Time at which data was last known valid */
LPDPSESSIONDESC2 data;
LPVOID lpNSAddrHdr;
};
typedef struct NSCacheData NSCacheData, *lpNSCacheData;
struct NSCache
{
lpNSCacheData present; /* keep track of what is to be looked at when walking */
DPQ_HEAD(NSCacheData) first;
BOOL bNsIsLocal;
LPVOID lpLocalAddrHdr; /* FIXME: Not yet used */
LPVOID lpRemoteAddrHdr; /* FIXME: Not yet used */
};
typedef struct NSCache NSCache, *lpNSCache;
/* Function prototypes */
DPQ_DECL_DELETECB( cbDeleteNSNodeFromHeap, lpNSCacheData );
/* Name Server functions
* ---------------------
*/
void NS_SetLocalComputerAsNameServer( LPCDPSESSIONDESC2 lpsd, LPVOID lpNSInfo )
{
#if 0
/* FIXME: Remove this method? */
DPLAYX_SetLocalSession( lpsd );
#endif
lpNSCache lpCache = (lpNSCache)lpNSInfo;
lpCache->bNsIsLocal = TRUE;
}
void NS_SetRemoteComputerAsNameServer( LPCDPSESSIONDESC2 lpsd, LPVOID lpNSInfo )
{
lpNSCache lpCache = (lpNSCache)lpNSInfo;
lpCache->bNsIsLocal = FALSE;
}
static DPQ_DECL_COMPARECB( cbUglyPig, GUID )
{
return IsEqualGUID( elem1, elem2 );
}
/* Store the given NS remote address for future reference */
/* FIXME: LPDPMSG_ENUMSESSIONSREPLY should be const */
void NS_AddRemoteComputerAsNameServer( LPCVOID lpcNSAddrHdr,
DWORD dwHdrSize,
LPDPMSG_ENUMSESSIONSREPLY lpMsg,
LPVOID lpNSInfo )
{
DWORD len;
lpNSCache lpCache = (lpNSCache)lpNSInfo;
lpNSCacheData lpCacheNode;
TRACE( "%p, %p, %p\n", lpcNSAddrHdr, lpMsg, lpNSInfo );
/* See if we can find this session. If we can, remove it as it's a dup */
DPQ_REMOVE_ENTRY_CB( lpCache->first, next, data->guidInstance, cbUglyPig,
lpMsg->sd.guidInstance, lpCacheNode );
if( lpCacheNode != NULL )
{
TRACE( "Duplicate session entry for %s removed - updated version kept\n",
debugstr_guid( &lpCacheNode->data->guidInstance ) );
cbDeleteNSNodeFromHeap( lpCacheNode );
}
/* Add this to the list */
lpCacheNode = 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, lpcNSAddrHdr, dwHdrSize );
lpCacheNode->data = 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 ) );
len = WideCharToMultiByte( CP_ACP, 0, (LPWSTR)(lpMsg+1), -1, NULL, 0, NULL, NULL );
if ((lpCacheNode->data->lpszSessionNameA = HeapAlloc( GetProcessHeap(), 0, len )))
{
WideCharToMultiByte( CP_ACP, 0, (LPWSTR)(lpMsg+1), -1,
lpCacheNode->data->lpszSessionNameA, len, NULL, NULL );
}
lpCacheNode->dwTime = timeGetTime();
DPQ_INSERT(lpCache->first, lpCacheNode, next );
lpCache->present = lpCacheNode;
/* Use this message as an opportunity 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?
* This is going to have to go into dplay somehow. Perhaps it
* comes back with app server id for the join command! Oh...that
* must be it. That would make this method obsolete once that's
* in place.
*/
#if 1
return lpCache->first.lpQHFirst->lpNSAddrHdr;
#else
/* FIXME: Should convert over to this */
return lpCache->bNsIsLocal ? lpCache->lpLocalAddrHdr
: lpCache->lpRemoteAddrHdr;
#endif
}
/* Get the magic number associated with the Name Server */
DWORD NS_GetNsMagic( LPVOID lpNSInfo )
{
LPDWORD lpHdrInfo = (LPDWORD)NS_GetNSAddr( lpNSInfo );
return lpHdrInfo[1];
}
/* Get the magic number associated with the non NS end */
DWORD NS_GetOtherMagic( LPVOID lpNSInfo )
{
lpNSCache lpCache = (lpNSCache)lpNSInfo;
return ((LPDWORD)lpCache->lpLocalAddrHdr)[1];
}
void NS_SetLocalAddr( LPVOID lpNSInfo, LPCVOID lpHdr, DWORD dwHdrSize )
{
lpNSCache lpCache = (lpNSCache)lpNSInfo;
lpCache->lpLocalAddrHdr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwHdrSize );
CopyMemory( lpCache->lpLocalAddrHdr, lpHdr, dwHdrSize );
}
/* This function is responsible for sending a request for all other known
nameservers to send us what sessions they have registered locally
*/
HRESULT NS_SendSessionRequestBroadcast( LPCGUID lpcGuid,
DWORD dwFlags,
LPSPINITDATA lpSpData )
{
DPSP_ENUMSESSIONSDATA data;
LPDPMSG_ENUMSESSIONSREQUEST lpMsg;
TRACE( "enumerating for guid %s\n", debugstr_guid( lpcGuid ) );
/* Get the SP to deal with sending the EnumSessions request */
FIXME( ": not all data fields are correct\n" );
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;
lpMsg = (LPDPMSG_ENUMSESSIONSREQUEST)(((BYTE*)data.lpMessage)+lpSpData->dwSPHeaderSize);
/* Setup EnumSession request 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 );
}
/* Delete a name server node which has been allocated on the heap */
DPQ_DECL_DELETECB( cbDeleteNSNodeFromHeap, lpNSCacheData )
{
/* NOTE: This proc doesn't deal with the walking pointer */
/* 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 nonexistent cache\n" );
return;
}
DPQ_DELETEQ( lpCache->first, next, lpNSCacheData, cbDeleteNSNodeFromHeap );
/* NULL out the walking pointer */
lpCache->present = NULL;
lpCache->bNsIsLocal = FALSE;
}
/* Create and initialize a session cache */
BOOL NS_InitializeSessionCache( LPVOID* lplpNSInfo )
{
lpNSCache lpCache = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpCache ) );
*lplpNSInfo = lpCache;
if( lpCache == NULL )
{
return FALSE;
}
DPQ_INIT(lpCache->first);
lpCache->present = NULL;
lpCache->bNsIsLocal = FALSE;
return TRUE;
}
/* Delete a session cache */
void NS_DeleteSessionCache( LPVOID lpNSInfo )
{
NS_InvalidateSessionCache( (lpNSCache)lpNSInfo );
}
/* Reinitialize the present pointer for this cache */
void NS_ResetSessionEnumeration( LPVOID lpNSInfo )
{
((lpNSCache)lpNSInfo)->present = ((lpNSCache)lpNSInfo)->first.lpQHFirst;
}
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 )
{
return NULL;
}
lpSessionDesc = lpCache->present->data;
/* Advance tracking pointer */
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.
*/
/* FIXME: This needs to be called by some periodic timer */
void NS_PruneSessionCache( LPVOID lpNSInfo )
{
lpNSCache lpCache = lpNSInfo;
const DWORD dwPresentTime = timeGetTime();
const DWORD dwPrunePeriod = DPMSG_WAIT_60_SECS; /* is 60 secs enough? */
/* This silly little algorithm is based on the fact we keep entries in
* the queue in a time based order. It also assumes that it is not possible
* to wrap around over yourself (which is not unreasonable).
* The if statements verify if the first entry in the queue is less
* than dwPrunePeriod old depending on the "clock" roll over.
*/
for( ;; )
{
lpNSCacheData lpFirstData;
if( DPQ_IS_EMPTY(lpCache->first) )
{
/* Nothing to prune */
break;
}
/* Deal with time in a wrap around safe manner - unsigned arithmetic.
* Check the difference in time */
if( (dwPresentTime - (DPQ_FIRST(lpCache->first)->dwTime)) < dwPrunePeriod )
{
/* First entry has not expired yet; don't prune */
break;
}
lpFirstData = DPQ_FIRST(lpCache->first);
DPQ_REMOVE( lpCache->first, DPQ_FIRST(lpCache->first), next );
cbDeleteNSNodeFromHeap( lpFirstData );
}
}
/* NAME SERVER Message stuff */
void NS_ReplyToEnumSessionsRequest( LPCVOID lpcMsg,
LPVOID* lplpReplyData,
LPDWORD lpdwReplySize,
IDirectPlay2Impl* lpDP )
{
LPDPMSG_ENUMSESSIONSREPLY rmsg;
DWORD dwVariableSize;
DWORD dwVariableLen;
/* LPCDPMSG_ENUMSESSIONSREQUEST msg = (LPDPMSG_ENUMSESSIONSREQUEST)lpcMsg; */
BOOL bAnsi = TRUE; /* FIXME: This needs to be in the DPLAY interface */
FIXME( ": few fixed + need to check request for response\n" );
if (bAnsi)
{
dwVariableLen = MultiByteToWideChar( CP_ACP, 0,
lpDP->dp2->lpSessionDesc->lpszSessionNameA,
-1, NULL, 0 );
}
else
{
dwVariableLen = strlenW( lpDP->dp2->lpSessionDesc->lpszSessionName ) + 1;
}
dwVariableSize = dwVariableLen * sizeof( WCHAR );
*lpdwReplySize = lpDP->dp2->spData.dwSPHeaderSize +
sizeof( *rmsg ) + dwVariableSize;
*lplpReplyData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
*lpdwReplySize );
rmsg = (LPDPMSG_ENUMSESSIONSREPLY)( (BYTE*)*lplpReplyData +
lpDP->dp2->spData.dwSPHeaderSize);
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 )
{
MultiByteToWideChar( CP_ACP, 0, lpDP->dp2->lpSessionDesc->lpszSessionNameA, -1,
(LPWSTR)(rmsg+1), dwVariableLen );
}
else
{
strcpyW( (LPWSTR)(rmsg+1), lpDP->dp2->lpSessionDesc->lpszSessionName );
}
}

View file

@ -0,0 +1,61 @@
/*
* Copyright 2000 Peter Hunnisett
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __WINE_DPLAYX_NAMESERVER
#define __WINE_DPLAYX_NAMESERVER
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "dplay.h"
#include "dplaysp.h"
#include "dplayx_messages.h"
#include "dplay_global.h"
void NS_SetLocalComputerAsNameServer( LPCDPSESSIONDESC2 lpsd, LPVOID lpNSInfo );
void NS_SetRemoteComputerAsNameServer( LPCDPSESSIONDESC2 lpsd, LPVOID lpNSInfo );
void NS_AddRemoteComputerAsNameServer( LPCVOID lpNSAddrHdr,
DWORD dwHdrSize,
LPDPMSG_ENUMSESSIONSREPLY lpMsg,
LPVOID lpNSInfo );
LPVOID NS_GetNSAddr( LPVOID lpNSInfo );
DWORD NS_GetNsMagic( LPVOID lpNSInfo );
DWORD NS_GetOtherMagic( LPVOID lpNSInfo );
void NS_SetLocalAddr( LPVOID lpNSInfo, LPCVOID lpHdr, DWORD dwHdrSize );
void NS_ReplyToEnumSessionsRequest( LPCVOID lpcMsg,
LPVOID* lplpReplyData,
LPDWORD lpdwReplySize,
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 */

556
reactos/lib/dplayx/regsvr.c Normal file
View file

@ -0,0 +1,556 @@
/*
* self-registerable dll functions for dplayx.dll
*
* Copyright (C) 2003 John K. Hohm
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdarg.h>
#include <string.h>
#include "windef.h"
#include "winbase.h"
#include "winuser.h"
#include "winreg.h"
#include "winerror.h"
#include "dplay.h"
#include "dplobby.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(dplayx);
/*
* Near the bottom of this file are the exported DllRegisterServer and
* DllUnregisterServer, which make all this worthwhile.
*/
/***********************************************************************
* interface for self-registering
*/
struct regsvr_interface
{
IID const *iid; /* NULL for end of list */
LPCSTR name; /* can be NULL to omit */
IID const *base_iid; /* can be NULL to omit */
int num_methods; /* can be <0 to omit */
CLSID const *ps_clsid; /* can be NULL to omit */
CLSID const *ps_clsid32; /* can be NULL to omit */
};
static HRESULT register_interfaces(struct regsvr_interface const *list);
static HRESULT unregister_interfaces(struct regsvr_interface const *list);
struct regsvr_coclass
{
CLSID const *clsid; /* NULL for end of list */
LPCSTR name; /* can be NULL to omit */
LPCSTR ips; /* can be NULL to omit */
LPCSTR ips32; /* can be NULL to omit */
LPCSTR ips32_tmodel; /* can be NULL to omit */
LPCSTR progid; /* can be NULL to omit */
LPCSTR viprogid; /* can be NULL to omit */
LPCSTR progid_extra; /* can be NULL to omit */
};
static HRESULT register_coclasses(struct regsvr_coclass const *list);
static HRESULT unregister_coclasses(struct regsvr_coclass const *list);
/***********************************************************************
* static string constants
*/
static WCHAR const interface_keyname[10] = {
'I', 'n', 't', 'e', 'r', 'f', 'a', 'c', 'e', 0 };
static WCHAR const base_ifa_keyname[14] = {
'B', 'a', 's', 'e', 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c',
'e', 0 };
static WCHAR const num_methods_keyname[11] = {
'N', 'u', 'm', 'M', 'e', 't', 'h', 'o', 'd', 's', 0 };
static WCHAR const ps_clsid_keyname[15] = {
'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
'i', 'd', 0 };
static WCHAR const ps_clsid32_keyname[17] = {
'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
'i', 'd', '3', '2', 0 };
static WCHAR const clsid_keyname[6] = {
'C', 'L', 'S', 'I', 'D', 0 };
static WCHAR const curver_keyname[7] = {
'C', 'u', 'r', 'V', 'e', 'r', 0 };
static WCHAR const ips_keyname[13] = {
'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
0 };
static WCHAR const ips32_keyname[15] = {
'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
'3', '2', 0 };
static WCHAR const progid_keyname[7] = {
'P', 'r', 'o', 'g', 'I', 'D', 0 };
static WCHAR const viprogid_keyname[25] = {
'V', 'e', 'r', 's', 'i', 'o', 'n', 'I', 'n', 'd', 'e', 'p',
'e', 'n', 'd', 'e', 'n', 't', 'P', 'r', 'o', 'g', 'I', 'D',
0 };
static char const tmodel_valuename[] = "ThreadingModel";
/***********************************************************************
* static helper functions
*/
static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid);
static LONG register_key_defvalueW(HKEY base, WCHAR const *name,
WCHAR const *value);
static LONG register_key_defvalueA(HKEY base, WCHAR const *name,
char const *value);
static LONG register_progid(WCHAR const *clsid,
char const *progid, char const *curver_progid,
char const *name, char const *extra);
static LONG recursive_delete_key(HKEY key);
static LONG recursive_delete_keyA(HKEY base, char const *name);
static LONG recursive_delete_keyW(HKEY base, WCHAR const *name);
/***********************************************************************
* register_interfaces
*/
static HRESULT register_interfaces(struct regsvr_interface const *list)
{
LONG res = ERROR_SUCCESS;
HKEY interface_key;
res = RegCreateKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0, NULL, 0,
KEY_READ | KEY_WRITE, NULL, &interface_key, NULL);
if (res != ERROR_SUCCESS) goto error_return;
for (; res == ERROR_SUCCESS && list->iid; ++list) {
WCHAR buf[39];
HKEY iid_key;
StringFromGUID2(list->iid, buf, 39);
res = RegCreateKeyExW(interface_key, buf, 0, NULL, 0,
KEY_READ | KEY_WRITE, NULL, &iid_key, NULL);
if (res != ERROR_SUCCESS) goto error_close_interface_key;
if (list->name) {
res = RegSetValueExA(iid_key, NULL, 0, REG_SZ,
(CONST BYTE*)(list->name),
strlen(list->name) + 1);
if (res != ERROR_SUCCESS) goto error_close_iid_key;
}
if (list->base_iid) {
register_key_guid(iid_key, base_ifa_keyname, list->base_iid);
if (res != ERROR_SUCCESS) goto error_close_iid_key;
}
if (0 <= list->num_methods) {
static WCHAR const fmt[3] = { '%', 'd', 0 };
HKEY key;
res = RegCreateKeyExW(iid_key, num_methods_keyname, 0, NULL, 0,
KEY_READ | KEY_WRITE, NULL, &key, NULL);
if (res != ERROR_SUCCESS) goto error_close_iid_key;
wsprintfW(buf, fmt, list->num_methods);
res = RegSetValueExW(key, NULL, 0, REG_SZ,
(CONST BYTE*)buf,
(lstrlenW(buf) + 1) * sizeof(WCHAR));
RegCloseKey(key);
if (res != ERROR_SUCCESS) goto error_close_iid_key;
}
if (list->ps_clsid) {
register_key_guid(iid_key, ps_clsid_keyname, list->ps_clsid);
if (res != ERROR_SUCCESS) goto error_close_iid_key;
}
if (list->ps_clsid32) {
register_key_guid(iid_key, ps_clsid32_keyname, list->ps_clsid32);
if (res != ERROR_SUCCESS) goto error_close_iid_key;
}
error_close_iid_key:
RegCloseKey(iid_key);
}
error_close_interface_key:
RegCloseKey(interface_key);
error_return:
return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
}
/***********************************************************************
* unregister_interfaces
*/
static HRESULT unregister_interfaces(struct regsvr_interface const *list)
{
LONG res = ERROR_SUCCESS;
HKEY interface_key;
res = RegOpenKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0,
KEY_READ | KEY_WRITE, &interface_key);
if (res == ERROR_FILE_NOT_FOUND) return S_OK;
if (res != ERROR_SUCCESS) goto error_return;
for (; res == ERROR_SUCCESS && list->iid; ++list) {
WCHAR buf[39];
StringFromGUID2(list->iid, buf, 39);
res = recursive_delete_keyW(interface_key, buf);
}
RegCloseKey(interface_key);
error_return:
return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
}
/***********************************************************************
* register_coclasses
*/
static HRESULT register_coclasses(struct regsvr_coclass const *list)
{
LONG res = ERROR_SUCCESS;
HKEY coclass_key;
res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
if (res != ERROR_SUCCESS) goto error_return;
for (; res == ERROR_SUCCESS && list->clsid; ++list) {
WCHAR buf[39];
HKEY clsid_key;
StringFromGUID2(list->clsid, buf, 39);
res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
if (res != ERROR_SUCCESS) goto error_close_coclass_key;
if (list->name) {
res = RegSetValueExA(clsid_key, NULL, 0, REG_SZ,
(CONST BYTE*)(list->name),
strlen(list->name) + 1);
if (res != ERROR_SUCCESS) goto error_close_clsid_key;
}
if (list->ips) {
res = register_key_defvalueA(clsid_key, ips_keyname, list->ips);
if (res != ERROR_SUCCESS) goto error_close_clsid_key;
}
if (list->ips32) {
HKEY ips32_key;
res = RegCreateKeyExW(clsid_key, ips32_keyname, 0, NULL, 0,
KEY_READ | KEY_WRITE, NULL,
&ips32_key, NULL);
if (res != ERROR_SUCCESS) goto error_close_clsid_key;
res = RegSetValueExA(ips32_key, NULL, 0, REG_SZ,
(CONST BYTE*)list->ips32,
lstrlenA(list->ips32) + 1);
if (res == ERROR_SUCCESS && list->ips32_tmodel)
res = RegSetValueExA(ips32_key, tmodel_valuename, 0, REG_SZ,
(CONST BYTE*)list->ips32_tmodel,
strlen(list->ips32_tmodel) + 1);
RegCloseKey(ips32_key);
if (res != ERROR_SUCCESS) goto error_close_clsid_key;
}
if (list->progid) {
res = register_key_defvalueA(clsid_key, progid_keyname,
list->progid);
if (res != ERROR_SUCCESS) goto error_close_clsid_key;
res = register_progid(buf, list->progid, NULL,
list->name, list->progid_extra);
if (res != ERROR_SUCCESS) goto error_close_clsid_key;
}
if (list->viprogid) {
res = register_key_defvalueA(clsid_key, viprogid_keyname,
list->viprogid);
if (res != ERROR_SUCCESS) goto error_close_clsid_key;
res = register_progid(buf, list->viprogid, list->progid,
list->name, list->progid_extra);
if (res != ERROR_SUCCESS) goto error_close_clsid_key;
}
error_close_clsid_key:
RegCloseKey(clsid_key);
}
error_close_coclass_key:
RegCloseKey(coclass_key);
error_return:
return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
}
/***********************************************************************
* unregister_coclasses
*/
static HRESULT unregister_coclasses(struct regsvr_coclass const *list)
{
LONG res = ERROR_SUCCESS;
HKEY coclass_key;
res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
KEY_READ | KEY_WRITE, &coclass_key);
if (res == ERROR_FILE_NOT_FOUND) return S_OK;
if (res != ERROR_SUCCESS) goto error_return;
for (; res == ERROR_SUCCESS && list->clsid; ++list) {
WCHAR buf[39];
StringFromGUID2(list->clsid, buf, 39);
res = recursive_delete_keyW(coclass_key, buf);
if (res != ERROR_SUCCESS) goto error_close_coclass_key;
if (list->progid) {
res = recursive_delete_keyA(HKEY_CLASSES_ROOT, list->progid);
if (res != ERROR_SUCCESS) goto error_close_coclass_key;
}
if (list->viprogid) {
res = recursive_delete_keyA(HKEY_CLASSES_ROOT, list->viprogid);
if (res != ERROR_SUCCESS) goto error_close_coclass_key;
}
}
error_close_coclass_key:
RegCloseKey(coclass_key);
error_return:
return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
}
/***********************************************************************
* regsvr_key_guid
*/
static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid)
{
WCHAR buf[39];
StringFromGUID2(guid, buf, 39);
return register_key_defvalueW(base, name, buf);
}
/***********************************************************************
* regsvr_key_defvalueW
*/
static LONG register_key_defvalueW(
HKEY base,
WCHAR const *name,
WCHAR const *value)
{
LONG res;
HKEY key;
res = RegCreateKeyExW(base, name, 0, NULL, 0,
KEY_READ | KEY_WRITE, NULL, &key, NULL);
if (res != ERROR_SUCCESS) return res;
res = RegSetValueExW(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
(lstrlenW(value) + 1) * sizeof(WCHAR));
RegCloseKey(key);
return res;
}
/***********************************************************************
* regsvr_key_defvalueA
*/
static LONG register_key_defvalueA(
HKEY base,
WCHAR const *name,
char const *value)
{
LONG res;
HKEY key;
res = RegCreateKeyExW(base, name, 0, NULL, 0,
KEY_READ | KEY_WRITE, NULL, &key, NULL);
if (res != ERROR_SUCCESS) return res;
res = RegSetValueExA(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
lstrlenA(value) + 1);
RegCloseKey(key);
return res;
}
/***********************************************************************
* regsvr_progid
*/
static LONG register_progid(
WCHAR const *clsid,
char const *progid,
char const *curver_progid,
char const *name,
char const *extra)
{
LONG res;
HKEY progid_key;
res = RegCreateKeyExA(HKEY_CLASSES_ROOT, progid, 0,
NULL, 0, KEY_READ | KEY_WRITE, NULL,
&progid_key, NULL);
if (res != ERROR_SUCCESS) return res;
if (name) {
res = RegSetValueExA(progid_key, NULL, 0, REG_SZ,
(CONST BYTE*)name, strlen(name) + 1);
if (res != ERROR_SUCCESS) goto error_close_progid_key;
}
if (clsid) {
res = register_key_defvalueW(progid_key, clsid_keyname, clsid);
if (res != ERROR_SUCCESS) goto error_close_progid_key;
}
if (curver_progid) {
res = register_key_defvalueA(progid_key, curver_keyname,
curver_progid);
if (res != ERROR_SUCCESS) goto error_close_progid_key;
}
if (extra) {
HKEY extra_key;
res = RegCreateKeyExA(progid_key, extra, 0,
NULL, 0, KEY_READ | KEY_WRITE, NULL,
&extra_key, NULL);
if (res == ERROR_SUCCESS)
RegCloseKey(extra_key);
}
error_close_progid_key:
RegCloseKey(progid_key);
return res;
}
/***********************************************************************
* recursive_delete_key
*/
static LONG recursive_delete_key(HKEY key)
{
LONG res;
WCHAR subkey_name[MAX_PATH];
DWORD cName;
HKEY subkey;
for (;;) {
cName = sizeof(subkey_name) / sizeof(WCHAR);
res = RegEnumKeyExW(key, 0, subkey_name, &cName,
NULL, NULL, NULL, NULL);
if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) {
res = ERROR_SUCCESS; /* presumably we're done enumerating */
break;
}
res = RegOpenKeyExW(key, subkey_name, 0,
KEY_READ | KEY_WRITE, &subkey);
if (res == ERROR_FILE_NOT_FOUND) continue;
if (res != ERROR_SUCCESS) break;
res = recursive_delete_key(subkey);
RegCloseKey(subkey);
if (res != ERROR_SUCCESS) break;
}
if (res == ERROR_SUCCESS) res = RegDeleteKeyW(key, 0);
return res;
}
/***********************************************************************
* recursive_delete_keyA
*/
static LONG recursive_delete_keyA(HKEY base, char const *name)
{
LONG res;
HKEY key;
res = RegOpenKeyExA(base, name, 0, KEY_READ | KEY_WRITE, &key);
if (res == ERROR_FILE_NOT_FOUND) return ERROR_SUCCESS;
if (res != ERROR_SUCCESS) return res;
res = recursive_delete_key(key);
RegCloseKey(key);
return res;
}
/***********************************************************************
* recursive_delete_keyW
*/
static LONG recursive_delete_keyW(HKEY base, WCHAR const *name)
{
LONG res;
HKEY key;
res = RegOpenKeyExW(base, name, 0, KEY_READ | KEY_WRITE, &key);
if (res == ERROR_FILE_NOT_FOUND) return ERROR_SUCCESS;
if (res != ERROR_SUCCESS) return res;
res = recursive_delete_key(key);
RegCloseKey(key);
return res;
}
/***********************************************************************
* coclass list
*/
static struct regsvr_coclass const coclass_list[] = {
{ &CLSID_DirectPlay,
"DirectPlay Object",
NULL,
"dplayx.dll",
"Both"
},
{ &CLSID_DirectPlayLobby,
"DirectPlayLobby Object",
NULL,
"dplayx.dll",
"Both"
},
{ NULL } /* list terminator */
};
/***********************************************************************
* interface list
*/
static struct regsvr_interface const interface_list[] = {
{ NULL } /* list terminator */
};
/***********************************************************************
* DllRegisterServer (DPLAYX.@)
*/
HRESULT WINAPI DllRegisterServer(void)
{
HRESULT hr;
TRACE("\n");
hr = register_coclasses(coclass_list);
if (SUCCEEDED(hr))
hr = register_interfaces(interface_list);
return hr;
}
/***********************************************************************
* DllUnregisterServer (DPLAYX.@)
*/
HRESULT WINAPI DllUnregisterServer(void)
{
HRESULT hr;
TRACE("\n");
hr = unregister_coclasses(coclass_list);
if (SUCCEEDED(hr))
hr = unregister_interfaces(interface_list);
return hr;
}

View file

@ -0,0 +1,27 @@
/*
* Copyright 2001 Ove Kaaven
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#define WINE_OLESELFREGISTER
#define WINE_FILEDESCRIPTION_STR "Wine DirectPlay"
#define WINE_FILENAME_STR "dplayx.dll"
#define WINE_FILEVERSION 5,3,0,900
#define WINE_FILEVERSION_STR "5.3.0.900"
#define WINE_PRODUCTVERSION 5,3,0,900
#define WINE_PRODUCTVERSION_STR "5.3"
#include "wine/wine_common_ver.rc"