diff --git a/dlls/dplayx/Makefile.in b/dlls/dplayx/Makefile.in index 08fd7d523ad..cf868e37ec7 100644 --- a/dlls/dplayx/Makefile.in +++ b/dlls/dplayx/Makefile.in @@ -16,6 +16,7 @@ C_SRCS = \ dplayx_main.c \ dplayx_messages.c \ dplobby.c \ + lobbysp.c \ name_server.c @MAKE_DLL_RULES@ diff --git a/dlls/dplayx/dpinit.h b/dlls/dplayx/dpinit.h index fceecc3e18c..92063d7d591 100644 --- a/dlls/dplayx/dpinit.h +++ b/dlls/dplayx/dpinit.h @@ -9,5 +9,8 @@ extern HRESULT DP_CreateInterface( REFIID riid, LPVOID* ppvObj ); extern HRESULT DPL_CreateInterface( REFIID riid, LPVOID* ppvObj ); extern HRESULT DPSP_CreateInterface( REFIID riid, LPVOID* ppvObj, IDirectPlay2Impl* dp ); +extern HRESULT DPLSP_CreateInterface( REFIID riid, LPVOID* ppvObj, + IDirectPlay2Impl* dp ); + #endif diff --git a/dlls/dplayx/dplay.c b/dlls/dplayx/dplay.c index 48f6cb42a44..7548c52ce6c 100644 --- a/dlls/dplayx/dplay.c +++ b/dlls/dplayx/dplay.c @@ -1,6 +1,6 @@ /* Direct Play 2,3,4 Implementation * - * Copyright 1998,1999,2000 - Peter Hunnisett + * Copyright 1998,1999,2000,2001 - Peter Hunnisett * * * @@ -169,6 +169,8 @@ static HRESULT WINAPI DP_IF_InitializeConnection static BOOL CALLBACK cbDPCreateEnumConnections( LPCGUID lpguidSP, LPVOID lpConnection, DWORD dwConnectionSize, LPCDPNAME lpName, DWORD dwFlags, LPVOID lpContext ); +static BOOL WINAPI DP_BuildSPCompoundAddr( LPGUID lpcSpGuid, LPVOID* lplpAddrBuf, + LPDWORD lpdwBufSize ); @@ -181,6 +183,9 @@ static void DP_CopySessionDesc( LPDPSESSIONDESC2 destSessionDesc, static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp ); +static HRESULT DP_InitializeDPSP( IDirectPlay3Impl* This, HMODULE hServiceProvider ); +static HRESULT DP_InitializeDPLSP( IDirectPlay3Impl* This, HMODULE hServiceProvider ); + @@ -283,6 +288,20 @@ static BOOL DP_CreateDirectPlay2( LPVOID lpDP ) return FALSE; } + /* Setup lobby provider information */ + This->dp2->dplspData.dwSPVersion = DPSP_MAJORVERSION; + This->dp2->dplspData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, + sizeof( *This->dp2->dplspData.lpCB ) ); + This->dp2->dplspData.lpCB->dwSize = sizeof( *This->dp2->dplspData.lpCB ); + + if( FAILED( DPLSP_CreateInterface( &IID_IDPLobbySP, + (LPVOID*)&This->dp2->dplspData.lpISP, This ) ) + ) + { + /* FIXME: Memory leak */ + return FALSE; + } + return TRUE; } @@ -347,12 +366,17 @@ static BOOL DP_DestroyDirectPlay2( LPVOID lpDP ) (*This->dp2->spData.lpCB->Shutdown)(); } - /* Unload the SP */ + /* Unload the SP (if it exists) */ if( This->dp2->hServiceProvider != 0 ) { FreeLibrary( This->dp2->hServiceProvider ); } + /* Unload the Lobby Provider (if it exists) */ + if( This->dp2->hDPLobbyProvider != 0 ) + { + FreeLibrary( This->dp2->hDPLobbyProvider ); + } #if 0 DPQ_DELETEQ( This->dp2->players, players, lpPlayerList, cbDeletePlayerElem ); @@ -631,6 +655,26 @@ HRESULT DP_HandleMessage( IDirectPlay2Impl* This, LPCVOID lpcMessageBody, switch( wCommandId ) { + /* Name server needs to handle this request */ + case DPMSGCMD_ENUMSESSIONSREQUEST: + { + /* Reply expected */ + NS_ReplyToEnumSessionsRequest( lpcMessageBody, lplpReply, lpdwMsgSize, This ); + + break; + } + + /* Name server needs to handle this request */ + case DPMSGCMD_ENUMSESSIONSREPLY: + { + /* No reply expected */ + NS_AddRemoteComputerAsNameServer( lpcMessageHeader, + This->dp2->spData.dwSPHeaderSize, + (LPDPMSG_ENUMSESSIONSREPLY)lpcMessageBody, + This->dp2->lpNameServerData ); + break; + } + case DPMSGCMD_REQUESTNEWPLAYERID: { LPCDPMSG_REQUESTNEWPLAYERID lpcMsg = @@ -667,11 +711,36 @@ HRESULT DP_HandleMessage( IDirectPlay2Impl* This, LPCVOID lpcMessageBody, case DPMSGCMD_NEWPLAYERIDREPLY: { +#if 0 + if( wCommandId == DPMSGCMD_NEWPLAYERIDREPLY ) + DebugBreak(); +#endif DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize ); break; } +#if 1 + case DPMSGCMD_JUSTENVELOPE: + { + TRACE( "GOT THE SELF MESSAGE: %p -> 0x%08lx\n", lpcMessageHeader, ((LPDWORD)lpcMessageHeader)[1] ); + NS_SetLocalAddr( This->dp2->lpNameServerData, lpcMessageHeader, 20 ); + DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize ); + } +#endif + + case DPMSGCMD_FORWARDADDPLAYER: + { +#if 0 + DebugBreak(); +#endif +#if 1 + TRACE( "Sending message to self to get my addr\n" ); + DP_MSG_ToSelf( This, 1 ); /* This is a hack right now */ +#endif + break; + } + case DPMSGCMD_FORWARDADDPLAYERNACK: { DP_MSG_ErrorReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize ); @@ -686,6 +755,8 @@ HRESULT DP_HandleMessage( IDirectPlay2Impl* This, LPCVOID lpcMessageBody, } } + /* FIXME: There is code in dplaysp.c to handle dplay commands. Move to here. */ + return DP_OK; } @@ -1475,6 +1546,11 @@ static HRESULT WINAPI DP_IF_CreatePlayer * is this used for regular players? If only for server players, move * this call to DP_SecureOpen(...); */ +#if 0 + TRACE( "Sending message to self to get my addr\n" ); + DP_MSG_ToSelf( This, *lpidPlayer ); /* This is a hack right now */ +#endif + hr = DP_MSG_ForwardPlayerCreation( This, *lpidPlayer); } #else @@ -2107,6 +2183,47 @@ static HRESULT WINAPI DP_IF_EnumSessions return DPERR_GENERIC; } +#if 1 + /* The loading of a lobby provider _seems_ to require a backdoor loading + * of the service provider to also associate with this DP object. This is + * because the app doesn't seem to have to call EnumConnections and + * InitializeConnection for the SP before calling this method. As such + * we'll do their dirty work for them with a quick hack so as to always + * load the TCP/IP service provider. + * + * The correct solution would seem to involve creating a dialog box which + * contains the possible SPs. These dialog boxes most likely follow SDK + * examples. + */ + if( This->dp2->bDPLSPInitialized && !This->dp2->bSPInitialized ) + { + LPVOID lpConnection; + DWORD dwSize; + + WARN( "Hack providing TCP/IP SP for lobby provider activated\n" ); + + if( !DP_BuildSPCompoundAddr( (LPGUID)&DPSPGUID_TCPIP, &lpConnection, &dwSize ) ) + { + ERR( "Can't build compound addr\n" ); + return DPERR_GENERIC; + } + + hr = DP_IF_InitializeConnection( (IDirectPlay3Impl*)This, lpConnection, + 0, bAnsi ); + if( FAILED(hr) ) + { + return hr; + } + + /* Free up the address buffer */ + HeapFree( GetProcessHeap(), 0, lpConnection ); + + /* The SP is now initialized */ + This->dp2->bSPInitialized = TRUE; + } +#endif + + /* Use the service provider default? */ if( dwTimeout == 0 ) { @@ -2158,6 +2275,7 @@ static HRESULT WINAPI DP_IF_EnumSessions sizeof( *lpData ) ); /* FIXME: need to kill the thread on object deletion */ lpData->lpSpData = &This->dp2->spData; + CopyMemory( &lpData->requestGuid, &lpsd->guidApplication, sizeof(GUID) ); lpData->dwEnumSessionFlags = dwFlags; lpData->dwTimeout = dwTimeout; @@ -2693,7 +2811,7 @@ static HRESULT WINAPI DP_SecureOpen { /* Rightoo - this computer is the host and the local computer needs to be the name server so that others can join this session */ - NS_SetLocalComputerAsNameServer( lpsd ); + NS_SetLocalComputerAsNameServer( lpsd, This->dp2->lpNameServerData ); This->dp2->bHostInterface = TRUE; @@ -3458,6 +3576,45 @@ static HRESULT WINAPI DirectPlay3WImpl_DeleteGroupFromGroup return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup ); } +static +BOOL WINAPI DP_BuildSPCompoundAddr( LPGUID lpcSpGuid, LPVOID* lplpAddrBuf, + LPDWORD lpdwBufSize ) +{ + DPCOMPOUNDADDRESSELEMENT dpCompoundAddress; + HRESULT hr; + + dpCompoundAddress.dwDataSize = sizeof( GUID ); + memcpy( &dpCompoundAddress.guidDataType, &DPAID_ServiceProvider, + sizeof( GUID ) ) ; + dpCompoundAddress.lpData = lpcSpGuid; + + *lplpAddrBuf = NULL; + *lpdwBufSize = 0; + + hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf, + lpdwBufSize, TRUE ); + + if( hr != DPERR_BUFFERTOOSMALL ) + { + ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) ); + return FALSE; + } + + /* Now allocate the buffer */ + *lplpAddrBuf = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, + *lpdwBufSize ); + + hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf, + lpdwBufSize, TRUE ); + if( FAILED(hr) ) + { + ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) ); + return FALSE; + } + + return TRUE; +} + static HRESULT WINAPI DirectPlay3AImpl_EnumConnections ( LPDIRECTPLAY3A iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags ) { @@ -3515,9 +3672,8 @@ static HRESULT WINAPI DirectPlay3AImpl_EnumConnections char returnBuffer[51]; WCHAR buff[51]; DPNAME dpName; - HRESULT hr; + BOOL bBuildPass; - DPCOMPOUNDADDRESSELEMENT dpCompoundAddress; LPVOID lpAddressBuffer = NULL; DWORD dwAddressBufferSize = 0; @@ -3551,31 +3707,19 @@ static HRESULT WINAPI DirectPlay3AImpl_EnumConnections dpName.u2.lpszLongNameA = NULL; /* Create the compound address for the service provider. - NOTE: This is a gruesome architectural scar right now. DP uses DPL and DPL uses DP, - nasty stuff. This may be why the native dll just gets around this little bit by - allocating an 80 byte buffer which isn't even filled with a valid compound - address. Oh well. Creating a proper compound address is the way to go anyway... - despite this method taking slightly more heap space and realtime :) */ - dpCompoundAddress.dwDataSize = sizeof( GUID ); - memcpy( &dpCompoundAddress.guidDataType, &DPAID_ServiceProvider, - sizeof( GUID ) ) ; - dpCompoundAddress.lpData = &serviceProviderGUID; + NOTE: This is a gruesome architectural scar right now. DP uses DPL and DPL uses DP + nast stuff. This may be why the native dll just gets around this little bit by + allocating an 80 byte buffer which isn't even a filled with a valid compound + address. Oh well. Creating a proper compound address is the way to go anyways + despite this method taking slightly more heap space and realtime :) */ - if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer, - &dwAddressBufferSize, TRUE ) ) != DPERR_BUFFERTOOSMALL ) + bBuildPass = DP_BuildSPCompoundAddr( &serviceProviderGUID, + &lpAddressBuffer, + &dwAddressBufferSize ); + if( !bBuildPass ) { - ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) ); - return hr; - } - - /* Now allocate the buffer */ - lpAddressBuffer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwAddressBufferSize ); - - if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer, - &dwAddressBufferSize, TRUE ) ) != DP_OK ) - { - ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) ); - return hr; + ERR( "Can't build compound addr\n" ); + return DPERR_GENERIC; } /* The enumeration will return FALSE if we are not to continue */ @@ -3656,11 +3800,12 @@ static HRESULT WINAPI DirectPlay3AImpl_EnumConnections dpName.u2.lpszLongNameA = NULL; /* Create the compound address for the service provider. - NOTE: This is a gruesome architectural scar right now. DP uses DPL and DPL uses DP, - nasty stuff. This may be why the native dll just gets around this little bit by - allocating an 80 byte buffer which isn't even filled with a valid compound - address. Oh well. Creating a proper compound address is the way to go anyway... + NOTE: This is a gruesome architectural scar right now. DP uses DPL and DPL uses DP + nast stuff. This may be why the native dll just gets around this little bit by + allocating an 80 byte buffer which isn't even a filled with a valid compound + address. Oh well. Creating a proper compound address is the way to go anyways despite this method taking slightly more heap space and realtime :) */ + dpCompoundAddress.guidDataType = DPAID_LobbyProvider; dpCompoundAddress.dwDataSize = sizeof( GUID ); dpCompoundAddress.lpData = &serviceProviderGUID; @@ -3895,10 +4040,12 @@ static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDp continue; } - /* Save the name of the SP or LP */ - len = MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, NULL, 0 ); - lpSpData->lpszName = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) ); - MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, lpSpData->lpszName, len ); + if( i == 0 ) /* DP SP */ + { + len = MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, NULL, 0 ); + lpSpData->lpszName = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) ); + MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, lpSpData->lpszName, len ); + } sizeOfReturnBuffer = 255; @@ -3911,7 +4058,10 @@ static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDp continue; } - lpSpData->dwReserved1 = GET_DWORD( returnBuffer ); + if( i == 0 ) + { + lpSpData->dwReserved1 = GET_DWORD( returnBuffer ); + } sizeOfReturnBuffer = 255; @@ -3924,8 +4074,10 @@ static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDp continue; } - lpSpData->dwReserved2 = GET_DWORD( returnBuffer ); - + if( i == 0 ) + { + lpSpData->dwReserved2 = GET_DWORD( returnBuffer ); + } sizeOfReturnBuffer = 255; @@ -3946,12 +4098,92 @@ static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDp return 0; } +static +HRESULT DP_InitializeDPSP( IDirectPlay3Impl* This, HMODULE hServiceProvider ) +{ + HRESULT hr; + LPDPSP_SPINIT SPInit; + + /* Initialize the service provider by calling SPInit */ + SPInit = (LPDPSP_SPINIT)GetProcAddress( hServiceProvider, "SPInit" ); + + if( SPInit == NULL ) + { + ERR( "Service provider doesn't provide SPInit interface?\n" ); + FreeLibrary( hServiceProvider ); + return DPERR_UNAVAILABLE; + } + + TRACE( "Calling SPInit (DP SP entry point)\n" ); + + hr = (*SPInit)( &This->dp2->spData ); + + if( FAILED(hr) ) + { + ERR( "DP SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) ); + FreeLibrary( hServiceProvider ); + return hr; + } + + /* FIXME: Need to verify the sanity of the returned callback table + * using IsBadCodePtr */ + This->dp2->bSPInitialized = TRUE; + + /* This interface is now initialized as a DP object */ + This->dp2->connectionInitialized = DP_SERVICE_PROVIDER; + + /* Store the handle of the module so that we can unload it later */ + This->dp2->hServiceProvider = hServiceProvider; + + return hr; +} + +static +HRESULT DP_InitializeDPLSP( IDirectPlay3Impl* This, HMODULE hLobbyProvider ) +{ + HRESULT hr; + LPSP_INIT DPLSPInit; + + /* Initialize the service provider by calling SPInit */ + DPLSPInit = (LPSP_INIT)GetProcAddress( hLobbyProvider, "DPLSPInit" ); + + if( DPLSPInit == NULL ) + { + ERR( "Service provider doesn't provide DPLSPInit interface?\n" ); + FreeLibrary( hLobbyProvider ); + return DPERR_UNAVAILABLE; + } + + TRACE( "Calling DPLSPInit (DPL SP entry point)\n" ); + + hr = (*DPLSPInit)( &This->dp2->dplspData ); + + if( FAILED(hr) ) + { + ERR( "DPL SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) ); + FreeLibrary( hLobbyProvider ); + return hr; + } + + /* FIXME: Need to verify the sanity of the returned callback table + * using IsBadCodePtr */ + + This->dp2->bDPLSPInitialized = TRUE; + + /* This interface is now initialized as a lobby object */ + This->dp2->connectionInitialized = DP_LOBBY_PROVIDER; + + /* Store the handle of the module so that we can unload it later */ + This->dp2->hDPLobbyProvider = hLobbyProvider; + + return hr; +} + static HRESULT WINAPI DP_IF_InitializeConnection ( IDirectPlay3Impl* This, LPVOID lpConnection, DWORD dwFlags, BOOL bAnsi ) { HMODULE hServiceProvider; HRESULT hr; - LPDPSP_SPINIT SPInit; GUID guidSP; const DWORD dwAddrSize = 80; /* FIXME: Need to calculate it correctly */ BOOL bIsDpSp; /* TRUE if Direct Play SP, FALSE if Direct Play Lobby SP */ @@ -3963,11 +4195,6 @@ static HRESULT WINAPI DP_IF_InitializeConnection return DPERR_INVALIDFLAGS; } - if( This->dp2->bConnectionInitialized == TRUE ) - { - return DPERR_ALREADYINITIALIZED; - } - /* Find out what the requested SP is and how large this buffer is */ hr = DPL_EnumAddress( DP_GetSpLpGuidFromCompoundAddress, lpConnection, dwAddrSize, &guidSP ); @@ -3978,13 +4205,6 @@ static HRESULT WINAPI DP_IF_InitializeConnection return DPERR_UNAVAILABLE; } - /* Initialize what we can of the Service Provider required information. - * The rest will be done in DP_LoadSP - */ - This->dp2->spData.lpAddress = lpConnection; - This->dp2->spData.dwAddressSize = dwAddrSize; - This->dp2->spData.lpGuid = &guidSP; - /* Load the service provider */ hServiceProvider = DP_LoadSP( &guidSP, &This->dp2->spData, &bIsDpSp ); @@ -3996,43 +4216,27 @@ static HRESULT WINAPI DP_IF_InitializeConnection if( bIsDpSp ) { - /* Initialize the service provider by calling SPInit */ - SPInit = (LPDPSP_SPINIT)GetProcAddress( hServiceProvider, "SPInit" ); + /* Fill in what we can of the Service Provider required information. + * The rest was be done in DP_LoadSP + */ + This->dp2->spData.lpAddress = lpConnection; + This->dp2->spData.dwAddressSize = dwAddrSize; + This->dp2->spData.lpGuid = &guidSP; + + hr = DP_InitializeDPSP( This, hServiceProvider ); } else { - /* Initialize the service provider by calling SPInit */ - SPInit = (LPDPSP_SPINIT)GetProcAddress( hServiceProvider, "DPLSPInit" ); + This->dp2->dplspData.lpAddress = lpConnection; + + hr = DP_InitializeDPLSP( This, hServiceProvider ); } - if( SPInit == NULL ) - { - ERR( "Service provider doesn't provide %s interface?\n", - bIsDpSp ? "SPInit" : "DPLSPInit" ); - FreeLibrary( hServiceProvider ); - return DPERR_UNAVAILABLE; - } - - TRACE( "Calling %s (SP entry point)\n", bIsDpSp ? "SPInit" : "DPLSPInit" ); - - /* FIXME: Need to break this out into a separate routine for DP SP and - * DPL SP as they actually use different stuff... - */ - hr = (*SPInit)( &This->dp2->spData ); - if( FAILED(hr) ) { - ERR( "DP/DPL SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) ); - FreeLibrary( hServiceProvider ); return hr; } - /* This interface is now initialized */ - This->dp2->bConnectionInitialized = TRUE; - - /* Store the handle of the module so that we can unload it later */ - This->dp2->hServiceProvider = hServiceProvider; - return DP_OK; } @@ -4040,6 +4244,13 @@ static HRESULT WINAPI DirectPlay3AImpl_InitializeConnection ( LPDIRECTPLAY3A iface, LPVOID lpConnection, DWORD dwFlags ) { ICOM_THIS(IDirectPlay3Impl,iface); + + /* This may not be externally invoked once either an SP or LP is initialized */ + if( This->dp2->connectionInitialized != NO_PROVIDER ) + { + return DPERR_ALREADYINITIALIZED; + } + return DP_IF_InitializeConnection( This, lpConnection, dwFlags, TRUE ); } @@ -4047,6 +4258,13 @@ static HRESULT WINAPI DirectPlay3WImpl_InitializeConnection ( LPDIRECTPLAY3 iface, LPVOID lpConnection, DWORD dwFlags ) { ICOM_THIS(IDirectPlay3Impl,iface); + + /* This may not be externally invoked once either an SP or LP is initialized */ + if( This->dp2->connectionInitialized != NO_PROVIDER ) + { + return DPERR_ALREADYINITIALIZED; + } + return DP_IF_InitializeConnection( This, lpConnection, dwFlags, FALSE ); } diff --git a/dlls/dplayx/dplay_global.h b/dlls/dplayx/dplay_global.h index b7daa7443bf..94208c20f1e 100644 --- a/dlls/dplayx/dplay_global.h +++ b/dlls/dplayx/dplay_global.h @@ -2,6 +2,7 @@ #define __WINE_DPLAY_GLOBAL_INCLUDED #include "dplaysp.h" +#include "lobbysp.h" #include "dplayx_queue.h" extern HRESULT DPL_EnumAddress( LPDPENUMADDRESSCALLBACK lpEnumAddressCallback, @@ -126,7 +127,14 @@ struct DPMSG }; typedef struct DPMSG* LPDPMSG; -/* Contains all dp1 and dp2 data members */ +enum SPSTATE +{ + NO_PROVIDER = 0, + DP_SERVICE_PROVIDER = 1, + DP_LOBBY_PROVIDER = 2 +}; + +/* Contains all data members. FIXME: Rename me */ typedef struct tagDirectPlay2Data { BOOL bConnectionOpen; @@ -149,11 +157,19 @@ typedef struct tagDirectPlay2Data /* Information about the service provider active on this connection */ SPINITDATA spData; + BOOL bSPInitialized; + + /* Information about the lobby server that's attached to this DP object */ + SPDATA_INIT dplspData; + BOOL bDPLSPInitialized; /* Our service provider */ HMODULE hServiceProvider; - BOOL bConnectionInitialized; + /* Our DP lobby provider */ + HMODULE hDPLobbyProvider; + + enum SPSTATE connectionInitialized; /* Expected messages queue */ DPQ_HEAD( tagDP_MSG_REPLY_STRUCT_LIST ) replysExpected; diff --git a/dlls/dplayx/dplaysp.c b/dlls/dplayx/dplaysp.c index 6fc0443d662..a6619811069 100644 --- a/dlls/dplayx/dplaysp.c +++ b/dlls/dplayx/dplaysp.c @@ -168,10 +168,8 @@ static BOOL DPSP_CreateDirectPlaySP( LPVOID lpSP, IDirectPlay2Impl* dp ) * to it (ie we'd be stuck with always having one reference to the dplay * object, and hence us, around). * NOTE: The dp object does reference count us. - */ - /* IDirectPlayX_AddRef( (LPDIRECTPLAY2)dp ); */ - - /* FIXME: This is a kludge to get around a problem where a queryinterface + * + * FIXME: This is a kludge to get around a problem where a queryinterface * is used to get a new interface and then is closed. We will then * reference garbage. However, with this we will never deallocate * the interface we store. The correct fix is to require all @@ -297,6 +295,8 @@ static HRESULT WINAPI IDirectPlaySPImpl_AddMRUEntry { ICOM_THIS(IDirectPlaySPImpl,iface); + /* Should be able to call the comctl32 undocumented MRU routines. + I suspect that the interface works appropriately */ FIXME( "(%p)->(%p,%p%p,0x%08lx,0x%08lx): stub\n", This, lpSection, lpKey, lpData, dwDataSize, dwMaxEntries ); @@ -350,6 +350,8 @@ static HRESULT WINAPI IDirectPlaySPImpl_EnumMRUEntries { ICOM_THIS(IDirectPlaySPImpl,iface); + /* Should be able to call the comctl32 undocumented MRU routines. + I suspect that the interface works appropriately */ FIXME( "(%p)->(%p,%p,%p,%p,): stub\n", This, lpSection, lpKey, lpEnumMRUCallback, lpContext ); @@ -382,7 +384,6 @@ static HRESULT WINAPI IDirectPlaySPImpl_GetSPPlayerData LPDP_SPPLAYERDATA lpPlayerData; ICOM_THIS(IDirectPlaySPImpl,iface); -/* TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() ); */ TRACE( "(%p)->(0x%08lx,%p,%p,0x%08lx)\n", This, idPlayer, lplpData, lpdwDataSize, dwFlags ); @@ -435,10 +436,10 @@ static HRESULT WINAPI IDirectPlaySPImpl_HandleMessage HRESULT hr = DPERR_GENERIC; WORD wCommandId; WORD wVersion; - + DPSP_REPLYDATA data; + ICOM_THIS(IDirectPlaySPImpl,iface); -/* TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() ); */ FIXME( "(%p)->(%p,0x%08lx,%p): mostly stub\n", This, lpMessageBody, dwMessageBodySize, lpMessageHeader ); @@ -451,81 +452,49 @@ static HRESULT WINAPI IDirectPlaySPImpl_HandleMessage if( lpMsg->dwMagic != DPMSGMAGIC_DPLAYMSG ) { ERR( "Unknown magic 0x%08lx!\n", lpMsg->dwMagic ); + return DPERR_GENERIC; } - switch( lpMsg->wCommandId ) +#if 0 { - /* Name server needs to handle this request */ - /* FIXME: This should be done in direct play handler */ - case DPMSGCMD_ENUMSESSIONSREQUEST: + const LPDWORD lpcHeader = (LPDWORD)lpMessageHeader; + + TRACE( "lpMessageHeader = [0x%08lx] [0x%08lx] [0x%08lx] [0x%08lx] [0x%08lx]\n", + lpcHeader[0], lpcHeader[1], lpcHeader[2], lpcHeader[3], lpcHeader[4] ); + } +#endif + + /* Pass everything else to Direct Play */ + data.lpMessage = NULL; + data.dwMessageSize = 0; + + /* Pass this message to the dplay interface to handle */ + hr = DP_HandleMessage( This->sp->dplay, lpMessageBody, dwMessageBodySize, + lpMessageHeader, wCommandId, wVersion, + &data.lpMessage, &data.dwMessageSize ); + + if( FAILED(hr) ) + { + ERR( "Command processing failed %s\n", DPLAYX_HresultToString(hr) ); + } + + /* Do we want a reply? */ + if( data.lpMessage != NULL ) + { + data.lpSPMessageHeader = lpMessageHeader; + data.idNameServer = 0; + data.lpISP = iface; + + hr = (This->sp->dplay->dp2->spData.lpCB->Reply)( &data ); + + if( FAILED(hr) ) { - DPSP_REPLYDATA data; - - data.lpSPMessageHeader = lpMessageHeader; - data.idNameServer = 0; - data.lpISP = iface; - - NS_ReplyToEnumSessionsRequest( lpMessageBody, &data, This->sp->dplay ); - - hr = (This->sp->dplay->dp2->spData.lpCB->Reply)( &data ); - - if( FAILED(hr) ) - { - ERR( "Reply failed 0x%08lx\n", hr ); - } - - break; - } - - /* Name server needs to handle this request */ - /* FIXME: This should be done in direct play handler */ - case DPMSGCMD_ENUMSESSIONSREPLY: - { - NS_SetRemoteComputerAsNameServer( lpMessageHeader, - This->sp->dplay->dp2->spData.dwSPHeaderSize, - (LPDPMSG_ENUMSESSIONSREPLY)lpMessageBody, - This->sp->dplay->dp2->lpNameServerData ); - - /* No reply expected */ - hr = DP_OK; - - break; - } - - /* Pass everything else to Direct Play */ - default: - { - DPSP_REPLYDATA data; - - data.lpMessage = NULL; - data.dwMessageSize = 0; - - /* Pass this message to the dplay interface to handle */ - hr = DP_HandleMessage( This->sp->dplay, lpMessageBody, dwMessageBodySize, - lpMessageHeader, wCommandId, wVersion, - &data.lpMessage, &data.dwMessageSize ); - - /* Do we want a reply? */ - if( data.lpMessage != NULL ) - { - HRESULT hr; - - data.lpSPMessageHeader = lpMessageHeader; - data.idNameServer = 0; - data.lpISP = iface; - - hr = (This->sp->dplay->dp2->spData.lpCB->Reply)( &data ); - - if( FAILED(hr) ) - { - ERR( "Reply failed %s\n", DPLAYX_HresultToString(hr) ); - } - } - - break; + ERR( "Reply failed %s\n", DPLAYX_HresultToString(hr) ); } } + return hr; + #if 0 HRESULT hr = DP_OK; HANDLE hReceiveEvent = 0; @@ -768,8 +737,6 @@ static HRESULT WINAPI IDirectPlaySPImpl_HandleMessage SetEvent( hReceiveEvent ); } #endif - - return hr; } static HRESULT WINAPI IDirectPlaySPImpl_SetSPPlayerData @@ -859,7 +826,7 @@ static HRESULT WINAPI IDirectPlaySPImpl_GetSPData */ if( dwFlags != DPSET_REMOTE ) { - FIXME( "Undocumented dwFlags 0x%08lx used\n", dwFlags ); + TRACE( "Undocumented dwFlags 0x%08lx used\n", dwFlags ); } #endif @@ -918,7 +885,7 @@ static HRESULT WINAPI IDirectPlaySPImpl_SetSPData */ if( dwFlags != DPSET_REMOTE ) { - FIXME( "Undocumented dwFlags 0x%08lx used\n", dwFlags ); + TRACE( "Undocumented dwFlags 0x%08lx used\n", dwFlags ); } #endif diff --git a/dlls/dplayx/dplayx_global.c b/dlls/dplayx/dplayx_global.c index d9b6fa58dfc..e77615ca220 100644 --- a/dlls/dplayx/dplayx_global.c +++ b/dlls/dplayx/dplayx_global.c @@ -1240,10 +1240,8 @@ LPCSTR DPLAYX_HresultToString(HRESULT hr) return "DPERR_NOPLAYERS"; case DPERR_NOSESSIONS: return "DPERR_NOSESSIONS"; -/* This one isn't defined yet in WINE sources. I don't know the value case DPERR_PENDING: return "DPERR_PENDING"; -*/ case DPERR_SENDTOOBIG: return "DPERR_SENDTOOBIG"; case DPERR_TIMEOUT: diff --git a/dlls/dplayx/dplayx_messages.c b/dlls/dplayx/dplayx_messages.c index cf36b6d783a..1e4342e91e9 100644 --- a/dlls/dplayx/dplayx_messages.c +++ b/dlls/dplayx/dplayx_messages.c @@ -1,6 +1,6 @@ /* DirectPlay & DirectPlayLobby messaging implementation * - * Copyright 2000 - Peter Hunnisett + * Copyright 2000,2001 - Peter Hunnisett * * * @@ -17,6 +17,7 @@ #include "dplayx_messages.h" #include "dplay_global.h" #include "dplayx_global.h" +#include "name_server.h" DEFAULT_DEBUG_CHANNEL(dplay); @@ -212,7 +213,6 @@ HRESULT DP_MSG_SendRequestPlayerId( IDirectPlay2AImpl* This, DWORD dwFlags, TRACE( "Asking for player id w/ dwFlags 0x%08lx\n", lpMsgBody->dwFlags ); - DP_MSG_ExpectReply( This, &data, DPMSG_DEFAULT_WAIT_TIME, DPMSGCMD_NEWPLAYERIDREPLY, &lpMsg, &dwMsgSize ); } @@ -267,7 +267,7 @@ HRESULT DP_MSG_ForwardPlayerCreation( IDirectPlay2AImpl* This, DPID dpidServer ) DWORD dwDataSize; /* SP Player remote data needs to be propagated at some point - is this the point? */ - IDirectPlaySP_GetSPPlayerData( This->dp2->spData.lpISP, dpidServer, (LPVOID*)&lpPData, &dwDataSize, DPSET_REMOTE ); + IDirectPlaySP_GetSPPlayerData( This->dp2->spData.lpISP, 0, (LPVOID*)&lpPData, &dwDataSize, DPSET_REMOTE ); ERR( "Player Data size is 0x%08lx\n" "[%02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x]\n" @@ -305,11 +305,22 @@ HRESULT DP_MSG_ForwardPlayerCreation( IDirectPlay2AImpl* This, DPID dpidServer ) lpMsgBody->unknown4[0] = 0x30; lpMsgBody->unknown4[1] = 0xb; lpMsgBody->unknown4[2] = 0x0; - lpMsgBody->unknown4[3] = 0x1e090002; + + lpMsgBody->unknown4[3] = NS_GetNsMagic( This->dp2->lpNameServerData ) - + 0x02000000; + TRACE( "Setting first magic to 0x%08lx\n", lpMsgBody->unknown4[3] ); + lpMsgBody->unknown4[4] = 0x0; lpMsgBody->unknown4[5] = 0x0; lpMsgBody->unknown4[6] = 0x0; - lpMsgBody->unknown4[7] = 0x32090002; + +#if 0 + lpMsgBody->unknown4[7] = NS_GetOtherMagic( This->dp2->lpNameServerData ) +#else + lpMsgBody->unknown4[7] = NS_GetNsMagic( This->dp2->lpNameServerData ); +#endif + TRACE( "Setting second magic to 0x%08lx\n", lpMsgBody->unknown4[7] ); + lpMsgBody->unknown4[8] = 0x0; lpMsgBody->unknown4[9] = 0x0; lpMsgBody->unknown4[10] = 0x0; @@ -331,6 +342,8 @@ HRESULT DP_MSG_ForwardPlayerCreation( IDirectPlay2AImpl* This, DPID dpidServer ) data.bSystemMessage = TRUE; /* Allow reply to be sent */ data.lpISP = This->dp2->spData.lpISP; + TRACE( "Sending forward player request with 0x%08lx\n", dpidServer ); + lpMsg = DP_MSG_ExpectReply( This, &data, DPMSG_WAIT_60_SECS, DPMSGCMD_GETNAMETABLEREPLY, @@ -372,11 +385,13 @@ LPVOID DP_MSG_ExpectReply( IDirectPlay2AImpl* This, LPDPSP_SENDDATA lpData, if( FAILED(hr) ) { - ERR( "Request for new playerID send failed: %s\n", - DPLAYX_HresultToString( hr ) ); + ERR( "Send failed: %s\n", DPLAYX_HresultToString( hr ) ); return NULL; } + /* The reply message will trigger the hMsgReceipt event effectively switching + * control back to this thread. See DP_MSG_ReplyReceived. + */ dwWaitReturn = WaitForSingleObject( hMsgReceipt, dwWaitTime ); if( dwWaitReturn != WAIT_OBJECT_0 ) { @@ -429,7 +444,43 @@ void DP_MSG_ReplyReceived( IDirectPlay2AImpl* This, WORD wCommandId, ERR( "No receipt event set - only expecting in reply mode\n" ); DebugBreak(); } - +} + +void DP_MSG_ToSelf( IDirectPlay2AImpl* This, DPID dpidSelf ) +{ + LPVOID lpMsg; + LPDPMSG_SENDENVELOPE lpMsgBody; + DWORD dwMsgSize; + + dwMsgSize = This->dp2->spData.dwSPHeaderSize + sizeof( *lpMsgBody ); + + lpMsg = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwMsgSize ); + + lpMsgBody = (LPDPMSG_SENDENVELOPE)( (BYTE*)lpMsg + + This->dp2->spData.dwSPHeaderSize ); + + /* Compose dplay message envelope */ + lpMsgBody->dwMagic = DPMSGMAGIC_DPLAYMSG; + lpMsgBody->wCommandId = DPMSGCMD_JUSTENVELOPE; + lpMsgBody->wVersion = DPMSGVER_DP6; + + /* Send the message to ourselves */ + { + DPSP_SENDDATA data; + + data.dwFlags = 0; + data.idPlayerTo = dpidSelf; /* Sending to session server */ + data.idPlayerFrom = 0; /* Sending from session server */ + data.lpMessage = lpMsg; + data.dwMessageSize = dwMsgSize; + data.bSystemMessage = TRUE; /* Allow reply to be sent */ + data.lpISP = This->dp2->spData.lpISP; + + lpMsg = DP_MSG_ExpectReply( This, &data, + DPMSG_WAIT_5_SECS, + DPMSGCMD_JUSTENVELOPE, + &lpMsg, &dwMsgSize ); + } } void DP_MSG_ErrorReceived( IDirectPlay2AImpl* This, WORD wCommandId, diff --git a/dlls/dplayx/dplayx_messages.h b/dlls/dplayx/dplayx_messages.h index 6c0dd61dd79..191858b47dd 100644 --- a/dlls/dplayx/dplayx_messages.h +++ b/dlls/dplayx/dplayx_messages.h @@ -19,6 +19,7 @@ void DP_MSG_ReplyReceived( IDirectPlay2AImpl* This, WORD wCommandId, LPCVOID lpMsgBody, DWORD dwMsgBodySize ); void DP_MSG_ErrorReceived( IDirectPlay2AImpl* This, WORD wCommandId, LPCVOID lpMsgBody, DWORD dwMsgBodySize ); +void DP_MSG_ToSelf( IDirectPlay2AImpl* This, DPID dpidSelf ); /* Timings -> 1000 ticks/sec */ #define DPMSG_WAIT_5_SECS 5000 @@ -47,8 +48,13 @@ void DP_MSG_ErrorReceived( IDirectPlay2AImpl* This, WORD wCommandId, #define DPMSGCMD_FORWARDADDPLAYER 19 +#define DPMSGCMD_PLAYERCHAT 22 + #define DPMSGCMD_FORWARDADDPLAYERNACK 36 +#define DPMSGCMD_JUSTENVELOPE 1000 +#define DPMSGCMD_JUSTENVELOPEREPLY 1001 + /* This is what DP 6 defines it as. Don't know what it means. All messages * defined below are DPMSGVER_DP6. */ @@ -163,21 +169,21 @@ typedef struct tagDPMSG_FORWARDADDPLAYER DWORD unknown; /* 0 */ DPID dpidAppServer; /* Remote application server id */ - DWORD unknown2[5]; /* ??? */ -#define FORWARDADDPLAYER_UNKNOWN2_INIT { 0x0, 0x1c, 0x6c, 0x50, 0x9 } + DWORD unknown2[5]; /* 0x0, 0x1c, 0x6c, 0x50, 0x9 */ DPID dpidAppServer2; /* Remote application server id again !? */ - DWORD unknown3[5]; /* ??? */ -#define FORWARDADDPLAYER_UNKNOWN3_INIT { 0x0, 0x0, 0x20, 0x0, 0x0 } + DWORD unknown3[5]; /* 0x0, 0x0, 0x20, 0x0, 0x0 */ DPID dpidAppServer3; /* Remote application server id again !? */ DWORD unknown4[12]; /* ??? - Is this a clump of 5 and then 8? */ - /* NOTE: 1 byte infront of the two 0x??090002 entries changes! */ + /* NOTE: 1 byte infront of the two 0x??090002 entries changes! + * Is it a timestamp of some sort? 1st always smaller than + * other... + */ #define FORWARDADDPLAYER_UNKNOWN4_INIT { 0x30, 0xb, 0x0, 0x1e090002, 0x0, 0x0, 0x0, 0x32090002, 0x0, 0x0, 0x0, 0x0 } - BYTE unknown5[2]; /* 2 bytes at the end. This may be a part of something! */ -#define FORWARDADDPLAYER_UNKNOWN5_INIT { 0x0 } + BYTE unknown5[2]; /* 2 bytes at the end. This may be a part of something! ( 0x0, 0x0) */ } DPMSG_FORWARDADDPLAYER, *LPDPMSG_FORWARDADDPLAYER; typedef const DPMSG_FORWARDADDPLAYER* LPCDPMSG_FORWARDADDPLAYER; diff --git a/dlls/dplayx/lobbysp.c b/dlls/dplayx/lobbysp.c new file mode 100644 index 00000000000..3a1883088b9 --- /dev/null +++ b/dlls/dplayx/lobbysp.c @@ -0,0 +1,454 @@ +/* This contains the implementation of the Lobby Service + * Providers interface required to communicate with Direct Play + * + * Copyright 2001 Peter Hunnisett + */ + +#include "winerror.h" +#include "debugtools.h" + +#include "lobbysp.h" +#include "dplay_global.h" +#include "dpinit.h" + +DEFAULT_DEBUG_CHANNEL(dplay); + +/* Prototypes */ +static BOOL DPLSP_CreateIUnknown( LPVOID lpSP ); +static BOOL DPLSP_DestroyIUnknown( LPVOID lpSP ); +static BOOL DPLSP_CreateDPLobbySP( LPVOID lpSP, IDirectPlay2Impl* dp ); +static BOOL DPLSP_DestroyDPLobbySP( LPVOID lpSP ); + + +/* Predefine the interface */ +typedef struct IDPLobbySPImpl IDPLobbySPImpl; + +typedef struct tagDPLobbySPIUnknownData +{ + ULONG ulObjRef; + CRITICAL_SECTION DPLSP_lock; +} DPLobbySPIUnknownData; + +typedef struct tagDPLobbySPData +{ + IDirectPlay2Impl* dplay; +} DPLobbySPData; + +#define DPLSP_IMPL_FIELDS \ + ULONG ulInterfaceRef; \ + DPLobbySPIUnknownData* unk; \ + DPLobbySPData* sp; + +struct IDPLobbySPImpl +{ + ICOM_VFIELD(IDPLobbySP); + DPLSP_IMPL_FIELDS +}; + +/* Forward declaration of virtual tables */ +static ICOM_VTABLE(IDPLobbySP) dpLobbySPVT; + +extern +HRESULT DPLSP_CreateInterface( REFIID riid, LPVOID* ppvObj, IDirectPlay2Impl* dp ) +{ + TRACE( " for %s\n", debugstr_guid( riid ) ); + + *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, + sizeof( IDPLobbySPImpl ) ); + + if( *ppvObj == NULL ) + { + return DPERR_OUTOFMEMORY; + } + + if( IsEqualGUID( &IID_IDPLobbySP, riid ) ) + { + ICOM_THIS(IDPLobbySPImpl,*ppvObj); + ICOM_VTBL(This) = &dpLobbySPVT; + } + else + { + /* Unsupported interface */ + HeapFree( GetProcessHeap(), 0, *ppvObj ); + *ppvObj = NULL; + + return E_NOINTERFACE; + } + + /* Initialize it */ + if( DPLSP_CreateIUnknown( *ppvObj ) && + DPLSP_CreateDPLobbySP( *ppvObj, dp ) + ) + { + IDPLobbySP_AddRef( (LPDPLOBBYSP)*ppvObj ); + return S_OK; + } + + /* Initialize failed, destroy it */ + DPLSP_DestroyDPLobbySP( *ppvObj ); + DPLSP_DestroyIUnknown( *ppvObj ); + + HeapFree( GetProcessHeap(), 0, *ppvObj ); + *ppvObj = NULL; + + return DPERR_NOMEMORY; +} + +static BOOL DPLSP_CreateIUnknown( LPVOID lpSP ) +{ + ICOM_THIS(IDPLobbySPImpl,lpSP); + + This->unk = (DPLobbySPIUnknownData*)HeapAlloc( GetProcessHeap(), + HEAP_ZERO_MEMORY, + sizeof( *(This->unk) ) ); + + if ( This->unk == NULL ) + { + return FALSE; + } + + InitializeCriticalSection( &This->unk->DPLSP_lock ); + + return TRUE; +} + +static BOOL DPLSP_DestroyIUnknown( LPVOID lpSP ) +{ + ICOM_THIS(IDPLobbySPImpl,lpSP); + + DeleteCriticalSection( &This->unk->DPLSP_lock ); + HeapFree( GetProcessHeap(), 0, This->unk ); + + return TRUE; +} + +static BOOL DPLSP_CreateDPLobbySP( LPVOID lpSP, IDirectPlay2Impl* dp ) +{ + ICOM_THIS(IDPLobbySPImpl,lpSP); + + This->sp = (DPLobbySPData*)HeapAlloc( GetProcessHeap(), + HEAP_ZERO_MEMORY, + sizeof( *(This->sp) ) ); + + if ( This->sp == NULL ) + { + return FALSE; + } + + This->sp->dplay = dp; + + /* Normally we should be keeping a reference, but since only the dplay + * interface that created us can destroy us, we do not keep a reference + * to it (ie we'd be stuck with always having one reference to the dplay + * object, and hence us, around). + * NOTE: The dp object does reference count us. + * + * FIXME: This is a kludge to get around a problem where a queryinterface + * is used to get a new interface and then is closed. We will then + * reference garbage. However, with this we will never deallocate + * the interface we store. The correct fix is to require all + * DP internal interfaces to use the This->dp2 interface which + * should be changed to This->dp + */ + IDirectPlayX_AddRef( (LPDIRECTPLAY2)dp ); + + + return TRUE; +} + +static BOOL DPLSP_DestroyDPLobbySP( LPVOID lpSP ) +{ + ICOM_THIS(IDPLobbySPImpl,lpSP); + + HeapFree( GetProcessHeap(), 0, This->sp ); + + return TRUE; +} + +static +HRESULT WINAPI DPLSP_QueryInterface +( LPDPLOBBYSP iface, + REFIID riid, + LPVOID* ppvObj +) +{ + ICOM_THIS(IDPLobbySPImpl,iface); + TRACE("(%p)->(%s,%p)\n", This, debugstr_guid( riid ), ppvObj ); + + *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, + sizeof( *This ) ); + + if( *ppvObj == NULL ) + { + return DPERR_OUTOFMEMORY; + } + + CopyMemory( *ppvObj, This, sizeof( *This ) ); + (*(IDPLobbySPImpl**)ppvObj)->ulInterfaceRef = 0; + + if( IsEqualGUID( &IID_IDPLobbySP, riid ) ) + { + ICOM_THIS(IDPLobbySPImpl,*ppvObj); + ICOM_VTBL(This) = &dpLobbySPVT; + } + else + { + /* Unsupported interface */ + HeapFree( GetProcessHeap(), 0, *ppvObj ); + *ppvObj = NULL; + + return E_NOINTERFACE; + } + + IDPLobbySP_AddRef( (LPDPLOBBYSP)*ppvObj ); + + return S_OK; +} + +static +ULONG WINAPI DPLSP_AddRef +( LPDPLOBBYSP iface ) +{ + ULONG ulInterfaceRefCount, ulObjRefCount; + ICOM_THIS(IDPLobbySPImpl,iface); + + ulObjRefCount = InterlockedIncrement( &This->unk->ulObjRef ); + ulInterfaceRefCount = InterlockedIncrement( &This->ulInterfaceRef ); + + TRACE( "ref count incremented to %lu:%lu for %p\n", + ulInterfaceRefCount, ulObjRefCount, This ); + + return ulObjRefCount; +} + +static +ULONG WINAPI DPLSP_Release +( LPDPLOBBYSP iface ) +{ + ULONG ulInterfaceRefCount, ulObjRefCount; + ICOM_THIS(IDPLobbySPImpl,iface); + + ulObjRefCount = InterlockedDecrement( &This->unk->ulObjRef ); + ulInterfaceRefCount = InterlockedDecrement( &This->ulInterfaceRef ); + + TRACE( "ref count decremented to %lu:%lu for %p\n", + ulInterfaceRefCount, ulObjRefCount, This ); + + /* Deallocate if this is the last reference to the object */ + if( ulObjRefCount == 0 ) + { + DPLSP_DestroyDPLobbySP( This ); + DPLSP_DestroyIUnknown( This ); + } + + if( ulInterfaceRefCount == 0 ) + { + HeapFree( GetProcessHeap(), 0, This ); + } + + return ulInterfaceRefCount; +} + +static +HRESULT WINAPI IDPLobbySPImpl_AddGroupToGroup +( LPDPLOBBYSP iface, + LPSPDATA_ADDREMOTEGROUPTOGROUP argtg +) +{ + ICOM_THIS(IDPLobbySPImpl,iface); + FIXME( "(%p)->(%p):stub\n", This, argtg ); + return DP_OK; +} + +static +HRESULT WINAPI IDPLobbySPImpl_AddPlayerToGroup +( LPDPLOBBYSP iface, + LPSPDATA_ADDREMOTEPLAYERTOGROUP arptg +) +{ + ICOM_THIS(IDPLobbySPImpl,iface); + FIXME( "(%p)->(%p):stub\n", This, arptg ); + return DP_OK; +} + +static +HRESULT WINAPI IDPLobbySPImpl_CreateGroup +( LPDPLOBBYSP iface, + LPSPDATA_CREATEREMOTEGROUP crg +) +{ + ICOM_THIS(IDPLobbySPImpl,iface); + FIXME( "(%p)->(%p):stub\n", This, crg ); + return DP_OK; +} + +static +HRESULT WINAPI IDPLobbySPImpl_CreateGroupInGroup +( LPDPLOBBYSP iface, + LPSPDATA_CREATEREMOTEGROUPINGROUP crgig +) +{ + ICOM_THIS(IDPLobbySPImpl,iface); + FIXME( "(%p)->(%p):stub\n", This, crgig ); + return DP_OK; +} + +static +HRESULT WINAPI IDPLobbySPImpl_DeleteGroupFromGroup +( LPDPLOBBYSP iface, + LPSPDATA_DELETEREMOTEGROUPFROMGROUP drgfg +) +{ + ICOM_THIS(IDPLobbySPImpl,iface); + FIXME( "(%p)->(%p):stub\n", This, drgfg ); + return DP_OK; +} + +static +HRESULT WINAPI IDPLobbySPImpl_DeletePlayerFromGroup +( LPDPLOBBYSP iface, + LPSPDATA_DELETEREMOTEPLAYERFROMGROUP drpfg +) +{ + ICOM_THIS(IDPLobbySPImpl,iface); + FIXME( "(%p)->(%p):stub\n", This, drpfg ); + return DP_OK; +} + +static +HRESULT WINAPI IDPLobbySPImpl_DestroyGroup +( LPDPLOBBYSP iface, + LPSPDATA_DESTROYREMOTEGROUP drg +) +{ + ICOM_THIS(IDPLobbySPImpl,iface); + FIXME( "(%p)->(%p):stub\n", This, drg ); + return DP_OK; +} + +static +HRESULT WINAPI IDPLobbySPImpl_EnumSessionsResponse +( LPDPLOBBYSP iface, + LPSPDATA_ENUMSESSIONSRESPONSE er +) +{ + ICOM_THIS(IDPLobbySPImpl,iface); + FIXME( "(%p)->(%p):stub\n", This, er ); + return DP_OK; +} + +static +HRESULT WINAPI IDPLobbySPImpl_GetSPDataPointer +( LPDPLOBBYSP iface, + LPVOID* lplpData +) +{ + ICOM_THIS(IDPLobbySPImpl,iface); + FIXME( "(%p)->(%p):stub\n", This, lplpData ); + return DP_OK; +} + +static +HRESULT WINAPI IDPLobbySPImpl_HandleMessage +( LPDPLOBBYSP iface, + LPSPDATA_HANDLEMESSAGE hm +) +{ + ICOM_THIS(IDPLobbySPImpl,iface); + FIXME( "(%p)->(%p):stub\n", This, hm ); + return DP_OK; +} + +static +HRESULT WINAPI IDPLobbySPImpl_SendChatMessage +( LPDPLOBBYSP iface, + LPSPDATA_CHATMESSAGE cm +) +{ + ICOM_THIS(IDPLobbySPImpl,iface); + FIXME( "(%p)->(%p):stub\n", This, cm ); + return DP_OK; +} + +static +HRESULT WINAPI IDPLobbySPImpl_SetGroupName +( LPDPLOBBYSP iface, + LPSPDATA_SETREMOTEGROUPNAME srgn +) +{ + ICOM_THIS(IDPLobbySPImpl,iface); + FIXME( "(%p)->(%p):stub\n", This, srgn ); + return DP_OK; +} + +static +HRESULT WINAPI IDPLobbySPImpl_SetPlayerName +( LPDPLOBBYSP iface, + LPSPDATA_SETREMOTEPLAYERNAME srpn +) +{ + ICOM_THIS(IDPLobbySPImpl,iface); + FIXME( "(%p)->(%p):stub\n", This, srpn ); + return DP_OK; +} + +static +HRESULT WINAPI IDPLobbySPImpl_SetSessionDesc +( LPDPLOBBYSP iface, + LPSPDATA_SETSESSIONDESC ssd +) +{ + ICOM_THIS(IDPLobbySPImpl,iface); + FIXME( "(%p)->(%p):stub\n", This, ssd ); + return DP_OK; +} + +static +HRESULT WINAPI IDPLobbySPImpl_SetSPDataPointer +( LPDPLOBBYSP iface, + LPVOID lpData +) +{ + ICOM_THIS(IDPLobbySPImpl,iface); + FIXME( "(%p)->(%p):stub\n", This, lpData ); + return DP_OK; +} + +static +HRESULT WINAPI IDPLobbySPImpl_StartSession +( LPDPLOBBYSP iface, + LPSPDATA_STARTSESSIONCOMMAND ssc +) +{ + ICOM_THIS(IDPLobbySPImpl,iface); + FIXME( "(%p)->(%p):stub\n", This, ssc ); + return DP_OK; +} + + +static struct ICOM_VTABLE(IDPLobbySP) dpLobbySPVT = +{ + ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE + + DPLSP_QueryInterface, + DPLSP_AddRef, + DPLSP_Release, + + IDPLobbySPImpl_AddGroupToGroup, + IDPLobbySPImpl_AddPlayerToGroup, + IDPLobbySPImpl_CreateGroup, + IDPLobbySPImpl_CreateGroupInGroup, + IDPLobbySPImpl_DeleteGroupFromGroup, + IDPLobbySPImpl_DeletePlayerFromGroup, + IDPLobbySPImpl_DestroyGroup, + IDPLobbySPImpl_EnumSessionsResponse, + IDPLobbySPImpl_GetSPDataPointer, + IDPLobbySPImpl_HandleMessage, + IDPLobbySPImpl_SendChatMessage, + IDPLobbySPImpl_SetGroupName, + IDPLobbySPImpl_SetPlayerName, + IDPLobbySPImpl_SetSessionDesc, + IDPLobbySPImpl_SetSPDataPointer, + IDPLobbySPImpl_StartSession + +}; diff --git a/dlls/dplayx/lobbysp.h b/dlls/dplayx/lobbysp.h new file mode 100644 index 00000000000..ff3bc6d9379 --- /dev/null +++ b/dlls/dplayx/lobbysp.h @@ -0,0 +1,494 @@ +#ifndef __WINE_LOBBY_SP_H +#define __WINE_LOBBY_SP_H + +#include "dplobby.h" + +/* GUID for IDPLobbySP {5A4E5A20-2CED-11d0-A889-00A0C905433C} */ +DEFINE_GUID(IID_IDPLobbySP, 0x5a4e5a20, 0x2ced, 0x11d0, 0xa8, 0x89, 0x0, 0xa0, 0xc9, 0x5, 0x43, 0x3c); +typedef struct IDPLobbySP IDPLobbySP, *LPDPLOBBYSP; + +/* For SP. Top 16 bits is dplay, bottom 16 is SP */ +#define DPLSP_MAJORVERSION 0x00050000 + +typedef struct SPDATA_ADDGROUPTOGROUP +{ + DWORD dwSize; + LPDPLOBBYSP lpISP; + DWORD dwParentID; + DWORD dwGroupID; +} SPDATA_ADDGROUPTOGROUP, *LPSPDATA_ADDGROUPTOGROUP; + +typedef struct SPDATA_ADDPLAYERTOGROUP +{ + DWORD dwSize; + LPDPLOBBYSP lpISP; + DWORD dwGroupID; + DWORD dwPlayerID; +} SPDATA_ADDPLAYERTOGROUP, *LPSPDATA_ADDPLAYERTOGROUP; + +typedef struct SPDATA_ADDREMOTEGROUPTOGROUP +{ + DWORD dwSize; + LPDPLOBBYSP lpISP; + DWORD dwAnchorID; + DWORD dwGroupID; + DWORD dwParentID; + LPDPNAME lpName; + DWORD dwGroupFlags; +} SPDATA_ADDREMOTEGROUPTOGROUP, *LPSPDATA_ADDREMOTEGROUPTOGROUP; + +typedef struct SPDATA_ADDREMOTEPLAYERTOGROUP +{ + DWORD dwSize; + LPDPLOBBYSP lpISP; + DWORD dwGroupID; + DWORD dwPlayerID; + DWORD dwPlayerFlags; + LPDPNAME lpName; +} SPDATA_ADDREMOTEPLAYERTOGROUP, *LPSPDATA_ADDREMOTEPLAYERTOGROUP; + +typedef struct SPDATA_BUILDPARENTALHEIRARCHY +{ + DWORD dwSize; + LPDPLOBBYSP lpISP; + DWORD dwGroupID; + DWORD dwMessage; + DWORD dwParentID; +} SPDATA_BUILDPARENTALHEIRARCHY, *LPSPDATA_BUILDPARENTALHEIRARCHY; + +typedef struct SPDATA_CLOSE +{ + DWORD dwSize; + LPDPLOBBYSP lpISP; +} SPDATA_CLOSE, *LPSPDATA_CLOSE; + +typedef struct SPDATA_CREATEGROUP +{ + DWORD dwSize; + LPDPLOBBYSP lpISP; + DWORD dwGroupID; + LPDPNAME lpName; + LPVOID lpData; + DWORD dwDataSize; + DWORD dwFlags; +} SPDATA_CREATEGROUP, *LPSPDATA_CREATEGROUP; + +typedef struct SPDATA_CREATEGROUPINGROUP +{ + DWORD dwSize; + LPDPLOBBYSP lpISP; + DWORD dwParentID; + DWORD dwGroupID; + LPDPNAME lpName; + LPVOID lpData; + DWORD dwDataSize; + DWORD dwFlags; +} SPDATA_CREATEGROUPINGROUP, *LPSPDATA_CREATEGROUPINGROUP; + +typedef struct SPDATA_CREATEREMOTEGROUP +{ + DWORD dwSize; + LPDPLOBBYSP lpISP; + DWORD dwGroupID; + LPDPNAME lpName; + LPVOID lpData; + DWORD dwDataSize; + DWORD dwFlags; +} SPDATA_CREATEREMOTEGROUP, *LPSPDATA_CREATEREMOTEGROUP; + +typedef struct SPDATA_CREATEREMOTEGROUPINGROUP +{ + DWORD dwSize; + LPDPLOBBYSP lpISP; + DWORD dwParentID; + DWORD dwGroupID; + LPDPNAME lpName; + DWORD dwFlags; +} SPDATA_CREATEREMOTEGROUPINGROUP, *LPSPDATA_CREATEREMOTEGROUPINGROUP; + +typedef struct SPDATA_CREATEPLAYER +{ + DWORD dwSize; + LPDPLOBBYSP lpISP; + DWORD dwPlayerID; + LPDPNAME lpName; + LPVOID lpData; + DWORD dwDataSize; + DWORD dwFlags; +} SPDATA_CREATEPLAYER, *LPSPDATA_CREATEPLAYER; + +typedef struct SPDATA_DELETEGROUPFROMGROUP +{ + DWORD dwSize; + LPDPLOBBYSP lpISP; + DWORD dwParentID; + DWORD dwGroupID; +} SPDATA_DELETEGROUPFROMGROUP, *LPSPDATA_DELETEGROUPFROMGROUP; + +typedef struct SPDATA_DELETEPLAYERFROMGROUP +{ + DWORD dwSize; + LPDPLOBBYSP lpISP; + DWORD dwGroupID; + DWORD dwPlayerID; +} SPDATA_DELETEPLAYERFROMGROUP, *LPSPDATA_DELETEPLAYERFROMGROUP; + +typedef struct SPDATA_DELETEREMOTEGROUPFROMGROUP +{ + DWORD dwSize; + LPDPLOBBYSP lpISP; + DWORD dwParentID; + DWORD dwGroupID; +} SPDATA_DELETEREMOTEGROUPFROMGROUP, *LPSPDATA_DELETEREMOTEGROUPFROMGROUP; + +typedef struct SPDATA_DELETEREMOTEPLAYERFROMGROUP +{ + DWORD dwSize; + LPDPLOBBYSP lpISP; + DWORD dwGroupID; + DWORD dwPlayerID; +} SPDATA_DELETEREMOTEPLAYERFROMGROUP, *LPSPDATA_DELETEREMOTEPLAYERFROMGROUP; + +typedef struct SPDATA_DESTROYGROUP +{ + DWORD dwSize; + LPDPLOBBYSP lpISP; + DWORD dwGroupID; +} SPDATA_DESTROYGROUP, *LPSPDATA_DESTROYGROUP; + +typedef struct SPDATA_DESTROYREMOTEGROUP +{ + DWORD dwSize; + LPDPLOBBYSP lpISP; + DWORD dwGroupID; +} SPDATA_DESTROYREMOTEGROUP, *LPSPDATA_DESTROYREMOTEGROUP; + +typedef struct SPDATA_DESTROYPLAYER +{ + DWORD dwSize; + LPDPLOBBYSP lpISP; + DWORD dwPlayerID; +} SPDATA_DESTROYPLAYER, *LPSPDATA_DESTROYPLAYER; + +typedef struct SPDATA_ENUMSESSIONS +{ + DWORD dwSize; + LPDPLOBBYSP lpISP; + LPDPSESSIONDESC2 lpsd; + DWORD dwTimeout; + DWORD dwFlags; +} SPDATA_ENUMSESSIONS, *LPSPDATA_ENUMSESSIONS; + +typedef struct SPDATA_ENUMSESSIONSRESPONSE +{ + DWORD dwSize; + LPDPSESSIONDESC2 lpsd; +} SPDATA_ENUMSESSIONSRESPONSE, *LPSPDATA_ENUMSESSIONSRESPONSE; + +typedef struct SPDATA_GETCAPS +{ + DWORD dwSize; + LPDPLOBBYSP lpISP; + DWORD dwFlags; + LPDPCAPS lpcaps; +} SPDATA_GETCAPS, *LPSPDATA_GETCAPS; + +typedef struct SPDATA_GETGROUPCONNECTIONSETTINGS +{ + DWORD dwSize; + DWORD dwFlags; + LPDPLOBBYSP lpISP; + DWORD dwGroupID; + LPDWORD lpdwBufferSize; + LPVOID lpBuffer; +} SPDATA_GETGROUPCONNECTIONSETTINGS, *LPSPDATA_GETGROUPCONNECTIONSETTINGS; + +typedef struct SPDATA_GETGROUPDATA +{ + DWORD dwSize; + LPDPLOBBYSP lpISP; + DWORD dwGroupID; + LPDWORD lpdwDataSize; + LPVOID lpData; +} SPDATA_GETGROUPDATA, *LPSPDATA_GETGROUPDATA; + +typedef struct SPDATA_GETPLAYERCAPS +{ + DWORD dwSize; + LPDPLOBBYSP lpISP; + DWORD dwFlags; + DWORD dwPlayerID; + LPDPCAPS lpcaps; +} SPDATA_GETPLAYERCAPS, *LPSPDATA_GETPLAYERCAPS; + +typedef struct SPDATA_GETPLAYERDATA +{ + DWORD dwSize; + LPDPLOBBYSP lpISP; + DWORD dwPlayerID; + LPDWORD lpdwDataSize; + LPVOID lpData; +} SPDATA_GETPLAYERDATA, *LPSPDATA_GETPLAYERDATA; + +typedef struct SPDATA_HANDLEMESSAGE +{ + DWORD dwSize; + DWORD dwFromID; + DWORD dwToID; + LPVOID lpBuffer; + DWORD dwBufSize; +} SPDATA_HANDLEMESSAGE, *LPSPDATA_HANDLEMESSAGE; + +typedef struct SPDATA_OPEN +{ + DWORD dwSize; + LPDPLOBBYSP lpISP; + LPDPSESSIONDESC2 lpsd; + DWORD dwFlags; + LPCDPCREDENTIALS lpCredentials; +} SPDATA_OPEN, *LPSPDATA_OPEN; + +typedef struct SPDATA_SEND +{ + DWORD dwSize; + LPDPLOBBYSP lpISP; + DWORD dwFromID; + DWORD dwToID; + DWORD dwFlags; + LPVOID lpBuffer; + DWORD dwBufSize; +} SPDATA_SEND, *LPSPDATA_SEND; + +typedef struct SPDATA_CHATMESSAGE +{ + DWORD dwSize; + LPDPLOBBYSP lpISP; + DWORD dwFromID; + DWORD dwToID; + DWORD dwFlags; + LPDPCHAT lpChat; +} SPDATA_CHATMESSAGE, *LPSPDATA_CHATMESSAGE; + +typedef struct SPDATA_SETGROUPCONNECTIONSETTINGS +{ + DWORD dwSize; + DWORD dwFlags; + LPDPLOBBYSP lpISP; + DWORD dwGroupID; + LPDPLCONNECTION lpConn; +} SPDATA_SETGROUPCONNECTIONSETTINGS, *LPSPDATA_SETGROUPCONNECTIONSETTINGS; + +typedef struct SPDATA_SETGROUPDATA +{ + DWORD dwSize; + LPDPLOBBYSP lpISP; + DWORD dwGroupID; + LPVOID lpData; + DWORD dwDataSize; + DWORD dwFlags; +} SPDATA_SETGROUPDATA, *LPSPDATA_SETGROUPDATA; + +typedef struct SPDATA_SETGROUPNAME +{ + DWORD dwSize; + LPDPLOBBYSP lpISP; + DWORD dwGroupID; + LPDPNAME lpName; + DWORD dwFlags; +} SPDATA_SETGROUPNAME, *LPSPDATA_SETGROUPNAME; + +typedef struct SPDATA_SETREMOTEGROUPNAME +{ + DWORD dwSize; + LPDPLOBBYSP lpISP; + DWORD dwGroupID; + LPDPNAME lpName; + DWORD dwFlags; +} SPDATA_SETREMOTEGROUPNAME, *LPSPDATA_SETREMOTEGROUPNAME; + +typedef struct SPDATA_SETPLAYERDATA +{ + DWORD dwSize; + LPDPLOBBYSP lpISP; + DWORD dwPlayerID; + LPVOID lpData; + DWORD dwDataSize; + DWORD dwFlags; +} SPDATA_SETPLAYERDATA, *LPSPDATA_SETPLAYERDATA; + +typedef struct SPDATA_SETPLAYERNAME +{ + DWORD dwSize; + LPDPLOBBYSP lpISP; + DWORD dwPlayerID; + LPDPNAME lpName; + DWORD dwFlags; +} SPDATA_SETPLAYERNAME, *LPSPDATA_SETPLAYERNAME; + +typedef struct SPDATA_SETREMOTEPLAYERNAME +{ + DWORD dwSize; + LPDPLOBBYSP lpISP; + DWORD dwPlayerID; + LPDPNAME lpName; + DWORD dwFlags; +} SPDATA_SETREMOTEPLAYERNAME, *LPSPDATA_SETREMOTEPLAYERNAME; + +typedef struct SPDATA_SETSESSIONDESC +{ + DWORD dwSize; + LPDPSESSIONDESC2 lpsd; +} SPDATA_SETSESSIONDESC, *LPSPDATA_SETSESSIONDESC; + +typedef struct SPDATA_SHUTDOWN +{ + DWORD dwSize; + LPDPLOBBYSP lpISP; +} SPDATA_SHUTDOWN, *LPSPDATA_SHUTDOWN; + +typedef struct SPDATA_STARTSESSION +{ + DWORD dwSize; + LPDPLOBBYSP lpISP; + DWORD dwFlags; + DWORD dwGroupID; +} SPDATA_STARTSESSION, *LPSPDATA_STARTSESSION; + +typedef struct SPDATA_STARTSESSIONCOMMAND +{ + DWORD dwFlags; + DWORD dwGroupID; + DWORD dwHostID; + LPDPLCONNECTION lpConn; +} SPDATA_STARTSESSIONCOMMAND, *LPSPDATA_STARTSESSIONCOMMAND; + +/* Prototypes for callbacks returned by DPLSPInit */ +typedef HRESULT (WINAPI *LPSP_ADDGROUPTOGROUP)(LPSPDATA_ADDGROUPTOGROUP); +typedef HRESULT (WINAPI *LPSP_ADDPLAYERTOGROUP)(LPSPDATA_ADDPLAYERTOGROUP); +typedef HRESULT (WINAPI *LPSP_BUILDPARENTALHEIRARCHY)(LPSPDATA_BUILDPARENTALHEIRARCHY); +typedef HRESULT (WINAPI *LPSP_CLOSE)(LPSPDATA_CLOSE); +typedef HRESULT (WINAPI *LPSP_CREATEGROUP)(LPSPDATA_CREATEGROUP); +typedef HRESULT (WINAPI *LPSP_CREATEGROUPINGROUP)(LPSPDATA_CREATEGROUPINGROUP); +typedef HRESULT (WINAPI *LPSP_CREATEPLAYER)(LPSPDATA_CREATEPLAYER); +typedef HRESULT (WINAPI *LPSP_DELETEGROUPFROMGROUP)(LPSPDATA_DELETEGROUPFROMGROUP); +typedef HRESULT (WINAPI *LPSP_DELETEPLAYERFROMGROUP)(LPSPDATA_DELETEPLAYERFROMGROUP); +typedef HRESULT (WINAPI *LPSP_DESTROYGROUP)(LPSPDATA_DESTROYGROUP); +typedef HRESULT (WINAPI *LPSP_DESTROYPLAYER)(LPSPDATA_DESTROYPLAYER); +typedef HRESULT (WINAPI *LPSP_ENUMSESSIONS)(LPSPDATA_ENUMSESSIONS); +typedef HRESULT (WINAPI *LPSP_GETCAPS)(LPSPDATA_GETCAPS); +typedef HRESULT (WINAPI *LPSP_GETGROUPCONNECTIONSETTINGS)(LPSPDATA_GETGROUPCONNECTIONSETTINGS); +typedef HRESULT (WINAPI *LPSP_GETGROUPDATA)(LPSPDATA_GETGROUPDATA); +typedef HRESULT (WINAPI *LPSP_GETPLAYERCAPS)(LPSPDATA_GETPLAYERCAPS); +typedef HRESULT (WINAPI *LPSP_GETPLAYERDATA)(LPSPDATA_GETPLAYERDATA); +typedef HRESULT (WINAPI *LPSP_HANDLEMESSAGE)(LPSPDATA_HANDLEMESSAGE); +typedef HRESULT (WINAPI *LPSP_OPEN)(LPSPDATA_OPEN); +typedef HRESULT (WINAPI *LPSP_SEND)(LPSPDATA_SEND); +typedef HRESULT (WINAPI *LPSP_SENDCHATMESSAGE)(LPSPDATA_CHATMESSAGE); +typedef HRESULT (WINAPI *LPSP_SETGROUPCONNECTIONSETTINGS)(LPSPDATA_SETGROUPCONNECTIONSETTINGS); +typedef HRESULT (WINAPI *LPSP_SETGROUPDATA)(LPSPDATA_SETGROUPDATA); +typedef HRESULT (WINAPI *LPSP_SETGROUPNAME)(LPSPDATA_SETGROUPNAME); +typedef HRESULT (WINAPI *LPSP_SETPLAYERDATA)(LPSPDATA_SETPLAYERDATA); +typedef HRESULT (WINAPI *LPSP_SETPLAYERNAME)(LPSPDATA_SETPLAYERNAME); +typedef HRESULT (WINAPI *LPSP_SHUTDOWN)(LPSPDATA_SHUTDOWN); +typedef HRESULT (WINAPI *LPSP_STARTSESSION)(LPSPDATA_STARTSESSION); + +/* Callback table for dplay to call into service provider */ +typedef struct SP_CALLBACKS +{ + DWORD dwSize; + DWORD dwFlags; + LPSP_ADDGROUPTOGROUP AddGroupToGroup; + LPSP_ADDPLAYERTOGROUP AddPlayerToGroup; + LPSP_BUILDPARENTALHEIRARCHY BuildParentalHeirarchy; + LPSP_CLOSE Close; + LPSP_CREATEGROUP CreateGroup; + LPSP_CREATEGROUPINGROUP CreateGroupInGroup; + LPSP_CREATEPLAYER CreatePlayer; + LPSP_DELETEGROUPFROMGROUP DeleteGroupFromGroup; + LPSP_DELETEPLAYERFROMGROUP DeletePlayerFromGroup; + LPSP_DESTROYGROUP DestroyGroup; + LPSP_DESTROYPLAYER DestroyPlayer; + LPSP_ENUMSESSIONS EnumSessions; + LPSP_GETCAPS GetCaps; + LPSP_GETGROUPCONNECTIONSETTINGS GetGroupConnectionSettings; + LPSP_GETGROUPDATA GetGroupData; + LPSP_GETPLAYERCAPS GetPlayerCaps; + LPSP_GETPLAYERDATA GetPlayerData; + LPSP_OPEN Open; + LPSP_SEND Send; + LPSP_SENDCHATMESSAGE SendChatMessage; + LPSP_SETGROUPCONNECTIONSETTINGS SetGroupConnectionSettings; + LPSP_SETGROUPDATA SetGroupData; + LPSP_SETGROUPNAME SetGroupName; + LPSP_SETPLAYERDATA SetPlayerData; + LPSP_SETPLAYERNAME SetPlayerName; + LPSP_SHUTDOWN Shutdown; + LPSP_STARTSESSION StartSession; +} SP_CALLBACKS, *LPSP_CALLBACKS; + +typedef struct SPDATA_INIT +{ + LPSP_CALLBACKS lpCB; + DWORD dwSPVersion; + LPDPLOBBYSP lpISP; + LPDPADDRESS lpAddress; +} SPDATA_INIT, *LPSPDATA_INIT; + +typedef HRESULT (WINAPI *LPSP_INIT)(LPSPDATA_INIT); +HRESULT WINAPI DPLSPInit(LPSPDATA_INIT); + +/* Define the COM interface */ +#define ICOM_INTERFACE IDPLobbySP +#define IDPLobbySP_METHODS \ + ICOM_METHOD1(HRESULT, AddGroupToGroup, LPSPDATA_ADDREMOTEGROUPTOGROUP, argtg ) \ + ICOM_METHOD1(HRESULT, AddPlayerToGroup, LPSPDATA_ADDREMOTEPLAYERTOGROUP, arptg ) \ + ICOM_METHOD1(HRESULT, CreateGroup, LPSPDATA_CREATEREMOTEGROUP, crg ) \ + ICOM_METHOD1(HRESULT, CreateGroupInGroup, LPSPDATA_CREATEREMOTEGROUPINGROUP, crgig ) \ + ICOM_METHOD1(HRESULT, DeleteGroupFromGroup, LPSPDATA_DELETEREMOTEGROUPFROMGROUP, drgfg ) \ + ICOM_METHOD1(HRESULT, DeletePlayerFromGroup, LPSPDATA_DELETEREMOTEPLAYERFROMGROUP, drpfg ) \ + ICOM_METHOD1(HRESULT, DestroyGroup, LPSPDATA_DESTROYREMOTEGROUP, drg ) \ + ICOM_METHOD1(HRESULT, EnumSessionsResponse, LPSPDATA_ENUMSESSIONSRESPONSE, er ) \ + ICOM_METHOD1(HRESULT, GetSPDataPointer, LPVOID*, lplpData ) \ + ICOM_METHOD1(HRESULT, HandleMessage, LPSPDATA_HANDLEMESSAGE, hm ) \ + ICOM_METHOD1(HRESULT, SendChatMessage, LPSPDATA_CHATMESSAGE, cm ) \ + ICOM_METHOD1(HRESULT, SetGroupName, LPSPDATA_SETREMOTEGROUPNAME, srgn ) \ + ICOM_METHOD1(HRESULT, SetPlayerName, LPSPDATA_SETREMOTEPLAYERNAME, srpn ) \ + ICOM_METHOD1(HRESULT, SetSessionDesc, LPSPDATA_SETSESSIONDESC, ssd ) \ + ICOM_METHOD1(HRESULT, SetSPDataPointer, LPVOID, lpData ) \ + ICOM_METHOD1(HRESULT, StartSession, LPSPDATA_STARTSESSIONCOMMAND, ssc ) + +#define IDPLobbySP_IMETHODS \ + IUnknown_IMETHODS \ + IDPLobbySP_METHODS + +ICOM_DEFINE(IDPLobbySP,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IDPLobbySP_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IDPLobbySP_AddRef(p) ICOM_CALL (AddRef,p) +#define IDPLobbySP_Release(p) ICOM_CALL (Release,p) + +/*** IDPLobbySP methods ***/ +#define IDPLobbySP_AddGroupToGroup(p,a) ICOM_CALL1(AddGroupToGroup,p,a) +#define IDPLobbySP_AddPlayerToGroup(p,a) ICOM_CALL1(AddPlayerToGroup,p,a) +#define IDPLobbySP_CreateGroup(p,a) ICOM_CALL1(CreateGroup,p,a) +#define IDPLobbySP_CreateGroupInGroup(p,a) ICOM_CALL1(CreateGroupInGroup,p,a) +#define IDPLobbySP_DeleteGroupFromGroup(p,a) ICOM_CALL1(DeleteGroupFromGroup,p,a) +#define IDPLobbySP_DeletePlayerFromGroup(p,a) ICOM_CALL1(DeletePlayerFromGroup,p,a) +#define IDPLobbySP_DestroyGroup(p,a) ICOM_CALL1(DestroyGroup,p,a) +#define IDPLobbySP_EnumSessionsResponse(p,a) ICOM_CALL1(EnumSessionsResponse,p,a) +#define IDPLobbySP_GetSPDataPointer(p,a) ICOM_CALL1(GetSPDataPointer,p,a) +#define IDPLobbySP_HandleMessage(p,a) ICOM_CALL1(HandleMessage,p,a) +#define IDPLobbySP_SetGroupName(p,a) ICOM_CALL1(SetGroupName,p,a) +#define IDPLobbySP_SetPlayerName(p,a) ICOM_CALL1(SetPlayerName,p,a) +#define IDPLobbySP_SetSessionDesc(p,a) ICOM_CALL1(SetSessionDesc,p,a) +#define IDPLobbySP_StartSession(p,a) ICOM_CALL1(StartSession,p,a) +#define IDPLobbySP_SetSPDataPointer(p,a) ICOM_CALL1(SetSPDataPointer,p,a) + +/* This variable is exported from the DLL at ordinal 6 to be accessed by the + * SP directly. This is the same variable that the DP SP will use. + */ +extern DWORD gdwDPlaySPRefCount; + +#endif diff --git a/dlls/dplayx/name_server.c b/dlls/dplayx/name_server.c index 4a3112d87b1..8323dab5317 100644 --- a/dlls/dplayx/name_server.c +++ b/dlls/dplayx/name_server.c @@ -1,6 +1,6 @@ /* DPLAYX.DLL name server implementation * - * Copyright 2000 - Peter Hunnisett + * Copyright 2000-2001 - Peter Hunnisett * * * @@ -43,6 +43,10 @@ struct NSCache lpNSCacheData present; /* keep track of what is to be looked at when walking */ DPQ_HEAD(NSCacheData) first; + + BOOL bNsIsLocal; + LPVOID lpLocalAddrHdr; /* FIXME: Not yet used */ + LPVOID lpRemoteAddrHdr; /* FIXME: Not yet used */ }; typedef struct NSCache NSCache, *lpNSCache; @@ -52,12 +56,22 @@ DPQ_DECL_DELETECB( cbDeleteNSNodeFromHeap, lpNSCacheData ); /* Name Server functions * --------------------- */ -void NS_SetLocalComputerAsNameServer( LPCDPSESSIONDESC2 lpsd ) +void NS_SetLocalComputerAsNameServer( LPCDPSESSIONDESC2 lpsd, LPVOID lpNSInfo ) { #if 0 /* FIXME: Remove this method? */ DPLAYX_SetLocalSession( lpsd ); #endif + lpNSCache lpCache = (lpNSCache)lpNSInfo; + + lpCache->bNsIsLocal = TRUE; +} + +void NS_SetRemoteComputerAsNameServer( LPCDPSESSIONDESC2 lpsd, LPVOID lpNSInfo ) +{ + lpNSCache lpCache = (lpNSCache)lpNSInfo; + + lpCache->bNsIsLocal = FALSE; } DPQ_DECL_COMPARECB( cbUglyPig, GUID ) @@ -66,7 +80,8 @@ DPQ_DECL_COMPARECB( cbUglyPig, GUID ) } /* Store the given NS remote address for future reference */ -void NS_SetRemoteComputerAsNameServer( LPVOID lpNSAddrHdr, +/* FIXME: LPDPMSG_ENUMSESSIONSREPLY should be const */ +void NS_AddRemoteComputerAsNameServer( LPCVOID lpcNSAddrHdr, DWORD dwHdrSize, LPDPMSG_ENUMSESSIONSREPLY lpMsg, LPVOID lpNSInfo ) @@ -75,15 +90,11 @@ void NS_SetRemoteComputerAsNameServer( LPVOID lpNSAddrHdr, lpNSCache lpCache = (lpNSCache)lpNSInfo; lpNSCacheData lpCacheNode; - TRACE( "%p, %p, %p\n", lpNSAddrHdr, lpMsg, lpNSInfo ); - - /* FIXME: Should check to see if the reply is for an existing session. If - * so we remove the old and add the new so oldest is at front. - */ + TRACE( "%p, %p, %p\n", lpcNSAddrHdr, lpMsg, lpNSInfo ); /* See if we can find this session. If we can, remove it as it's a dup */ DPQ_REMOVE_ENTRY_CB( lpCache->first, next, data->guidInstance, cbUglyPig, - lpMsg->sd.guidInstance, lpCacheNode ); + lpMsg->sd.guidInstance, lpCacheNode ); if( lpCacheNode != NULL ) { @@ -104,12 +115,12 @@ void NS_SetRemoteComputerAsNameServer( LPVOID lpNSAddrHdr, lpCacheNode->lpNSAddrHdr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwHdrSize ); - CopyMemory( lpCacheNode->lpNSAddrHdr, lpNSAddrHdr, dwHdrSize ); + CopyMemory( lpCacheNode->lpNSAddrHdr, lpcNSAddrHdr, dwHdrSize ); lpCacheNode->data = (LPDPSESSIONDESC2)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, - sizeof( *lpCacheNode->data ) ); + sizeof( *(lpCacheNode->data) ) ); if( lpCacheNode->data == NULL ) { @@ -120,8 +131,10 @@ void NS_SetRemoteComputerAsNameServer( LPVOID lpNSAddrHdr, CopyMemory( lpCacheNode->data, &lpMsg->sd, sizeof( *lpCacheNode->data ) ); len = WideCharToMultiByte( CP_ACP, 0, (LPWSTR)(lpMsg+1), -1, NULL, 0, NULL, NULL ); if ((lpCacheNode->data->u1.lpszSessionNameA = HeapAlloc( GetProcessHeap(), 0, len ))) + { WideCharToMultiByte( CP_ACP, 0, (LPWSTR)(lpMsg+1), -1, lpCacheNode->data->u1.lpszSessionNameA, len, NULL, NULL ); + } lpCacheNode->dwTime = timeGetTime(); @@ -148,8 +161,38 @@ LPVOID NS_GetNSAddr( LPVOID lpNSInfo ) * must be it. That would make this method obsolete once that's * in place. */ - +#if 1 return lpCache->first.lpQHFirst->lpNSAddrHdr; +#else + /* FIXME: Should convert over to this */ + return lpCache->bNsIsLocal ? lpCache->lpLocalAddrHdr + : lpCache->lpRemoteAddrHdr; +#endif +} + +/* Get the magic number associated with the Name Server */ +DWORD NS_GetNsMagic( LPVOID lpNSInfo ) +{ + LPDWORD lpHdrInfo = (LPDWORD)NS_GetNSAddr( lpNSInfo ); + + return lpHdrInfo[1]; +} + +/* Get the magic number associated with the non NS end */ +DWORD NS_GetOtherMagic( LPVOID lpNSInfo ) +{ + lpNSCache lpCache = (lpNSCache)lpNSInfo; + + return ((LPDWORD)lpCache->lpLocalAddrHdr)[1]; +} + +void NS_SetLocalAddr( LPVOID lpNSInfo, LPCVOID lpHdr, DWORD dwHdrSize ) +{ + lpNSCache lpCache = (lpNSCache)lpNSInfo; + + lpCache->lpLocalAddrHdr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwHdrSize ); + + CopyMemory( lpCache->lpLocalAddrHdr, lpHdr, dwHdrSize ); } /* This function is responsible for sending a request for all other known @@ -216,6 +259,9 @@ void NS_InvalidateSessionCache( LPVOID lpNSInfo ) /* NULL out the walking pointer */ lpCache->present = NULL; + + lpCache->bNsIsLocal = FALSE; + } /* Create and initialize a session cache */ @@ -235,6 +281,8 @@ BOOL NS_InitializeSessionCache( LPVOID* lplpNSInfo ) DPQ_INIT(lpCache->first); lpCache->present = NULL; + lpCache->bNsIsLocal = FALSE; + return TRUE; } @@ -280,8 +328,7 @@ void NS_PruneSessionCache( LPVOID lpNSInfo ) lpNSCache lpCache = lpNSInfo; const DWORD dwPresentTime = timeGetTime(); - const DWORD dwPrunePeriod = 60000; /* is 60 secs enough? */ - const DWORD dwPruneTime = dwPresentTime - dwPrunePeriod; + const DWORD dwPrunePeriod = DPMSG_WAIT_60_SECS; /* is 60 secs enough? */ /* This silly little algorithm is based on the fact we keep entries in * the queue in a time based order. It also assumes that it is not possible @@ -299,25 +346,12 @@ void NS_PruneSessionCache( LPVOID lpNSInfo ) break; } - if( dwPruneTime > dwPresentTime ) /* 0 <= dwPresentTime <= dwPrunePeriod */ + /* Deal with time in a wrap around safe manner - unsigned arithmatic. + * Check the difference in time */ + if( (dwPresentTime - (DPQ_FIRST(lpCache->first)->dwTime)) < dwPrunePeriod ) { - if( ( DPQ_FIRST(lpCache->first)->dwTime <= dwPresentTime ) || - ( DPQ_FIRST(lpCache->first)->dwTime > dwPruneTime ) - ) - { - /* Less than dwPrunePeriod old - keep */ - break; - } - } - else /* dwPrunePeriod <= dwPresentTime <= max dword */ - { - if( ( DPQ_FIRST(lpCache->first)->dwTime <= dwPresentTime ) && - ( DPQ_FIRST(lpCache->first)->dwTime > dwPruneTime ) - ) - { - /* Less than dwPrunePeriod old - keep */ - break; - } + /* First entry has not expired yet; don't prune */ + break; } lpFirstData = DPQ_FIRST(lpCache->first); @@ -328,33 +362,38 @@ void NS_PruneSessionCache( LPVOID lpNSInfo ) } /* NAME SERVER Message stuff */ -void NS_ReplyToEnumSessionsRequest( LPVOID lpMsg, - LPDPSP_REPLYDATA lpReplyData, +void NS_ReplyToEnumSessionsRequest( LPCVOID lpcMsg, + LPVOID* lplpReplyData, + LPDWORD lpdwReplySize, IDirectPlay2Impl* lpDP ) { LPDPMSG_ENUMSESSIONSREPLY rmsg; DWORD dwVariableSize; DWORD dwVariableLen; - /* LPDPMSG_ENUMSESSIONSREQUEST msg = (LPDPMSG_ENUMSESSIONSREQUEST)lpMsg; */ + /* LPCDPMSG_ENUMSESSIONSREQUEST msg = (LPDPMSG_ENUMSESSIONSREQUEST)lpcMsg; */ BOOL bAnsi = TRUE; /* FIXME: This needs to be in the DPLAY interface */ FIXME( ": few fixed + need to check request for response\n" ); if (bAnsi) + { dwVariableLen = MultiByteToWideChar( CP_ACP, 0, lpDP->dp2->lpSessionDesc->u1.lpszSessionNameA, -1, NULL, 0 ); + } else + { dwVariableLen = strlenW( lpDP->dp2->lpSessionDesc->u1.lpszSessionName ) + 1; + } dwVariableSize = dwVariableLen * sizeof( WCHAR ); - lpReplyData->dwMessageSize = lpDP->dp2->spData.dwSPHeaderSize + - sizeof( *rmsg ) + dwVariableSize; - lpReplyData->lpMessage = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, - lpReplyData->dwMessageSize ); + *lpdwReplySize = lpDP->dp2->spData.dwSPHeaderSize + + sizeof( *rmsg ) + dwVariableSize; + *lplpReplyData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, + *lpdwReplySize ); - rmsg = (LPDPMSG_ENUMSESSIONSREPLY)( (BYTE*)lpReplyData->lpMessage + + rmsg = (LPDPMSG_ENUMSESSIONSREPLY)( (BYTE*)*lplpReplyData + lpDP->dp2->spData.dwSPHeaderSize); rmsg->envelope.dwMagic = DPMSGMAGIC_DPLAYMSG; @@ -365,8 +404,12 @@ void NS_ReplyToEnumSessionsRequest( LPVOID lpMsg, sizeof( lpDP->dp2->lpSessionDesc->dwSize ) ); rmsg->dwUnknown = 0x0000005c; if( bAnsi ) + { MultiByteToWideChar( CP_ACP, 0, lpDP->dp2->lpSessionDesc->u1.lpszSessionNameA, -1, (LPWSTR)(rmsg+1), dwVariableLen ); + } else + { strcpyW( (LPWSTR)(rmsg+1), lpDP->dp2->lpSessionDesc->u1.lpszSessionName ); + } } diff --git a/dlls/dplayx/name_server.h b/dlls/dplayx/name_server.h index 9c500cda31a..36a95a890d7 100644 --- a/dlls/dplayx/name_server.h +++ b/dlls/dplayx/name_server.h @@ -7,15 +7,20 @@ #include "dplayx_messages.h" #include "dplay_global.h" -void NS_SetLocalComputerAsNameServer( LPCDPSESSIONDESC2 lpsd ); -void NS_SetRemoteComputerAsNameServer( LPVOID lpNSAddrHdr, +void NS_SetLocalComputerAsNameServer( LPCDPSESSIONDESC2 lpsd, LPVOID lpNSInfo ); +void NS_SetRemoteComputerAsNameServer( LPCDPSESSIONDESC2 lpsd, LPVOID lpNSInfo ); +void NS_AddRemoteComputerAsNameServer( LPCVOID lpNSAddrHdr, DWORD dwHdrSize, LPDPMSG_ENUMSESSIONSREPLY lpMsg, LPVOID lpNSInfo ); LPVOID NS_GetNSAddr( LPVOID lpNSInfo ); +DWORD NS_GetNsMagic( LPVOID lpNSInfo ); +DWORD NS_GetOtherMagic( LPVOID lpNSInfo ); +void NS_SetLocalAddr( LPVOID lpNSInfo, LPCVOID lpHdr, DWORD dwHdrSize ); -void NS_ReplyToEnumSessionsRequest( LPVOID lpMsg, - LPDPSP_REPLYDATA lpReplyData, +void NS_ReplyToEnumSessionsRequest( LPCVOID lpcMsg, + LPVOID* lplpReplyData, + LPDWORD lpdwReplySize, IDirectPlay2Impl* lpDP ); HRESULT NS_SendSessionRequestBroadcast( LPCGUID lpcGuid, diff --git a/include/dplay.h b/include/dplay.h index e22da01feb2..31e11c822b9 100644 --- a/include/dplay.h +++ b/include/dplay.h @@ -1,6 +1,7 @@ #ifndef __WINE_DPLAY_H #define __WINE_DPLAY_H +#include "ole2.h" #include "wine/obj_base.h" #ifdef __cplusplus diff --git a/include/objbase.h b/include/objbase.h index af22e366ff7..52c04ab1803 100644 --- a/include/objbase.h +++ b/include/objbase.h @@ -26,7 +26,9 @@ #include #endif +#ifndef INITGUID #include "cguid.h" +#endif #ifdef __cplusplus extern "C" { diff --git a/include/winerror.h b/include/winerror.h index c9857dc5248..8bbeed23272 100644 --- a/include/winerror.h +++ b/include/winerror.h @@ -1464,6 +1464,8 @@ extern int WIN32_LastError; #define S_OK ((HRESULT)0L) #define S_FALSE ((HRESULT)1L) +#define E_PENDING 0x8000000AL + #define E_NOTIMPL 0x80004001L #define E_NOINTERFACE 0x80004002L diff --git a/ole/uuid.c b/ole/uuid.c index b7c1c9cf4a9..0b3e6ff0567 100644 --- a/ole/uuid.c +++ b/ole/uuid.c @@ -49,3 +49,4 @@ DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0); /* GUIDs not declared in an exported header file */ DEFINE_GUID(IID_IDirectPlaySP,0xc9f6360,0xcc61,0x11cf,0xac,0xec,0x00,0xaa,0x00,0x68,0x86,0xe3); DEFINE_GUID(IID_ISFHelper,0x1fe68efb,0x1874,0x9812,0x56,0xdc,0x00,0x00,0x00,0x00,0x00,0x00); +DEFINE_GUID(IID_IDPLobbySP,0x5a4e5a20,0x2ced,0x11d0,0xa8,0x89,0x00,0xa0,0xc9,0x05,0x43,0x3c);