📄 dplobby.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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdarg.h>
#include <string.h>
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
#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"
#include "dpinit.h"
WINE_DEFAULT_DEBUG_CHANNEL(dplay);
/*****************************************************************************
* Predeclare the interface implementation structures
*/
typedef struct IDirectPlayLobbyImpl IDirectPlayLobbyAImpl;
typedef struct IDirectPlayLobbyImpl IDirectPlayLobbyWImpl;
typedef struct IDirectPlayLobby2Impl IDirectPlayLobby2AImpl;
typedef struct IDirectPlayLobby2Impl IDirectPlayLobby2WImpl;
typedef struct IDirectPlayLobby3Impl IDirectPlayLobby3AImpl;
typedef struct IDirectPlayLobby3Impl IDirectPlayLobby3WImpl;
/* Forward declarations for this module helper methods */
HRESULT DPL_CreateCompoundAddress ( LPCDPCOMPOUNDADDRESSELEMENT lpElements, DWORD dwElementCount,
LPVOID lpAddress, LPDWORD lpdwAddressSize, BOOL bAnsiInterface );
HRESULT DPL_CreateAddress( REFGUID guidSP, REFGUID guidDataType, LPCVOID lpData, DWORD dwDataSize,
LPVOID lpAddress, LPDWORD lpdwAddressSize, BOOL bAnsiInterface );
extern HRESULT DPL_EnumAddress( LPDPENUMADDRESSCALLBACK lpEnumAddressCallback, LPCVOID lpAddress,
DWORD dwAddressSize, LPVOID lpContext );
static HRESULT WINAPI DPL_ConnectEx( IDirectPlayLobbyAImpl* This,
DWORD dwFlags, REFIID riid,
LPVOID* lplpDP, IUnknown* pUnk );
BOOL DPL_CreateAndSetLobbyHandles( DWORD dwDestProcessId, HANDLE hDestProcess,
LPHANDLE lphStart, LPHANDLE lphDeath,
LPHANDLE lphRead );
/*****************************************************************************
* 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 tagDirectPlayLobbyIUnknownData
{
LONG ulObjRef;
CRITICAL_SECTION DPL_lock;
} DirectPlayLobbyIUnknownData;
typedef struct tagDirectPlayLobbyData
{
HKEY hkCallbackKeyHack;
DWORD dwMsgThread;
DPQ_HEAD( DPLMSG ) msgs; /* List of messages received */
} DirectPlayLobbyData;
typedef struct tagDirectPlayLobby2Data
{
BOOL dummy;
} DirectPlayLobby2Data;
typedef struct tagDirectPlayLobby3Data
{
BOOL dummy;
} DirectPlayLobby3Data;
#define DPL_IMPL_FIELDS \
LONG ulInterfaceRef; \
DirectPlayLobbyIUnknownData* unk; \
DirectPlayLobbyData* dpl; \
DirectPlayLobby2Data* dpl2; \
DirectPlayLobby3Data* dpl3;
struct IDirectPlayLobbyImpl
{
const IDirectPlayLobbyVtbl *lpVtbl;
DPL_IMPL_FIELDS
};
struct IDirectPlayLobby2Impl
{
const IDirectPlayLobby2Vtbl *lpVtbl;
DPL_IMPL_FIELDS
};
struct IDirectPlayLobby3Impl
{
const IDirectPlayLobby3Vtbl *lpVtbl;
DPL_IMPL_FIELDS
};
/* Forward declarations of virtual tables */
static const IDirectPlayLobbyVtbl directPlayLobbyWVT;
static const IDirectPlayLobby2Vtbl directPlayLobby2WVT;
static const IDirectPlayLobby3Vtbl directPlayLobby3WVT;
static const IDirectPlayLobbyVtbl directPlayLobbyAVT;
static const IDirectPlayLobby2Vtbl directPlayLobby2AVT;
static const IDirectPlayLobby3Vtbl directPlayLobby3AVT;
static BOOL DPL_CreateIUnknown( LPVOID lpDPL )
{
IDirectPlayLobbyAImpl *This = (IDirectPlayLobbyAImpl *)lpDPL;
This->unk = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->unk) ) );
if ( This->unk == NULL )
{
return FALSE;
}
InitializeCriticalSection( &This->unk->DPL_lock );
return TRUE;
}
static BOOL DPL_DestroyIUnknown( LPVOID lpDPL )
{
IDirectPlayLobbyAImpl *This = (IDirectPlayLobbyAImpl *)lpDPL;
DeleteCriticalSection( &This->unk->DPL_lock );
HeapFree( GetProcessHeap(), 0, This->unk );
return TRUE;
}
static BOOL DPL_CreateLobby1( LPVOID lpDPL )
{
IDirectPlayLobbyAImpl *This = (IDirectPlayLobbyAImpl *)lpDPL;
This->dpl = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->dpl) ) );
if ( This->dpl == NULL )
{
return FALSE;
}
DPQ_INIT( This->dpl->msgs );
return TRUE;
}
static BOOL DPL_DestroyLobby1( LPVOID lpDPL )
{
IDirectPlayLobbyAImpl *This = (IDirectPlayLobbyAImpl *)lpDPL;
if( This->dpl->dwMsgThread )
{
FIXME( "Should kill the msg thread\n" );
}
DPQ_DELETEQ( This->dpl->msgs, msgs, LPDPLMSG, cbDeleteElemFromHeap );
/* Delete the contents */
HeapFree( GetProcessHeap(), 0, This->dpl );
return TRUE;
}
static BOOL DPL_CreateLobby2( LPVOID lpDPL )
{
IDirectPlayLobby2AImpl *This = (IDirectPlayLobby2AImpl *)lpDPL;
This->dpl2 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->dpl2) ) );
if ( This->dpl2 == NULL )
{
return FALSE;
}
return TRUE;
}
static BOOL DPL_DestroyLobby2( LPVOID lpDPL )
{
IDirectPlayLobby2AImpl *This = (IDirectPlayLobby2AImpl *)lpDPL;
HeapFree( GetProcessHeap(), 0, This->dpl2 );
return TRUE;
}
static BOOL DPL_CreateLobby3( LPVOID lpDPL )
{
IDirectPlayLobby3AImpl *This = (IDirectPlayLobby3AImpl *)lpDPL;
This->dpl3 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->dpl3) ) );
if ( This->dpl3 == NULL )
{
return FALSE;
}
return TRUE;
}
static BOOL DPL_DestroyLobby3( LPVOID lpDPL )
{
IDirectPlayLobby3AImpl *This = (IDirectPlayLobby3AImpl *)lpDPL;
HeapFree( GetProcessHeap(), 0, This->dpl3 );
return TRUE;
}
/* The COM interface for upversioning an interface
* We've been given a GUID (riid) and we need to replace the present
* interface with that of the requested interface.
*
* Snip from some Microsoft document:
* There are four requirements for implementations of QueryInterface (In these
* cases, "must succeed" means "must succeed barring catastrophic failure."):
*
* * The set of interfaces accessible on an object through
* IUnknown::QueryInterface must be static, not dynamic. This means that
* if a call to QueryInterface for a pointer to a specified interface
* succeeds the first time, it must succeed again, and if it fails the
* first time, it must fail on all subsequent queries.
* * It must be symmetric ~W if a client holds a pointer to an interface on
* an object, and queries for that interface, the call must succeed.
* * It must be reflexive ~W if a client holding a pointer to one interface
* queries successfully for another, a query through the obtained pointer
* for the first interface must succeed.
* * It must be transitive ~W if a client holding a pointer to one interface
* queries successfully for a second, and through that pointer queries
* successfully for a third interface, a query for the first interface
* through the pointer for the third interface must succeed.
*/
extern
HRESULT DPL_CreateInterface
( REFIID riid, LPVOID* ppvObj )
{
TRACE( " for %s\n", debugstr_guid( riid ) );
*ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof( IDirectPlayLobbyWImpl ) );
if( *ppvObj == NULL )
{
return DPERR_OUTOFMEMORY;
}
if( IsEqualGUID( &IID_IDirectPlayLobby, riid ) )
{
IDirectPlayLobbyWImpl *This = (IDirectPlayLobbyWImpl *)*ppvObj;
This->lpVtbl = &directPlayLobbyWVT;
}
else if( IsEqualGUID( &IID_IDirectPlayLobbyA, riid ) )
{
IDirectPlayLobbyAImpl *This = (IDirectPlayLobbyAImpl *)*ppvObj;
This->lpVtbl = &directPlayLobbyAVT;
}
else if( IsEqualGUID( &IID_IDirectPlayLobby2, riid ) )
{
IDirectPlayLobby2WImpl *This = (IDirectPlayLobby2WImpl *)*ppvObj;
This->lpVtbl = &directPlayLobby2WVT;
}
else if( IsEqualGUID( &IID_IDirectPlayLobby2A, riid ) )
{
IDirectPlayLobby2AImpl *This = (IDirectPlayLobby2AImpl *)*ppvObj;
This->lpVtbl = &directPlayLobby2AVT;
}
else if( IsEqualGUID( &IID_IDirectPlayLobby3, riid ) )
{
IDirectPlayLobby3WImpl *This = (IDirectPlayLobby3WImpl *)*ppvObj;
This->lpVtbl = &directPlayLobby3WVT;
}
else if( IsEqualGUID( &IID_IDirectPlayLobby3A, riid ) )
{
IDirectPlayLobby3AImpl *This = (IDirectPlayLobby3AImpl *)*ppvObj;
This->lpVtbl = &directPlayLobby3AVT;
}
else
{
/* Unsupported interface */
HeapFree( GetProcessHeap(), 0, *ppvObj );
*ppvObj = NULL;
return E_NOINTERFACE;
}
/* Initialize it */
if ( DPL_CreateIUnknown( *ppvObj ) &&
DPL_CreateLobby1( *ppvObj ) &&
DPL_CreateLobby2( *ppvObj ) &&
DPL_CreateLobby3( *ppvObj )
)
{
IDirectPlayLobby_AddRef( (LPDIRECTPLAYLOBBY)*ppvObj );
return S_OK;
}
/* Initialize failed, destroy it */
DPL_DestroyLobby3( *ppvObj );
DPL_DestroyLobby2( *ppvObj );
DPL_DestroyLobby1( *ppvObj );
DPL_DestroyIUnknown( *ppvObj );
HeapFree( GetProcessHeap(), 0, *ppvObj );
*ppvObj = NULL;
return DPERR_NOMEMORY;
}
static HRESULT WINAPI DPL_QueryInterface
( LPDIRECTPLAYLOBBYA iface,
REFIID riid,
LPVOID* ppvObj )
{
IDirectPlayLobbyAImpl *This = (IDirectPlayLobbyAImpl *)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 ) );
(*(IDirectPlayLobbyAImpl**)ppvObj)->ulInterfaceRef = 0;
if( IsEqualGUID( &IID_IDirectPlayLobby, riid ) )
{
IDirectPlayLobbyWImpl *This = (IDirectPlayLobbyWImpl *)*ppvObj;
This->lpVtbl = &directPlayLobbyWVT;
}
else if( IsEqualGUID( &IID_IDirectPlayLobbyA, riid ) )
{
IDirectPlayLobbyAImpl *This = (IDirectPlayLobbyAImpl *)*ppvObj;
This->lpVtbl = &directPlayLobbyAVT;
}
else if( IsEqualGUID( &IID_IDirectPlayLobby2, riid ) )
{
IDirectPlayLobby2WImpl *This = (IDirectPlayLobby2WImpl *)*ppvObj;
This->lpVtbl = &directPlayLobby2WVT;
}
else if( IsEqualGUID( &IID_IDirectPlayLobby2A, riid ) )
{
IDirectPlayLobby2AImpl *This = (IDirectPlayLobby2AImpl *)*ppvObj;
This->lpVtbl = &directPlayLobby2AVT;
}
else if( IsEqualGUID( &IID_IDirectPlayLobby3, riid ) )
{
IDirectPlayLobby3WImpl *This = (IDirectPlayLobby3WImpl *)*ppvObj;
This->lpVtbl = &directPlayLobby3WVT;
}
else if( IsEqualGUID( &IID_IDirectPlayLobby3A, riid ) )
{
IDirectPlayLobby3AImpl *This = (IDirectPlayLobby3AImpl *)*ppvObj;
This->lpVtbl = &directPlayLobby3AVT;
}
else
{
/* Unsupported interface */
HeapFree( GetProcessHeap(), 0, *ppvObj );
*ppvObj = NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -