Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1139 lines
29 KiB

/*==========================================================================
*
* 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