| /* Direct Play 3 and Direct Play Lobby 1 Implementation |
| * Presently only the Lobby skeleton is implemented. |
| * |
| * Copyright 1998 - Peter Hunnisett |
| * |
| */ |
| #include "windows.h" |
| #include "heap.h" |
| #include "wintypes.h" |
| #include "winerror.h" |
| #include "interfaces.h" |
| #include "mmsystem.h" |
| #include "dplay.h" |
| #include "debug.h" |
| #include "winnt.h" |
| #include "winreg.h" |
| |
| |
| static HRESULT WINAPI IDirectPlayLobby_QueryInterface |
| ( LPDIRECTPLAYLOBBY2 this, |
| REFIID riid, |
| LPVOID* ppvObj ) |
| { |
| FIXME( dplay, ":stub\n"); |
| return DPERR_OUTOFMEMORY; |
| } |
| |
| static ULONG WINAPI IDirectPlayLobby_AddRef |
| ( LPDIRECTPLAYLOBBY2 this ) |
| { |
| ++(this->ref); |
| TRACE( dplay," ref count now %ld\n", this->ref ); |
| return (this->ref); |
| } |
| |
| static ULONG WINAPI IDirectPlayLobby_Release |
| ( LPDIRECTPLAYLOBBY2 this ) |
| { |
| this->ref--; |
| |
| TRACE( dplay, " ref count now %ld\n", this->ref ); |
| |
| /* Deallocate if this is the last reference to the object */ |
| if( !(this->ref) ) |
| { |
| HeapFree( GetProcessHeap(), 0, this ); |
| return 0; |
| } |
| |
| return this->ref; |
| } |
| |
| /******************************************************************** |
| * |
| * Connects an application to the session specified by the DPLCONNECTION |
| * structure currently stored with the DirectPlayLobby object. |
| * |
| * Returns a IDirectPlay2 or IDirectPlay2A interface. |
| * |
| */ |
| static HRESULT WINAPI IDirectPlayLobby_Connect |
| ( LPDIRECTPLAYLOBBY2 this, |
| DWORD dwFlags, |
| LPDIRECTPLAY2* lplpDP, |
| IUnknown* pUnk) |
| { |
| FIXME( dplay, ":stub\n"); |
| return DPERR_OUTOFMEMORY; |
| } |
| |
| /******************************************************************** |
| * |
| * 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 IDirectPlayLobby_CreateAddress |
| ( LPDIRECTPLAYLOBBY2 this, |
| REFGUID guidSP, |
| REFGUID guidDataType, |
| LPCVOID lpData, |
| DWORD dwDataSize, |
| LPVOID lpAddress, |
| LPDWORD lpdwAddressSize ) |
| { |
| FIXME( dplay, ":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 IDirectPlayLobby_EnumAddress |
| ( LPDIRECTPLAYLOBBY2 this, |
| LPDPENUMADDRESSCALLBACK lpEnumAddressCallback, |
| LPCVOID lpAddress, |
| DWORD dwAddressSize, |
| LPVOID lpContext ) |
| { |
| FIXME( dplay, ":stub\n"); |
| return DPERR_OUTOFMEMORY; |
| } |
| |
| /******************************************************************** |
| * |
| * Enumerates all the address types that a given service provider needs to |
| * build the DirectPlay Address. |
| * |
| */ |
| static HRESULT WINAPI IDirectPlayLobby_EnumAddressTypes |
| ( LPDIRECTPLAYLOBBY2 this, |
| LPDPLENUMADDRESSTYPESCALLBACK lpEnumAddressTypeCallback, |
| REFGUID guidSP, |
| LPVOID lpContext, |
| DWORD dwFlags ) |
| { |
| FIXME( dplay, ":stub\n"); |
| return DPERR_OUTOFMEMORY; |
| } |
| |
| /******************************************************************** |
| * |
| * Enumerates what applications are registered with DirectPlay by |
| * invoking the callback function with lpContext. |
| * |
| */ |
| static HRESULT WINAPI IDirectPlayLobby_EnumLocalApplications |
| ( LPDIRECTPLAYLOBBY2 this, |
| LPDPLENUMLOCALAPPLICATIONSCALLBACK a, |
| LPVOID lpContext, |
| DWORD dwFlags ) |
| { |
| FIXME( dplay, ":stub\n"); |
| 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 IDirectPlayLobby_GetConnectionSettings |
| ( LPDIRECTPLAYLOBBY2 this, |
| DWORD dwAppID, |
| LPVOID lpData, |
| LPDWORD lpdwDataSize ) |
| { |
| LPDPLCONNECTION lpConnectionSettings; |
| |
| FIXME( dplay, ":semi stub %p %08lx %p %p \n", this, dwAppID, lpData, lpdwDataSize ); |
| |
| 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; |
| } |
| } |
| |
| /* Ok we assume that we've been given a buffer that is large enough for our needs */ |
| lpConnectionSettings = ( LPDPLCONNECTION ) lpData; |
| |
| /* Fill in the fields */ |
| |
| return DPERR_NOTLOBBIED; |
| } |
| |
| /******************************************************************** |
| * |
| * Retrieves the message sent between a lobby client and a DirectPlay |
| * application. All messages are queued until received. |
| * |
| */ |
| static HRESULT WINAPI IDirectPlayLobby_ReceiveLobbyMessage |
| ( LPDIRECTPLAYLOBBY2 this, |
| DWORD dwFlags, |
| DWORD dwAppID, |
| LPDWORD lpdwMessageFlags, |
| LPVOID lpData, |
| LPDWORD lpdwDataSize ) |
| { |
| FIXME( dplay, ":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 IDirectPlayLobby_RunApplication |
| ( LPDIRECTPLAYLOBBY2 this, |
| DWORD dwFlags, |
| LPDWORD lpdwAppID, |
| LPDPLCONNECTION lpConn, |
| HANDLE32 hReceiveEvent ) |
| { |
| FIXME( dplay, ":stub\n"); |
| return DPERR_OUTOFMEMORY; |
| } |
| |
| /******************************************************************** |
| * |
| * Sends a message between the application and the lobby client. |
| * All messages are queued until received. |
| * |
| */ |
| static HRESULT WINAPI IDirectPlayLobby_SendLobbyMessage |
| ( LPDIRECTPLAYLOBBY2 this, |
| DWORD dwFlags, |
| DWORD dwAppID, |
| LPVOID lpData, |
| DWORD dwDataSize ) |
| { |
| FIXME( dplay, ":stub\n"); |
| return DPERR_OUTOFMEMORY; |
| } |
| |
| /******************************************************************** |
| * |
| * Modifies the DPLCONNECTION structure to contain all information |
| * needed to start and connect an application. |
| * |
| */ |
| static HRESULT WINAPI IDirectPlayLobby_SetConnectionSettings |
| ( LPDIRECTPLAYLOBBY2 this, |
| DWORD dwFlags, |
| DWORD dwAppID, |
| LPDPLCONNECTION lpConn ) |
| { |
| FIXME( dplay, ": this=%p, dwFlags=%08lx, dwAppId=%08lx, lpConn=%p: stub\n", |
| this, dwFlags, dwAppID, lpConn ); |
| |
| /* Paramater check */ |
| if( dwFlags || !this || !lpConn ) |
| { |
| return DPERR_INVALIDPARAMS; |
| } |
| |
| if( !( lpConn->dwSize == sizeof(DPLCONNECTION) ) ) |
| { |
| /* Is this the right return code? */ |
| return DPERR_INVALIDPARAMS; |
| } |
| |
| return DPERR_OUTOFMEMORY; |
| } |
| |
| /******************************************************************** |
| * |
| * Registers an event that will be set when a lobby message is received. |
| * |
| */ |
| static HRESULT WINAPI IDirectPlayLobby_SetLobbyMessageEvent |
| ( LPDIRECTPLAYLOBBY2 this, |
| DWORD dwFlags, |
| DWORD dwAppID, |
| HANDLE32 hReceiveEvent ) |
| { |
| FIXME( dplay, ":stub\n"); |
| return DPERR_OUTOFMEMORY; |
| } |
| |
| static HRESULT WINAPI IDirectPlayLobby_CreateCompoundAddress |
| ( LPDIRECTPLAYLOBBY2 this, |
| LPCDPCOMPOUNDADDRESSELEMENT lpElements, |
| DWORD dwElementCount, |
| LPVOID lpAddress, |
| LPDWORD lpdwAddressSize ) |
| { |
| FIXME( dplay, ":stub\n"); |
| return DPERR_OUTOFMEMORY; |
| } |
| |
| /* Direct Play Lobby 2 Virtual Table for methods */ |
| static struct tagLPDIRECTPLAYLOBBY2_VTABLE lobby2VT = { |
| IDirectPlayLobby_QueryInterface, |
| IDirectPlayLobby_AddRef, |
| IDirectPlayLobby_Release, |
| IDirectPlayLobby_Connect, |
| IDirectPlayLobby_CreateAddress, |
| IDirectPlayLobby_EnumAddress, |
| IDirectPlayLobby_EnumAddressTypes, |
| IDirectPlayLobby_EnumLocalApplications, |
| IDirectPlayLobby_GetConnectionSettings, |
| IDirectPlayLobby_ReceiveLobbyMessage, |
| IDirectPlayLobby_RunApplication, |
| IDirectPlayLobby_SendLobbyMessage, |
| IDirectPlayLobby_SetConnectionSettings, |
| IDirectPlayLobby_SetLobbyMessageEvent, |
| IDirectPlayLobby_CreateCompoundAddress |
| }; |
| |
| /*************************************************************************** |
| * DirectPlayLobbyCreateA (DPLAYX.4) |
| * |
| */ |
| HRESULT WINAPI DirectPlayLobbyCreateA( LPGUID lpGUIDDSP, |
| LPDIRECTPLAYLOBBY2A *lplpDPL, |
| IUnknown *lpUnk, |
| LPVOID lpData, |
| DWORD dwDataSize ) |
| { |
| TRACE(dplay,"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; |
| } |
| |
| *lplpDPL = (LPDIRECTPLAYLOBBY2A)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, |
| sizeof( IDirectPlayLobby2A ) ); |
| |
| if( ! (*lplpDPL) ) |
| { |
| return DPERR_OUTOFMEMORY; |
| } |
| |
| (*lplpDPL)->lpvtbl = &lobby2VT; |
| (*lplpDPL)->ref = 1; |
| |
| /* Still some stuff to do here */ |
| |
| return DP_OK; |
| } |
| |
| /*************************************************************************** |
| * DirectPlayLobbyCreateW (DPLAYX.5) |
| * |
| */ |
| HRESULT WINAPI DirectPlayLobbyCreateW( LPGUID lpGUIDDSP, |
| LPDIRECTPLAYLOBBY2 *lplpDPL, |
| IUnknown *lpUnk, |
| LPVOID lpData, |
| DWORD dwDataSize ) |
| { |
| TRACE(dplay,"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; |
| } |
| |
| *lplpDPL = (LPDIRECTPLAYLOBBY2)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, |
| sizeof( IDirectPlayLobby2 ) ); |
| |
| if( !*lplpDPL) |
| { |
| return DPERR_OUTOFMEMORY; |
| } |
| |
| (*lplpDPL)->lpvtbl = &lobby2VT; |
| (*lplpDPL)->ref = 1; |
| |
| return DP_OK; |
| |
| } |
| |
| /*************************************************************************** |
| * DirectPlayEnumerateA (DPLAYX.2) |
| * |
| * The pointer to the structure lpContext will be filled with the |
| * appropriate data for each service offered by the OS. These services are |
| * not necessarily available on this particular machine but are defined |
| * as simple service providers under the "Service Providers" registry key. |
| * This structure is then passed to lpEnumCallback for each of the different |
| * services. |
| * |
| * This API is useful only for applications written using DirectX3 or |
| * worse. It is superceeded by IDirectPlay3::EnumConnections which also |
| * gives information on the actual connections. |
| * |
| * defn of a service provider: |
| * A dynamic-link library used by DirectPlay to communicate over a network. |
| * The service provider contains all the network-specific code required |
| * to send and receive messages. Online services and network operators can |
| * supply service providers to use specialized hardware, protocols, communications |
| * media, and network resources. |
| * |
| * TODO: Allocate string buffer space from the heap (length from reg) |
| * Pass real device driver numbers... |
| * Get the GUID properly... |
| */ |
| HRESULT WINAPI DirectPlayEnumerateA( LPDPENUMDPCALLBACKA lpEnumCallback, |
| LPVOID lpContext ) |
| { |
| |
| HKEY hkResult; |
| LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers"; |
| LPSTR guidDataSubKey = "Guid"; |
| LPSTR majVerDataSubKey = "dwReserved1"; |
| DWORD dwIndex, sizeOfSubKeyName=50; |
| char subKeyName[51]; |
| |
| TRACE( dplay, ": lpEnumCallback=%p lpContext=%p\n", lpEnumCallback, lpContext ); |
| |
| if( !lpEnumCallback || !*lpEnumCallback ) |
| { |
| return DPERR_INVALIDPARAMS; |
| } |
| |
| /* Need to loop over the service providers in the registry */ |
| if( RegOpenKeyEx32A( HKEY_LOCAL_MACHINE, searchSubKey, |
| 0, KEY_ENUMERATE_SUB_KEYS, &hkResult ) != ERROR_SUCCESS ) |
| { |
| /* Hmmm. Does this mean that there are no service providers? */ |
| ERR(dplay, ": no service providers?\n"); |
| return DP_OK; |
| } |
| |
| /* Traverse all the service providers we have available */ |
| for( dwIndex=0; |
| RegEnumKey32A( hkResult, dwIndex, subKeyName, sizeOfSubKeyName ) != |
| ERROR_NO_MORE_ITEMS; |
| ++dwIndex ) |
| { |
| HKEY hkServiceProvider; |
| GUID serviceProviderGUID; |
| DWORD returnTypeGUID, returnTypeReserved1, sizeOfReturnBuffer=50; |
| char returnBuffer[51]; |
| DWORD majVersionNum, minVersionNum; |
| LPWSTR lpWGUIDString; |
| |
| TRACE( dplay, " this time through: %s\n", subKeyName ); |
| |
| /* Get a handle for this particular service provider */ |
| if( RegOpenKeyEx32A( hkResult, subKeyName, 0, KEY_QUERY_VALUE, |
| &hkServiceProvider ) != ERROR_SUCCESS ) |
| { |
| ERR( dplay, ": what the heck is going on?\n" ); |
| continue; |
| } |
| |
| /* Get the GUID, Device major number and device minor number |
| * from the registry. |
| */ |
| if( RegQueryValueEx32A( hkServiceProvider, guidDataSubKey, |
| NULL, &returnTypeGUID, returnBuffer, |
| &sizeOfReturnBuffer ) != ERROR_SUCCESS ) |
| { |
| ERR( dplay, ": missing GUID registry data members\n" ); |
| continue; |
| } |
| |
| /* FIXME: Check return types to ensure we're interpreting data right */ |
| lpWGUIDString = HEAP_strdupAtoW( GetProcessHeap(), 0, returnBuffer ); |
| CLSIDFromString32( (LPCOLESTR32)lpWGUIDString, &serviceProviderGUID ); |
| HeapFree( GetProcessHeap(), 0, lpWGUIDString ); |
| |
| sizeOfReturnBuffer = 50; |
| |
| if( RegQueryValueEx32A( hkServiceProvider, majVerDataSubKey, |
| NULL, &returnTypeReserved1, returnBuffer, |
| &sizeOfReturnBuffer ) != ERROR_SUCCESS ) |
| { |
| ERR( dplay, ": missing dwReserved1 registry data members\n") ; |
| continue; |
| } |
| /* FIXME: This couldn't possibly be right...*/ |
| majVersionNum = GET_DWORD( returnBuffer ); |
| |
| /* The enumeration will return FALSE if we are not to continue */ |
| if( !lpEnumCallback( &serviceProviderGUID , subKeyName, |
| majVersionNum, (DWORD)0, lpContext ) ) |
| { |
| WARN( dplay, "lpEnumCallback returning FALSE\n" ); |
| break; |
| } |
| } |
| |
| return DP_OK; |
| |
| } |
| |
| /*************************************************************************** |
| * DirectPlayEnumerateW (DPLAYX.3) |
| * |
| */ |
| HRESULT WINAPI DirectPlayEnumerateW( LPDPENUMDPCALLBACKW lpEnumCallback, LPVOID lpContext ) |
| { |
| |
| FIXME( dplay, ":stub\n"); |
| |
| return DPERR_OUTOFMEMORY; |
| |
| } |
| |
| /*************************************************************************** |
| * DirectPlayCreate (DPLAYX.1) (DPLAY.1) |
| * |
| */ |
| HRESULT WINAPI DirectPlayCreate |
| ( LPGUID lpGUID, LPDIRECTPLAY *lplpDP, IUnknown *pUnk) |
| { |
| |
| FIXME( dplay, ":stub\n"); |
| return DPERR_OUTOFMEMORY; |
| |
| } |