2123 lines
74 KiB
C
2123 lines
74 KiB
C
/* Direct Play Lobby 2 & 3 Implementation
|
|
*
|
|
* Copyright 1998,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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
*/
|
|
#include <stdarg.h>
|
|
#include <string.h>
|
|
|
|
#define COBJMACROS
|
|
#define NONAMELESSUNION
|
|
|
|
#include "windef.h"
|
|
#include "winbase.h"
|
|
#include "winerror.h"
|
|
#include "winreg.h"
|
|
#include "winnls.h"
|
|
#include "wine/debug.h"
|
|
|
|
#include "dplayx_global.h"
|
|
#include "dplayx_messages.h"
|
|
#include "dplayx_queue.h"
|
|
#include "dplobby.h"
|
|
|
|
WINE_DEFAULT_DEBUG_CHANNEL(dplay);
|
|
|
|
/* Forward declarations for this module helper methods */
|
|
HRESULT DPL_CreateCompoundAddress ( LPCDPCOMPOUNDADDRESSELEMENT lpElements, DWORD dwElementCount,
|
|
LPVOID lpAddress, LPDWORD lpdwAddressSize, BOOL bAnsiInterface )DECLSPEC_HIDDEN;
|
|
|
|
static HRESULT DPL_CreateAddress( REFGUID guidSP, REFGUID guidDataType, LPCVOID lpData, DWORD dwDataSize,
|
|
LPVOID lpAddress, LPDWORD lpdwAddressSize, BOOL bAnsiInterface );
|
|
|
|
|
|
/*****************************************************************************
|
|
* IDirectPlayLobby {1,2,3} implementation structure
|
|
*
|
|
* The philosophy behind this extra pointer dereference is that I wanted to
|
|
* have the same structure for all types of objects without having to do
|
|
* a lot of casting. I also only wanted to implement an interface in the
|
|
* object it was "released" with IUnknown interface being implemented in the 1 version.
|
|
* Of course, with these new interfaces comes the data required to keep the state required
|
|
* by these interfaces. So, basically, the pointers contain the data associated with
|
|
* a release. If you use the data associated with release 3 in a release 2 object, you'll
|
|
* get a run time trap, as that won't have any data.
|
|
*
|
|
*/
|
|
struct DPLMSG
|
|
{
|
|
DPQ_ENTRY( DPLMSG ) msgs; /* Link to next queued message */
|
|
};
|
|
typedef struct DPLMSG* LPDPLMSG;
|
|
|
|
typedef struct IDirectPlayLobbyImpl
|
|
{
|
|
IDirectPlayLobby IDirectPlayLobby_iface;
|
|
IDirectPlayLobbyA IDirectPlayLobbyA_iface;
|
|
IDirectPlayLobby2 IDirectPlayLobby2_iface;
|
|
IDirectPlayLobby2A IDirectPlayLobby2A_iface;
|
|
IDirectPlayLobby3 IDirectPlayLobby3_iface;
|
|
IDirectPlayLobby3A IDirectPlayLobby3A_iface;
|
|
LONG numIfaces; /* "in use interfaces" refcount */
|
|
LONG ref, refA, ref2, ref2A, ref3, ref3A;
|
|
CRITICAL_SECTION lock;
|
|
HKEY cbkeyhack;
|
|
DWORD msgtid;
|
|
DPQ_HEAD( DPLMSG ) msgs; /* List of messages received */
|
|
} IDirectPlayLobbyImpl;
|
|
|
|
static inline IDirectPlayLobbyImpl *impl_from_IDirectPlayLobby( IDirectPlayLobby *iface )
|
|
{
|
|
return CONTAINING_RECORD( iface, IDirectPlayLobbyImpl, IDirectPlayLobby_iface );
|
|
}
|
|
|
|
static inline IDirectPlayLobbyImpl *impl_from_IDirectPlayLobbyA( IDirectPlayLobbyA *iface )
|
|
{
|
|
return CONTAINING_RECORD( iface, IDirectPlayLobbyImpl, IDirectPlayLobbyA_iface );
|
|
}
|
|
|
|
static inline IDirectPlayLobbyImpl *impl_from_IDirectPlayLobby2( IDirectPlayLobby2 *iface )
|
|
{
|
|
return CONTAINING_RECORD( iface, IDirectPlayLobbyImpl, IDirectPlayLobby2_iface );
|
|
}
|
|
|
|
static inline IDirectPlayLobbyImpl *impl_from_IDirectPlayLobby2A( IDirectPlayLobby2A *iface )
|
|
{
|
|
return CONTAINING_RECORD( iface, IDirectPlayLobbyImpl, IDirectPlayLobby2A_iface );
|
|
}
|
|
|
|
static inline IDirectPlayLobbyImpl *impl_from_IDirectPlayLobby3( IDirectPlayLobby3 *iface )
|
|
{
|
|
return CONTAINING_RECORD( iface, IDirectPlayLobbyImpl, IDirectPlayLobby3_iface );
|
|
}
|
|
|
|
static inline IDirectPlayLobbyImpl *impl_from_IDirectPlayLobby3A( IDirectPlayLobby3A *iface )
|
|
{
|
|
return CONTAINING_RECORD( iface, IDirectPlayLobbyImpl, IDirectPlayLobby3A_iface );
|
|
}
|
|
|
|
static void dplobby_destroy(IDirectPlayLobbyImpl *obj)
|
|
{
|
|
if ( obj->msgtid )
|
|
FIXME( "Should kill the msg thread\n" );
|
|
|
|
DPQ_DELETEQ( obj->msgs, msgs, LPDPLMSG, cbDeleteElemFromHeap );
|
|
obj->lock.DebugInfo->Spare[0] = 0;
|
|
DeleteCriticalSection( &obj->lock );
|
|
HeapFree( GetProcessHeap(), 0, obj );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobbyAImpl_QueryInterface( IDirectPlayLobbyA *iface, REFIID riid,
|
|
void **ppv )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobbyA( iface );
|
|
return IDirectPlayLobby_QueryInterface( &This->IDirectPlayLobby3_iface, riid, ppv );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobbyImpl_QueryInterface( IDirectPlayLobby *iface, REFIID riid,
|
|
void **ppv )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby( iface );
|
|
return IDirectPlayLobby_QueryInterface( &This->IDirectPlayLobby3_iface, riid, ppv );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby2AImpl_QueryInterface( IDirectPlayLobby2A *iface, REFIID riid,
|
|
void **ppv )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2A( iface );
|
|
return IDirectPlayLobby_QueryInterface( &This->IDirectPlayLobby3_iface, riid, ppv );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby2Impl_QueryInterface( IDirectPlayLobby2 *iface, REFIID riid,
|
|
void **ppv )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2( iface );
|
|
return IDirectPlayLobby_QueryInterface( &This->IDirectPlayLobby3_iface, riid, ppv );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby3AImpl_QueryInterface( IDirectPlayLobby3A *iface, REFIID riid,
|
|
void **ppv )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3A( iface );
|
|
return IDirectPlayLobby_QueryInterface( &This->IDirectPlayLobby3_iface, riid, ppv );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby3Impl_QueryInterface( IDirectPlayLobby3 *iface, REFIID riid,
|
|
void **ppv )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3( iface );
|
|
|
|
if ( IsEqualGUID( &IID_IUnknown, riid ) )
|
|
{
|
|
TRACE( "(%p)->(IID_IUnknown %p)\n", This, ppv );
|
|
*ppv = &This->IDirectPlayLobby_iface;
|
|
}
|
|
else if ( IsEqualGUID( &IID_IDirectPlayLobby, riid ) )
|
|
{
|
|
TRACE( "(%p)->(IID_IDirectPlayLobby %p)\n", This, ppv );
|
|
*ppv = &This->IDirectPlayLobby_iface;
|
|
}
|
|
else if ( IsEqualGUID( &IID_IDirectPlayLobbyA, riid ) )
|
|
{
|
|
TRACE( "(%p)->(IID_IDirectPlayLobbyA %p)\n", This, ppv );
|
|
*ppv = &This->IDirectPlayLobbyA_iface;
|
|
}
|
|
else if ( IsEqualGUID( &IID_IDirectPlayLobby2, riid ) )
|
|
{
|
|
TRACE( "(%p)->(IID_IDirectPlayLobby2 %p)\n", This, ppv );
|
|
*ppv = &This->IDirectPlayLobby2_iface;
|
|
}
|
|
else if ( IsEqualGUID( &IID_IDirectPlayLobby2A, riid ) )
|
|
{
|
|
TRACE( "(%p)->(IID_IDirectPlayLobby2A %p)\n", This, ppv );
|
|
*ppv = &This->IDirectPlayLobby2A_iface;
|
|
}
|
|
else if ( IsEqualGUID( &IID_IDirectPlayLobby3, riid ) )
|
|
{
|
|
TRACE( "(%p)->(IID_IDirectPlay3 %p)\n", This, ppv );
|
|
*ppv = &This->IDirectPlayLobby3_iface;
|
|
}
|
|
else if ( IsEqualGUID( &IID_IDirectPlayLobby3A, riid ) )
|
|
{
|
|
TRACE( "(%p)->(IID_IDirectPlayLobby3A %p)\n", This, ppv );
|
|
*ppv = &This->IDirectPlayLobby3A_iface;
|
|
}
|
|
else
|
|
{
|
|
WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
|
|
*ppv = NULL;
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
IUnknown_AddRef((IUnknown*)*ppv);
|
|
return S_OK;
|
|
}
|
|
|
|
static ULONG WINAPI IDirectPlayLobbyAImpl_AddRef( IDirectPlayLobbyA *iface )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobbyA( iface );
|
|
ULONG ref = InterlockedIncrement( &This->refA );
|
|
|
|
TRACE( "(%p) refA=%d\n", This, ref );
|
|
|
|
if ( ref == 1 )
|
|
InterlockedIncrement( &This->numIfaces );
|
|
|
|
return ref;
|
|
}
|
|
|
|
static ULONG WINAPI IDirectPlayLobbyImpl_AddRef( IDirectPlayLobby *iface )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby( iface );
|
|
ULONG ref = InterlockedIncrement( &This->ref );
|
|
|
|
TRACE( "(%p) ref=%d\n", This, ref );
|
|
|
|
if ( ref == 1 )
|
|
InterlockedIncrement( &This->numIfaces );
|
|
|
|
return ref;
|
|
}
|
|
|
|
static ULONG WINAPI IDirectPlayLobby2AImpl_AddRef(IDirectPlayLobby2A *iface)
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2A( iface );
|
|
ULONG ref = InterlockedIncrement( &This->ref2A );
|
|
|
|
TRACE( "(%p) ref2A=%d\n", This, ref );
|
|
|
|
if ( ref == 1 )
|
|
InterlockedIncrement( &This->numIfaces );
|
|
|
|
return ref;
|
|
}
|
|
|
|
static ULONG WINAPI IDirectPlayLobby2Impl_AddRef(IDirectPlayLobby2 *iface)
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2( iface );
|
|
ULONG ref = InterlockedIncrement( &This->ref2 );
|
|
|
|
TRACE( "(%p) ref2=%d\n", This, ref );
|
|
|
|
if ( ref == 1 )
|
|
InterlockedIncrement( &This->numIfaces );
|
|
|
|
return ref;
|
|
}
|
|
|
|
static ULONG WINAPI IDirectPlayLobby3AImpl_AddRef(IDirectPlayLobby3A *iface)
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3A( iface );
|
|
ULONG ref = InterlockedIncrement( &This->ref3A );
|
|
|
|
TRACE( "(%p) ref3A=%d\n", This, ref );
|
|
|
|
if ( ref == 1 )
|
|
InterlockedIncrement( &This->numIfaces );
|
|
|
|
return ref;
|
|
}
|
|
|
|
static ULONG WINAPI IDirectPlayLobby3Impl_AddRef(IDirectPlayLobby3 *iface)
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3( iface );
|
|
ULONG ref = InterlockedIncrement( &This->ref3 );
|
|
|
|
TRACE( "(%p) ref3=%d\n", This, ref );
|
|
|
|
if ( ref == 1 )
|
|
InterlockedIncrement( &This->numIfaces );
|
|
|
|
return ref;
|
|
}
|
|
|
|
static ULONG WINAPI IDirectPlayLobbyAImpl_Release( IDirectPlayLobbyA *iface )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobbyA( iface );
|
|
ULONG ref = InterlockedDecrement( &This->refA );
|
|
|
|
TRACE( "(%p) refA=%d\n", This, ref );
|
|
|
|
if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
|
|
dplobby_destroy( This );
|
|
|
|
return ref;
|
|
}
|
|
|
|
static ULONG WINAPI IDirectPlayLobbyImpl_Release( IDirectPlayLobby *iface )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby( iface );
|
|
ULONG ref = InterlockedDecrement( &This->ref );
|
|
|
|
TRACE( "(%p) ref=%d\n", This, ref );
|
|
|
|
if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
|
|
dplobby_destroy( This );
|
|
|
|
return ref;
|
|
}
|
|
|
|
static ULONG WINAPI IDirectPlayLobby2AImpl_Release(IDirectPlayLobby2A *iface)
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2A( iface );
|
|
ULONG ref = InterlockedDecrement( &This->ref2A );
|
|
|
|
TRACE( "(%p) ref2A=%d\n", This, ref );
|
|
|
|
if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
|
|
dplobby_destroy( This );
|
|
|
|
return ref;
|
|
}
|
|
|
|
static ULONG WINAPI IDirectPlayLobby2Impl_Release(IDirectPlayLobby2 *iface)
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2( iface );
|
|
ULONG ref = InterlockedDecrement( &This->ref2 );
|
|
|
|
TRACE( "(%p) ref2=%d\n", This, ref );
|
|
|
|
if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
|
|
dplobby_destroy( This );
|
|
|
|
return ref;
|
|
}
|
|
|
|
static ULONG WINAPI IDirectPlayLobby3AImpl_Release(IDirectPlayLobby3A *iface)
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3A( iface );
|
|
ULONG ref = InterlockedDecrement( &This->ref3A );
|
|
|
|
TRACE( "(%p) ref3A=%d\n", This, ref );
|
|
|
|
if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
|
|
dplobby_destroy( This );
|
|
|
|
return ref;
|
|
}
|
|
|
|
static ULONG WINAPI IDirectPlayLobby3Impl_Release(IDirectPlayLobby3 *iface)
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3( iface );
|
|
ULONG ref = InterlockedDecrement( &This->ref3 );
|
|
|
|
TRACE( "(%p) ref3=%d\n", This, ref );
|
|
|
|
if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
|
|
dplobby_destroy( This );
|
|
|
|
return ref;
|
|
}
|
|
|
|
|
|
/********************************************************************
|
|
*
|
|
* Connects an application to the session specified by the DPLCONNECTION
|
|
* structure currently stored with the DirectPlayLobby object.
|
|
*
|
|
* Returns an IDirectPlay interface.
|
|
*
|
|
*/
|
|
static HRESULT DPL_ConnectEx( IDirectPlayLobbyImpl *This, DWORD dwFlags, REFIID riid, void **lplpDP,
|
|
IUnknown* pUnk)
|
|
{
|
|
HRESULT hr;
|
|
DWORD dwOpenFlags = 0;
|
|
DWORD dwConnSize = 0;
|
|
LPDPLCONNECTION lpConn;
|
|
|
|
FIXME("(%p)->(0x%08x,%p,%p): semi stub\n", This, dwFlags, lplpDP, pUnk );
|
|
|
|
if( pUnk )
|
|
{
|
|
return DPERR_INVALIDPARAMS;
|
|
}
|
|
|
|
/* Backwards compatibility */
|
|
if( dwFlags == 0 )
|
|
{
|
|
dwFlags = DPCONNECT_RETURNSTATUS;
|
|
}
|
|
|
|
if ( ( hr = dplay_create( riid, lplpDP ) ) != DP_OK )
|
|
{
|
|
ERR( "error creating interface for %s:%s.\n",
|
|
debugstr_guid( riid ), DPLAYX_HresultToString( hr ) );
|
|
return hr;
|
|
}
|
|
|
|
/* FIXME: Is it safe/correct to use appID of 0? */
|
|
hr = IDirectPlayLobby_GetConnectionSettings( &This->IDirectPlayLobby3_iface,
|
|
0, NULL, &dwConnSize );
|
|
if( hr != DPERR_BUFFERTOOSMALL )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
lpConn = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwConnSize );
|
|
|
|
if( lpConn == NULL )
|
|
{
|
|
return DPERR_NOMEMORY;
|
|
}
|
|
|
|
/* FIXME: Is it safe/correct to use appID of 0? */
|
|
hr = IDirectPlayLobby_GetConnectionSettings( &This->IDirectPlayLobby3_iface,
|
|
0, lpConn, &dwConnSize );
|
|
if( FAILED( hr ) )
|
|
{
|
|
HeapFree( GetProcessHeap(), 0, lpConn );
|
|
return hr;
|
|
}
|
|
|
|
#if 0
|
|
/* - Need to call IDirectPlay::EnumConnections with the service provider to get that good information
|
|
* - Need to call CreateAddress to create the lpConnection param for IDirectPlay::InitializeConnection
|
|
* - Call IDirectPlay::InitializeConnection
|
|
*/
|
|
|
|
/* Now initialize the Service Provider */
|
|
hr = IDirectPlayX_InitializeConnection( (*(LPDIRECTPLAY2*)lplpDP),
|
|
#endif
|
|
|
|
|
|
/* Setup flags to pass into DirectPlay::Open */
|
|
if( dwFlags & DPCONNECT_RETURNSTATUS )
|
|
{
|
|
dwOpenFlags |= DPOPEN_RETURNSTATUS;
|
|
}
|
|
dwOpenFlags |= lpConn->dwFlags;
|
|
|
|
hr = IDirectPlayX_Open( (*(LPDIRECTPLAY2*)lplpDP), lpConn->lpSessionDesc,
|
|
dwOpenFlags );
|
|
|
|
HeapFree( GetProcessHeap(), 0, lpConn );
|
|
|
|
return hr;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobbyAImpl_Connect( IDirectPlayLobbyA *iface, DWORD flags,
|
|
IDirectPlay2A **dp, IUnknown *unk )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobbyA( iface );
|
|
return IDirectPlayLobby_Connect( &This->IDirectPlayLobby3A_iface, flags, dp, unk );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobbyImpl_Connect( IDirectPlayLobby *iface, DWORD flags,
|
|
IDirectPlay2A **dp, IUnknown *unk )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby( iface );
|
|
return IDirectPlayLobby_Connect( &This->IDirectPlayLobby3_iface, flags, dp, unk );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby2AImpl_Connect( IDirectPlayLobby2A *iface, DWORD flags,
|
|
IDirectPlay2A **dp, IUnknown *unk )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2A( iface );
|
|
return IDirectPlayLobby_Connect( &This->IDirectPlayLobby3A_iface, flags, dp, unk );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby2Impl_Connect( IDirectPlayLobby2 *iface, DWORD flags,
|
|
IDirectPlay2A **dp, IUnknown *unk )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2( iface );
|
|
return IDirectPlayLobby_Connect( &This->IDirectPlayLobby3_iface, flags, dp, unk );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby3AImpl_Connect( IDirectPlayLobby3A *iface, DWORD flags,
|
|
IDirectPlay2A **dp, IUnknown *unk)
|
|
{
|
|
return IDirectPlayLobby_ConnectEx( iface, flags, &IID_IDirectPlay2A, (void**)dp, unk );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby3Impl_Connect( IDirectPlayLobby3 *iface, DWORD flags,
|
|
IDirectPlay2 **dp, IUnknown *unk)
|
|
{
|
|
return IDirectPlayLobby_ConnectEx( iface, flags, &IID_IDirectPlay2A, (void**)dp, unk );
|
|
}
|
|
|
|
/********************************************************************
|
|
*
|
|
* Creates a DirectPlay Address, given a service provider-specific network
|
|
* address.
|
|
* Returns an address contains the globally unique identifier
|
|
* (GUID) of the service provider and data that the service provider can
|
|
* interpret as a network address.
|
|
*
|
|
* NOTE: It appears that this method is supposed to be really really stupid
|
|
* with no error checking on the contents.
|
|
*/
|
|
static HRESULT WINAPI IDirectPlayLobbyAImpl_CreateAddress( IDirectPlayLobbyA *iface, REFGUID sp,
|
|
REFGUID datatype, const void *data, DWORD datasize, void *address, DWORD *addrsize )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobbyA( iface );
|
|
return IDirectPlayLobby_CreateAddress( &This->IDirectPlayLobby3A_iface, sp, datatype, data,
|
|
datasize, address, addrsize );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobbyImpl_CreateAddress( IDirectPlayLobby *iface, REFGUID sp,
|
|
REFGUID datatype, const void *data, DWORD datasize, void *address, DWORD *addrsize )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby( iface );
|
|
return IDirectPlayLobby_CreateAddress( &This->IDirectPlayLobby3_iface, sp, datatype, data,
|
|
datasize, address, addrsize );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby2AImpl_CreateAddress( IDirectPlayLobby2A *iface, REFGUID sp,
|
|
REFGUID datatype, const void *data, DWORD datasize, void *address, DWORD *addrsize )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2A( iface );
|
|
return IDirectPlayLobby_CreateAddress( &This->IDirectPlayLobby3A_iface, sp, datatype, data,
|
|
datasize, address, addrsize );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby2Impl_CreateAddress( IDirectPlayLobby2 *iface, REFGUID sp,
|
|
REFGUID datatype, const void *data, DWORD datasize, void *address, DWORD *addrsize )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2( iface );
|
|
return IDirectPlayLobby_CreateAddress( &This->IDirectPlayLobby3_iface, sp, datatype, data,
|
|
datasize, address, addrsize );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby3AImpl_CreateAddress( IDirectPlayLobby3A *iface,
|
|
REFGUID guidSP, REFGUID guidDataType, const void *lpData, DWORD dwDataSize, void *lpAddress,
|
|
DWORD *lpdwAddressSize )
|
|
{
|
|
return DPL_CreateAddress( guidSP, guidDataType, lpData, dwDataSize,
|
|
lpAddress, lpdwAddressSize, TRUE );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby3Impl_CreateAddress( IDirectPlayLobby3 *iface, REFGUID guidSP,
|
|
REFGUID guidDataType, const void *lpData, DWORD dwDataSize, void *lpAddress,
|
|
DWORD *lpdwAddressSize )
|
|
{
|
|
return DPL_CreateAddress( guidSP, guidDataType, lpData, dwDataSize,
|
|
lpAddress, lpdwAddressSize, FALSE );
|
|
}
|
|
|
|
static HRESULT DPL_CreateAddress(
|
|
REFGUID guidSP,
|
|
REFGUID guidDataType,
|
|
LPCVOID lpData,
|
|
DWORD dwDataSize,
|
|
LPVOID lpAddress,
|
|
LPDWORD lpdwAddressSize,
|
|
BOOL bAnsiInterface )
|
|
{
|
|
const DWORD dwNumAddElements = 2; /* Service Provide & address data type */
|
|
DPCOMPOUNDADDRESSELEMENT addressElements[ 2 /* dwNumAddElements */ ];
|
|
|
|
TRACE( "(%p)->(%p,%p,0x%08x,%p,%p,%d)\n", guidSP, guidDataType, lpData, dwDataSize,
|
|
lpAddress, lpdwAddressSize, bAnsiInterface );
|
|
|
|
addressElements[ 0 ].guidDataType = DPAID_ServiceProvider;
|
|
addressElements[ 0 ].dwDataSize = sizeof( GUID );
|
|
addressElements[ 0 ].lpData = (LPVOID)guidSP;
|
|
|
|
addressElements[ 1 ].guidDataType = *guidDataType;
|
|
addressElements[ 1 ].dwDataSize = dwDataSize;
|
|
addressElements[ 1 ].lpData = (LPVOID)lpData;
|
|
|
|
/* Call CreateCompoundAddress to cut down on code.
|
|
NOTE: We can do this because we don't support DPL 1 interfaces! */
|
|
return DPL_CreateCompoundAddress( addressElements, dwNumAddElements,
|
|
lpAddress, lpdwAddressSize, bAnsiInterface );
|
|
}
|
|
|
|
|
|
|
|
/********************************************************************
|
|
*
|
|
* Parses out chunks from the DirectPlay Address buffer by calling the
|
|
* given callback function, with lpContext, for each of the chunks.
|
|
*
|
|
*/
|
|
static HRESULT WINAPI IDirectPlayLobbyAImpl_EnumAddress( IDirectPlayLobbyA *iface,
|
|
LPDPENUMADDRESSCALLBACK enumaddrcb, const void *address, DWORD size, void *context )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobbyA( iface );
|
|
return IDirectPlayLobby_EnumAddress( &This->IDirectPlayLobby3A_iface, enumaddrcb, address, size,
|
|
context );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobbyImpl_EnumAddress( IDirectPlayLobby *iface,
|
|
LPDPENUMADDRESSCALLBACK enumaddrcb, const void *address, DWORD size, void *context )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby( iface );
|
|
return IDirectPlayLobby_EnumAddress( &This->IDirectPlayLobby3_iface, enumaddrcb, address, size,
|
|
context );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby2AImpl_EnumAddress( IDirectPlayLobby2A *iface,
|
|
LPDPENUMADDRESSCALLBACK enumaddrcb, const void *address, DWORD size, void *context )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2A( iface );
|
|
return IDirectPlayLobby_EnumAddress( &This->IDirectPlayLobby3A_iface, enumaddrcb, address, size,
|
|
context );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby2Impl_EnumAddress( IDirectPlayLobby2 *iface,
|
|
LPDPENUMADDRESSCALLBACK enumaddrcb, const void *address, DWORD size, void *context )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2( iface );
|
|
return IDirectPlayLobby_EnumAddress( &This->IDirectPlayLobby3_iface, enumaddrcb, address, size,
|
|
context );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby3AImpl_EnumAddress( IDirectPlayLobby3A *iface,
|
|
LPDPENUMADDRESSCALLBACK lpEnumAddressCallback, const void *lpAddress, DWORD dwAddressSize,
|
|
void *lpContext )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3A( iface );
|
|
|
|
TRACE("(%p)->(%p,%p,0x%08x,%p)\n", This, lpEnumAddressCallback, lpAddress,
|
|
dwAddressSize, lpContext );
|
|
|
|
return DPL_EnumAddress( lpEnumAddressCallback, lpAddress, dwAddressSize, lpContext );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby3Impl_EnumAddress( IDirectPlayLobby3 *iface,
|
|
LPDPENUMADDRESSCALLBACK lpEnumAddressCallback, const void *lpAddress, DWORD dwAddressSize,
|
|
void *lpContext )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3( iface );
|
|
|
|
TRACE("(%p)->(%p,%p,0x%08x,%p)\n", This, lpEnumAddressCallback, lpAddress,
|
|
dwAddressSize, lpContext );
|
|
|
|
return DPL_EnumAddress( lpEnumAddressCallback, lpAddress, dwAddressSize, lpContext );
|
|
}
|
|
|
|
HRESULT DPL_EnumAddress( LPDPENUMADDRESSCALLBACK lpEnumAddressCallback, LPCVOID lpAddress,
|
|
DWORD dwAddressSize, LPVOID lpContext )
|
|
{
|
|
DWORD dwTotalSizeEnumerated = 0;
|
|
|
|
/* FIXME: First chunk is always the total size chunk - Should we report it? */
|
|
|
|
while ( dwTotalSizeEnumerated < dwAddressSize )
|
|
{
|
|
const DPADDRESS* lpElements = lpAddress;
|
|
DWORD dwSizeThisEnumeration;
|
|
|
|
/* Invoke the enum method. If false is returned, stop enumeration */
|
|
if ( !lpEnumAddressCallback( &lpElements->guidDataType,
|
|
lpElements->dwDataSize,
|
|
(const BYTE *)lpElements + sizeof( DPADDRESS ),
|
|
lpContext ) )
|
|
{
|
|
break;
|
|
}
|
|
|
|
dwSizeThisEnumeration = sizeof( DPADDRESS ) + lpElements->dwDataSize;
|
|
lpAddress = (const BYTE*) lpAddress + dwSizeThisEnumeration;
|
|
dwTotalSizeEnumerated += dwSizeThisEnumeration;
|
|
}
|
|
|
|
return DP_OK;
|
|
}
|
|
|
|
/********************************************************************
|
|
*
|
|
* Enumerates all the address types that a given service provider needs to
|
|
* build the DirectPlay Address.
|
|
*
|
|
*/
|
|
static HRESULT WINAPI IDirectPlayLobbyAImpl_EnumAddressTypes( IDirectPlayLobbyA *iface,
|
|
LPDPLENUMADDRESSTYPESCALLBACK enumaddrtypecb, REFGUID sp, void *context, DWORD flags )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobbyA( iface );
|
|
return IDirectPlayLobby_EnumAddressTypes( &This->IDirectPlayLobby3A_iface, enumaddrtypecb, sp,
|
|
context, flags );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobbyImpl_EnumAddressTypes( IDirectPlayLobby *iface,
|
|
LPDPLENUMADDRESSTYPESCALLBACK enumaddrtypecb, REFGUID sp, void *context, DWORD flags )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby( iface );
|
|
return IDirectPlayLobby_EnumAddressTypes( &This->IDirectPlayLobby3_iface, enumaddrtypecb, sp,
|
|
context, flags );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby2AImpl_EnumAddressTypes( IDirectPlayLobby2A *iface,
|
|
LPDPLENUMADDRESSTYPESCALLBACK enumaddrtypecb, REFGUID sp, void *context, DWORD flags )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2A( iface );
|
|
return IDirectPlayLobby_EnumAddressTypes( &This->IDirectPlayLobby3A_iface, enumaddrtypecb, sp,
|
|
context, flags );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby2Impl_EnumAddressTypes( IDirectPlayLobby2 *iface,
|
|
LPDPLENUMADDRESSTYPESCALLBACK enumaddrtypecb, REFGUID sp, void *context, DWORD flags )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2( iface );
|
|
return IDirectPlayLobby_EnumAddressTypes( &This->IDirectPlayLobby3_iface, enumaddrtypecb, sp,
|
|
context, flags );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby3AImpl_EnumAddressTypes( IDirectPlayLobby3A *iface,
|
|
LPDPLENUMADDRESSTYPESCALLBACK lpEnumAddressTypeCallback, REFGUID guidSP, void *lpContext,
|
|
DWORD dwFlags )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3A( iface );
|
|
|
|
HKEY hkResult;
|
|
LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
|
|
DWORD dwIndex, sizeOfSubKeyName=50;
|
|
char subKeyName[51];
|
|
FILETIME filetime;
|
|
|
|
TRACE(" (%p)->(%p,%p,%p,0x%08x)\n", This, lpEnumAddressTypeCallback, guidSP, lpContext, dwFlags );
|
|
|
|
if( dwFlags != 0 )
|
|
{
|
|
return DPERR_INVALIDPARAMS;
|
|
}
|
|
|
|
if( !lpEnumAddressTypeCallback )
|
|
{
|
|
return DPERR_INVALIDPARAMS;
|
|
}
|
|
|
|
if( guidSP == NULL )
|
|
{
|
|
return DPERR_INVALIDOBJECT;
|
|
}
|
|
|
|
/* Need to loop over the service providers in the registry */
|
|
if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
|
|
0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
|
|
{
|
|
/* Hmmm. Does this mean that there are no service providers? */
|
|
ERR(": no service providers?\n");
|
|
return DP_OK;
|
|
}
|
|
|
|
/* Traverse all the service providers we have available */
|
|
for( dwIndex=0;
|
|
RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
|
|
NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
|
|
++dwIndex, sizeOfSubKeyName=50 )
|
|
{
|
|
|
|
HKEY hkServiceProvider, hkServiceProviderAt;
|
|
GUID serviceProviderGUID;
|
|
DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
|
|
char atSubKey[51];
|
|
char returnBuffer[51];
|
|
WCHAR buff[51];
|
|
DWORD dwAtIndex;
|
|
LPCSTR atKey = "Address Types";
|
|
LPCSTR guidDataSubKey = "Guid";
|
|
|
|
TRACE(" this time through: %s\n", subKeyName );
|
|
|
|
/* Get a handle for this particular service provider */
|
|
if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
|
|
&hkServiceProvider ) != ERROR_SUCCESS )
|
|
{
|
|
ERR(": what the heck is going on?\n" );
|
|
continue;
|
|
}
|
|
|
|
if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
|
|
NULL, &returnTypeGUID, (LPBYTE)returnBuffer,
|
|
&sizeOfReturnBuffer ) != ERROR_SUCCESS )
|
|
{
|
|
ERR(": missing GUID registry data members\n" );
|
|
continue;
|
|
}
|
|
|
|
/* FIXME: Check return types to ensure we're interpreting data right */
|
|
MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, ARRAY_SIZE( buff ));
|
|
CLSIDFromString( buff, &serviceProviderGUID );
|
|
/* FIXME: Have I got a memory leak on the serviceProviderGUID? */
|
|
|
|
/* Determine if this is the Service Provider that the user asked for */
|
|
if( !IsEqualGUID( &serviceProviderGUID, guidSP ) )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
/* Get a handle for this particular service provider */
|
|
if( RegOpenKeyExA( hkServiceProvider, atKey, 0, KEY_READ,
|
|
&hkServiceProviderAt ) != ERROR_SUCCESS )
|
|
{
|
|
TRACE(": No Address Types registry data sub key/members\n" );
|
|
break;
|
|
}
|
|
|
|
/* Traverse all the address type we have available */
|
|
for( dwAtIndex=0;
|
|
RegEnumKeyExA( hkServiceProviderAt, dwAtIndex, atSubKey, &sizeOfSubKeyName,
|
|
NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
|
|
++dwAtIndex, sizeOfSubKeyName=50 )
|
|
{
|
|
TRACE( "Found Address Type GUID %s\n", atSubKey );
|
|
|
|
/* FIXME: Check return types to ensure we're interpreting data right */
|
|
MultiByteToWideChar( CP_ACP, 0, atSubKey, -1, buff, ARRAY_SIZE( buff ));
|
|
CLSIDFromString( buff, &serviceProviderGUID );
|
|
/* FIXME: Have I got a memory leak on the serviceProviderGUID? */
|
|
|
|
/* The enumeration will return FALSE if we are not to continue */
|
|
if( !lpEnumAddressTypeCallback( &serviceProviderGUID, lpContext, 0 ) )
|
|
{
|
|
WARN("lpEnumCallback returning FALSE\n" );
|
|
break; /* FIXME: This most likely has to break from the procedure...*/
|
|
}
|
|
|
|
}
|
|
|
|
/* We only enumerate address types for 1 GUID. We've found it, so quit looking */
|
|
break;
|
|
}
|
|
|
|
return DP_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby3Impl_EnumAddressTypes( IDirectPlayLobby3 *iface,
|
|
LPDPLENUMADDRESSTYPESCALLBACK enumaddrtypecb, REFGUID sp, void *context, DWORD flags )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3( iface );
|
|
return IDirectPlayLobby_EnumAddressTypes( &This->IDirectPlayLobby3A_iface, enumaddrtypecb, sp,
|
|
context, flags );
|
|
}
|
|
|
|
/********************************************************************
|
|
*
|
|
* Enumerates what applications are registered with DirectPlay by
|
|
* invoking the callback function with lpContext.
|
|
*
|
|
*/
|
|
static HRESULT WINAPI IDirectPlayLobby3Impl_EnumLocalApplications( IDirectPlayLobby3 *iface,
|
|
LPDPLENUMLOCALAPPLICATIONSCALLBACK lpEnumLocalAppCallback, void *lpContext, DWORD dwFlags )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3( iface );
|
|
|
|
FIXME("(%p)->(%p,%p,0x%08x):stub\n", This, lpEnumLocalAppCallback, lpContext, dwFlags );
|
|
|
|
return DPERR_OUTOFMEMORY;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobbyAImpl_EnumLocalApplications( IDirectPlayLobbyA *iface,
|
|
LPDPLENUMLOCALAPPLICATIONSCALLBACK enumlocalappcb, void *context, DWORD flags )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobbyA( iface );
|
|
return IDirectPlayLobby_EnumLocalApplications( &This->IDirectPlayLobby3A_iface, enumlocalappcb,
|
|
context, flags );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobbyImpl_EnumLocalApplications( IDirectPlayLobby *iface,
|
|
LPDPLENUMLOCALAPPLICATIONSCALLBACK enumlocalappcb, void *context, DWORD flags )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby( iface );
|
|
return IDirectPlayLobby_EnumLocalApplications( &This->IDirectPlayLobby3_iface, enumlocalappcb,
|
|
context, flags );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby2AImpl_EnumLocalApplications( IDirectPlayLobby2A *iface,
|
|
LPDPLENUMLOCALAPPLICATIONSCALLBACK enumlocalappcb, void *context, DWORD flags )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2A( iface );
|
|
return IDirectPlayLobby_EnumLocalApplications( &This->IDirectPlayLobby3A_iface, enumlocalappcb,
|
|
context, flags );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby2Impl_EnumLocalApplications( IDirectPlayLobby2 *iface,
|
|
LPDPLENUMLOCALAPPLICATIONSCALLBACK enumlocalappcb, void *context, DWORD flags )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2( iface );
|
|
return IDirectPlayLobby_EnumLocalApplications( &This->IDirectPlayLobby3_iface, enumlocalappcb,
|
|
context, flags );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby3AImpl_EnumLocalApplications( IDirectPlayLobby3A *iface,
|
|
LPDPLENUMLOCALAPPLICATIONSCALLBACK lpEnumLocalAppCallback, void *lpContext, DWORD dwFlags )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3A( iface );
|
|
|
|
HKEY hkResult;
|
|
LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Applications";
|
|
LPCSTR guidDataSubKey = "Guid";
|
|
DWORD dwIndex, sizeOfSubKeyName=50;
|
|
char subKeyName[51];
|
|
FILETIME filetime;
|
|
|
|
TRACE("(%p)->(%p,%p,0x%08x)\n", This, lpEnumLocalAppCallback, lpContext, dwFlags );
|
|
|
|
if( dwFlags != 0 )
|
|
{
|
|
return DPERR_INVALIDPARAMS;
|
|
}
|
|
|
|
if( !lpEnumLocalAppCallback )
|
|
{
|
|
return DPERR_INVALIDPARAMS;
|
|
}
|
|
|
|
/* Need to loop over the service providers in the registry */
|
|
if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
|
|
0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
|
|
{
|
|
/* Hmmm. Does this mean that there are no service providers? */
|
|
ERR(": no service providers?\n");
|
|
return DP_OK;
|
|
}
|
|
|
|
/* Traverse all registered applications */
|
|
for( dwIndex=0;
|
|
RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName, NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
|
|
++dwIndex, sizeOfSubKeyName=50 )
|
|
{
|
|
|
|
HKEY hkServiceProvider;
|
|
GUID serviceProviderGUID;
|
|
DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
|
|
char returnBuffer[51];
|
|
WCHAR buff[51];
|
|
DPLAPPINFO dplAppInfo;
|
|
|
|
TRACE(" this time through: %s\n", subKeyName );
|
|
|
|
/* Get a handle for this particular service provider */
|
|
if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
|
|
&hkServiceProvider ) != ERROR_SUCCESS )
|
|
{
|
|
ERR(": what the heck is going on?\n" );
|
|
continue;
|
|
}
|
|
|
|
if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
|
|
NULL, &returnTypeGUID, (LPBYTE)returnBuffer,
|
|
&sizeOfReturnBuffer ) != ERROR_SUCCESS )
|
|
{
|
|
ERR(": missing GUID registry data members\n" );
|
|
continue;
|
|
}
|
|
|
|
/* FIXME: Check return types to ensure we're interpreting data right */
|
|
MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, ARRAY_SIZE( buff ));
|
|
CLSIDFromString( buff, &serviceProviderGUID );
|
|
/* FIXME: Have I got a memory leak on the serviceProviderGUID? */
|
|
|
|
dplAppInfo.dwSize = sizeof( dplAppInfo );
|
|
dplAppInfo.guidApplication = serviceProviderGUID;
|
|
dplAppInfo.u.lpszAppNameA = subKeyName;
|
|
|
|
EnterCriticalSection( &This->lock );
|
|
|
|
memcpy( &This->cbkeyhack, &hkServiceProvider, sizeof( hkServiceProvider ) );
|
|
|
|
if( !lpEnumLocalAppCallback( &dplAppInfo, lpContext, dwFlags ) )
|
|
{
|
|
LeaveCriticalSection( &This->lock );
|
|
break;
|
|
}
|
|
|
|
LeaveCriticalSection( &This->lock );
|
|
}
|
|
|
|
return DP_OK;
|
|
}
|
|
|
|
/********************************************************************
|
|
*
|
|
* Retrieves the DPLCONNECTION structure that contains all the information
|
|
* needed to start and connect an application. This was generated using
|
|
* either the RunApplication or SetConnectionSettings methods.
|
|
*
|
|
* NOTES: If lpData is NULL then just return lpdwDataSize. This allows
|
|
* the data structure to be allocated by our caller which can then
|
|
* call this procedure/method again with a valid data pointer.
|
|
*/
|
|
static HRESULT WINAPI IDirectPlayLobbyAImpl_GetConnectionSettings( IDirectPlayLobbyA *iface,
|
|
DWORD appid, void *data, DWORD *size )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobbyA( iface );
|
|
return IDirectPlayLobby_GetConnectionSettings( &This->IDirectPlayLobby3A_iface, appid, data,
|
|
size );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobbyImpl_GetConnectionSettings( IDirectPlayLobby *iface,
|
|
DWORD appid, void *data, DWORD *size )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby( iface );
|
|
return IDirectPlayLobby_GetConnectionSettings( &This->IDirectPlayLobby3_iface, appid, data,
|
|
size );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby2AImpl_GetConnectionSettings( IDirectPlayLobby2A *iface,
|
|
DWORD appid, void *data, DWORD *size )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2A( iface );
|
|
return IDirectPlayLobby_GetConnectionSettings( &This->IDirectPlayLobby3A_iface, appid, data,
|
|
size );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby2Impl_GetConnectionSettings( IDirectPlayLobby2 *iface,
|
|
DWORD appid, void *data, DWORD *size )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2( iface );
|
|
return IDirectPlayLobby_GetConnectionSettings( &This->IDirectPlayLobby3_iface, appid, data,
|
|
size );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby3AImpl_GetConnectionSettings( IDirectPlayLobby3A *iface,
|
|
DWORD dwAppID, void *lpData, DWORD *lpdwDataSize )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3A( iface );
|
|
HRESULT hr;
|
|
|
|
TRACE("(%p)->(0x%08x,%p,%p)\n", This, dwAppID, lpData, lpdwDataSize );
|
|
|
|
EnterCriticalSection( &This->lock );
|
|
|
|
hr = DPLAYX_GetConnectionSettingsA( dwAppID,
|
|
lpData,
|
|
lpdwDataSize
|
|
);
|
|
|
|
LeaveCriticalSection( &This->lock );
|
|
|
|
return hr;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby3Impl_GetConnectionSettings( IDirectPlayLobby3 *iface,
|
|
DWORD dwAppID, void *lpData, DWORD *lpdwDataSize )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3( iface );
|
|
HRESULT hr;
|
|
|
|
TRACE("(%p)->(0x%08x,%p,%p)\n", This, dwAppID, lpData, lpdwDataSize );
|
|
|
|
EnterCriticalSection( &This->lock );
|
|
|
|
hr = DPLAYX_GetConnectionSettingsW( dwAppID,
|
|
lpData,
|
|
lpdwDataSize
|
|
);
|
|
|
|
LeaveCriticalSection( &This->lock );
|
|
|
|
return hr;
|
|
}
|
|
|
|
/********************************************************************
|
|
*
|
|
* Retrieves the message sent between a lobby client and a DirectPlay
|
|
* application. All messages are queued until received.
|
|
*
|
|
*/
|
|
static HRESULT WINAPI IDirectPlayLobbyAImpl_ReceiveLobbyMessage( IDirectPlayLobbyA *iface,
|
|
DWORD flags, DWORD appid, DWORD *msgflags, void *data, DWORD *size )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobbyA( iface );
|
|
return IDirectPlayLobby_ReceiveLobbyMessage( &This->IDirectPlayLobby3A_iface, flags, appid,
|
|
msgflags, data, size );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobbyImpl_ReceiveLobbyMessage( IDirectPlayLobby *iface,
|
|
DWORD flags, DWORD appid, DWORD *msgflags, void *data, DWORD *size )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby( iface );
|
|
return IDirectPlayLobby_ReceiveLobbyMessage( &This->IDirectPlayLobby3_iface, flags, appid,
|
|
msgflags, data, size );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby2AImpl_ReceiveLobbyMessage( IDirectPlayLobby2A *iface,
|
|
DWORD flags, DWORD appid, DWORD *msgflags, void *data, DWORD *size )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2A( iface );
|
|
return IDirectPlayLobby_ReceiveLobbyMessage( &This->IDirectPlayLobby3A_iface, flags, appid,
|
|
msgflags, data, size );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby2Impl_ReceiveLobbyMessage( IDirectPlayLobby2 *iface,
|
|
DWORD flags, DWORD appid, DWORD *msgflags, void *data, DWORD *size )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2( iface );
|
|
return IDirectPlayLobby_ReceiveLobbyMessage( &This->IDirectPlayLobby3_iface, flags, appid,
|
|
msgflags, data, size );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby3AImpl_ReceiveLobbyMessage( IDirectPlayLobby3A *iface,
|
|
DWORD dwFlags, DWORD dwAppID, DWORD *lpdwMessageFlags, void *lpData,
|
|
DWORD *lpdwDataSize )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3A( iface );
|
|
FIXME(":stub %p %08x %08x %p %p %p\n", This, dwFlags, dwAppID, lpdwMessageFlags, lpData,
|
|
lpdwDataSize );
|
|
return DPERR_OUTOFMEMORY;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby3Impl_ReceiveLobbyMessage( IDirectPlayLobby3 *iface,
|
|
DWORD dwFlags, DWORD dwAppID, DWORD *lpdwMessageFlags, void *lpData,
|
|
DWORD *lpdwDataSize )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3( iface );
|
|
FIXME(":stub %p %08x %08x %p %p %p\n", This, dwFlags, dwAppID, lpdwMessageFlags, lpData,
|
|
lpdwDataSize );
|
|
return DPERR_OUTOFMEMORY;
|
|
}
|
|
|
|
typedef struct tagRunApplicationEnumStruct
|
|
{
|
|
IDirectPlayLobbyImpl *This;
|
|
|
|
GUID appGUID;
|
|
LPSTR lpszPath;
|
|
LPSTR lpszFileName;
|
|
LPSTR lpszCommandLine;
|
|
LPSTR lpszCurrentDirectory;
|
|
} RunApplicationEnumStruct, *lpRunApplicationEnumStruct;
|
|
|
|
/* To be called by RunApplication to find how to invoke the function */
|
|
static BOOL CALLBACK RunApplicationA_EnumLocalApplications
|
|
( LPCDPLAPPINFO lpAppInfo,
|
|
LPVOID lpContext,
|
|
DWORD dwFlags )
|
|
{
|
|
lpRunApplicationEnumStruct lpData = (lpRunApplicationEnumStruct)lpContext;
|
|
|
|
if( IsEqualGUID( &lpAppInfo->guidApplication, &lpData->appGUID ) )
|
|
{
|
|
char returnBuffer[200];
|
|
DWORD returnType, sizeOfReturnBuffer;
|
|
LPCSTR clSubKey = "CommandLine";
|
|
LPCSTR cdSubKey = "CurrentDirectory";
|
|
LPCSTR fileSubKey = "File";
|
|
LPCSTR pathSubKey = "Path";
|
|
|
|
/* FIXME: Lazy man hack - dplay struct has the present reg key saved */
|
|
|
|
sizeOfReturnBuffer = 200;
|
|
|
|
/* Get all the appropriate data from the registry */
|
|
if( RegQueryValueExA( lpData->This->cbkeyhack, clSubKey,
|
|
NULL, &returnType, (LPBYTE)returnBuffer,
|
|
&sizeOfReturnBuffer ) != ERROR_SUCCESS )
|
|
{
|
|
ERR( ": missing CommandLine registry data member\n" );
|
|
}
|
|
else
|
|
{
|
|
if ((lpData->lpszCommandLine = HeapAlloc( GetProcessHeap(), 0, strlen(returnBuffer)+1 )))
|
|
strcpy( lpData->lpszCommandLine, returnBuffer );
|
|
}
|
|
|
|
sizeOfReturnBuffer = 200;
|
|
|
|
if( RegQueryValueExA( lpData->This->cbkeyhack, cdSubKey,
|
|
NULL, &returnType, (LPBYTE)returnBuffer,
|
|
&sizeOfReturnBuffer ) != ERROR_SUCCESS )
|
|
{
|
|
ERR( ": missing CurrentDirectory registry data member\n" );
|
|
}
|
|
else
|
|
{
|
|
if ((lpData->lpszCurrentDirectory = HeapAlloc( GetProcessHeap(), 0, strlen(returnBuffer)+1 )))
|
|
strcpy( lpData->lpszCurrentDirectory, returnBuffer );
|
|
}
|
|
|
|
sizeOfReturnBuffer = 200;
|
|
|
|
if( RegQueryValueExA( lpData->This->cbkeyhack, fileSubKey,
|
|
NULL, &returnType, (LPBYTE)returnBuffer,
|
|
&sizeOfReturnBuffer ) != ERROR_SUCCESS )
|
|
{
|
|
ERR( ": missing File registry data member\n" );
|
|
}
|
|
else
|
|
{
|
|
if ((lpData->lpszFileName = HeapAlloc( GetProcessHeap(), 0, strlen(returnBuffer)+1 )))
|
|
strcpy( lpData->lpszFileName, returnBuffer );
|
|
}
|
|
|
|
sizeOfReturnBuffer = 200;
|
|
|
|
if( RegQueryValueExA( lpData->This->cbkeyhack, pathSubKey,
|
|
NULL, &returnType, (LPBYTE)returnBuffer,
|
|
&sizeOfReturnBuffer ) != ERROR_SUCCESS )
|
|
{
|
|
ERR( ": missing Path registry data member\n" );
|
|
}
|
|
else
|
|
{
|
|
if ((lpData->lpszPath = HeapAlloc( GetProcessHeap(), 0, strlen(returnBuffer)+1 )))
|
|
strcpy( lpData->lpszPath, returnBuffer );
|
|
}
|
|
|
|
return FALSE; /* No need to keep going as we found what we wanted */
|
|
}
|
|
|
|
return TRUE; /* Keep enumerating, haven't found the application yet */
|
|
}
|
|
|
|
static BOOL DPL_CreateAndSetLobbyHandles( DWORD dwDestProcessId, HANDLE hDestProcess,
|
|
LPHANDLE lphStart, LPHANDLE lphDeath,
|
|
LPHANDLE lphRead )
|
|
{
|
|
/* These are the handles for the created process */
|
|
HANDLE hAppStart = 0, hAppDeath = 0, hAppRead = 0;
|
|
SECURITY_ATTRIBUTES s_attrib;
|
|
|
|
s_attrib.nLength = sizeof( s_attrib );
|
|
s_attrib.lpSecurityDescriptor = NULL;
|
|
s_attrib.bInheritHandle = TRUE;
|
|
|
|
*lphStart = CreateEventW( &s_attrib, TRUE, FALSE, NULL );
|
|
*lphDeath = CreateEventW( &s_attrib, TRUE, FALSE, NULL );
|
|
*lphRead = CreateEventW( &s_attrib, TRUE, FALSE, NULL );
|
|
|
|
if( ( !DuplicateHandle( GetCurrentProcess(), *lphStart,
|
|
hDestProcess, &hAppStart,
|
|
0, FALSE, DUPLICATE_SAME_ACCESS ) ) ||
|
|
( !DuplicateHandle( GetCurrentProcess(), *lphDeath,
|
|
hDestProcess, &hAppDeath,
|
|
0, FALSE, DUPLICATE_SAME_ACCESS ) ) ||
|
|
( !DuplicateHandle( GetCurrentProcess(), *lphRead,
|
|
hDestProcess, &hAppRead,
|
|
0, FALSE, DUPLICATE_SAME_ACCESS ) )
|
|
)
|
|
{
|
|
if (*lphStart) { CloseHandle(*lphStart); *lphStart = 0; }
|
|
if (*lphDeath) { CloseHandle(*lphDeath); *lphDeath = 0; }
|
|
if (*lphRead) { CloseHandle(*lphRead); *lphRead = 0; }
|
|
/* FIXME: Handle leak... */
|
|
ERR( "Unable to dup handles\n" );
|
|
return FALSE;
|
|
}
|
|
|
|
if( !DPLAYX_SetLobbyHandles( dwDestProcessId,
|
|
hAppStart, hAppDeath, hAppRead ) )
|
|
{
|
|
/* FIXME: Handle leak... */
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/********************************************************************
|
|
*
|
|
* Starts an application and passes to it all the information to
|
|
* connect to a session.
|
|
*
|
|
*/
|
|
static HRESULT WINAPI IDirectPlayLobbyAImpl_RunApplication( IDirectPlayLobbyA *iface, DWORD flags,
|
|
DWORD *appid, DPLCONNECTION *conn, HANDLE event )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobbyA( iface );
|
|
return IDirectPlayLobby_RunApplication( &This->IDirectPlayLobby3A_iface, flags, appid, conn,
|
|
event );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobbyImpl_RunApplication( IDirectPlayLobby *iface, DWORD flags,
|
|
DWORD *appid, DPLCONNECTION *conn, HANDLE event )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby( iface );
|
|
return IDirectPlayLobby_RunApplication( &This->IDirectPlayLobby3_iface, flags, appid, conn,
|
|
event );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby2AImpl_RunApplication( IDirectPlayLobby2A *iface, DWORD flags,
|
|
DWORD *appid, DPLCONNECTION *conn, HANDLE event )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2A( iface );
|
|
return IDirectPlayLobby_RunApplication( &This->IDirectPlayLobby3A_iface, flags, appid, conn,
|
|
event );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby2Impl_RunApplication( IDirectPlayLobby2 *iface, DWORD flags,
|
|
DWORD *appid, DPLCONNECTION *conn, HANDLE event )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2( iface );
|
|
return IDirectPlayLobby_RunApplication( &This->IDirectPlayLobby3_iface, flags, appid, conn,
|
|
event );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby3AImpl_RunApplication( IDirectPlayLobby3A *iface,
|
|
DWORD dwFlags, DWORD *lpdwAppID, DPLCONNECTION *lpConn, HANDLE hReceiveEvent )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3A( iface );
|
|
HRESULT hr;
|
|
RunApplicationEnumStruct enumData;
|
|
char temp[200];
|
|
STARTUPINFOA startupInfo;
|
|
PROCESS_INFORMATION newProcessInfo;
|
|
LPSTR appName;
|
|
DWORD dwSuspendCount;
|
|
HANDLE hStart, hDeath, hSettingRead;
|
|
|
|
TRACE( "(%p)->(0x%08x,%p,%p,%p)\n",
|
|
This, dwFlags, lpdwAppID, lpConn, hReceiveEvent );
|
|
|
|
if( dwFlags != 0 )
|
|
{
|
|
return DPERR_INVALIDPARAMS;
|
|
}
|
|
|
|
if( DPLAYX_AnyLobbiesWaitingForConnSettings() )
|
|
{
|
|
FIXME( "Waiting lobby not being handled correctly\n" );
|
|
}
|
|
|
|
EnterCriticalSection( &This->lock );
|
|
|
|
ZeroMemory( &enumData, sizeof( enumData ) );
|
|
enumData.This = This;
|
|
enumData.appGUID = lpConn->lpSessionDesc->guidApplication;
|
|
|
|
/* Our callback function will fill up the enumData structure with all the information
|
|
required to start a new process */
|
|
IDirectPlayLobby_EnumLocalApplications( iface, RunApplicationA_EnumLocalApplications,
|
|
(&enumData), 0 );
|
|
|
|
/* First the application name */
|
|
strcpy( temp, enumData.lpszPath );
|
|
strcat( temp, "\\" );
|
|
strcat( temp, enumData.lpszFileName );
|
|
HeapFree( GetProcessHeap(), 0, enumData.lpszPath );
|
|
HeapFree( GetProcessHeap(), 0, enumData.lpszFileName );
|
|
if ((appName = HeapAlloc( GetProcessHeap(), 0, strlen(temp)+1 ))) strcpy( appName, temp );
|
|
|
|
/* Now the command line */
|
|
strcat( temp, " " );
|
|
strcat( temp, enumData.lpszCommandLine );
|
|
HeapFree( GetProcessHeap(), 0, enumData.lpszCommandLine );
|
|
if ((enumData.lpszCommandLine = HeapAlloc( GetProcessHeap(), 0, strlen(temp)+1 )))
|
|
strcpy( enumData.lpszCommandLine, temp );
|
|
|
|
ZeroMemory( &startupInfo, sizeof( startupInfo ) );
|
|
startupInfo.cb = sizeof( startupInfo );
|
|
/* FIXME: Should any fields be filled in? */
|
|
|
|
ZeroMemory( &newProcessInfo, sizeof( newProcessInfo ) );
|
|
|
|
if( !CreateProcessA( appName,
|
|
enumData.lpszCommandLine,
|
|
NULL,
|
|
NULL,
|
|
FALSE,
|
|
CREATE_DEFAULT_ERROR_MODE | CREATE_NEW_CONSOLE | CREATE_SUSPENDED, /* Creation Flags */
|
|
NULL,
|
|
enumData.lpszCurrentDirectory,
|
|
&startupInfo,
|
|
&newProcessInfo
|
|
)
|
|
)
|
|
{
|
|
ERR( "Failed to create process for app %s\n", appName );
|
|
|
|
HeapFree( GetProcessHeap(), 0, appName );
|
|
HeapFree( GetProcessHeap(), 0, enumData.lpszCommandLine );
|
|
HeapFree( GetProcessHeap(), 0, enumData.lpszCurrentDirectory );
|
|
|
|
LeaveCriticalSection( &This->lock );
|
|
return DPERR_CANTCREATEPROCESS;
|
|
}
|
|
|
|
HeapFree( GetProcessHeap(), 0, appName );
|
|
HeapFree( GetProcessHeap(), 0, enumData.lpszCommandLine );
|
|
HeapFree( GetProcessHeap(), 0, enumData.lpszCurrentDirectory );
|
|
|
|
/* Reserve this global application id! */
|
|
if( !DPLAYX_CreateLobbyApplication( newProcessInfo.dwProcessId ) )
|
|
{
|
|
ERR( "Unable to create global application data for 0x%08x\n",
|
|
newProcessInfo.dwProcessId );
|
|
}
|
|
|
|
hr = IDirectPlayLobby_SetConnectionSettings( iface, 0, newProcessInfo.dwProcessId, lpConn );
|
|
|
|
if( hr != DP_OK )
|
|
{
|
|
ERR( "SetConnectionSettings failure %s\n", DPLAYX_HresultToString( hr ) );
|
|
LeaveCriticalSection( &This->lock );
|
|
return hr;
|
|
}
|
|
|
|
/* Setup the handles for application notification */
|
|
DPL_CreateAndSetLobbyHandles( newProcessInfo.dwProcessId,
|
|
newProcessInfo.hProcess,
|
|
&hStart, &hDeath, &hSettingRead );
|
|
|
|
/* Setup the message thread ID */
|
|
This->msgtid = CreateLobbyMessageReceptionThread( hReceiveEvent, hStart, hDeath, hSettingRead );
|
|
|
|
DPLAYX_SetLobbyMsgThreadId( newProcessInfo.dwProcessId, This->msgtid );
|
|
|
|
LeaveCriticalSection( &This->lock );
|
|
|
|
/* Everything seems to have been set correctly, update the dwAppID */
|
|
*lpdwAppID = newProcessInfo.dwProcessId;
|
|
|
|
/* Unsuspend the process - should return the prev suspension count */
|
|
if( ( dwSuspendCount = ResumeThread( newProcessInfo.hThread ) ) != 1 )
|
|
{
|
|
ERR( "ResumeThread failed with 0x%08x\n", dwSuspendCount );
|
|
}
|
|
|
|
return DP_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby3Impl_RunApplication( IDirectPlayLobby3 *iface, DWORD dwFlags,
|
|
DWORD *lpdwAppID, DPLCONNECTION *lpConn, HANDLE hReceiveEvent )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3( iface );
|
|
FIXME( "(%p)->(0x%08x,%p,%p,%p):stub\n", This, dwFlags, lpdwAppID, lpConn, hReceiveEvent );
|
|
return DPERR_OUTOFMEMORY;
|
|
}
|
|
|
|
/********************************************************************
|
|
*
|
|
* Sends a message between the application and the lobby client.
|
|
* All messages are queued until received.
|
|
*
|
|
*/
|
|
static HRESULT WINAPI IDirectPlayLobbyAImpl_SendLobbyMessage( IDirectPlayLobbyA *iface, DWORD flags,
|
|
DWORD appid, void *data, DWORD size )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobbyA( iface );
|
|
return IDirectPlayLobby_SendLobbyMessage( &This->IDirectPlayLobby3A_iface, flags, appid, data,
|
|
size );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobbyImpl_SendLobbyMessage( IDirectPlayLobby *iface, DWORD flags,
|
|
DWORD appid, void *data, DWORD size )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby( iface );
|
|
return IDirectPlayLobby_SendLobbyMessage( &This->IDirectPlayLobby3_iface, flags, appid, data,
|
|
size );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby2AImpl_SendLobbyMessage( IDirectPlayLobby2A *iface,
|
|
DWORD flags, DWORD appid, void *data, DWORD size )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2A( iface );
|
|
return IDirectPlayLobby_SendLobbyMessage( &This->IDirectPlayLobby3A_iface, flags, appid, data,
|
|
size );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby2Impl_SendLobbyMessage( IDirectPlayLobby2 *iface, DWORD flags,
|
|
DWORD appid, void *data, DWORD size )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2( iface );
|
|
return IDirectPlayLobby_SendLobbyMessage( &This->IDirectPlayLobby3_iface, flags, appid, data,
|
|
size );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby3AImpl_SendLobbyMessage( IDirectPlayLobby3A *iface,
|
|
DWORD flags, DWORD appid, void *data, DWORD size )
|
|
{
|
|
FIXME(":stub\n");
|
|
return DPERR_OUTOFMEMORY;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby3Impl_SendLobbyMessage( IDirectPlayLobby3 *iface,
|
|
DWORD flags, DWORD appid, void *data, DWORD size )
|
|
{
|
|
FIXME(":stub\n");
|
|
return DPERR_OUTOFMEMORY;
|
|
}
|
|
|
|
/********************************************************************
|
|
*
|
|
* Modifies the DPLCONNECTION structure to contain all information
|
|
* needed to start and connect an application.
|
|
*
|
|
*/
|
|
static HRESULT WINAPI IDirectPlayLobby3Impl_SetConnectionSettings( IDirectPlayLobby3 *iface,
|
|
DWORD dwFlags, DWORD dwAppID, DPLCONNECTION *lpConn )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3( iface );
|
|
HRESULT hr;
|
|
|
|
TRACE("(%p)->(0x%08x,0x%08x,%p)\n", This, dwFlags, dwAppID, lpConn );
|
|
|
|
EnterCriticalSection( &This->lock );
|
|
|
|
hr = DPLAYX_SetConnectionSettingsW( dwFlags, dwAppID, lpConn );
|
|
|
|
/* FIXME: Don't think that this is supposed to fail, but the documentation
|
|
is somewhat sketchy. I'll try creating a lobby application
|
|
for this... */
|
|
if( hr == DPERR_NOTLOBBIED )
|
|
{
|
|
FIXME( "Unlobbied app setting connections. Is this correct behavior?\n" );
|
|
if( dwAppID == 0 )
|
|
{
|
|
dwAppID = GetCurrentProcessId();
|
|
}
|
|
DPLAYX_CreateLobbyApplication( dwAppID );
|
|
hr = DPLAYX_SetConnectionSettingsW( dwFlags, dwAppID, lpConn );
|
|
}
|
|
|
|
LeaveCriticalSection( &This->lock );
|
|
|
|
return hr;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobbyAImpl_SetConnectionSettings( IDirectPlayLobbyA *iface,
|
|
DWORD flags, DWORD appid, DPLCONNECTION *conn )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobbyA( iface );
|
|
return IDirectPlayLobby_SetConnectionSettings( &This->IDirectPlayLobby3A_iface, flags,
|
|
appid, conn );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobbyImpl_SetConnectionSettings( IDirectPlayLobby *iface,
|
|
DWORD flags, DWORD appid, DPLCONNECTION *conn )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby( iface );
|
|
return IDirectPlayLobby_SetConnectionSettings( &This->IDirectPlayLobby3_iface, flags,
|
|
appid, conn );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby2AImpl_SetConnectionSettings( IDirectPlayLobby2A *iface,
|
|
DWORD flags, DWORD appid, DPLCONNECTION *conn )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2A( iface );
|
|
return IDirectPlayLobby_SetConnectionSettings( &This->IDirectPlayLobby3A_iface, flags,
|
|
appid, conn );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby2Impl_SetConnectionSettings( IDirectPlayLobby2 *iface,
|
|
DWORD flags, DWORD appid, DPLCONNECTION *conn )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2( iface );
|
|
return IDirectPlayLobby_SetConnectionSettings( &This->IDirectPlayLobby3_iface, flags,
|
|
appid, conn );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby3AImpl_SetConnectionSettings( IDirectPlayLobby3A *iface,
|
|
DWORD dwFlags, DWORD dwAppID, DPLCONNECTION *lpConn )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3A( iface );
|
|
HRESULT hr;
|
|
|
|
TRACE("(%p)->(0x%08x,0x%08x,%p)\n", This, dwFlags, dwAppID, lpConn );
|
|
|
|
EnterCriticalSection( &This->lock );
|
|
|
|
hr = DPLAYX_SetConnectionSettingsA( dwFlags, dwAppID, lpConn );
|
|
|
|
/* FIXME: Don't think that this is supposed to fail, but the documentation
|
|
is somewhat sketchy. I'll try creating a lobby application
|
|
for this... */
|
|
if( hr == DPERR_NOTLOBBIED )
|
|
{
|
|
FIXME( "Unlobbied app setting connections. Is this correct behavior?\n" );
|
|
dwAppID = GetCurrentProcessId();
|
|
DPLAYX_CreateLobbyApplication( dwAppID );
|
|
hr = DPLAYX_SetConnectionSettingsA( dwFlags, dwAppID, lpConn );
|
|
}
|
|
|
|
LeaveCriticalSection( &This->lock );
|
|
|
|
return hr;
|
|
}
|
|
|
|
/********************************************************************
|
|
*
|
|
* Registers an event that will be set when a lobby message is received.
|
|
*
|
|
*/
|
|
static HRESULT WINAPI IDirectPlayLobbyAImpl_SetLobbyMessageEvent( IDirectPlayLobbyA *iface,
|
|
DWORD flags, DWORD appid, HANDLE event )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobbyA( iface );
|
|
return IDirectPlayLobby_SetLobbyMessageEvent( &This->IDirectPlayLobby3A_iface, flags, appid,
|
|
event );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobbyImpl_SetLobbyMessageEvent( IDirectPlayLobby *iface,
|
|
DWORD flags, DWORD appid, HANDLE event )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby( iface );
|
|
return IDirectPlayLobby_SetLobbyMessageEvent( &This->IDirectPlayLobby3_iface, flags, appid,
|
|
event );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby2AImpl_SetLobbyMessageEvent( IDirectPlayLobby2A *iface,
|
|
DWORD flags, DWORD appid, HANDLE event )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2A( iface );
|
|
return IDirectPlayLobby_SetLobbyMessageEvent( &This->IDirectPlayLobby3A_iface, flags, appid,
|
|
event );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby2Impl_SetLobbyMessageEvent( IDirectPlayLobby2 *iface,
|
|
DWORD flags, DWORD appid, HANDLE event )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2( iface );
|
|
return IDirectPlayLobby_SetLobbyMessageEvent( &This->IDirectPlayLobby3_iface, flags, appid,
|
|
event );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby3AImpl_SetLobbyMessageEvent( IDirectPlayLobby3A *iface,
|
|
DWORD flags, DWORD appid, HANDLE event )
|
|
{
|
|
FIXME(":stub\n");
|
|
return DPERR_OUTOFMEMORY;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby3Impl_SetLobbyMessageEvent( IDirectPlayLobby3 *iface,
|
|
DWORD flags, DWORD appid, HANDLE event )
|
|
{
|
|
FIXME(":stub\n");
|
|
return DPERR_OUTOFMEMORY;
|
|
}
|
|
|
|
|
|
/* DPL 2 methods */
|
|
static HRESULT WINAPI IDirectPlayLobby2AImpl_CreateCompoundAddress( IDirectPlayLobby2A *iface,
|
|
const DPCOMPOUNDADDRESSELEMENT *elements, DWORD count, void *address, DWORD *size )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2A( iface );
|
|
return IDirectPlayLobby_CreateCompoundAddress( &This->IDirectPlayLobby3A_iface, elements,
|
|
count, address, size );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby2Impl_CreateCompoundAddress( IDirectPlayLobby2 *iface,
|
|
const DPCOMPOUNDADDRESSELEMENT *elements, DWORD count, void *address, DWORD *size )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2( iface );
|
|
return IDirectPlayLobby_CreateCompoundAddress( &This->IDirectPlayLobby3_iface, elements,
|
|
count, address, size );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby3Impl_CreateCompoundAddress( IDirectPlayLobby3 *iface,
|
|
const DPCOMPOUNDADDRESSELEMENT *lpElements, DWORD dwElementCount, void *lpAddress,
|
|
DWORD *lpdwAddressSize )
|
|
{
|
|
return DPL_CreateCompoundAddress( lpElements, dwElementCount, lpAddress, lpdwAddressSize, FALSE );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby3AImpl_CreateCompoundAddress( IDirectPlayLobby3A *iface,
|
|
const DPCOMPOUNDADDRESSELEMENT *lpElements, DWORD dwElementCount, void *lpAddress,
|
|
DWORD *lpdwAddressSize )
|
|
{
|
|
return DPL_CreateCompoundAddress( lpElements, dwElementCount, lpAddress, lpdwAddressSize, TRUE );
|
|
}
|
|
|
|
HRESULT DPL_CreateCompoundAddress
|
|
( LPCDPCOMPOUNDADDRESSELEMENT lpElements,
|
|
DWORD dwElementCount,
|
|
LPVOID lpAddress,
|
|
LPDWORD lpdwAddressSize,
|
|
BOOL bAnsiInterface )
|
|
{
|
|
DWORD dwSizeRequired = 0;
|
|
DWORD dwElements;
|
|
LPCDPCOMPOUNDADDRESSELEMENT lpOrigElements = lpElements;
|
|
|
|
TRACE("(%p,0x%08x,%p,%p)\n", lpElements, dwElementCount, lpAddress, lpdwAddressSize );
|
|
|
|
/* Parameter check */
|
|
if( ( lpElements == NULL ) ||
|
|
( dwElementCount == 0 ) /* FIXME: Not sure if this is a failure case */
|
|
)
|
|
{
|
|
return DPERR_INVALIDPARAMS;
|
|
}
|
|
|
|
/* Add the total size chunk */
|
|
dwSizeRequired += sizeof( DPADDRESS ) + sizeof( DWORD );
|
|
|
|
/* Calculate the size of the buffer required */
|
|
for ( dwElements = dwElementCount; dwElements > 0; --dwElements, ++lpElements )
|
|
{
|
|
if ( ( IsEqualGUID( &lpElements->guidDataType, &DPAID_ServiceProvider ) ) ||
|
|
( IsEqualGUID( &lpElements->guidDataType, &DPAID_LobbyProvider ) )
|
|
)
|
|
{
|
|
dwSizeRequired += sizeof( DPADDRESS ) + sizeof( GUID );
|
|
}
|
|
else if ( ( IsEqualGUID( &lpElements->guidDataType, &DPAID_Phone ) ) ||
|
|
( IsEqualGUID( &lpElements->guidDataType, &DPAID_Modem ) ) ||
|
|
( IsEqualGUID( &lpElements->guidDataType, &DPAID_INet ) )
|
|
)
|
|
{
|
|
if( !bAnsiInterface )
|
|
{
|
|
ERR( "Ansi GUIDs used for unicode interface\n" );
|
|
return DPERR_INVALIDFLAGS;
|
|
}
|
|
|
|
dwSizeRequired += sizeof( DPADDRESS ) + lpElements->dwDataSize;
|
|
}
|
|
else if ( ( IsEqualGUID( &lpElements->guidDataType, &DPAID_PhoneW ) ) ||
|
|
( IsEqualGUID( &lpElements->guidDataType, &DPAID_ModemW ) ) ||
|
|
( IsEqualGUID( &lpElements->guidDataType, &DPAID_INetW ) )
|
|
)
|
|
{
|
|
if( bAnsiInterface )
|
|
{
|
|
ERR( "Unicode GUIDs used for ansi interface\n" );
|
|
return DPERR_INVALIDFLAGS;
|
|
}
|
|
|
|
FIXME( "Right size for unicode interface?\n" );
|
|
dwSizeRequired += sizeof( DPADDRESS ) + lpElements->dwDataSize * sizeof( WCHAR );
|
|
}
|
|
else if ( IsEqualGUID( &lpElements->guidDataType, &DPAID_INetPort ) )
|
|
{
|
|
dwSizeRequired += sizeof( DPADDRESS ) + sizeof( WORD );
|
|
}
|
|
else if ( IsEqualGUID( &lpElements->guidDataType, &DPAID_ComPort ) )
|
|
{
|
|
FIXME( "Right size for unicode interface?\n" );
|
|
dwSizeRequired += sizeof( DPADDRESS ) + sizeof( DPCOMPORTADDRESS ); /* FIXME: Right size? */
|
|
}
|
|
else
|
|
{
|
|
WARN( "Skipping Unknown GUID %s\n", debugstr_guid(&lpElements->guidDataType) );
|
|
}
|
|
}
|
|
|
|
/* The user wants to know how big a buffer to allocate for us */
|
|
if( ( lpAddress == NULL ) ||
|
|
( *lpdwAddressSize < dwSizeRequired )
|
|
)
|
|
{
|
|
*lpdwAddressSize = dwSizeRequired;
|
|
return DPERR_BUFFERTOOSMALL;
|
|
}
|
|
|
|
/* Add the total size chunk */
|
|
{
|
|
LPDPADDRESS lpdpAddress = lpAddress;
|
|
|
|
lpdpAddress->guidDataType = DPAID_TotalSize;
|
|
lpdpAddress->dwDataSize = sizeof( DWORD );
|
|
lpAddress = (char *) lpAddress + sizeof( DPADDRESS );
|
|
|
|
*(LPDWORD)lpAddress = dwSizeRequired;
|
|
lpAddress = (char *) lpAddress + sizeof( DWORD );
|
|
}
|
|
|
|
/* Calculate the size of the buffer required */
|
|
for( dwElements = dwElementCount, lpElements = lpOrigElements;
|
|
dwElements > 0;
|
|
--dwElements, ++lpElements )
|
|
{
|
|
if ( ( IsEqualGUID( &lpElements->guidDataType, &DPAID_ServiceProvider ) ) ||
|
|
( IsEqualGUID( &lpElements->guidDataType, &DPAID_LobbyProvider ) )
|
|
)
|
|
{
|
|
LPDPADDRESS lpdpAddress = lpAddress;
|
|
|
|
lpdpAddress->guidDataType = lpElements->guidDataType;
|
|
lpdpAddress->dwDataSize = sizeof( GUID );
|
|
lpAddress = (char *) lpAddress + sizeof( DPADDRESS );
|
|
|
|
CopyMemory( lpAddress, lpElements->lpData, sizeof( GUID ) );
|
|
lpAddress = (char *) lpAddress + sizeof( GUID );
|
|
}
|
|
else if ( ( IsEqualGUID( &lpElements->guidDataType, &DPAID_Phone ) ) ||
|
|
( IsEqualGUID( &lpElements->guidDataType, &DPAID_Modem ) ) ||
|
|
( IsEqualGUID( &lpElements->guidDataType, &DPAID_INet ) )
|
|
)
|
|
{
|
|
LPDPADDRESS lpdpAddress = lpAddress;
|
|
|
|
lpdpAddress->guidDataType = lpElements->guidDataType;
|
|
lpdpAddress->dwDataSize = lpElements->dwDataSize;
|
|
lpAddress = (char *) lpAddress + sizeof( DPADDRESS );
|
|
|
|
lstrcpynA( lpAddress, lpElements->lpData, lpElements->dwDataSize );
|
|
lpAddress = (char *) lpAddress + lpElements->dwDataSize;
|
|
}
|
|
else if ( ( IsEqualGUID( &lpElements->guidDataType, &DPAID_PhoneW ) ) ||
|
|
( IsEqualGUID( &lpElements->guidDataType, &DPAID_ModemW ) ) ||
|
|
( IsEqualGUID( &lpElements->guidDataType, &DPAID_INetW ) )
|
|
)
|
|
{
|
|
LPDPADDRESS lpdpAddress = lpAddress;
|
|
|
|
lpdpAddress->guidDataType = lpElements->guidDataType;
|
|
lpdpAddress->dwDataSize = lpElements->dwDataSize;
|
|
lpAddress = (char *) lpAddress + sizeof( DPADDRESS );
|
|
|
|
lstrcpynW( lpAddress, lpElements->lpData, lpElements->dwDataSize );
|
|
lpAddress = (char *) lpAddress + lpElements->dwDataSize * sizeof( WCHAR );
|
|
}
|
|
else if ( IsEqualGUID( &lpElements->guidDataType, &DPAID_INetPort ) )
|
|
{
|
|
LPDPADDRESS lpdpAddress = lpAddress;
|
|
|
|
lpdpAddress->guidDataType = lpElements->guidDataType;
|
|
lpdpAddress->dwDataSize = lpElements->dwDataSize;
|
|
lpAddress = (char *) lpAddress + sizeof( DPADDRESS );
|
|
|
|
*((LPWORD)lpAddress) = *((LPWORD)lpElements->lpData);
|
|
lpAddress = (char *) lpAddress + sizeof( WORD );
|
|
}
|
|
else if ( IsEqualGUID( &lpElements->guidDataType, &DPAID_ComPort ) )
|
|
{
|
|
LPDPADDRESS lpdpAddress = lpAddress;
|
|
|
|
lpdpAddress->guidDataType = lpElements->guidDataType;
|
|
lpdpAddress->dwDataSize = lpElements->dwDataSize;
|
|
lpAddress = (char *) lpAddress + sizeof( DPADDRESS );
|
|
|
|
CopyMemory( lpAddress, lpElements->lpData, sizeof( DPADDRESS ) );
|
|
lpAddress = (char *) lpAddress + sizeof( DPADDRESS );
|
|
}
|
|
}
|
|
|
|
return DP_OK;
|
|
}
|
|
|
|
/* DPL 3 methods */
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby3Impl_ConnectEx( IDirectPlayLobby3 *iface, DWORD dwFlags,
|
|
REFIID riid, LPVOID* lplpDP, IUnknown* pUnk )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3( iface );
|
|
return DPL_ConnectEx( This, dwFlags, riid, lplpDP, pUnk );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby3AImpl_ConnectEx( IDirectPlayLobby3A *iface, DWORD dwFlags,
|
|
REFIID riid, void **lplpDP, IUnknown *pUnk )
|
|
{
|
|
IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3A( iface );
|
|
return DPL_ConnectEx( This, dwFlags, riid, lplpDP, pUnk );
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby3Impl_RegisterApplication( IDirectPlayLobby3 *iface,
|
|
DWORD flags, DPAPPLICATIONDESC *appdesc )
|
|
{
|
|
FIXME(":stub\n");
|
|
return DP_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby3AImpl_RegisterApplication( IDirectPlayLobby3A *iface,
|
|
DWORD flags, DPAPPLICATIONDESC *appdesc )
|
|
{
|
|
FIXME(":stub\n");
|
|
return DP_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby3Impl_UnregisterApplication( IDirectPlayLobby3 *iface,
|
|
DWORD flags, REFGUID appdesc )
|
|
{
|
|
FIXME(":stub\n");
|
|
return DP_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby3AImpl_UnregisterApplication( IDirectPlayLobby3A *iface,
|
|
DWORD flags, REFGUID appdesc )
|
|
{
|
|
FIXME(":stub\n");
|
|
return DP_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby3Impl_WaitForConnectionSettings( IDirectPlayLobby3 *iface,
|
|
DWORD dwFlags )
|
|
{
|
|
HRESULT hr = DP_OK;
|
|
BOOL bStartWait = !(dwFlags & DPLWAIT_CANCEL);
|
|
|
|
TRACE( "(%p)->(0x%08x)\n", iface, dwFlags );
|
|
|
|
if( DPLAYX_WaitForConnectionSettings( bStartWait ) )
|
|
{
|
|
/* FIXME: What is the correct error return code? */
|
|
hr = DPERR_NOTLOBBIED;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectPlayLobby3AImpl_WaitForConnectionSettings( IDirectPlayLobby3A *iface,
|
|
DWORD dwFlags )
|
|
{
|
|
HRESULT hr = DP_OK;
|
|
BOOL bStartWait = !(dwFlags & DPLWAIT_CANCEL);
|
|
|
|
TRACE( "(%p)->(0x%08x)\n", iface, dwFlags );
|
|
|
|
if( DPLAYX_WaitForConnectionSettings( bStartWait ) )
|
|
{
|
|
/* FIXME: What is the correct error return code? */
|
|
hr = DPERR_NOTLOBBIED;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
static const IDirectPlayLobbyVtbl dplA_vt =
|
|
{
|
|
IDirectPlayLobbyAImpl_QueryInterface,
|
|
IDirectPlayLobbyAImpl_AddRef,
|
|
IDirectPlayLobbyAImpl_Release,
|
|
IDirectPlayLobbyAImpl_Connect,
|
|
IDirectPlayLobbyAImpl_CreateAddress,
|
|
IDirectPlayLobbyAImpl_EnumAddress,
|
|
IDirectPlayLobbyAImpl_EnumAddressTypes,
|
|
IDirectPlayLobbyAImpl_EnumLocalApplications,
|
|
IDirectPlayLobbyAImpl_GetConnectionSettings,
|
|
IDirectPlayLobbyAImpl_ReceiveLobbyMessage,
|
|
IDirectPlayLobbyAImpl_RunApplication,
|
|
IDirectPlayLobbyAImpl_SendLobbyMessage,
|
|
IDirectPlayLobbyAImpl_SetConnectionSettings,
|
|
IDirectPlayLobbyAImpl_SetLobbyMessageEvent
|
|
};
|
|
|
|
static const IDirectPlayLobbyVtbl dpl_vt =
|
|
{
|
|
IDirectPlayLobbyImpl_QueryInterface,
|
|
IDirectPlayLobbyImpl_AddRef,
|
|
IDirectPlayLobbyImpl_Release,
|
|
IDirectPlayLobbyImpl_Connect,
|
|
IDirectPlayLobbyImpl_CreateAddress,
|
|
IDirectPlayLobbyImpl_EnumAddress,
|
|
IDirectPlayLobbyImpl_EnumAddressTypes,
|
|
IDirectPlayLobbyImpl_EnumLocalApplications,
|
|
IDirectPlayLobbyImpl_GetConnectionSettings,
|
|
IDirectPlayLobbyImpl_ReceiveLobbyMessage,
|
|
IDirectPlayLobbyImpl_RunApplication,
|
|
IDirectPlayLobbyImpl_SendLobbyMessage,
|
|
IDirectPlayLobbyImpl_SetConnectionSettings,
|
|
IDirectPlayLobbyImpl_SetLobbyMessageEvent
|
|
};
|
|
|
|
static const IDirectPlayLobby2Vtbl dpl2A_vt =
|
|
{
|
|
IDirectPlayLobby2AImpl_QueryInterface,
|
|
IDirectPlayLobby2AImpl_AddRef,
|
|
IDirectPlayLobby2AImpl_Release,
|
|
IDirectPlayLobby2AImpl_Connect,
|
|
IDirectPlayLobby2AImpl_CreateAddress,
|
|
IDirectPlayLobby2AImpl_EnumAddress,
|
|
IDirectPlayLobby2AImpl_EnumAddressTypes,
|
|
IDirectPlayLobby2AImpl_EnumLocalApplications,
|
|
IDirectPlayLobby2AImpl_GetConnectionSettings,
|
|
IDirectPlayLobby2AImpl_ReceiveLobbyMessage,
|
|
IDirectPlayLobby2AImpl_RunApplication,
|
|
IDirectPlayLobby2AImpl_SendLobbyMessage,
|
|
IDirectPlayLobby2AImpl_SetConnectionSettings,
|
|
IDirectPlayLobby2AImpl_SetLobbyMessageEvent,
|
|
IDirectPlayLobby2AImpl_CreateCompoundAddress
|
|
};
|
|
|
|
static const IDirectPlayLobby2Vtbl dpl2_vt =
|
|
{
|
|
IDirectPlayLobby2Impl_QueryInterface,
|
|
IDirectPlayLobby2Impl_AddRef,
|
|
IDirectPlayLobby2Impl_Release,
|
|
IDirectPlayLobby2Impl_Connect,
|
|
IDirectPlayLobby2Impl_CreateAddress,
|
|
IDirectPlayLobby2Impl_EnumAddress,
|
|
IDirectPlayLobby2Impl_EnumAddressTypes,
|
|
IDirectPlayLobby2Impl_EnumLocalApplications,
|
|
IDirectPlayLobby2Impl_GetConnectionSettings,
|
|
IDirectPlayLobby2Impl_ReceiveLobbyMessage,
|
|
IDirectPlayLobby2Impl_RunApplication,
|
|
IDirectPlayLobby2Impl_SendLobbyMessage,
|
|
IDirectPlayLobby2Impl_SetConnectionSettings,
|
|
IDirectPlayLobby2Impl_SetLobbyMessageEvent,
|
|
IDirectPlayLobby2Impl_CreateCompoundAddress
|
|
};
|
|
|
|
static const IDirectPlayLobby3Vtbl dpl3A_vt =
|
|
{
|
|
IDirectPlayLobby3AImpl_QueryInterface,
|
|
IDirectPlayLobby3AImpl_AddRef,
|
|
IDirectPlayLobby3AImpl_Release,
|
|
IDirectPlayLobby3AImpl_Connect,
|
|
IDirectPlayLobby3AImpl_CreateAddress,
|
|
IDirectPlayLobby3AImpl_EnumAddress,
|
|
IDirectPlayLobby3AImpl_EnumAddressTypes,
|
|
IDirectPlayLobby3AImpl_EnumLocalApplications,
|
|
IDirectPlayLobby3AImpl_GetConnectionSettings,
|
|
IDirectPlayLobby3AImpl_ReceiveLobbyMessage,
|
|
IDirectPlayLobby3AImpl_RunApplication,
|
|
IDirectPlayLobby3AImpl_SendLobbyMessage,
|
|
IDirectPlayLobby3AImpl_SetConnectionSettings,
|
|
IDirectPlayLobby3AImpl_SetLobbyMessageEvent,
|
|
IDirectPlayLobby3AImpl_CreateCompoundAddress,
|
|
IDirectPlayLobby3AImpl_ConnectEx,
|
|
IDirectPlayLobby3AImpl_RegisterApplication,
|
|
IDirectPlayLobby3AImpl_UnregisterApplication,
|
|
IDirectPlayLobby3AImpl_WaitForConnectionSettings
|
|
};
|
|
|
|
static const IDirectPlayLobby3Vtbl dpl3_vt =
|
|
{
|
|
IDirectPlayLobby3Impl_QueryInterface,
|
|
IDirectPlayLobby3Impl_AddRef,
|
|
IDirectPlayLobby3Impl_Release,
|
|
IDirectPlayLobby3Impl_Connect,
|
|
IDirectPlayLobby3Impl_CreateAddress,
|
|
IDirectPlayLobby3Impl_EnumAddress,
|
|
IDirectPlayLobby3Impl_EnumAddressTypes,
|
|
IDirectPlayLobby3Impl_EnumLocalApplications,
|
|
IDirectPlayLobby3Impl_GetConnectionSettings,
|
|
IDirectPlayLobby3Impl_ReceiveLobbyMessage,
|
|
IDirectPlayLobby3Impl_RunApplication,
|
|
IDirectPlayLobby3Impl_SendLobbyMessage,
|
|
IDirectPlayLobby3Impl_SetConnectionSettings,
|
|
IDirectPlayLobby3Impl_SetLobbyMessageEvent,
|
|
IDirectPlayLobby3Impl_CreateCompoundAddress,
|
|
IDirectPlayLobby3Impl_ConnectEx,
|
|
IDirectPlayLobby3Impl_RegisterApplication,
|
|
IDirectPlayLobby3Impl_UnregisterApplication,
|
|
IDirectPlayLobby3Impl_WaitForConnectionSettings
|
|
};
|
|
|
|
HRESULT dplobby_create( REFIID riid, void **ppv )
|
|
{
|
|
IDirectPlayLobbyImpl *obj;
|
|
HRESULT hr;
|
|
|
|
TRACE( "(%s, %p)\n", debugstr_guid( riid ), ppv );
|
|
|
|
*ppv = NULL;
|
|
obj = HeapAlloc( GetProcessHeap(), 0, sizeof( *obj ) );
|
|
if ( !obj )
|
|
return DPERR_OUTOFMEMORY;
|
|
|
|
obj->IDirectPlayLobby_iface.lpVtbl = &dpl_vt;
|
|
obj->IDirectPlayLobbyA_iface.lpVtbl = &dplA_vt;
|
|
obj->IDirectPlayLobby2_iface.lpVtbl = &dpl2_vt;
|
|
obj->IDirectPlayLobby2A_iface.lpVtbl = &dpl2A_vt;
|
|
obj->IDirectPlayLobby3_iface.lpVtbl = &dpl3_vt;
|
|
obj->IDirectPlayLobby3A_iface.lpVtbl = &dpl3A_vt;
|
|
obj->numIfaces = 1;
|
|
obj->msgtid = 0;
|
|
obj->ref = 0;
|
|
obj->refA = 0;
|
|
obj->ref2 = 0;
|
|
obj->ref2A = 0;
|
|
obj->ref3 = 1;
|
|
obj->ref3A = 0;
|
|
|
|
InitializeCriticalSection( &obj->lock );
|
|
obj->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IDirectPlayLobbyImpl.lock");
|
|
DPQ_INIT( obj->msgs );
|
|
|
|
hr = IDirectPlayLobby_QueryInterface( &obj->IDirectPlayLobby3_iface, riid, ppv );
|
|
IDirectPlayLobby_Release( &obj->IDirectPlayLobby3_iface );
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
* DirectPlayLobbyCreateA (DPLAYX.4)
|
|
*
|
|
*/
|
|
HRESULT WINAPI DirectPlayLobbyCreateA( GUID *lpGUIDDSP, IDirectPlayLobbyA **lplpDPL,
|
|
IUnknown *lpUnk, void *lpData, DWORD dwDataSize )
|
|
{
|
|
TRACE("lpGUIDDSP=%p lplpDPL=%p lpUnk=%p lpData=%p dwDataSize=%08x\n",
|
|
lpGUIDDSP,lplpDPL,lpUnk,lpData,dwDataSize);
|
|
|
|
/* Parameter Check: lpGUIDSP, lpUnk & lpData must be NULL. dwDataSize must
|
|
* equal 0. These fields are mostly for future expansion.
|
|
*/
|
|
if ( lpGUIDDSP || lpData || dwDataSize )
|
|
{
|
|
*lplpDPL = NULL;
|
|
return DPERR_INVALIDPARAMS;
|
|
}
|
|
|
|
if( lpUnk )
|
|
{
|
|
*lplpDPL = NULL;
|
|
ERR("Bad parameters!\n" );
|
|
return CLASS_E_NOAGGREGATION;
|
|
}
|
|
|
|
return dplobby_create( &IID_IDirectPlayLobbyA, (void**)lplpDPL );
|
|
}
|
|
|
|
/***************************************************************************
|
|
* DirectPlayLobbyCreateW (DPLAYX.5)
|
|
*
|
|
*/
|
|
HRESULT WINAPI DirectPlayLobbyCreateW( GUID *lpGUIDDSP, IDirectPlayLobby **lplpDPL,
|
|
IUnknown *lpUnk, void *lpData, DWORD dwDataSize )
|
|
{
|
|
TRACE("lpGUIDDSP=%p lplpDPL=%p lpUnk=%p lpData=%p dwDataSize=%08x\n",
|
|
lpGUIDDSP,lplpDPL,lpUnk,lpData,dwDataSize);
|
|
|
|
/* Parameter Check: lpGUIDSP, lpUnk & lpData must be NULL. dwDataSize must
|
|
* equal 0. These fields are mostly for future expansion.
|
|
*/
|
|
if ( lpGUIDDSP || lpData || dwDataSize )
|
|
{
|
|
*lplpDPL = NULL;
|
|
ERR("Bad parameters!\n" );
|
|
return DPERR_INVALIDPARAMS;
|
|
}
|
|
|
|
if( lpUnk )
|
|
{
|
|
*lplpDPL = NULL;
|
|
ERR("Bad parameters!\n" );
|
|
return CLASS_E_NOAGGREGATION;
|
|
}
|
|
|
|
return dplobby_create( &IID_IDirectPlayLobby, (void**)lplpDPL );
|
|
}
|