/*========================================================================== * * Copyright (C) 1996-1997 Microsoft Corporation. All Rights Reserved. * * File: dplobby.c * Content: Methods for lobby management * * History: * Date By Reason * ======= ======= ====== * 4/13/96 myronth Created it * 10/23/96 myronth Added client/server methods * 1/2/97 myronth Added wrappers for CreateAddress and EnumAddress * 2/12/97 myronth Mass DX5 changes * 3/24/97 kipo Added support for IDirectPlayLobby2 interface * 4/3/97 myronth Fixed interface pointer casts for CreateAddress and * EnumAddress * 4/10/97 myronth Added support for GetCaps * 5/8/97 myronth Drop lobby lock when calling LP * 11/13/97 myronth Added functions for asynchronous Connect (#12541) * 12/2/97 myronth Added Register/UnregisterApplication * 12/4/97 myronth Added ConnectEx * 10/22/99 aarono added support for application flags * 12/13/99 pnewson bugs #123583, 123601, 123604 - support to launch dpvhelp.exe on * apps that are not registered or badly registered ***************************************************************************/ #include "dplobpr.h" //-------------------------------------------------------------------------- // // Functions // //-------------------------------------------------------------------------- #undef DPF_MODNAME #define DPF_MODNAME "DPL_Connect" HRESULT DPLAPI DPL_Connect(LPDIRECTPLAYLOBBY lpDPL, DWORD dwFlags, LPDIRECTPLAY2 * lplpDP2, IUnknown FAR * lpUnk) { LPDPLOBBYI_DPLOBJECT this; HRESULT hr; DPF(7, "Entering DPL_Connect"); DPF(9, "Parameters: 0x%08x, 0x%08x, 0x%08x, 0x%08x", lpDPL, dwFlags, lplpDP2, lpUnk); ENTER_DPLOBBY(); TRY { if( !VALID_DPLOBBY_INTERFACE( lpDPL )) { LEAVE_DPLOBBY(); return DPERR_INVALIDINTERFACE; } this = DPLOBJECT_FROM_INTERFACE(lpDPL); if( !VALID_DPLOBBY_PTR( this ) ) { LEAVE_DPLOBBY(); return DPERR_INVALIDOBJECT; } if( !VALID_WRITE_PTR( lplpDP2, sizeof(LPDIRECTPLAY2 *)) ) { LEAVE_DPLOBBY(); return DPERR_INVALIDPARAMS; } if( lpUnk != NULL ) { LEAVE_DPLOBBY(); return CLASS_E_NOAGGREGATION; } if(!VALID_CONNECT_FLAGS(dwFlags)) { LEAVE_DPLOBBY(); return DPERR_INVALIDFLAGS; } } EXCEPT( EXCEPTION_EXECUTE_HANDLER ) { DPF_ERR( "Exception encountered validating parameters" ); LEAVE_DPLOBBY(); return DPERR_INVALIDPARAMS; } // Call the ConnectMe function which resides in the DPlay project hr = ConnectMe(lpDPL, lplpDP2, lpUnk, dwFlags); LEAVE_DPLOBBY(); return hr; } // DPL_Connect #undef DPF_MODNAME #define DPF_MODNAME "DPL_ConnectEx" HRESULT DPLAPI DPL_ConnectEx(LPDIRECTPLAYLOBBY lpDPL, DWORD dwFlags, REFIID riid, LPVOID * ppvObj, IUnknown FAR * lpUnk) { LPDIRECTPLAY2 lpDP2 = NULL; HRESULT hr; DPF(7, "Entering DPL_ConnectEx"); DPF(9, "Parameters: 0x%08x, 0x%08x, iid, 0x%08x, 0x%08x", lpDPL, dwFlags, ppvObj, lpUnk); // Call the ConnectMe function which resides in the DPlay project hr = DPL_Connect(lpDPL, dwFlags, &lpDP2, lpUnk); if(SUCCEEDED(hr)) { hr = DP_QueryInterface((LPDIRECTPLAY)lpDP2, riid, ppvObj); if(FAILED(hr)) { DPF_ERRVAL("Failed calling QueryInterface, hr = 0x%08x", hr); } // Release the DP2 object DP_Release((LPDIRECTPLAY)lpDP2); } return hr; } // DPL_ConnectEx #undef DPF_MODNAME #define DPF_MODNAME "PRV_SaveConnectPointers" void PRV_SaveConnectPointers(LPDIRECTPLAYLOBBY lpDPL, LPDIRECTPLAY2 lpDP2, LPDPLCONNECTION lpConn) { LPDPLOBBYI_DPLOBJECT this; DPF(7, "Entering PRV_SaveConnectPointers"); DPF(9, "Parameters: 0x%08x, 0x%08x, 0x%08x", lpDPL, lpDP2, lpConn); this = DPLOBJECT_FROM_INTERFACE(lpDPL); #ifdef DEBUG if( !VALID_DPLOBBY_PTR( this ) ) return; #endif // Save the pointers this->lpDP2 = lpDP2; this->lpConn = lpConn; } // PRV_SaveConnectPointers #undef DPF_MODNAME #define DPF_MODNAME "PRV_GetConnectPointers" BOOL PRV_GetConnectPointers(LPDIRECTPLAYLOBBY lpDPL, LPDIRECTPLAY2 * lplpDP2, LPDPLCONNECTION * lplpConn) { LPDPLOBBYI_DPLOBJECT this; DPF(7, "Entering PRV_GetConnectPointers"); DPF(9, "Parameters: 0x%08x, 0x%08x, 0x%08x", lpDPL, lplpDP2, lplpConn); ASSERT(lplpDP2); ASSERT(lplpConn); this = DPLOBJECT_FROM_INTERFACE(lpDPL); #ifdef DEBUG if( !VALID_DPLOBBY_PTR( this ) ) return FALSE; #endif // See if we have the pointers if((!this->lpDP2) || (!this->lpConn)) return FALSE; // Set the output pointers *lplpDP2 = this->lpDP2; *lplpConn = this->lpConn; return TRUE; } // PRV_GetConnectPointers #undef DPF_MODNAME #define DPF_MODNAME "PRV_IsAsyncConnectOn" BOOL PRV_IsAsyncConnectOn(LPDIRECTPLAYLOBBY lpDPL) { LPDPLOBBYI_DPLOBJECT this; DPF(7, "Entering PRV_IsAsyncConnectOn"); DPF(9, "Parameters: 0x%08x", lpDPL); this = DPLOBJECT_FROM_INTERFACE(lpDPL); #ifdef DEBUG if( !VALID_DPLOBBY_PTR( this ) ) return FALSE; #endif // Check the flag if(this->dwFlags & DPLOBBYPR_ASYNCCONNECT) return TRUE; else return FALSE; } // PRV_IsAsyncConnectOn #undef DPF_MODNAME #define DPF_MODNAME "PRV_TurnAsyncConnectOn" void PRV_TurnAsyncConnectOn(LPDIRECTPLAYLOBBY lpDPL) { LPDPLOBBYI_DPLOBJECT this; DPF(7, "Entering PRV_TurnAsyncConnectOn"); DPF(9, "Parameters: 0x%08x", lpDPL); this = DPLOBJECT_FROM_INTERFACE(lpDPL); #ifdef DEBUG if( !VALID_DPLOBBY_PTR( this ) ) { ASSERT(FALSE); return; } #endif // Set the flag this->dwFlags |= DPLOBBYPR_ASYNCCONNECT; } // PRV_TurnAsyncConnectOn #undef DPF_MODNAME #define DPF_MODNAME "PRV_TurnAsyncConnectOff" void PRV_TurnAsyncConnectOff(LPDIRECTPLAYLOBBY lpDPL) { LPDPLOBBYI_DPLOBJECT this; DPF(7, "Entering PRV_TurnAsyncConnectOff"); DPF(9, "Parameters: 0x%08x", lpDPL); this = DPLOBJECT_FROM_INTERFACE(lpDPL); #ifdef DEBUG if( !VALID_DPLOBBY_PTR( this ) ) { ASSERT(FALSE); return; } #endif // Clear the flag this->dwFlags &= (~DPLOBBYPR_ASYNCCONNECT); } // PRV_TurnAsyncConnectOff #undef DPF_MODNAME #define DPF_MODNAME "DPL_CreateAddress" HRESULT DPLAPI DPL_CreateAddress(LPDIRECTPLAYLOBBY lpDPL, REFGUID lpguidSP, REFGUID lpguidDataType, LPCVOID lpData, DWORD dwDataSize, LPDPADDRESS lpAddress, LPDWORD lpdwAddressSize) { LPDPLOBBYI_DPLOBJECT this; HRESULT hr; DPF(7, "Entering DPL_CreateAddress"); DPF(9, "Parameters: 0x%08x, guid, guid, 0x%08x, %lu, 0x%08x, 0x%08x", lpDPL, lpData, dwDataSize, lpAddress, lpdwAddressSize); TRY { // We only need to validate the interface pointer here. Everything else // will get validated by the main function. if( !VALID_DPLOBBY_INTERFACE( lpDPL )) { return DPERR_INVALIDINTERFACE; } this = DPLOBJECT_FROM_INTERFACE(lpDPL); if( !VALID_DPLOBBY_PTR( this ) ) { return DPERR_INVALIDOBJECT; } } EXCEPT( EXCEPTION_EXECUTE_HANDLER ) { DPF_ERR( "Exception encountered validating parameters" ); return DPERR_INVALIDPARAMS; } // Call the CreateAddress function which resides in the DPlay project hr = InternalCreateAddress((LPDIRECTPLAYSP)lpDPL, lpguidSP, lpguidDataType, lpData, dwDataSize, lpAddress, lpdwAddressSize); return hr; } // DPL_CreateCompoundAddress #undef DPF_MODNAME #define DPF_MODNAME "DPL_CreateCompoundAddress" HRESULT DPLAPI DPL_CreateCompoundAddress(LPDIRECTPLAYLOBBY lpDPL, LPDPCOMPOUNDADDRESSELEMENT lpAddressElements, DWORD dwAddressElementCount, LPDPADDRESS lpAddress, LPDWORD lpdwAddressSize) { LPDPLOBBYI_DPLOBJECT this; HRESULT hr; DPF(7, "Entering DPL_CreateCompoundAddress"); DPF(9, "Parameters: 0x%08x, 0x%08x, %lu, 0x%08x, 0x%08x", lpDPL, lpAddressElements, dwAddressElementCount, lpAddress, lpdwAddressSize); TRY { // We only need to validate the interface pointer here. Everything else // will get validated by the main function. if( !VALID_DPLOBBY_INTERFACE( lpDPL )) { return DPERR_INVALIDINTERFACE; } this = DPLOBJECT_FROM_INTERFACE(lpDPL); if( !VALID_DPLOBBY_PTR( this ) ) { return DPERR_INVALIDOBJECT; } } EXCEPT( EXCEPTION_EXECUTE_HANDLER ) { DPF_ERR( "Exception encountered validating parameters" ); return DPERR_INVALIDPARAMS; } // Call the CreateCompoundAddress function which resides in the DPlay project hr = InternalCreateCompoundAddress(lpAddressElements, dwAddressElementCount, lpAddress, lpdwAddressSize); return hr; } // DPL_CreateCompoundAddress #undef DPF_MODNAME #define DPF_MODNAME "DPL_EnumAddress" HRESULT DPLAPI DPL_EnumAddress(LPDIRECTPLAYLOBBY lpDPL, LPDPENUMADDRESSCALLBACK lpEnumCallback, LPCVOID lpAddress, DWORD dwAddressSize, LPVOID lpContext) { LPDPLOBBYI_DPLOBJECT this; HRESULT hr; DPF(7, "Entering DPL_EnumAddress"); DPF(9, "Parameters: 0x%08x, 0x%08x, 0x%08x, %lu, 0x%08x", lpDPL, lpEnumCallback, lpAddress, dwAddressSize, lpContext); TRY { // We only need to validate the interface pointer here. Everything else // will get validated by the main function. if( !VALID_DPLOBBY_INTERFACE( lpDPL )) { return DPERR_INVALIDINTERFACE; } this = DPLOBJECT_FROM_INTERFACE(lpDPL); if( !VALID_DPLOBBY_PTR( this ) ) { return DPERR_INVALIDOBJECT; } } EXCEPT( EXCEPTION_EXECUTE_HANDLER ) { DPF_ERR( "Exception encountered validating parameters" ); return DPERR_INVALIDPARAMS; } // Call the CreateAddress function which resides in the DPlay project hr = InternalEnumAddress((LPDIRECTPLAYSP)lpDPL, lpEnumCallback, lpAddress, dwAddressSize, lpContext); return hr; } // DPL_EnumAddress #undef DPF_MODNAME #define DPF_MODNAME "PRV_GetCaps" HRESULT DPLAPI PRV_GetCaps(LPDPLOBBYI_DPLOBJECT this, DWORD dwFlags, LPDPCAPS lpcaps) { SPDATA_GETCAPS gcd; HRESULT hr = DP_OK; DPF(7, "Entering PRV_GetCaps"); DPF(9, "Parameters: 0x%08x, 0x%08x, 0x%08x", this, dwFlags, lpcaps); ENTER_DPLOBBY(); TRY { if( !VALID_DPLOBBY_PTR( this ) ) { LEAVE_DPLOBBY(); return DPERR_INVALIDOBJECT; } } EXCEPT( EXCEPTION_EXECUTE_HANDLER ) { LEAVE_DPLOBBY(); DPF_ERR( "Exception encountered validating parameters" ); return DPERR_INVALIDPARAMS; } // Setup our SPDATA struct memset(&gcd, 0, sizeof(SPDATA_GETCAPS)); gcd.dwSize = sizeof(SPDATA_GETCAPS); gcd.dwFlags = dwFlags; gcd.lpcaps = lpcaps; // Call the GetCaps method in the LP if(CALLBACK_EXISTS(GetCaps)) { gcd.lpISP = PRV_GetDPLobbySPInterface(this); // Drop the lock so the lobby provider's receive thread can get back // in with other messages if they show up in the queue before our // CreatePlayer response (which always happens) LEAVE_DPLOBBY(); hr = CALL_LP(this, GetCaps, &gcd); ENTER_DPLOBBY(); } else { // GetCaps is required DPF_ERR("The Lobby Provider callback for GetCaps doesn't exist -- it's required"); ASSERT(FALSE); LEAVE_DPLOBBY(); return DPERR_UNAVAILABLE; } if(FAILED(hr)) { DPF(2, "Failed calling GetCaps in the Lobby Provider, hr = 0x%08x", hr); } LEAVE_DPLOBBY(); return hr; } // PRV_GetCaps #undef DPF_MODNAME #define DPF_MODNAME "PRV_DeleteAppKeyFromRegistry" HRESULT PRV_DeleteAppKeyFromRegistry(LPGUID lpguid) { LPWSTR lpwszAppName = NULL; HKEY hkeyApp, hkeyDPApps = NULL; HRESULT hr; LONG lReturn; DPF(7, "Entering PRV_DeleteAppKeyFromRegistry"); DPF(9, "Parameters: 0x%08x", lpguid); // Allocate memory for the App Name lpwszAppName = DPMEM_ALLOC(DPLOBBY_REGISTRY_NAMELEN*sizeof(WCHAR)); if(!lpwszAppName) { DPF_ERR("Unable to allocate memory for App Name!"); return DPERR_OUTOFMEMORY; } // Open the registry key for the App if(!PRV_FindGameInRegistry(lpguid, lpwszAppName, DPLOBBY_REGISTRY_NAMELEN, &hkeyApp)) { DPF_ERR("Unable to find game in registry!"); hr = DPERR_UNKNOWNAPPLICATION; goto EXIT_DELETEAPPKEY; } // Close the app key RegCloseKey(hkeyApp); // Open the Applications key lReturn = OS_RegOpenKeyEx(HKEY_LOCAL_MACHINE, SZ_DPLAY_APPS_KEY, 0, KEY_READ, &hkeyDPApps); if(lReturn != ERROR_SUCCESS) { // If we can't open it, we assume it doesn't exist, so // we'll call it a success. hr = DP_OK; goto EXIT_DELETEAPPKEY; } // Now delete the key hr = OS_RegDeleteKey(hkeyDPApps, lpwszAppName); if(FAILED(hr)) { DPF_ERRVAL("Unable to delete app key, hr = 0x%08x", hr); goto EXIT_DELETEAPPKEY; } EXIT_DELETEAPPKEY: // Free our string memory if(lpwszAppName) DPMEM_FREE(lpwszAppName); // Close the DP Applications key if(hkeyDPApps) RegCloseKey(hkeyDPApps); return hr; } // PRV_DeleteAppKeyFromRegistry #undef DPF_MODNAME #define DPF_MODNAME "PRV_WriteAppDescInRegistryAnsi" HRESULT PRV_WriteAppDescInRegistryAnsi(LPDPAPPLICATIONDESC lpDesc) { HKEY hkeyDPApps = NULL, hkeyApp = NULL; LONG lReturn; DWORD dwDisposition; WCHAR wszGuid[GUID_STRING_SIZE]; CHAR szGuid[GUID_STRING_SIZE]; LPWSTR lpwszAppName = NULL; HRESULT hr; LPDPAPPLICATIONDESC2 lpDesc2=(LPDPAPPLICATIONDESC2)lpDesc; DWORD dwRegFlags; DWORD dwRegFlagsSize; DWORD dwType; DPF(7, "Entering PRV_WriteAppDescInRegistryAnsi"); DPF(9, "Parameters: 0x%08x", lpDesc); // Open the registry key for the App, if it exists, so we can // check for the autovoice flag DPF(5, "Checking to see if game already present in registry"); lpwszAppName = DPMEM_ALLOC(DPLOBBY_REGISTRY_NAMELEN*sizeof(WCHAR)); if (lpwszAppName == NULL) { DPF_ERR("Unable to allocate memory"); hr = DPERR_NOMEMORY; goto ERROR_WRITEAPPINREGISTRYANSI; } if(PRV_FindGameInRegistry(&(lpDesc->guidApplication), lpwszAppName, DPLOBBY_REGISTRY_NAMELEN, &hkeyApp)) { // Get the application flags DPF(5, "Game already registered"); dwRegFlags = 0; dwRegFlagsSize = sizeof(dwRegFlags); dwType = 0; lReturn = OS_RegQueryValueEx(hkeyApp, SZ_DWFLAGS, NULL, &dwType, (CHAR *)&dwRegFlags, &dwRegFlagsSize); if(lReturn == ERROR_SUCCESS) { // This application is already registered. We want to maintain the state // of the autovoice flag despite this re-registration, so set the appropriate // bit of lpDesc->dwFlags to the correct value. DPF(5, "Current Game flags: 0x%08x", dwRegFlags); if (dwRegFlags & DPLAPP_AUTOVOICE) { DPF(5, "Forcing DPLAPP_AUTOVOICE flag ON", dwRegFlags); lpDesc->dwFlags |= DPLAPP_AUTOVOICE; } else { DPF(5, "Forcing DPLAPP_AUTOVOICE flag OFF", dwRegFlags); lpDesc->dwFlags &= (~DPLAPP_AUTOVOICE); } } // Close the app key RegCloseKey(hkeyApp); } DPMEM_FREE(lpwszAppName); lpwszAppName = NULL; // Delete the application key if it exists hr = PRV_DeleteAppKeyFromRegistry(&lpDesc->guidApplication); // Open the Applications key (or create it if it doesn't exist lReturn = OS_RegCreateKeyEx(HKEY_LOCAL_MACHINE, SZ_DPLAY_APPS_KEY, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkeyDPApps, &dwDisposition); if(lReturn != ERROR_SUCCESS) { DPF_ERRVAL("Unable to open DPlay Applications registry key!, lReturn = %lu", lReturn); hr = DPERR_GENERIC; goto ERROR_WRITEAPPINREGISTRYANSI; } // Create the app's key lReturn = RegCreateKeyExA(hkeyDPApps, lpDesc->lpszApplicationNameA, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkeyApp, &dwDisposition); if(lReturn != ERROR_SUCCESS) { DPF_ERRVAL("Unable to create application registry key, lReturn = %lu", lReturn); hr = DPERR_GENERIC; goto ERROR_WRITEAPPINREGISTRYANSI; } // Set the guid value hr = StringFromGUID(&lpDesc->guidApplication, wszGuid, (sizeof(wszGuid)/sizeof(WCHAR))); if(FAILED(hr)) { DPF_ERRVAL("Unable to convert application guid to string, hr = 0x%08x", hr); goto ERROR_WRITEAPPINREGISTRYANSI; } WideToAnsi(szGuid, wszGuid, WSTRLEN_BYTES(wszGuid)); lReturn = OS_RegSetValueEx(hkeyApp, SZ_GUID, 0, REG_SZ, (LPBYTE)szGuid, lstrlenA(szGuid)); if(lReturn != ERROR_SUCCESS) { DPF_ERRVAL("Unable to register Application guid, lReturn = %lu", lReturn); hr = DPERR_GENERIC; goto ERROR_WRITEAPPINREGISTRYANSI; } // Set the Filename value ASSERT(lpDesc->lpszFilenameA); lReturn = OS_RegSetValueEx(hkeyApp, SZ_FILE, 0, REG_SZ, lpDesc->lpszFilenameA, lstrlenA(lpDesc->lpszFilenameA)); if(lReturn != ERROR_SUCCESS) { DPF_ERRVAL("Unable to register Filename string, lReturn = %lu", lReturn); hr = DPERR_GENERIC; goto ERROR_WRITEAPPINREGISTRYANSI; } // Set the CommandLine value (optional) if(lpDesc->lpszCommandLineA) { lReturn = OS_RegSetValueEx(hkeyApp, SZ_COMMANDLINE, 0, REG_SZ, lpDesc->lpszCommandLineA, lstrlenA(lpDesc->lpszCommandLineA)); if(lReturn != ERROR_SUCCESS) { DPF_ERRVAL("Unable to register CommandLine string, lReturn = %lu", lReturn); } } // Set the Path value ASSERT(lpDesc->lpszPathA); lReturn = OS_RegSetValueEx(hkeyApp, SZ_PATH, 0, REG_SZ, lpDesc->lpszPathA, lstrlenA(lpDesc->lpszPathA)); if(lReturn != ERROR_SUCCESS) { DPF_ERRVAL("Unable to register Path string, lReturn = %lu", lReturn); hr = DPERR_GENERIC; goto ERROR_WRITEAPPINREGISTRYANSI; } // Set the CurrentDirectory value (optional) if(lpDesc->lpszCurrentDirectoryA) { lReturn = OS_RegSetValueEx(hkeyApp, SZ_CURRENTDIR, 0, REG_SZ, lpDesc->lpszCurrentDirectoryA, lstrlenA(lpDesc->lpszCurrentDirectoryA)); if(lReturn != ERROR_SUCCESS) { DPF_ERRVAL("Unable to register CurrentDirectory string, lReturn = %lu", lReturn); } } // Set the DescriptionA value (optional) if(lpDesc->lpszDescriptionA) { lReturn = OS_RegSetValueEx(hkeyApp, SZ_DESCRIPTIONA, 0, REG_SZ, lpDesc->lpszDescriptionA, lstrlenA(lpDesc->lpszDescriptionA)); if(lReturn != ERROR_SUCCESS) { DPF_ERRVAL("Unable to register DescriptionA string, lReturn = %lu", lReturn); } } // Set the DescriptionW value (optional) if(lpDesc->lpszDescriptionW) { lReturn = OS_RegSetValueEx(hkeyApp, SZ_DESCRIPTIONW, 0, REG_BINARY, (BYTE *)lpDesc->lpszDescriptionW, WSTRLEN_BYTES(lpDesc->lpszDescriptionW)); if(lReturn != ERROR_SUCCESS) { DPF_ERRVAL("Unable to register DescriptionW string, lReturn = %lu", lReturn); } } if(IS_DPLOBBY_APPLICATIONDESC2(lpDesc) && lpDesc2->lpszAppLauncherNameA){ lReturn = OS_RegSetValueEx(hkeyApp, SZ_LAUNCHER, 0, REG_SZ, lpDesc2->lpszAppLauncherNameA, lstrlenA(lpDesc2->lpszAppLauncherNameA)); if(lReturn != ERROR_SUCCESS) { DPF_ERRVAL("Unable to register LauncherA string, lReturn = %lu", lReturn); } } // set the dwFlags field lReturn=OS_RegSetValueEx(hkeyApp, SZ_DWFLAGS, 0, REG_DWORD, (CHAR *)&lpDesc->dwFlags,sizeof(DWORD)); if(lReturn != ERROR_SUCCESS) { DPF_ERRVAL("Unable to write dwFlags field to registry, lReturn= %lu", lReturn); } // Close the two keys RegCloseKey(hkeyDPApps); RegCloseKey(hkeyApp); return DP_OK; ERROR_WRITEAPPINREGISTRYANSI: if(hkeyApp) { // Delete the key // REVIEW!!!! -- TODO // Now close the key RegCloseKey(hkeyApp); } if(hkeyDPApps) RegCloseKey(hkeyDPApps); return hr; } // PRV_WriteAppDescInRegistryAnsi #undef DPF_MODNAME #define DPF_MODNAME "PRV_WriteAppDescInRegistryUnicode" HRESULT PRV_WriteAppDescInRegistryUnicode(LPDPAPPLICATIONDESC lpDesc) { HKEY hkeyDPApps = NULL, hkeyApp = NULL; LONG lReturn; DWORD dwDisposition; WCHAR wszGuid[GUID_STRING_SIZE]; HRESULT hr; LPWSTR lpwszAppName = NULL; LPDPAPPLICATIONDESC2 lpDesc2=(LPDPAPPLICATIONDESC2)lpDesc; DWORD dwRegFlags; DWORD dwRegFlagsSize; DWORD dwType; DPF(7, "Entering PRV_WriteAppDescInRegistryUnicode"); DPF(9, "Parameters: 0x%08x", lpDesc); // Open the registry key for the App, if it exists, so we can // check for the autovoice flag DPF(5, "Checking to see if game already present in registry"); lpwszAppName = DPMEM_ALLOC(DPLOBBY_REGISTRY_NAMELEN*sizeof(WCHAR)); if (lpwszAppName == NULL) { DPF_ERR("Unable to allocate memory"); hr = DPERR_NOMEMORY; goto ERROR_WRITEAPPINREGISTRYUNICODE; } if(PRV_FindGameInRegistry(&(lpDesc->guidApplication), lpwszAppName, DPLOBBY_REGISTRY_NAMELEN, &hkeyApp)) { // Get the application flags DPF(5, "Game already registered"); dwRegFlags = 0; dwRegFlagsSize = sizeof(dwRegFlags); dwType = 0; lReturn = OS_RegQueryValueEx(hkeyApp, SZ_DWFLAGS, NULL, &dwType, (CHAR *)&dwRegFlags, &dwRegFlagsSize); if(lReturn == ERROR_SUCCESS) { // This application is already registered. We want to maintain the state // of the autovoice flag despite this re-registration, so set the appropriate // bit of lpDesc->dwFlags to the correct value. DPF(5, "Current Game flags: 0x%08x", dwRegFlags); if (dwRegFlags & DPLAPP_AUTOVOICE) { DPF(5, "Forcing DPLAPP_AUTOVOICE flag ON", dwRegFlags); lpDesc->dwFlags |= DPLAPP_AUTOVOICE; } else { DPF(5, "Forcing DPLAPP_AUTOVOICE flag OFF", dwRegFlags); lpDesc->dwFlags &= (~DPLAPP_AUTOVOICE); } } // Close the app key RegCloseKey(hkeyApp); } DPMEM_FREE(lpwszAppName); lpwszAppName = NULL; // Delete the application key if it exists hr = PRV_DeleteAppKeyFromRegistry(&lpDesc->guidApplication); // Open the Applications key (or create it if it doesn't exist lReturn = RegCreateKeyEx(HKEY_LOCAL_MACHINE, SZ_DPLAY_APPS_KEY, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkeyDPApps, &dwDisposition); if(lReturn != ERROR_SUCCESS) { DPF_ERRVAL("Unable to open DPlay Applications registry key!, lReturn = %lu", lReturn); hr = DPERR_GENERIC; goto ERROR_WRITEAPPINREGISTRYUNICODE; } // Create the app's key lReturn = RegCreateKeyEx(hkeyDPApps, lpDesc->lpszApplicationName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkeyApp, &dwDisposition); if(lReturn != ERROR_SUCCESS) { DPF_ERRVAL("Unable to create application registry key, lReturn = %lu", lReturn); hr = DPERR_GENERIC; goto ERROR_WRITEAPPINREGISTRYUNICODE; } // Set the guid value hr = StringFromGUID(&lpDesc->guidApplication, wszGuid, (sizeof(wszGuid)/sizeof(WCHAR))); if(FAILED(hr)) { DPF_ERRVAL("Unable to convert application guid to string, hr = 0x%08x", hr); goto ERROR_WRITEAPPINREGISTRYUNICODE; } lReturn = RegSetValueEx(hkeyApp, SZ_GUID, 0, REG_SZ, (BYTE *)wszGuid, WSTRLEN_BYTES(wszGuid)); if(lReturn != ERROR_SUCCESS) { DPF_ERRVAL("Unable to register Application guid, lReturn = %lu", lReturn); hr = DPERR_GENERIC; goto ERROR_WRITEAPPINREGISTRYUNICODE; } // Set the Filename value ASSERT(lpDesc->lpszFilename); lReturn = RegSetValueEx(hkeyApp, SZ_FILE, 0, REG_SZ, (LPBYTE)lpDesc->lpszFilename, WSTRLEN_BYTES(lpDesc->lpszFilename)); if(lReturn != ERROR_SUCCESS) { DPF_ERRVAL("Unable to register Filename string, lReturn = %lu", lReturn); hr = DPERR_GENERIC; goto ERROR_WRITEAPPINREGISTRYUNICODE; } // Set the CommandLine value (optional) if(lpDesc->lpszCommandLine) { lReturn = RegSetValueEx(hkeyApp, SZ_COMMANDLINE, 0, REG_SZ, (LPBYTE)lpDesc->lpszCommandLine, WSTRLEN_BYTES(lpDesc->lpszCommandLine)); if(lReturn != ERROR_SUCCESS) { DPF_ERRVAL("Unable to register CommandLine string, lReturn = %lu", lReturn); } } // Set the Path value ASSERT(lpDesc->lpszPath); lReturn = RegSetValueEx(hkeyApp, SZ_PATH, 0, REG_SZ, (LPBYTE)lpDesc->lpszPath, WSTRLEN_BYTES(lpDesc->lpszPath)); if(lReturn != ERROR_SUCCESS) { DPF_ERRVAL("Unable to register Path string, lReturn = %lu", lReturn); hr = DPERR_GENERIC; goto ERROR_WRITEAPPINREGISTRYUNICODE; } // Set the CurrentDirectory value (optional) if(lpDesc->lpszCurrentDirectory) { lReturn = RegSetValueEx(hkeyApp, SZ_CURRENTDIR, 0, REG_SZ, (LPBYTE)lpDesc->lpszCurrentDirectory, WSTRLEN_BYTES(lpDesc->lpszCurrentDirectory)); if(lReturn != ERROR_SUCCESS) { DPF_ERRVAL("Unable to register CurrentDirectory string, lReturn = %lu", lReturn); } } // Set the DescriptionA value (optional) if(lpDesc->lpszDescriptionA) { lReturn = RegSetValueExA(hkeyApp, "DescriptionA", 0, REG_SZ, lpDesc->lpszDescriptionA, lstrlenA(lpDesc->lpszDescriptionA)); if(lReturn != ERROR_SUCCESS) { DPF_ERRVAL("Unable to register DescriptionA string, lReturn = %lu", lReturn); } } // Set the DescriptionW value (optional) if(lpDesc->lpszDescriptionW) { lReturn = RegSetValueEx(hkeyApp, SZ_DESCRIPTIONW, 0, REG_SZ, (LPBYTE)lpDesc->lpszDescriptionW, WSTRLEN_BYTES(lpDesc->lpszDescriptionW)); if(lReturn != ERROR_SUCCESS) { DPF_ERRVAL("Unable to register DescriptionW string, lReturn = %lu", lReturn); } } // Set the LauncherName value (optional, DESC2 only) if(IS_DPLOBBY_APPLICATIONDESC2(lpDesc) && lpDesc2->lpszAppLauncherName){ lReturn = RegSetValueEx(hkeyApp, SZ_LAUNCHER, 0, REG_SZ, (LPBYTE)lpDesc2->lpszAppLauncherName, WSTRLEN_BYTES(lpDesc2->lpszAppLauncherName)); if(lReturn != ERROR_SUCCESS) { DPF_ERRVAL("Unable to register LauncherName string, lReturn = %lu", lReturn); } } // set the dwFlags field lReturn=RegSetValueEx(hkeyApp, SZ_DWFLAGS, 0, REG_DWORD, (CHAR *)&lpDesc->dwFlags,sizeof(DWORD)); if(lReturn != ERROR_SUCCESS) { DPF_ERRVAL("Unable to write dwFlags field to registry, lReturn= %lu", lReturn); } // Close the two keys RegCloseKey(hkeyDPApps); RegCloseKey(hkeyApp); return DP_OK; ERROR_WRITEAPPINREGISTRYUNICODE: if(hkeyApp) { // Delete the key // REVIEW!!!! -- TODO // Now close the key RegCloseKey(hkeyApp); } if(hkeyDPApps) RegCloseKey(hkeyDPApps); return hr; } // PRV_WriteAppDescInRegistryUnicode #undef DPF_MODNAME #define DPF_MODNAME "DPL_RegisterApplication" HRESULT DPLAPI DPL_RegisterApplication(LPDIRECTPLAYLOBBY lpDPL, DWORD dwFlags, LPVOID lpvDesc) { LPDPLOBBYI_DPLOBJECT this; LPDPAPPLICATIONDESC lpDescA = NULL; HRESULT hr = DP_OK; LPDPAPPLICATIONDESC lpDesc=(LPDPAPPLICATIONDESC)lpvDesc; DPF(7, "Entering DPL_RegisterApplication"); DPF(9, "Parameters: 0x%08x, 0x%08x, 0x%08x", lpDPL, dwFlags, lpDesc); ENTER_DPLOBBY(); TRY { // We only need to validate the interface pointer here. Everything else // will get validated by the main function. if( !VALID_DPLOBBY_INTERFACE( lpDPL )) { LEAVE_DPLOBBY(); return DPERR_INVALIDINTERFACE; } this = DPLOBJECT_FROM_INTERFACE(lpDPL); if( !VALID_DPLOBBY_PTR( this ) ) { LEAVE_DPLOBBY(); return DPERR_INVALIDOBJECT; } if(dwFlags) { LEAVE_DPLOBBY(); return DPERR_INVALIDFLAGS; } // Validate the ApplicationDesc struct hr = PRV_ValidateDPAPPLICATIONDESC(lpDesc, FALSE); if(FAILED(hr)) { LEAVE_DPLOBBY(); DPF_ERR("Invalid DPAPPLICATIONDESC structure"); return hr; } } EXCEPT( EXCEPTION_EXECUTE_HANDLER ) { LEAVE_DPLOBBY(); DPF_ERR( "Exception encountered validating parameters" ); return DPERR_INVALIDPARAMS; } // If we're on a Unicode platform, just write the stuff in the registry. // If it's not, we need to convert the DPAPPLICATIONDESC struct to ANSI if(OS_IsPlatformUnicode()) { // Just write to the registry hr = PRV_WriteAppDescInRegistryUnicode(lpDesc); } else { // Convert the APPDESC struct to ANSI hr = PRV_ConvertDPAPPLICATIONDESCToAnsi(lpDesc, &lpDescA); if(FAILED(hr)) { DPF_ERRVAL("Unable to convert DPAPPLICATIONDESC to Ansi, hr = 0x%08x", hr); goto ERROR_REGISTERAPPLICATION; } // Write to the registry hr = PRV_WriteAppDescInRegistryAnsi(lpDescA); // Free our APPDESC structure PRV_FreeLocalDPAPPLICATIONDESC(lpDescA); } if(FAILED(hr)) { DPF_ERRVAL("Failed writing ApplicationDesc to registry, hr = 0x%08x", hr); } ERROR_REGISTERAPPLICATION: LEAVE_DPLOBBY(); return hr; } // DPL_RegisterApplication #undef DPF_MODNAME #define DPF_MODNAME "DPL_UnregisterApplication" HRESULT DPLAPI DPL_UnregisterApplication(LPDIRECTPLAYLOBBY lpDPL, DWORD dwFlags, REFGUID lpguid) { LPDPLOBBYI_DPLOBJECT this; HRESULT hr = DP_OK; DPF(7, "Entering DPL_UnregisterApplication"); DPF(9, "Parameters: 0x%08x, 0x%08x, 0x%08x", lpDPL, dwFlags, lpguid); ENTER_DPLOBBY(); TRY { // We only need to validate the interface pointer here. Everything else // will get validated by the main function. if( !VALID_DPLOBBY_INTERFACE( lpDPL )) { LEAVE_DPLOBBY(); return DPERR_INVALIDINTERFACE; } this = DPLOBJECT_FROM_INTERFACE(lpDPL); if( !VALID_DPLOBBY_PTR( this ) ) { LEAVE_DPLOBBY(); return DPERR_INVALIDOBJECT; } if(dwFlags) { LEAVE_DPLOBBY(); return DPERR_INVALIDFLAGS; } if(!VALID_READ_UUID_PTR(lpguid)) { LEAVE_DPLOBBY(); return DPERR_INVALIDPARAMS; } } EXCEPT( EXCEPTION_EXECUTE_HANDLER ) { LEAVE_DPLOBBY(); DPF_ERR( "Exception encountered validating parameters" ); return DPERR_INVALIDPARAMS; } hr = PRV_DeleteAppKeyFromRegistry((LPGUID)lpguid); if(FAILED(hr)) { DPF_ERRVAL("Unable to delete app key from registry, hr = 0x%08x", hr); } LEAVE_DPLOBBY(); return hr; } // DPL_UnregisterApplication