/* Direct Play Lobby 2 & 3 Implementation * * Copyright 1998,1999 - Peter Hunnisett * * * */ #include #include "winerror.h" #include "winnt.h" #include "winreg.h" #include "dplobby.h" #include "heap.h" #include "debugtools.h" DEFAULT_DEBUG_CHANNEL(dplay) /***************************************************************************** * Predeclare the interface implementation structures */ typedef struct IDirectPlayLobbyImpl IDirectPlayLobbyImpl; typedef struct IDirectPlayLobbyImpl IDirectPlayLobbyAImpl; typedef struct IDirectPlayLobbyImpl IDirectPlayLobbyWImpl; typedef struct IDirectPlayLobbyImpl IDirectPlayLobby2Impl; typedef struct IDirectPlayLobbyImpl IDirectPlayLobby2AImpl; typedef struct IDirectPlayLobbyImpl IDirectPlayLobby3Impl; typedef struct IDirectPlayLobbyImpl IDirectPlayLobby3AImpl; /***************************************************************************** * IDirectPlayLobby {1,2,3} implementation structure * * The philosophy behind this extra pointer derefernce is that I wanted to * have the same structure for all types of objects without having to do * alot 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. * */ typedef struct tagDirectPlayLobbyIUnknownData { DWORD ref; CRITICAL_SECTION DPL_lock; } DirectPlayLobbyIUnknownData; /* FIXME: I don't think that everything belongs here...*/ typedef struct tagDirectPlayLobbyData { DWORD dwConnFlags; DPSESSIONDESC2 sessionDesc; DPNAME playerName; GUID guidSP; LPVOID lpAddress; DWORD dwAddressSize; } DirectPlayLobbyData; typedef struct tagDirectPlayLobby2Data { BOOL dummy; } DirectPlayLobby2Data; typedef struct tagDirectPlayLobby3Data { BOOL dummy; } DirectPlayLobby3Data; struct IDirectPlayLobbyImpl { ICOM_VFIELD(IDirectPlayLobby); /* IUnknown fields */ DirectPlayLobbyIUnknownData* unk; /* IDirectPlayLobby 1 fields */ DirectPlayLobbyData* dpl; /* IDirectPlayLobby 2 fields */ DirectPlayLobby2Data* dpl2; /* IDirectPlayLobby 3 fields */ DirectPlayLobby3Data* dpl3; }; /* Forward declarations of virtual tables */ static ICOM_VTABLE(IDirectPlayLobby) directPlayLobbyAVT; static ICOM_VTABLE(IDirectPlayLobby) directPlayLobbyWVT; static ICOM_VTABLE(IDirectPlayLobby2) directPlayLobby2AVT; static ICOM_VTABLE(IDirectPlayLobby2) directPlayLobby2WVT; static ICOM_VTABLE(IDirectPlayLobby3) directPlayLobby3AVT; static ICOM_VTABLE(IDirectPlayLobby3) directPlayLobby3WVT; /* 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. * * As you can see, this interface doesn't qualify but will most likely * be good enough for the time being. */ BOOL DPL_CreateIUnknown( IDirectPlayLobbyImpl* lpDPL ) { lpDPL->unk = (DirectPlayLobbyIUnknownData*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(lpDPL->unk) ) ); if ( lpDPL->unk != NULL ) { InitializeCriticalSection( &lpDPL->unk->DPL_lock ); IDirectPlayLobby_AddRef( (IDirectPlayLobby*)lpDPL ); return TRUE; } return FALSE; } BOOL DPL_DestroyIUnknown( IDirectPlayLobbyImpl* lpDPL ) { DeleteCriticalSection( &lpDPL->unk->DPL_lock ); HeapFree( GetProcessHeap(), 0, lpDPL->unk ); return TRUE; } BOOL DPL_CreateLobby1( IDirectPlayLobbyImpl* lpDPL ) { lpDPL->dpl = (DirectPlayLobbyIUnknownData*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(lpDPL->dpl) ) ); if ( lpDPL->dpl == NULL ) { return FALSE; } /* Initialize the dwSize fields for internal structures */ lpDPL->dpl->sessionDesc.dwSize = sizeof( lpDPL->dpl->sessionDesc ); lpDPL->dpl->playerName.dwSize = sizeof( lpDPL->dpl->playerName ); /* lpDPL->dpl->dwAddressSize = 0; Done in HeapAlloc */ return TRUE; } BOOL DPL_DestroyLobby1( IDirectPlayLobbyImpl* lpDPL ) { /* Delete the contents */ HeapFree( GetProcessHeap(), 0, lpDPL->dpl->sessionDesc.sess.lpszSessionNameA ); HeapFree( GetProcessHeap(), 0, lpDPL->dpl->sessionDesc.pass.lpszPasswordA ); HeapFree( GetProcessHeap(), 0, lpDPL->dpl->playerName.psn.lpszShortNameA ); HeapFree( GetProcessHeap(), 0, lpDPL->dpl->playerName.pln.lpszLongNameA ); HeapFree( GetProcessHeap(), 0, lpDPL->dpl->lpAddress ); HeapFree( GetProcessHeap(), 0, lpDPL->dpl ); return TRUE; } BOOL DPL_CreateLobby2( IDirectPlayLobbyImpl* lpDPL ) { lpDPL->dpl2 = (DirectPlayLobbyIUnknownData*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(lpDPL->dpl2) ) ); if ( lpDPL->dpl2 == NULL ) { return FALSE; } return TRUE; } BOOL DPL_DestroyLobby2( IDirectPlayLobbyImpl* lpDPL ) { HeapFree( GetProcessHeap(), 0, lpDPL->dpl2 ); return TRUE; } BOOL DPL_CreateLobby3( IDirectPlayLobbyImpl* lpDPL ) { lpDPL->dpl3 = (DirectPlayLobbyIUnknownData*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(lpDPL->dpl3) ) ); if ( lpDPL->dpl3 == NULL ) { return FALSE; } return TRUE; } BOOL DPL_DestroyLobby3( IDirectPlayLobbyImpl* lpDPL ) { HeapFree( GetProcessHeap(), 0, lpDPL->dpl3 ); return TRUE; } /* Helper function for DirectPlayLobby QueryInterface */ extern HRESULT directPlayLobby_QueryInterface ( REFIID riid, LPVOID* ppvObj ) { IDirectPlayLobby3AImpl* lpDPL = NULL; if( IsEqualGUID( &IID_IDirectPlayLobby, riid ) ) { lpDPL = (IDirectPlayLobbyImpl*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpDPL ) ); if( !lpDPL ) { return E_OUTOFMEMORY; } ICOM_VTBL(lpDPL) = &directPlayLobbyWVT; if ( DPL_CreateIUnknown( lpDPL ) && DPL_CreateLobby1( lpDPL ) ) { *ppvObj = lpDPL; return S_OK; } } else if( IsEqualGUID( &IID_IDirectPlayLobbyA, riid ) ) { lpDPL = (IDirectPlayLobbyAImpl*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpDPL ) ); if( !lpDPL ) { return E_OUTOFMEMORY; } ICOM_VTBL(lpDPL) = &directPlayLobbyAVT; if ( DPL_CreateIUnknown( lpDPL ) && DPL_CreateLobby1( lpDPL ) ) { *ppvObj = lpDPL; return S_OK; } } else if( IsEqualGUID( &IID_IDirectPlayLobby2, riid ) ) { lpDPL = (IDirectPlayLobby2Impl*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpDPL ) ); if( !lpDPL ) { return E_OUTOFMEMORY; } ICOM_VTBL(lpDPL) = &directPlayLobby2WVT; if ( DPL_CreateIUnknown( lpDPL ) && DPL_CreateLobby1( lpDPL ) && DPL_CreateLobby2( lpDPL ) ) { *ppvObj = lpDPL; return S_OK; } } else if( IsEqualGUID( &IID_IDirectPlayLobby2A, riid ) ) { lpDPL = (IDirectPlayLobby2AImpl*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpDPL ) ); if( !lpDPL ) { return E_OUTOFMEMORY; } ICOM_VTBL(lpDPL) = &directPlayLobby2AVT; if ( DPL_CreateIUnknown( lpDPL ) && DPL_CreateLobby1( lpDPL ) && DPL_CreateLobby2( lpDPL ) ) { *ppvObj = lpDPL; return S_OK; } } else if( IsEqualGUID( &IID_IDirectPlayLobby3, riid ) ) { lpDPL = (IDirectPlayLobby3Impl*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpDPL ) ); if( !lpDPL ) { return E_OUTOFMEMORY; } ICOM_VTBL(lpDPL) = &directPlayLobby3WVT; if ( DPL_CreateIUnknown( lpDPL ) && DPL_CreateLobby1( lpDPL ) && DPL_CreateLobby2( lpDPL ) && DPL_CreateLobby3( lpDPL ) ) { *ppvObj = lpDPL; return S_OK; } } else if( IsEqualGUID( &IID_IDirectPlayLobby3A, riid ) ) { lpDPL = (IDirectPlayLobby3AImpl*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpDPL ) ); if( !lpDPL ) { return E_OUTOFMEMORY; } ICOM_VTBL(lpDPL) = &directPlayLobby3AVT; if ( DPL_CreateIUnknown( lpDPL ) && DPL_CreateLobby1( lpDPL ) && DPL_CreateLobby2( lpDPL ) && DPL_CreateLobby3( lpDPL ) ) { *ppvObj = lpDPL; return S_OK; } } /* Check if we had problems creating an interface */ if ( lpDPL != NULL ) { DPL_DestroyLobby3( lpDPL ); DPL_DestroyLobby2( lpDPL ); DPL_DestroyLobby1( lpDPL ); DPL_DestroyIUnknown( lpDPL ); HeapFree( GetProcessHeap(), 0, lpDPL ); *ppvObj = NULL; return DPERR_NOMEMORY; } else /* Unsupported interface */ { *ppvObj = NULL; return E_NOINTERFACE; } } static HRESULT WINAPI IDirectPlayLobbyAImpl_QueryInterface ( LPDIRECTPLAYLOBBYA iface, REFIID riid, LPVOID* ppvObj ) { ICOM_THIS(IDirectPlayLobby2Impl,iface); TRACE("(%p)->(%p,%p)\n", This, riid, ppvObj ); if( IsEqualGUID( &IID_IUnknown, riid ) || IsEqualGUID( &IID_IDirectPlayLobbyA, riid ) ) { IDirectPlayLobby_AddRef( iface ); *ppvObj = This; return S_OK; } return directPlayLobby_QueryInterface( riid, ppvObj ); } static HRESULT WINAPI IDirectPlayLobbyW_QueryInterface ( LPDIRECTPLAYLOBBY iface, REFIID riid, LPVOID* ppvObj ) { ICOM_THIS(IDirectPlayLobbyImpl,iface); TRACE("(%p)->(%p,%p)\n", This, riid, ppvObj ); if( IsEqualGUID( &IID_IUnknown, riid ) || IsEqualGUID( &IID_IDirectPlayLobby, riid ) ) { IDirectPlayLobby_AddRef( iface ); *ppvObj = This; return S_OK; } return directPlayLobby_QueryInterface( riid, ppvObj ); } static HRESULT WINAPI IDirectPlayLobby2AImpl_QueryInterface ( LPDIRECTPLAYLOBBY2A iface, REFIID riid, LPVOID* ppvObj ) { ICOM_THIS(IDirectPlayLobby2Impl,iface); TRACE("(%p)->(%p,%p)\n", This, riid, ppvObj ); /* Compare riids. We know this object is a direct play lobby 2A object. If we are asking about the same type of interface we're fine. */ if( IsEqualGUID( &IID_IUnknown, riid ) || IsEqualGUID( &IID_IDirectPlayLobby2A, riid ) ) { IDirectPlayLobby_AddRef( iface ); *ppvObj = This; return S_OK; } return directPlayLobby_QueryInterface( riid, ppvObj ); } static HRESULT WINAPI IDirectPlayLobby2WImpl_QueryInterface ( LPDIRECTPLAYLOBBY2 iface, REFIID riid, LPVOID* ppvObj ) { ICOM_THIS(IDirectPlayLobby2Impl,iface); /* Compare riids. We know this object is a direct play lobby 2 object. If we are asking about the same type of interface we're fine. */ if( IsEqualGUID( &IID_IUnknown, riid ) || IsEqualGUID( &IID_IDirectPlayLobby2, riid ) ) { IDirectPlayLobby_AddRef( iface ); *ppvObj = This; return S_OK; } return directPlayLobby_QueryInterface( riid, ppvObj ); } static HRESULT WINAPI IDirectPlayLobby3AImpl_QueryInterface ( LPDIRECTPLAYLOBBY3A iface, REFIID riid, LPVOID* ppvObj ) { ICOM_THIS(IDirectPlayLobby3Impl,iface); /* Compare riids. We know this object is a direct play lobby 3 object. If we are asking about the same type of interface we're fine. */ if( IsEqualGUID( &IID_IUnknown, riid ) || IsEqualGUID( &IID_IDirectPlayLobby3A, riid ) ) { IDirectPlayLobby_AddRef( This ); *ppvObj = This; return S_OK; } return directPlayLobby_QueryInterface( riid, ppvObj ); } static HRESULT WINAPI IDirectPlayLobby3WImpl_QueryInterface ( LPDIRECTPLAYLOBBY3 iface, REFIID riid, LPVOID* ppvObj ) { ICOM_THIS(IDirectPlayLobby3Impl,iface); /* Compare riids. We know this object is a direct play lobby 3 object. If we are asking about the same type of interface we're fine. */ if( IsEqualGUID( &IID_IUnknown, riid ) || IsEqualGUID( &IID_IDirectPlayLobby3, riid ) ) { IDirectPlayLobby_AddRef( iface ); *ppvObj = This; return S_OK; } return directPlayLobby_QueryInterface( riid, ppvObj ); } /* * Simple procedure. Just increment the reference count to this * structure and return the new reference count. */ static ULONG WINAPI IDirectPlayLobbyAImpl_AddRef ( LPDIRECTPLAYLOBBYA iface ) { ULONG refCount; ICOM_THIS(IDirectPlayLobby2Impl,iface); EnterCriticalSection( &This->unk->DPL_lock ); { refCount = ++(This->unk->ref); } LeaveCriticalSection( &This->unk->DPL_lock ); TRACE("ref count incremented to %lu for %p\n", refCount, This ); return refCount; } /* * Simple COM procedure. Decrease the reference count to this object. * If the object no longer has any reference counts, free up the associated * memory. */ static ULONG WINAPI IDirectPlayLobbyAImpl_Release ( LPDIRECTPLAYLOBBYA iface ) { ULONG refCount; ICOM_THIS(IDirectPlayLobby2Impl,iface); EnterCriticalSection( &This->unk->DPL_lock ); { refCount = --(This->unk->ref); } LeaveCriticalSection( &This->unk->DPL_lock ); TRACE("ref count decremeneted to %lu for %p\n", refCount, This ); /* Deallocate if this is the last reference to the object */ if( refCount ) { DPL_DestroyLobby3( This ); DPL_DestroyLobby2( This ); DPL_DestroyLobby1( This ); DPL_DestroyIUnknown( This ); HeapFree( GetProcessHeap(), 0, This ); } return refCount; } /******************************************************************** * * Connects an application to the session specified by the DPLCONNECTION * structure currently stored with the DirectPlayLobby object. * * Returns a IDirectPlay interface. * */ static HRESULT WINAPI IDirectPlayLobbyAImpl_Connect ( LPDIRECTPLAYLOBBYA iface, DWORD dwFlags, LPDIRECTPLAY2A* lplpDP, IUnknown* pUnk) { ICOM_THIS(IDirectPlayLobbyImpl,iface); LPDIRECTPLAY2A lpDirectPlay2A; LPDIRECTPLAY3A lpDirectPlay3A; LPDIRECTPLAYLOBBY2A lpDirectPlayLobby2A; HRESULT rc; FIXME("(%p)->(0x%08lx,%p,%p): stub\n", This, dwFlags, lplpDP, pUnk ); if( dwFlags || pUnk ) { return DPERR_INVALIDPARAMS; } if( ( rc = DirectPlayCreate( (LPGUID)&IID_IDirectPlay2A, lplpDP, pUnk ) ) != DP_OK ) { ERR("error creating Direct Play 2W interface. Return Code = 0x%lx.\n", rc ); return rc; } lpDirectPlay2A = *lplpDP; /* This should invoke IDirectPlay3::InitializeConnection IDirectPlay3::Open */ /* - Use This object to get a DPL2 object using QueryInterface * - Need to call CreateCompoundAddress to create the lpConnection param for IDirectPlay::InitializeConnection * - Call IDirectPlay::InitializeConnection * - Call IDirectPlay::Open */ #if 0 create_address: { DPCOMPOUNDADDRESSELEMENT compoundAddress; /* Get lobby version capable of supporting CreateCompoundAddress */ if( ( rc = IDirectPlayLobby_QueryInterface( This, &IID_IDirectPlayLobby2A, &lpDirectPlayLobby2A ) ) != DP_OK ) { return rc; } EnterCriticalSection( &This->unk->DPL_lock ); /* Actually create the compound address */ memcpy( compoundAddress.guidDataType, This->dpl->guidSP, sizeof( compoundAddress.guidDataType ) ); LeaveCriticalSection( &This->unk->DPL_lock ); rc = IDirectPlayLobby_CreateCompoundAddress( lpDirectPlayLobby2A, lpElements, dwElementCount, lpAddress, lpdwAddressSize ) /* Free the lobby object since we're done with it */ IDirectPlayLobby_Release( lpDirectPlayLobby2A ); if( rc != DP_OK ) { return rc; } } if( ( rc = IDirectPlayX_QueryInterface( directPlay2A, &IID_IDirectPlay3A, &lpDirectPlay3A ) ) != DP_OK ) { return rc; } #endif return DP_OK; } static HRESULT WINAPI IDirectPlayLobbyWImpl_Connect ( LPDIRECTPLAYLOBBY iface, DWORD dwFlags, LPDIRECTPLAY2* lplpDP, IUnknown* pUnk) { ICOM_THIS(IDirectPlayLobbyImpl,iface); LPDIRECTPLAY2* directPlay2W; HRESULT createRC; FIXME("(%p)->(0x%08lx,%p,%p): stub\n", This, dwFlags, lplpDP, pUnk ); if( dwFlags || pUnk ) { return DPERR_INVALIDPARAMS; } if( ( createRC = DirectPlayCreate( (LPGUID)&IID_IDirectPlay2, lplpDP, pUnk ) ) != DP_OK ) { ERR("error creating Direct Play 2W interface. Return Code = 0x%lx.\n", createRC ); return createRC; } /* This should invoke IDirectPlay3::InitializeConnection IDirectPlay3::Open */ directPlay2W = lplpDP; return DP_OK; } /******************************************************************** * * 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. * */ static HRESULT WINAPI IDirectPlayLobbyAImpl_CreateAddress ( LPDIRECTPLAYLOBBYA iface, REFGUID guidSP, REFGUID guidDataType, LPCVOID lpData, DWORD dwDataSize, LPVOID lpAddress, LPDWORD lpdwAddressSize ) { FIXME(":stub\n"); return DPERR_OUTOFMEMORY; } static HRESULT WINAPI IDirectPlayLobbyWImpl_CreateAddress ( LPDIRECTPLAYLOBBY iface, REFGUID guidSP, REFGUID guidDataType, LPCVOID lpData, DWORD dwDataSize, LPVOID lpAddress, LPDWORD lpdwAddressSize ) { FIXME(":stub\n"); return DPERR_OUTOFMEMORY; } /******************************************************************** * * 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 ( LPDIRECTPLAYLOBBYA iface, LPDPENUMADDRESSCALLBACK lpEnumAddressCallback, LPCVOID lpAddress, DWORD dwAddressSize, LPVOID lpContext ) { FIXME(":stub\n"); return DPERR_OUTOFMEMORY; } static HRESULT WINAPI IDirectPlayLobbyWImpl_EnumAddress ( LPDIRECTPLAYLOBBY iface, LPDPENUMADDRESSCALLBACK lpEnumAddressCallback, LPCVOID lpAddress, DWORD dwAddressSize, LPVOID lpContext ) { FIXME(":stub\n"); return DPERR_OUTOFMEMORY; } /******************************************************************** * * Enumerates all the address types that a given service provider needs to * build the DirectPlay Address. * */ static HRESULT WINAPI IDirectPlayLobbyAImpl_EnumAddressTypes ( LPDIRECTPLAYLOBBYA iface, LPDPLENUMADDRESSTYPESCALLBACK lpEnumAddressTypeCallback, REFGUID guidSP, LPVOID lpContext, DWORD dwFlags ) { FIXME(":stub\n"); return DPERR_OUTOFMEMORY; } static HRESULT WINAPI IDirectPlayLobbyWImpl_EnumAddressTypes ( LPDIRECTPLAYLOBBY iface, LPDPLENUMADDRESSTYPESCALLBACK lpEnumAddressTypeCallback, REFGUID guidSP, LPVOID lpContext, DWORD dwFlags ) { FIXME(":stub\n"); return DPERR_OUTOFMEMORY; } /******************************************************************** * * Enumerates what applications are registered with DirectPlay by * invoking the callback function with lpContext. * */ static HRESULT WINAPI IDirectPlayLobbyWImpl_EnumLocalApplications ( LPDIRECTPLAYLOBBY iface, LPDPLENUMLOCALAPPLICATIONSCALLBACK lpEnumLocalAppCallback, LPVOID lpContext, DWORD dwFlags ) { ICOM_THIS(IDirectPlayLobbyImpl,iface); FIXME("(%p)->(%p,%p,0x%08lx):stub\n", This, lpEnumLocalAppCallback, lpContext, dwFlags ); return DPERR_OUTOFMEMORY; } static HRESULT WINAPI IDirectPlayLobbyAImpl_EnumLocalApplications ( LPDIRECTPLAYLOBBYA iface, LPDPLENUMLOCALAPPLICATIONSCALLBACK lpEnumLocalAppCallback, LPVOID lpContext, DWORD dwFlags ) { ICOM_THIS(IDirectPlayLobbyImpl,iface); FIXME("(%p)->(%p,%p,0x%08lx):stub\n", This, lpEnumLocalAppCallback, lpContext, dwFlags ); return DPERR_OUTOFMEMORY; } /******************************************************************** * * 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 ( LPDIRECTPLAYLOBBYA iface, DWORD dwAppID, LPVOID lpData, LPDWORD lpdwDataSize ) { ICOM_THIS(IDirectPlayLobbyImpl,iface); LPDPLCONNECTION lpDplConnection; FIXME(": semi stub (%p)->(0x%08lx,%p,%p)\n", This, dwAppID, lpData, lpdwDataSize ); /* Application is requesting us to give the required size */ if ( lpData == NULL ) { *lpdwDataSize = sizeof( DPLCONNECTION ); return DPERR_BUFFERTOOSMALL; } /* Let's check the size of the buffer that the application has allocated */ if ( *lpdwDataSize < sizeof( DPLCONNECTION ) ) { *lpdwDataSize = sizeof( DPLCONNECTION ); return DPERR_BUFFERTOOSMALL; } /* FIXME: Who's supposed to own the data */ /* Fill in the fields - let them just use the ptrs */ lpDplConnection = (LPDPLCONNECTION)lpData; /* Copy everything we've got into here */ /* Need to actually store the stuff here. Check if we've already allocated each field first. */ lpDplConnection->dwFlags = This->dpl->dwConnFlags; /* Copy LPDPSESSIONDESC2 struct */ lpDplConnection->lpSessionDesc = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( This->dpl->sessionDesc ) ); memcpy( lpDplConnection->lpSessionDesc, &This->dpl->sessionDesc, sizeof( This->dpl->sessionDesc ) ); if( This->dpl->sessionDesc.sess.lpszSessionName ) { lpDplConnection->lpSessionDesc->sess.lpszSessionName = HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, This->dpl->sessionDesc.sess.lpszSessionNameA ); } if( This->dpl->sessionDesc.pass.lpszPassword ) { lpDplConnection->lpSessionDesc->pass.lpszPassword = HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, This->dpl->sessionDesc.pass.lpszPasswordA ); } lpDplConnection->lpSessionDesc->dwReserved1 = This->dpl->sessionDesc.dwReserved1; lpDplConnection->lpSessionDesc->dwReserved2 = This->dpl->sessionDesc.dwReserved2; /* Copy DPNAME struct - seems to be optional - check for existance first */ lpDplConnection->lpPlayerName = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( This->dpl->playerName ) ); memcpy( lpDplConnection->lpPlayerName, &(This->dpl->playerName), sizeof( This->dpl->playerName ) ); if( This->dpl->playerName.psn.lpszShortName ) { lpDplConnection->lpPlayerName->psn.lpszShortName = HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, This->dpl->playerName.psn.lpszShortNameA ); } if( This->dpl->playerName.pln.lpszLongName ) { lpDplConnection->lpPlayerName->pln.lpszLongName = HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, This->dpl->playerName.pln.lpszLongNameA ); } memcpy( &lpDplConnection->guidSP, &This->dpl->guidSP, sizeof( This->dpl->guidSP ) ); lpDplConnection->lpAddress = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, This->dpl->dwAddressSize ); memcpy( lpDplConnection->lpAddress, This->dpl->lpAddress, This->dpl->dwAddressSize ); lpDplConnection->dwAddressSize = This->dpl->dwAddressSize; return DP_OK; } static HRESULT WINAPI IDirectPlayLobbyWImpl_GetConnectionSettings ( LPDIRECTPLAYLOBBY iface, DWORD dwAppID, LPVOID lpData, LPDWORD lpdwDataSize ) { ICOM_THIS(IDirectPlayLobbyImpl,iface); FIXME(":semi stub %p %08lx %p %p \n", This, dwAppID, lpData, lpdwDataSize ); /* Application is requesting us to give the required size */ if ( !lpData ) { /* Let's check the size of the buffer that the application has allocated */ if( *lpdwDataSize >= sizeof( DPLCONNECTION ) ) { return DP_OK; } else { *lpdwDataSize = sizeof( DPLCONNECTION ); return DPERR_BUFFERTOOSMALL; } } /* Fill in the fields - see above */ FIXME("stub\n" ); return DP_OK; } /******************************************************************** * * Retrieves the message sent between a lobby client and a DirectPlay * application. All messages are queued until received. * */ static HRESULT WINAPI IDirectPlayLobbyAImpl_ReceiveLobbyMessage ( LPDIRECTPLAYLOBBYA iface, DWORD dwFlags, DWORD dwAppID, LPDWORD lpdwMessageFlags, LPVOID lpData, LPDWORD lpdwDataSize ) { ICOM_THIS(IDirectPlayLobbyImpl,iface); FIXME(":stub %p %08lx %08lx %p %p %p\n", This, dwFlags, dwAppID, lpdwMessageFlags, lpData, lpdwDataSize ); return DPERR_OUTOFMEMORY; } static HRESULT WINAPI IDirectPlayLobbyWImpl_ReceiveLobbyMessage ( LPDIRECTPLAYLOBBY iface, DWORD dwFlags, DWORD dwAppID, LPDWORD lpdwMessageFlags, LPVOID lpData, LPDWORD lpdwDataSize ) { ICOM_THIS(IDirectPlayLobbyImpl,iface); FIXME(":stub %p %08lx %08lx %p %p %p\n", This, dwFlags, dwAppID, lpdwMessageFlags, lpData, lpdwDataSize ); return DPERR_OUTOFMEMORY; } /******************************************************************** * * Starts an application and passes to it all the information to * connect to a session. * */ static HRESULT WINAPI IDirectPlayLobbyAImpl_RunApplication ( LPDIRECTPLAYLOBBYA iface, DWORD dwFlags, LPDWORD lpdwAppID, LPDPLCONNECTION lpConn, HANDLE hReceiveEvent ) { FIXME(":stub\n"); return DPERR_OUTOFMEMORY; } static HRESULT WINAPI IDirectPlayLobbyWImpl_RunApplication ( LPDIRECTPLAYLOBBY iface, DWORD dwFlags, LPDWORD lpdwAppID, LPDPLCONNECTION lpConn, HANDLE hReceiveEvent ) { FIXME(":stub\n"); return DPERR_OUTOFMEMORY; } /******************************************************************** * * Sends a message between the application and the lobby client. * All messages are queued until received. * */ static HRESULT WINAPI IDirectPlayLobbyAImpl_SendLobbyMessage ( LPDIRECTPLAYLOBBYA iface, DWORD dwFlags, DWORD dwAppID, LPVOID lpData, DWORD dwDataSize ) { FIXME(":stub\n"); return DPERR_OUTOFMEMORY; } static HRESULT WINAPI IDirectPlayLobbyWImpl_SendLobbyMessage ( LPDIRECTPLAYLOBBY iface, DWORD dwFlags, DWORD dwAppID, LPVOID lpData, DWORD dwDataSize ) { FIXME(":stub\n"); return DPERR_OUTOFMEMORY; } /******************************************************************** * * Modifies the DPLCONNECTION structure to contain all information * needed to start and connect an application. * */ static HRESULT WINAPI IDirectPlayLobbyWImpl_SetConnectionSettings ( LPDIRECTPLAYLOBBY iface, DWORD dwFlags, DWORD dwAppID, LPDPLCONNECTION lpConn ) { ICOM_THIS(IDirectPlayLobbyImpl,iface); TRACE(": This=%p, dwFlags=%08lx, dwAppId=%08lx, lpConn=%p\n", This, dwFlags, dwAppID, lpConn ); /* Paramater check */ if( dwFlags || !This || !lpConn ) { ERR("invalid parameters.\n"); return DPERR_INVALIDPARAMS; } /* See if there is a connection associated with this request. * dwAppID == 0 indicates that this request isn't associated with a connection. */ if( dwAppID ) { FIXME(": Connection dwAppID=%08lx given. Not implemented yet.\n", dwAppID ); /* Need to add a check for this application Id...*/ return DPERR_NOTLOBBIED; } if( lpConn->dwSize != sizeof(DPLCONNECTION) ) { ERR(": old/new DPLCONNECTION type? Size=%08lx vs. expected=%ul bytes\n", lpConn->dwSize, sizeof( DPLCONNECTION ) ); return DPERR_INVALIDPARAMS; } /* Need to investigate the lpConn->lpSessionDesc to figure out * what type of session we need to join/create. */ if( (!lpConn->lpSessionDesc ) || ( lpConn->lpSessionDesc->dwSize != sizeof( DPSESSIONDESC2 ) ) ) { ERR("DPSESSIONDESC passed in? Size=%08lx vs. expected=%ul bytes\n", lpConn->lpSessionDesc->dwSize, sizeof( DPSESSIONDESC2 ) ); return DPERR_INVALIDPARAMS; } EnterCriticalSection( &This->unk->DPL_lock ); /* Need to actually store the stuff here. Check if we've already allocated each field first. */ This->dpl->dwConnFlags = lpConn->dwFlags; /* Copy LPDPSESSIONDESC2 struct - this is required */ memcpy( &This->dpl->sessionDesc, lpConn->lpSessionDesc, sizeof( *(lpConn->lpSessionDesc) ) ); /* FIXME: Can this just be shorted? Does it handle the NULL case correctly? */ if( lpConn->lpSessionDesc->sess.lpszSessionName ) This->dpl->sessionDesc.sess.lpszSessionName = HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->lpSessionDesc->sess.lpszSessionName ); else This->dpl->sessionDesc.sess.lpszSessionName = NULL; if( lpConn->lpSessionDesc->pass.lpszPassword ) This->dpl->sessionDesc.pass.lpszPassword = HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->lpSessionDesc->pass.lpszPassword ); else This->dpl->sessionDesc.pass.lpszPassword = NULL; This->dpl->sessionDesc.dwReserved1 = lpConn->lpSessionDesc->dwReserved1; This->dpl->sessionDesc.dwReserved2 = lpConn->lpSessionDesc->dwReserved2; /* Copy DPNAME struct - seems to be optional - check for existance first */ if( lpConn->lpPlayerName ) { memcpy( &This->dpl->playerName, lpConn->lpPlayerName, sizeof( *lpConn->lpPlayerName ) ); if( lpConn->lpPlayerName->psn.lpszShortName ) This->dpl->playerName.psn.lpszShortName = HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->lpPlayerName->psn.lpszShortName ); if( lpConn->lpPlayerName->pln.lpszLongName ) This->dpl->playerName.pln.lpszLongName = HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->lpPlayerName->pln.lpszLongName ); } memcpy( &This->dpl->guidSP, &lpConn->guidSP, sizeof( lpConn->guidSP ) ); This->dpl->lpAddress = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->dwAddressSize ); memcpy( This->dpl->lpAddress, lpConn->lpAddress, lpConn->dwAddressSize ); This->dpl->dwAddressSize = lpConn->dwAddressSize; LeaveCriticalSection( &This->unk->DPL_lock ); return DP_OK; } static HRESULT WINAPI IDirectPlayLobbyAImpl_SetConnectionSettings ( LPDIRECTPLAYLOBBYA iface, DWORD dwFlags, DWORD dwAppID, LPDPLCONNECTION lpConn ) { ICOM_THIS(IDirectPlayLobbyImpl,iface); TRACE(": This=%p, dwFlags=%08lx, dwAppId=%08lx, lpConn=%p\n", This, dwFlags, dwAppID, lpConn ); /* Paramater check */ if( dwFlags || !This || !lpConn ) { ERR("invalid parameters.\n"); return DPERR_INVALIDPARAMS; } /* See if there is a connection associated with this request. * dwAppID == 0 indicates that this request isn't associated with a connection. */ if( dwAppID ) { FIXME(": Connection dwAppID=%08lx given. Not implemented yet.\n", dwAppID ); /* Need to add a check for this application Id...*/ return DPERR_NOTLOBBIED; } if( lpConn->dwSize != sizeof(DPLCONNECTION) ) { ERR(": old/new DPLCONNECTION type? Size=%08lx vs. expected=%ul bytes\n", lpConn->dwSize, sizeof( DPLCONNECTION ) ); return DPERR_INVALIDPARAMS; } /* Need to investigate the lpConn->lpSessionDesc to figure out * what type of session we need to join/create. */ if( (!lpConn->lpSessionDesc ) || ( lpConn->lpSessionDesc->dwSize != sizeof( DPSESSIONDESC2 ) ) ) { ERR("DPSESSIONDESC passed in? Size=%08lx vs. expected=%ul bytes\n", lpConn->lpSessionDesc->dwSize, sizeof( DPSESSIONDESC2 ) ); return DPERR_INVALIDPARAMS; } EnterCriticalSection( &This->unk->DPL_lock ); /* Need to actually store the stuff here. Check if we've already allocated each field first. */ This->dpl->dwConnFlags = lpConn->dwFlags; /* Copy LPDPSESSIONDESC2 struct - this is required */ memcpy( &This->dpl->sessionDesc, lpConn->lpSessionDesc, sizeof( *(lpConn->lpSessionDesc) ) ); /* FIXME: Can this just be shorted? Does it handle the NULL case correctly? */ if( lpConn->lpSessionDesc->sess.lpszSessionNameA ) This->dpl->sessionDesc.sess.lpszSessionNameA = HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->lpSessionDesc->sess.lpszSessionNameA ); else This->dpl->sessionDesc.sess.lpszSessionNameA = NULL; if( lpConn->lpSessionDesc->pass.lpszPasswordA ) This->dpl->sessionDesc.pass.lpszPasswordA = HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->lpSessionDesc->pass.lpszPasswordA ); else This->dpl->sessionDesc.pass.lpszPasswordA = NULL; This->dpl->sessionDesc.dwReserved1 = lpConn->lpSessionDesc->dwReserved1; This->dpl->sessionDesc.dwReserved2 = lpConn->lpSessionDesc->dwReserved2; /* Copy DPNAME struct - seems to be optional - check for existance first */ if( lpConn->lpPlayerName ) { memcpy( &This->dpl->playerName, lpConn->lpPlayerName, sizeof( *lpConn->lpPlayerName ) ); if( lpConn->lpPlayerName->psn.lpszShortNameA ) This->dpl->playerName.psn.lpszShortNameA = HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->lpPlayerName->psn.lpszShortNameA ); if( lpConn->lpPlayerName->pln.lpszLongNameA ) This->dpl->playerName.pln.lpszLongNameA = HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->lpPlayerName->pln.lpszLongNameA ); } memcpy( &This->dpl->guidSP, &lpConn->guidSP, sizeof( lpConn->guidSP ) ); This->dpl->lpAddress = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->dwAddressSize ); memcpy( This->dpl->lpAddress, lpConn->lpAddress, lpConn->dwAddressSize ); This->dpl->dwAddressSize = lpConn->dwAddressSize; LeaveCriticalSection( &This->unk->DPL_lock ); return DP_OK; } /******************************************************************** * * Registers an event that will be set when a lobby message is received. * */ static HRESULT WINAPI IDirectPlayLobbyAImpl_SetLobbyMessageEvent ( LPDIRECTPLAYLOBBYA iface, DWORD dwFlags, DWORD dwAppID, HANDLE hReceiveEvent ) { FIXME(":stub\n"); return DPERR_OUTOFMEMORY; } static HRESULT WINAPI IDirectPlayLobbyWImpl_SetLobbyMessageEvent ( LPDIRECTPLAYLOBBY iface, DWORD dwFlags, DWORD dwAppID, HANDLE hReceiveEvent ) { FIXME(":stub\n"); return DPERR_OUTOFMEMORY; } /* DPL 2 methods - well actuall only one */ /******************************************************************** * * Registers an event that will be set when a lobby message is received. * */ static HRESULT WINAPI IDirectPlayLobby2WImpl_CreateCompoundAddress ( LPDIRECTPLAYLOBBY2 iface, LPCDPCOMPOUNDADDRESSELEMENT lpElements, DWORD dwElementCount, LPVOID lpAddress, LPDWORD lpdwAddressSize ) { FIXME(":stub\n"); return DPERR_OUTOFMEMORY; } static HRESULT WINAPI IDirectPlayLobby2AImpl_CreateCompoundAddress ( LPDIRECTPLAYLOBBY2A iface, LPCDPCOMPOUNDADDRESSELEMENT lpElements, DWORD dwElementCount, LPVOID lpAddress, LPDWORD lpdwAddressSize ) { FIXME(":stub\n"); return DPERR_OUTOFMEMORY; } /* DPL 3 methods */ static HRESULT WINAPI IDirectPlayLobby3WImpl_ConnectEx ( LPDIRECTPLAYLOBBY3 iface, DWORD dwFlags, REFIID riid, LPVOID* lplpDP, IUnknown* pUnk ) { FIXME(":stub\n"); return DP_OK; } static HRESULT WINAPI IDirectPlayLobby3AImpl_ConnectEx ( LPDIRECTPLAYLOBBY3A iface, DWORD dwFlags, REFIID riid, LPVOID* lplpDP, IUnknown* pUnk ) { FIXME(":stub\n"); return DP_OK; } static HRESULT WINAPI IDirectPlayLobby3WImpl_RegisterApplication ( LPDIRECTPLAYLOBBY3 iface, DWORD dwFlags, LPDPAPPLICATIONDESC lpAppDesc ) { FIXME(":stub\n"); return DP_OK; } static HRESULT WINAPI IDirectPlayLobby3AImpl_RegisterApplication ( LPDIRECTPLAYLOBBY3A iface, DWORD dwFlags, LPDPAPPLICATIONDESC lpAppDesc ) { FIXME(":stub\n"); return DP_OK; } static HRESULT WINAPI IDirectPlayLobby3WImpl_UnregisterApplication ( LPDIRECTPLAYLOBBY3 iface, DWORD dwFlags, REFGUID lpAppDesc ) { FIXME(":stub\n"); return DP_OK; } static HRESULT WINAPI IDirectPlayLobby3AImpl_UnregisterApplication ( LPDIRECTPLAYLOBBY3A iface, DWORD dwFlags, REFGUID lpAppDesc ) { FIXME(":stub\n"); return DP_OK; } static HRESULT WINAPI IDirectPlayLobby3WImpl_WaitForConnectionSettings ( LPDIRECTPLAYLOBBY3 iface, DWORD dwFlags ) { FIXME(":stub\n"); return DP_OK; } static HRESULT WINAPI IDirectPlayLobby3AImpl_WaitForConnectionSettings ( LPDIRECTPLAYLOBBY3A iface, DWORD dwFlags ) { FIXME(":stub\n"); return DP_OK; } /* Virtual Table definitions for DPL{1,2,3}{A,W} */ /* Note: Hack so we can reuse the old functions without compiler warnings */ #if !defined(__STRICT_ANSI__) && defined(__GNUC__) # define XCAST(fun) (typeof(directPlayLobbyAVT.fn##fun)) #else # define XCAST(fun) (void*) #endif /* Direct Play Lobby 1 (ascii) Virtual Table for methods */ /* All lobby 1 methods are exactly the same except QueryInterface */ static struct ICOM_VTABLE(IDirectPlayLobby) directPlayLobbyAVT = { ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE IDirectPlayLobbyAImpl_QueryInterface, XCAST(AddRef)IDirectPlayLobbyAImpl_AddRef, XCAST(Release)IDirectPlayLobbyAImpl_Release, IDirectPlayLobbyAImpl_Connect, IDirectPlayLobbyAImpl_CreateAddress, IDirectPlayLobbyAImpl_EnumAddress, IDirectPlayLobbyAImpl_EnumAddressTypes, IDirectPlayLobbyAImpl_EnumLocalApplications, IDirectPlayLobbyAImpl_GetConnectionSettings, IDirectPlayLobbyAImpl_ReceiveLobbyMessage, IDirectPlayLobbyAImpl_RunApplication, IDirectPlayLobbyAImpl_SendLobbyMessage, IDirectPlayLobbyAImpl_SetConnectionSettings, IDirectPlayLobbyAImpl_SetLobbyMessageEvent }; #undef XCAST /* Note: Hack so we can reuse the old functions without compiler warnings */ #if !defined(__STRICT_ANSI__) && defined(__GNUC__) # define XCAST(fun) (typeof(directPlayLobbyWVT.fn##fun)) #else # define XCAST(fun) (void*) #endif /* Direct Play Lobby 1 (unicode) Virtual Table for methods */ static ICOM_VTABLE(IDirectPlayLobby) directPlayLobbyWVT = { ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE IDirectPlayLobbyW_QueryInterface, XCAST(AddRef)IDirectPlayLobbyAImpl_AddRef, XCAST(Release)IDirectPlayLobbyAImpl_Release, IDirectPlayLobbyWImpl_Connect, IDirectPlayLobbyWImpl_CreateAddress, IDirectPlayLobbyWImpl_EnumAddress, IDirectPlayLobbyWImpl_EnumAddressTypes, IDirectPlayLobbyWImpl_EnumLocalApplications, IDirectPlayLobbyWImpl_GetConnectionSettings, IDirectPlayLobbyWImpl_ReceiveLobbyMessage, IDirectPlayLobbyWImpl_RunApplication, IDirectPlayLobbyWImpl_SendLobbyMessage, IDirectPlayLobbyWImpl_SetConnectionSettings, IDirectPlayLobbyWImpl_SetLobbyMessageEvent }; #undef XCAST /* Note: Hack so we can reuse the old functions without compiler warnings */ #if !defined(__STRICT_ANSI__) && defined(__GNUC__) # define XCAST(fun) (typeof(directPlayLobby2AVT.fn##fun)) #else # define XCAST(fun) (void*) #endif /* Direct Play Lobby 2 (ascii) Virtual Table for methods */ static ICOM_VTABLE(IDirectPlayLobby2) directPlayLobby2AVT = { ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE IDirectPlayLobby2AImpl_QueryInterface, XCAST(AddRef)IDirectPlayLobbyAImpl_AddRef, XCAST(Release)IDirectPlayLobbyAImpl_Release, XCAST(Connect)IDirectPlayLobbyAImpl_Connect, XCAST(CreateAddress)IDirectPlayLobbyAImpl_CreateAddress, XCAST(EnumAddress)IDirectPlayLobbyAImpl_EnumAddress, XCAST(EnumAddressTypes)IDirectPlayLobbyAImpl_EnumAddressTypes, XCAST(EnumLocalApplications)IDirectPlayLobbyAImpl_EnumLocalApplications, XCAST(GetConnectionSettings)IDirectPlayLobbyAImpl_GetConnectionSettings, XCAST(ReceiveLobbyMessage)IDirectPlayLobbyAImpl_ReceiveLobbyMessage, XCAST(RunApplication)IDirectPlayLobbyAImpl_RunApplication, XCAST(SendLobbyMessage)IDirectPlayLobbyAImpl_SendLobbyMessage, XCAST(SetConnectionSettings)IDirectPlayLobbyAImpl_SetConnectionSettings, XCAST(SetLobbyMessageEvent)IDirectPlayLobbyAImpl_SetLobbyMessageEvent, IDirectPlayLobby2AImpl_CreateCompoundAddress }; #undef XCAST /* Note: Hack so we can reuse the old functions without compiler warnings */ #if !defined(__STRICT_ANSI__) && defined(__GNUC__) # define XCAST(fun) (typeof(directPlayLobby2AVT.fn##fun)) #else # define XCAST(fun) (void*) #endif /* Direct Play Lobby 2 (unicode) Virtual Table for methods */ static ICOM_VTABLE(IDirectPlayLobby2) directPlayLobby2WVT = { ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE IDirectPlayLobby2WImpl_QueryInterface, XCAST(AddRef)IDirectPlayLobbyAImpl_AddRef, XCAST(Release)IDirectPlayLobbyAImpl_Release, XCAST(Connect)IDirectPlayLobbyWImpl_Connect, XCAST(CreateAddress)IDirectPlayLobbyWImpl_CreateAddress, XCAST(EnumAddress)IDirectPlayLobbyWImpl_EnumAddress, XCAST(EnumAddressTypes)IDirectPlayLobbyWImpl_EnumAddressTypes, XCAST(EnumLocalApplications)IDirectPlayLobbyWImpl_EnumLocalApplications, XCAST(GetConnectionSettings)IDirectPlayLobbyWImpl_GetConnectionSettings, XCAST(ReceiveLobbyMessage)IDirectPlayLobbyWImpl_ReceiveLobbyMessage, XCAST(RunApplication)IDirectPlayLobbyWImpl_RunApplication, XCAST(SendLobbyMessage)IDirectPlayLobbyWImpl_SendLobbyMessage, XCAST(SetConnectionSettings)IDirectPlayLobbyWImpl_SetConnectionSettings, XCAST(SetLobbyMessageEvent)IDirectPlayLobbyWImpl_SetLobbyMessageEvent, IDirectPlayLobby2WImpl_CreateCompoundAddress }; #undef XCAST /* Direct Play Lobby 3 (ascii) Virtual Table for methods */ /* Note: Hack so we can reuse the old functions without compiler warnings */ #if !defined(__STRICT_ANSI__) && defined(__GNUC__) # define XCAST(fun) (typeof(directPlayLobby3AVT.fn##fun)) #else # define XCAST(fun) (void*) #endif static ICOM_VTABLE(IDirectPlayLobby3) directPlayLobby3AVT = { ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE IDirectPlayLobby3AImpl_QueryInterface, XCAST(AddRef)IDirectPlayLobbyAImpl_AddRef, XCAST(Release)IDirectPlayLobbyAImpl_Release, XCAST(Connect)IDirectPlayLobbyAImpl_Connect, XCAST(CreateAddress)IDirectPlayLobbyAImpl_CreateAddress, XCAST(EnumAddress)IDirectPlayLobbyAImpl_EnumAddress, XCAST(EnumAddressTypes)IDirectPlayLobbyAImpl_EnumAddressTypes, XCAST(EnumLocalApplications)IDirectPlayLobbyAImpl_EnumLocalApplications, XCAST(GetConnectionSettings)IDirectPlayLobbyAImpl_GetConnectionSettings, XCAST(ReceiveLobbyMessage)IDirectPlayLobbyAImpl_ReceiveLobbyMessage, XCAST(RunApplication)IDirectPlayLobbyAImpl_RunApplication, XCAST(SendLobbyMessage)IDirectPlayLobbyAImpl_SendLobbyMessage, XCAST(SetConnectionSettings)IDirectPlayLobbyAImpl_SetConnectionSettings, XCAST(SetLobbyMessageEvent)IDirectPlayLobbyAImpl_SetLobbyMessageEvent, XCAST(CreateCompoundAddress)IDirectPlayLobby2AImpl_CreateCompoundAddress, IDirectPlayLobby3AImpl_ConnectEx, IDirectPlayLobby3AImpl_RegisterApplication, IDirectPlayLobby3AImpl_UnregisterApplication, IDirectPlayLobby3AImpl_WaitForConnectionSettings }; #undef XCAST /* Direct Play Lobby 3 (unicode) Virtual Table for methods */ /* Note: Hack so we can reuse the old functions without compiler warnings */ #if !defined(__STRICT_ANSI__) && defined(__GNUC__) # define XCAST(fun) (typeof(directPlayLobby3WVT.fn##fun)) #else # define XCAST(fun) (void*) #endif static ICOM_VTABLE(IDirectPlayLobby3) directPlayLobby3WVT = { ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE IDirectPlayLobby3WImpl_QueryInterface, XCAST(AddRef)IDirectPlayLobbyAImpl_AddRef, XCAST(Release)IDirectPlayLobbyAImpl_Release, XCAST(Connect)IDirectPlayLobbyWImpl_Connect, XCAST(CreateAddress)IDirectPlayLobbyWImpl_CreateAddress, XCAST(EnumAddress)IDirectPlayLobbyWImpl_EnumAddress, XCAST(EnumAddressTypes)IDirectPlayLobbyWImpl_EnumAddressTypes, XCAST(EnumLocalApplications)IDirectPlayLobbyWImpl_EnumLocalApplications, XCAST(GetConnectionSettings)IDirectPlayLobbyWImpl_GetConnectionSettings, XCAST(ReceiveLobbyMessage)IDirectPlayLobbyWImpl_ReceiveLobbyMessage, XCAST(RunApplication)IDirectPlayLobbyWImpl_RunApplication, XCAST(SendLobbyMessage)IDirectPlayLobbyWImpl_SendLobbyMessage, XCAST(SetConnectionSettings)IDirectPlayLobbyWImpl_SetConnectionSettings, XCAST(SetLobbyMessageEvent)IDirectPlayLobbyWImpl_SetLobbyMessageEvent, XCAST(CreateCompoundAddress)IDirectPlayLobby2WImpl_CreateCompoundAddress, IDirectPlayLobby3WImpl_ConnectEx, IDirectPlayLobby3WImpl_RegisterApplication, IDirectPlayLobby3WImpl_UnregisterApplication, IDirectPlayLobby3WImpl_WaitForConnectionSettings }; #undef XCAST /********************************************************* * * Direct Play and Direct Play Lobby Interface Implementation * *********************************************************/ /*************************************************************************** * DirectPlayLobbyCreateA (DPLAYX.4) * */ HRESULT WINAPI DirectPlayLobbyCreateA( LPGUID lpGUIDDSP, LPDIRECTPLAYLOBBYA *lplpDPL, IUnknown *lpUnk, LPVOID lpData, DWORD dwDataSize ) { TRACE("lpGUIDDSP=%p lplpDPL=%p lpUnk=%p lpData=%p dwDataSize=%08lx\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 || lpUnk || lpData || dwDataSize ) { *lplpDPL = NULL; return DPERR_INVALIDPARAMS; } return directPlayLobby_QueryInterface( &IID_IDirectPlayLobbyA, (void**)lplpDPL ); } /*************************************************************************** * DirectPlayLobbyCreateW (DPLAYX.5) * */ HRESULT WINAPI DirectPlayLobbyCreateW( LPGUID lpGUIDDSP, LPDIRECTPLAYLOBBY *lplpDPL, IUnknown *lpUnk, LPVOID lpData, DWORD dwDataSize ) { TRACE("lpGUIDDSP=%p lplpDPL=%p lpUnk=%p lpData=%p dwDataSize=%08lx\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 || lpUnk || lpData || dwDataSize ) { *lplpDPL = NULL; ERR("Bad parameters!\n" ); return DPERR_INVALIDPARAMS; } return directPlayLobby_QueryInterface( &IID_IDirectPlayLobby, (void**)lplpDPL ); }