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

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1996-1997 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: dplobby.c
  6. * Content: Methods for lobby management
  7. *
  8. * History:
  9. * Date By Reason
  10. * ======= ======= ======
  11. * 4/13/96 myronth Created it
  12. * 10/23/96 myronth Added client/server methods
  13. * 1/2/97 myronth Added wrappers for CreateAddress and EnumAddress
  14. * 2/12/97 myronth Mass DX5 changes
  15. * 3/24/97 kipo Added support for IDirectPlayLobby2 interface
  16. * 4/3/97 myronth Fixed interface pointer casts for CreateAddress and
  17. * EnumAddress
  18. * 4/10/97 myronth Added support for GetCaps
  19. * 5/8/97 myronth Drop lobby lock when calling LP
  20. * 11/13/97 myronth Added functions for asynchronous Connect (#12541)
  21. * 12/2/97 myronth Added Register/UnregisterApplication
  22. * 12/4/97 myronth Added ConnectEx
  23. * 10/22/99 aarono added support for application flags
  24. * 12/13/99 pnewson bugs #123583, 123601, 123604 - support to launch dpvhelp.exe on
  25. * apps that are not registered or badly registered
  26. ***************************************************************************/
  27. #include "dplobpr.h"
  28. //--------------------------------------------------------------------------
  29. //
  30. // Functions
  31. //
  32. //--------------------------------------------------------------------------
  33. #undef DPF_MODNAME
  34. #define DPF_MODNAME "DPL_Connect"
  35. HRESULT DPLAPI DPL_Connect(LPDIRECTPLAYLOBBY lpDPL, DWORD dwFlags,
  36. LPDIRECTPLAY2 * lplpDP2, IUnknown FAR * lpUnk)
  37. {
  38. LPDPLOBBYI_DPLOBJECT this;
  39. HRESULT hr;
  40. DPF(7, "Entering DPL_Connect");
  41. DPF(9, "Parameters: 0x%08x, 0x%08x, 0x%08x, 0x%08x",
  42. lpDPL, dwFlags, lplpDP2, lpUnk);
  43. ENTER_DPLOBBY();
  44. TRY
  45. {
  46. if( !VALID_DPLOBBY_INTERFACE( lpDPL ))
  47. {
  48. LEAVE_DPLOBBY();
  49. return DPERR_INVALIDINTERFACE;
  50. }
  51. this = DPLOBJECT_FROM_INTERFACE(lpDPL);
  52. if( !VALID_DPLOBBY_PTR( this ) )
  53. {
  54. LEAVE_DPLOBBY();
  55. return DPERR_INVALIDOBJECT;
  56. }
  57. if( !VALID_WRITE_PTR( lplpDP2, sizeof(LPDIRECTPLAY2 *)) )
  58. {
  59. LEAVE_DPLOBBY();
  60. return DPERR_INVALIDPARAMS;
  61. }
  62. if( lpUnk != NULL )
  63. {
  64. LEAVE_DPLOBBY();
  65. return CLASS_E_NOAGGREGATION;
  66. }
  67. if(!VALID_CONNECT_FLAGS(dwFlags))
  68. {
  69. LEAVE_DPLOBBY();
  70. return DPERR_INVALIDFLAGS;
  71. }
  72. }
  73. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  74. {
  75. DPF_ERR( "Exception encountered validating parameters" );
  76. LEAVE_DPLOBBY();
  77. return DPERR_INVALIDPARAMS;
  78. }
  79. // Call the ConnectMe function which resides in the DPlay project
  80. hr = ConnectMe(lpDPL, lplpDP2, lpUnk, dwFlags);
  81. LEAVE_DPLOBBY();
  82. return hr;
  83. } // DPL_Connect
  84. #undef DPF_MODNAME
  85. #define DPF_MODNAME "DPL_ConnectEx"
  86. HRESULT DPLAPI DPL_ConnectEx(LPDIRECTPLAYLOBBY lpDPL, DWORD dwFlags,
  87. REFIID riid, LPVOID * ppvObj, IUnknown FAR * lpUnk)
  88. {
  89. LPDIRECTPLAY2 lpDP2 = NULL;
  90. HRESULT hr;
  91. DPF(7, "Entering DPL_ConnectEx");
  92. DPF(9, "Parameters: 0x%08x, 0x%08x, iid, 0x%08x, 0x%08x",
  93. lpDPL, dwFlags, ppvObj, lpUnk);
  94. // Call the ConnectMe function which resides in the DPlay project
  95. hr = DPL_Connect(lpDPL, dwFlags, &lpDP2, lpUnk);
  96. if(SUCCEEDED(hr))
  97. {
  98. hr = DP_QueryInterface((LPDIRECTPLAY)lpDP2, riid, ppvObj);
  99. if(FAILED(hr))
  100. {
  101. DPF_ERRVAL("Failed calling QueryInterface, hr = 0x%08x", hr);
  102. }
  103. // Release the DP2 object
  104. DP_Release((LPDIRECTPLAY)lpDP2);
  105. }
  106. return hr;
  107. } // DPL_ConnectEx
  108. #undef DPF_MODNAME
  109. #define DPF_MODNAME "PRV_SaveConnectPointers"
  110. void PRV_SaveConnectPointers(LPDIRECTPLAYLOBBY lpDPL,
  111. LPDIRECTPLAY2 lpDP2, LPDPLCONNECTION lpConn)
  112. {
  113. LPDPLOBBYI_DPLOBJECT this;
  114. DPF(7, "Entering PRV_SaveConnectPointers");
  115. DPF(9, "Parameters: 0x%08x, 0x%08x, 0x%08x",
  116. lpDPL, lpDP2, lpConn);
  117. this = DPLOBJECT_FROM_INTERFACE(lpDPL);
  118. #ifdef DEBUG
  119. if( !VALID_DPLOBBY_PTR( this ) )
  120. return;
  121. #endif
  122. // Save the pointers
  123. this->lpDP2 = lpDP2;
  124. this->lpConn = lpConn;
  125. } // PRV_SaveConnectPointers
  126. #undef DPF_MODNAME
  127. #define DPF_MODNAME "PRV_GetConnectPointers"
  128. BOOL PRV_GetConnectPointers(LPDIRECTPLAYLOBBY lpDPL,
  129. LPDIRECTPLAY2 * lplpDP2, LPDPLCONNECTION * lplpConn)
  130. {
  131. LPDPLOBBYI_DPLOBJECT this;
  132. DPF(7, "Entering PRV_GetConnectPointers");
  133. DPF(9, "Parameters: 0x%08x, 0x%08x, 0x%08x",
  134. lpDPL, lplpDP2, lplpConn);
  135. ASSERT(lplpDP2);
  136. ASSERT(lplpConn);
  137. this = DPLOBJECT_FROM_INTERFACE(lpDPL);
  138. #ifdef DEBUG
  139. if( !VALID_DPLOBBY_PTR( this ) )
  140. return FALSE;
  141. #endif
  142. // See if we have the pointers
  143. if((!this->lpDP2) || (!this->lpConn))
  144. return FALSE;
  145. // Set the output pointers
  146. *lplpDP2 = this->lpDP2;
  147. *lplpConn = this->lpConn;
  148. return TRUE;
  149. } // PRV_GetConnectPointers
  150. #undef DPF_MODNAME
  151. #define DPF_MODNAME "PRV_IsAsyncConnectOn"
  152. BOOL PRV_IsAsyncConnectOn(LPDIRECTPLAYLOBBY lpDPL)
  153. {
  154. LPDPLOBBYI_DPLOBJECT this;
  155. DPF(7, "Entering PRV_IsAsyncConnectOn");
  156. DPF(9, "Parameters: 0x%08x", lpDPL);
  157. this = DPLOBJECT_FROM_INTERFACE(lpDPL);
  158. #ifdef DEBUG
  159. if( !VALID_DPLOBBY_PTR( this ) )
  160. return FALSE;
  161. #endif
  162. // Check the flag
  163. if(this->dwFlags & DPLOBBYPR_ASYNCCONNECT)
  164. return TRUE;
  165. else
  166. return FALSE;
  167. } // PRV_IsAsyncConnectOn
  168. #undef DPF_MODNAME
  169. #define DPF_MODNAME "PRV_TurnAsyncConnectOn"
  170. void PRV_TurnAsyncConnectOn(LPDIRECTPLAYLOBBY lpDPL)
  171. {
  172. LPDPLOBBYI_DPLOBJECT this;
  173. DPF(7, "Entering PRV_TurnAsyncConnectOn");
  174. DPF(9, "Parameters: 0x%08x", lpDPL);
  175. this = DPLOBJECT_FROM_INTERFACE(lpDPL);
  176. #ifdef DEBUG
  177. if( !VALID_DPLOBBY_PTR( this ) )
  178. {
  179. ASSERT(FALSE);
  180. return;
  181. }
  182. #endif
  183. // Set the flag
  184. this->dwFlags |= DPLOBBYPR_ASYNCCONNECT;
  185. } // PRV_TurnAsyncConnectOn
  186. #undef DPF_MODNAME
  187. #define DPF_MODNAME "PRV_TurnAsyncConnectOff"
  188. void PRV_TurnAsyncConnectOff(LPDIRECTPLAYLOBBY lpDPL)
  189. {
  190. LPDPLOBBYI_DPLOBJECT this;
  191. DPF(7, "Entering PRV_TurnAsyncConnectOff");
  192. DPF(9, "Parameters: 0x%08x", lpDPL);
  193. this = DPLOBJECT_FROM_INTERFACE(lpDPL);
  194. #ifdef DEBUG
  195. if( !VALID_DPLOBBY_PTR( this ) )
  196. {
  197. ASSERT(FALSE);
  198. return;
  199. }
  200. #endif
  201. // Clear the flag
  202. this->dwFlags &= (~DPLOBBYPR_ASYNCCONNECT);
  203. } // PRV_TurnAsyncConnectOff
  204. #undef DPF_MODNAME
  205. #define DPF_MODNAME "DPL_CreateAddress"
  206. HRESULT DPLAPI DPL_CreateAddress(LPDIRECTPLAYLOBBY lpDPL,
  207. REFGUID lpguidSP, REFGUID lpguidDataType, LPCVOID lpData, DWORD dwDataSize,
  208. LPDPADDRESS lpAddress, LPDWORD lpdwAddressSize)
  209. {
  210. LPDPLOBBYI_DPLOBJECT this;
  211. HRESULT hr;
  212. DPF(7, "Entering DPL_CreateAddress");
  213. DPF(9, "Parameters: 0x%08x, guid, guid, 0x%08x, %lu, 0x%08x, 0x%08x",
  214. lpDPL, lpData, dwDataSize, lpAddress, lpdwAddressSize);
  215. TRY
  216. {
  217. // We only need to validate the interface pointer here. Everything else
  218. // will get validated by the main function.
  219. if( !VALID_DPLOBBY_INTERFACE( lpDPL ))
  220. {
  221. return DPERR_INVALIDINTERFACE;
  222. }
  223. this = DPLOBJECT_FROM_INTERFACE(lpDPL);
  224. if( !VALID_DPLOBBY_PTR( this ) )
  225. {
  226. return DPERR_INVALIDOBJECT;
  227. }
  228. }
  229. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  230. {
  231. DPF_ERR( "Exception encountered validating parameters" );
  232. return DPERR_INVALIDPARAMS;
  233. }
  234. // Call the CreateAddress function which resides in the DPlay project
  235. hr = InternalCreateAddress((LPDIRECTPLAYSP)lpDPL, lpguidSP, lpguidDataType, lpData,
  236. dwDataSize, lpAddress, lpdwAddressSize);
  237. return hr;
  238. } // DPL_CreateCompoundAddress
  239. #undef DPF_MODNAME
  240. #define DPF_MODNAME "DPL_CreateCompoundAddress"
  241. HRESULT DPLAPI DPL_CreateCompoundAddress(LPDIRECTPLAYLOBBY lpDPL,
  242. LPDPCOMPOUNDADDRESSELEMENT lpAddressElements, DWORD dwAddressElementCount,
  243. LPDPADDRESS lpAddress, LPDWORD lpdwAddressSize)
  244. {
  245. LPDPLOBBYI_DPLOBJECT this;
  246. HRESULT hr;
  247. DPF(7, "Entering DPL_CreateCompoundAddress");
  248. DPF(9, "Parameters: 0x%08x, 0x%08x, %lu, 0x%08x, 0x%08x",
  249. lpDPL, lpAddressElements, dwAddressElementCount, lpAddress, lpdwAddressSize);
  250. TRY
  251. {
  252. // We only need to validate the interface pointer here. Everything else
  253. // will get validated by the main function.
  254. if( !VALID_DPLOBBY_INTERFACE( lpDPL ))
  255. {
  256. return DPERR_INVALIDINTERFACE;
  257. }
  258. this = DPLOBJECT_FROM_INTERFACE(lpDPL);
  259. if( !VALID_DPLOBBY_PTR( this ) )
  260. {
  261. return DPERR_INVALIDOBJECT;
  262. }
  263. }
  264. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  265. {
  266. DPF_ERR( "Exception encountered validating parameters" );
  267. return DPERR_INVALIDPARAMS;
  268. }
  269. // Call the CreateCompoundAddress function which resides in the DPlay project
  270. hr = InternalCreateCompoundAddress(lpAddressElements, dwAddressElementCount,
  271. lpAddress, lpdwAddressSize);
  272. return hr;
  273. } // DPL_CreateCompoundAddress
  274. #undef DPF_MODNAME
  275. #define DPF_MODNAME "DPL_EnumAddress"
  276. HRESULT DPLAPI DPL_EnumAddress(LPDIRECTPLAYLOBBY lpDPL,
  277. LPDPENUMADDRESSCALLBACK lpEnumCallback, LPCVOID lpAddress,
  278. DWORD dwAddressSize, LPVOID lpContext)
  279. {
  280. LPDPLOBBYI_DPLOBJECT this;
  281. HRESULT hr;
  282. DPF(7, "Entering DPL_EnumAddress");
  283. DPF(9, "Parameters: 0x%08x, 0x%08x, 0x%08x, %lu, 0x%08x",
  284. lpDPL, lpEnumCallback, lpAddress, dwAddressSize, lpContext);
  285. TRY
  286. {
  287. // We only need to validate the interface pointer here. Everything else
  288. // will get validated by the main function.
  289. if( !VALID_DPLOBBY_INTERFACE( lpDPL ))
  290. {
  291. return DPERR_INVALIDINTERFACE;
  292. }
  293. this = DPLOBJECT_FROM_INTERFACE(lpDPL);
  294. if( !VALID_DPLOBBY_PTR( this ) )
  295. {
  296. return DPERR_INVALIDOBJECT;
  297. }
  298. }
  299. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  300. {
  301. DPF_ERR( "Exception encountered validating parameters" );
  302. return DPERR_INVALIDPARAMS;
  303. }
  304. // Call the CreateAddress function which resides in the DPlay project
  305. hr = InternalEnumAddress((LPDIRECTPLAYSP)lpDPL, lpEnumCallback, lpAddress,
  306. dwAddressSize, lpContext);
  307. return hr;
  308. } // DPL_EnumAddress
  309. #undef DPF_MODNAME
  310. #define DPF_MODNAME "PRV_GetCaps"
  311. HRESULT DPLAPI PRV_GetCaps(LPDPLOBBYI_DPLOBJECT this, DWORD dwFlags,
  312. LPDPCAPS lpcaps)
  313. {
  314. SPDATA_GETCAPS gcd;
  315. HRESULT hr = DP_OK;
  316. DPF(7, "Entering PRV_GetCaps");
  317. DPF(9, "Parameters: 0x%08x, 0x%08x, 0x%08x", this, dwFlags, lpcaps);
  318. ENTER_DPLOBBY();
  319. TRY
  320. {
  321. if( !VALID_DPLOBBY_PTR( this ) )
  322. {
  323. LEAVE_DPLOBBY();
  324. return DPERR_INVALIDOBJECT;
  325. }
  326. }
  327. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  328. {
  329. LEAVE_DPLOBBY();
  330. DPF_ERR( "Exception encountered validating parameters" );
  331. return DPERR_INVALIDPARAMS;
  332. }
  333. // Setup our SPDATA struct
  334. memset(&gcd, 0, sizeof(SPDATA_GETCAPS));
  335. gcd.dwSize = sizeof(SPDATA_GETCAPS);
  336. gcd.dwFlags = dwFlags;
  337. gcd.lpcaps = lpcaps;
  338. // Call the GetCaps method in the LP
  339. if(CALLBACK_EXISTS(GetCaps))
  340. {
  341. gcd.lpISP = PRV_GetDPLobbySPInterface(this);
  342. // Drop the lock so the lobby provider's receive thread can get back
  343. // in with other messages if they show up in the queue before our
  344. // CreatePlayer response (which always happens)
  345. LEAVE_DPLOBBY();
  346. hr = CALL_LP(this, GetCaps, &gcd);
  347. ENTER_DPLOBBY();
  348. }
  349. else
  350. {
  351. // GetCaps is required
  352. DPF_ERR("The Lobby Provider callback for GetCaps doesn't exist -- it's required");
  353. ASSERT(FALSE);
  354. LEAVE_DPLOBBY();
  355. return DPERR_UNAVAILABLE;
  356. }
  357. if(FAILED(hr))
  358. {
  359. DPF(2, "Failed calling GetCaps in the Lobby Provider, hr = 0x%08x", hr);
  360. }
  361. LEAVE_DPLOBBY();
  362. return hr;
  363. } // PRV_GetCaps
  364. #undef DPF_MODNAME
  365. #define DPF_MODNAME "PRV_DeleteAppKeyFromRegistry"
  366. HRESULT PRV_DeleteAppKeyFromRegistry(LPGUID lpguid)
  367. {
  368. LPWSTR lpwszAppName = NULL;
  369. HKEY hkeyApp, hkeyDPApps = NULL;
  370. HRESULT hr;
  371. LONG lReturn;
  372. DPF(7, "Entering PRV_DeleteAppKeyFromRegistry");
  373. DPF(9, "Parameters: 0x%08x", lpguid);
  374. // Allocate memory for the App Name
  375. lpwszAppName = DPMEM_ALLOC(DPLOBBY_REGISTRY_NAMELEN*sizeof(WCHAR));
  376. if(!lpwszAppName)
  377. {
  378. DPF_ERR("Unable to allocate memory for App Name!");
  379. return DPERR_OUTOFMEMORY;
  380. }
  381. // Open the registry key for the App
  382. if(!PRV_FindGameInRegistry(lpguid, lpwszAppName,
  383. DPLOBBY_REGISTRY_NAMELEN, &hkeyApp))
  384. {
  385. DPF_ERR("Unable to find game in registry!");
  386. hr = DPERR_UNKNOWNAPPLICATION;
  387. goto EXIT_DELETEAPPKEY;
  388. }
  389. // Close the app key
  390. RegCloseKey(hkeyApp);
  391. // Open the Applications key
  392. lReturn = OS_RegOpenKeyEx(HKEY_LOCAL_MACHINE, SZ_DPLAY_APPS_KEY, 0,
  393. KEY_READ, &hkeyDPApps);
  394. if(lReturn != ERROR_SUCCESS)
  395. {
  396. // If we can't open it, we assume it doesn't exist, so
  397. // we'll call it a success.
  398. hr = DP_OK;
  399. goto EXIT_DELETEAPPKEY;
  400. }
  401. // Now delete the key
  402. hr = OS_RegDeleteKey(hkeyDPApps, lpwszAppName);
  403. if(FAILED(hr))
  404. {
  405. DPF_ERRVAL("Unable to delete app key, hr = 0x%08x", hr);
  406. goto EXIT_DELETEAPPKEY;
  407. }
  408. EXIT_DELETEAPPKEY:
  409. // Free our string memory
  410. if(lpwszAppName)
  411. DPMEM_FREE(lpwszAppName);
  412. // Close the DP Applications key
  413. if(hkeyDPApps)
  414. RegCloseKey(hkeyDPApps);
  415. return hr;
  416. } // PRV_DeleteAppKeyFromRegistry
  417. #undef DPF_MODNAME
  418. #define DPF_MODNAME "PRV_WriteAppDescInRegistryAnsi"
  419. HRESULT PRV_WriteAppDescInRegistryAnsi(LPDPAPPLICATIONDESC lpDesc)
  420. {
  421. HKEY hkeyDPApps = NULL, hkeyApp = NULL;
  422. LONG lReturn;
  423. DWORD dwDisposition;
  424. WCHAR wszGuid[GUID_STRING_SIZE];
  425. CHAR szGuid[GUID_STRING_SIZE];
  426. LPWSTR lpwszAppName = NULL;
  427. HRESULT hr;
  428. LPDPAPPLICATIONDESC2 lpDesc2=(LPDPAPPLICATIONDESC2)lpDesc;
  429. DWORD dwRegFlags;
  430. DWORD dwRegFlagsSize;
  431. DWORD dwType;
  432. DPF(7, "Entering PRV_WriteAppDescInRegistryAnsi");
  433. DPF(9, "Parameters: 0x%08x", lpDesc);
  434. // Open the registry key for the App, if it exists, so we can
  435. // check for the autovoice flag
  436. DPF(5, "Checking to see if game already present in registry");
  437. lpwszAppName = DPMEM_ALLOC(DPLOBBY_REGISTRY_NAMELEN*sizeof(WCHAR));
  438. if (lpwszAppName == NULL)
  439. {
  440. DPF_ERR("Unable to allocate memory");
  441. hr = DPERR_NOMEMORY;
  442. goto ERROR_WRITEAPPINREGISTRYANSI;
  443. }
  444. if(PRV_FindGameInRegistry(&(lpDesc->guidApplication), lpwszAppName,
  445. DPLOBBY_REGISTRY_NAMELEN, &hkeyApp))
  446. {
  447. // Get the application flags
  448. DPF(5, "Game already registered");
  449. dwRegFlags = 0;
  450. dwRegFlagsSize = sizeof(dwRegFlags);
  451. dwType = 0;
  452. lReturn = OS_RegQueryValueEx(hkeyApp, SZ_DWFLAGS, NULL, &dwType, (CHAR *)&dwRegFlags, &dwRegFlagsSize);
  453. if(lReturn == ERROR_SUCCESS)
  454. {
  455. // This application is already registered. We want to maintain the state
  456. // of the autovoice flag despite this re-registration, so set the appropriate
  457. // bit of lpDesc->dwFlags to the correct value.
  458. DPF(5, "Current Game flags: 0x%08x", dwRegFlags);
  459. if (dwRegFlags & DPLAPP_AUTOVOICE)
  460. {
  461. DPF(5, "Forcing DPLAPP_AUTOVOICE flag ON", dwRegFlags);
  462. lpDesc->dwFlags |= DPLAPP_AUTOVOICE;
  463. }
  464. else
  465. {
  466. DPF(5, "Forcing DPLAPP_AUTOVOICE flag OFF", dwRegFlags);
  467. lpDesc->dwFlags &= (~DPLAPP_AUTOVOICE);
  468. }
  469. }
  470. // Close the app key
  471. RegCloseKey(hkeyApp);
  472. }
  473. DPMEM_FREE(lpwszAppName);
  474. lpwszAppName = NULL;
  475. // Delete the application key if it exists
  476. hr = PRV_DeleteAppKeyFromRegistry(&lpDesc->guidApplication);
  477. // Open the Applications key (or create it if it doesn't exist
  478. lReturn = OS_RegCreateKeyEx(HKEY_LOCAL_MACHINE, SZ_DPLAY_APPS_KEY, 0, NULL,
  479. REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkeyDPApps,
  480. &dwDisposition);
  481. if(lReturn != ERROR_SUCCESS)
  482. {
  483. DPF_ERRVAL("Unable to open DPlay Applications registry key!, lReturn = %lu", lReturn);
  484. hr = DPERR_GENERIC;
  485. goto ERROR_WRITEAPPINREGISTRYANSI;
  486. }
  487. // Create the app's key
  488. lReturn = RegCreateKeyExA(hkeyDPApps, lpDesc->lpszApplicationNameA,
  489. 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL,
  490. &hkeyApp, &dwDisposition);
  491. if(lReturn != ERROR_SUCCESS)
  492. {
  493. DPF_ERRVAL("Unable to create application registry key, lReturn = %lu", lReturn);
  494. hr = DPERR_GENERIC;
  495. goto ERROR_WRITEAPPINREGISTRYANSI;
  496. }
  497. // Set the guid value
  498. hr = StringFromGUID(&lpDesc->guidApplication, wszGuid, (sizeof(wszGuid)/sizeof(WCHAR)));
  499. if(FAILED(hr))
  500. {
  501. DPF_ERRVAL("Unable to convert application guid to string, hr = 0x%08x", hr);
  502. goto ERROR_WRITEAPPINREGISTRYANSI;
  503. }
  504. WideToAnsi(szGuid, wszGuid, WSTRLEN_BYTES(wszGuid));
  505. lReturn = OS_RegSetValueEx(hkeyApp, SZ_GUID, 0, REG_SZ,
  506. (LPBYTE)szGuid, lstrlenA(szGuid));
  507. if(lReturn != ERROR_SUCCESS)
  508. {
  509. DPF_ERRVAL("Unable to register Application guid, lReturn = %lu", lReturn);
  510. hr = DPERR_GENERIC;
  511. goto ERROR_WRITEAPPINREGISTRYANSI;
  512. }
  513. // Set the Filename value
  514. ASSERT(lpDesc->lpszFilenameA);
  515. lReturn = OS_RegSetValueEx(hkeyApp, SZ_FILE, 0, REG_SZ,
  516. lpDesc->lpszFilenameA, lstrlenA(lpDesc->lpszFilenameA));
  517. if(lReturn != ERROR_SUCCESS)
  518. {
  519. DPF_ERRVAL("Unable to register Filename string, lReturn = %lu", lReturn);
  520. hr = DPERR_GENERIC;
  521. goto ERROR_WRITEAPPINREGISTRYANSI;
  522. }
  523. // Set the CommandLine value (optional)
  524. if(lpDesc->lpszCommandLineA)
  525. {
  526. lReturn = OS_RegSetValueEx(hkeyApp, SZ_COMMANDLINE, 0, REG_SZ,
  527. lpDesc->lpszCommandLineA, lstrlenA(lpDesc->lpszCommandLineA));
  528. if(lReturn != ERROR_SUCCESS)
  529. {
  530. DPF_ERRVAL("Unable to register CommandLine string, lReturn = %lu", lReturn);
  531. }
  532. }
  533. // Set the Path value
  534. ASSERT(lpDesc->lpszPathA);
  535. lReturn = OS_RegSetValueEx(hkeyApp, SZ_PATH, 0, REG_SZ,
  536. lpDesc->lpszPathA, lstrlenA(lpDesc->lpszPathA));
  537. if(lReturn != ERROR_SUCCESS)
  538. {
  539. DPF_ERRVAL("Unable to register Path string, lReturn = %lu", lReturn);
  540. hr = DPERR_GENERIC;
  541. goto ERROR_WRITEAPPINREGISTRYANSI;
  542. }
  543. // Set the CurrentDirectory value (optional)
  544. if(lpDesc->lpszCurrentDirectoryA)
  545. {
  546. lReturn = OS_RegSetValueEx(hkeyApp, SZ_CURRENTDIR, 0, REG_SZ,
  547. lpDesc->lpszCurrentDirectoryA, lstrlenA(lpDesc->lpszCurrentDirectoryA));
  548. if(lReturn != ERROR_SUCCESS)
  549. {
  550. DPF_ERRVAL("Unable to register CurrentDirectory string, lReturn = %lu", lReturn);
  551. }
  552. }
  553. // Set the DescriptionA value (optional)
  554. if(lpDesc->lpszDescriptionA)
  555. {
  556. lReturn = OS_RegSetValueEx(hkeyApp, SZ_DESCRIPTIONA, 0, REG_SZ,
  557. lpDesc->lpszDescriptionA, lstrlenA(lpDesc->lpszDescriptionA));
  558. if(lReturn != ERROR_SUCCESS)
  559. {
  560. DPF_ERRVAL("Unable to register DescriptionA string, lReturn = %lu", lReturn);
  561. }
  562. }
  563. // Set the DescriptionW value (optional)
  564. if(lpDesc->lpszDescriptionW)
  565. {
  566. lReturn = OS_RegSetValueEx(hkeyApp, SZ_DESCRIPTIONW, 0, REG_BINARY,
  567. (BYTE *)lpDesc->lpszDescriptionW,
  568. WSTRLEN_BYTES(lpDesc->lpszDescriptionW));
  569. if(lReturn != ERROR_SUCCESS)
  570. {
  571. DPF_ERRVAL("Unable to register DescriptionW string, lReturn = %lu", lReturn);
  572. }
  573. }
  574. if(IS_DPLOBBY_APPLICATIONDESC2(lpDesc) && lpDesc2->lpszAppLauncherNameA){
  575. lReturn = OS_RegSetValueEx(hkeyApp, SZ_LAUNCHER, 0, REG_SZ,
  576. lpDesc2->lpszAppLauncherNameA, lstrlenA(lpDesc2->lpszAppLauncherNameA));
  577. if(lReturn != ERROR_SUCCESS)
  578. {
  579. DPF_ERRVAL("Unable to register LauncherA string, lReturn = %lu", lReturn);
  580. }
  581. }
  582. // set the dwFlags field
  583. lReturn=OS_RegSetValueEx(hkeyApp, SZ_DWFLAGS, 0, REG_DWORD, (CHAR *)&lpDesc->dwFlags,sizeof(DWORD));
  584. if(lReturn != ERROR_SUCCESS)
  585. {
  586. DPF_ERRVAL("Unable to write dwFlags field to registry, lReturn= %lu", lReturn);
  587. }
  588. // Close the two keys
  589. RegCloseKey(hkeyDPApps);
  590. RegCloseKey(hkeyApp);
  591. return DP_OK;
  592. ERROR_WRITEAPPINREGISTRYANSI:
  593. if(hkeyApp)
  594. {
  595. // Delete the key
  596. // REVIEW!!!! -- TODO
  597. // Now close the key
  598. RegCloseKey(hkeyApp);
  599. }
  600. if(hkeyDPApps)
  601. RegCloseKey(hkeyDPApps);
  602. return hr;
  603. } // PRV_WriteAppDescInRegistryAnsi
  604. #undef DPF_MODNAME
  605. #define DPF_MODNAME "PRV_WriteAppDescInRegistryUnicode"
  606. HRESULT PRV_WriteAppDescInRegistryUnicode(LPDPAPPLICATIONDESC lpDesc)
  607. {
  608. HKEY hkeyDPApps = NULL, hkeyApp = NULL;
  609. LONG lReturn;
  610. DWORD dwDisposition;
  611. WCHAR wszGuid[GUID_STRING_SIZE];
  612. HRESULT hr;
  613. LPWSTR lpwszAppName = NULL;
  614. LPDPAPPLICATIONDESC2 lpDesc2=(LPDPAPPLICATIONDESC2)lpDesc;
  615. DWORD dwRegFlags;
  616. DWORD dwRegFlagsSize;
  617. DWORD dwType;
  618. DPF(7, "Entering PRV_WriteAppDescInRegistryUnicode");
  619. DPF(9, "Parameters: 0x%08x", lpDesc);
  620. // Open the registry key for the App, if it exists, so we can
  621. // check for the autovoice flag
  622. DPF(5, "Checking to see if game already present in registry");
  623. lpwszAppName = DPMEM_ALLOC(DPLOBBY_REGISTRY_NAMELEN*sizeof(WCHAR));
  624. if (lpwszAppName == NULL)
  625. {
  626. DPF_ERR("Unable to allocate memory");
  627. hr = DPERR_NOMEMORY;
  628. goto ERROR_WRITEAPPINREGISTRYUNICODE;
  629. }
  630. if(PRV_FindGameInRegistry(&(lpDesc->guidApplication), lpwszAppName,
  631. DPLOBBY_REGISTRY_NAMELEN, &hkeyApp))
  632. {
  633. // Get the application flags
  634. DPF(5, "Game already registered");
  635. dwRegFlags = 0;
  636. dwRegFlagsSize = sizeof(dwRegFlags);
  637. dwType = 0;
  638. lReturn = OS_RegQueryValueEx(hkeyApp, SZ_DWFLAGS, NULL, &dwType, (CHAR *)&dwRegFlags, &dwRegFlagsSize);
  639. if(lReturn == ERROR_SUCCESS)
  640. {
  641. // This application is already registered. We want to maintain the state
  642. // of the autovoice flag despite this re-registration, so set the appropriate
  643. // bit of lpDesc->dwFlags to the correct value.
  644. DPF(5, "Current Game flags: 0x%08x", dwRegFlags);
  645. if (dwRegFlags & DPLAPP_AUTOVOICE)
  646. {
  647. DPF(5, "Forcing DPLAPP_AUTOVOICE flag ON", dwRegFlags);
  648. lpDesc->dwFlags |= DPLAPP_AUTOVOICE;
  649. }
  650. else
  651. {
  652. DPF(5, "Forcing DPLAPP_AUTOVOICE flag OFF", dwRegFlags);
  653. lpDesc->dwFlags &= (~DPLAPP_AUTOVOICE);
  654. }
  655. }
  656. // Close the app key
  657. RegCloseKey(hkeyApp);
  658. }
  659. DPMEM_FREE(lpwszAppName);
  660. lpwszAppName = NULL;
  661. // Delete the application key if it exists
  662. hr = PRV_DeleteAppKeyFromRegistry(&lpDesc->guidApplication);
  663. // Open the Applications key (or create it if it doesn't exist
  664. lReturn = RegCreateKeyEx(HKEY_LOCAL_MACHINE, SZ_DPLAY_APPS_KEY, 0, NULL,
  665. REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkeyDPApps,
  666. &dwDisposition);
  667. if(lReturn != ERROR_SUCCESS)
  668. {
  669. DPF_ERRVAL("Unable to open DPlay Applications registry key!, lReturn = %lu", lReturn);
  670. hr = DPERR_GENERIC;
  671. goto ERROR_WRITEAPPINREGISTRYUNICODE;
  672. }
  673. // Create the app's key
  674. lReturn = RegCreateKeyEx(hkeyDPApps, lpDesc->lpszApplicationName,
  675. 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL,
  676. &hkeyApp, &dwDisposition);
  677. if(lReturn != ERROR_SUCCESS)
  678. {
  679. DPF_ERRVAL("Unable to create application registry key, lReturn = %lu", lReturn);
  680. hr = DPERR_GENERIC;
  681. goto ERROR_WRITEAPPINREGISTRYUNICODE;
  682. }
  683. // Set the guid value
  684. hr = StringFromGUID(&lpDesc->guidApplication, wszGuid, (sizeof(wszGuid)/sizeof(WCHAR)));
  685. if(FAILED(hr))
  686. {
  687. DPF_ERRVAL("Unable to convert application guid to string, hr = 0x%08x", hr);
  688. goto ERROR_WRITEAPPINREGISTRYUNICODE;
  689. }
  690. lReturn = RegSetValueEx(hkeyApp, SZ_GUID, 0, REG_SZ, (BYTE *)wszGuid,
  691. WSTRLEN_BYTES(wszGuid));
  692. if(lReturn != ERROR_SUCCESS)
  693. {
  694. DPF_ERRVAL("Unable to register Application guid, lReturn = %lu", lReturn);
  695. hr = DPERR_GENERIC;
  696. goto ERROR_WRITEAPPINREGISTRYUNICODE;
  697. }
  698. // Set the Filename value
  699. ASSERT(lpDesc->lpszFilename);
  700. lReturn = RegSetValueEx(hkeyApp, SZ_FILE, 0, REG_SZ,
  701. (LPBYTE)lpDesc->lpszFilename, WSTRLEN_BYTES(lpDesc->lpszFilename));
  702. if(lReturn != ERROR_SUCCESS)
  703. {
  704. DPF_ERRVAL("Unable to register Filename string, lReturn = %lu", lReturn);
  705. hr = DPERR_GENERIC;
  706. goto ERROR_WRITEAPPINREGISTRYUNICODE;
  707. }
  708. // Set the CommandLine value (optional)
  709. if(lpDesc->lpszCommandLine)
  710. {
  711. lReturn = RegSetValueEx(hkeyApp, SZ_COMMANDLINE, 0, REG_SZ,
  712. (LPBYTE)lpDesc->lpszCommandLine,
  713. WSTRLEN_BYTES(lpDesc->lpszCommandLine));
  714. if(lReturn != ERROR_SUCCESS)
  715. {
  716. DPF_ERRVAL("Unable to register CommandLine string, lReturn = %lu", lReturn);
  717. }
  718. }
  719. // Set the Path value
  720. ASSERT(lpDesc->lpszPath);
  721. lReturn = RegSetValueEx(hkeyApp, SZ_PATH, 0, REG_SZ,
  722. (LPBYTE)lpDesc->lpszPath, WSTRLEN_BYTES(lpDesc->lpszPath));
  723. if(lReturn != ERROR_SUCCESS)
  724. {
  725. DPF_ERRVAL("Unable to register Path string, lReturn = %lu", lReturn);
  726. hr = DPERR_GENERIC;
  727. goto ERROR_WRITEAPPINREGISTRYUNICODE;
  728. }
  729. // Set the CurrentDirectory value (optional)
  730. if(lpDesc->lpszCurrentDirectory)
  731. {
  732. lReturn = RegSetValueEx(hkeyApp, SZ_CURRENTDIR, 0, REG_SZ,
  733. (LPBYTE)lpDesc->lpszCurrentDirectory,
  734. WSTRLEN_BYTES(lpDesc->lpszCurrentDirectory));
  735. if(lReturn != ERROR_SUCCESS)
  736. {
  737. DPF_ERRVAL("Unable to register CurrentDirectory string, lReturn = %lu", lReturn);
  738. }
  739. }
  740. // Set the DescriptionA value (optional)
  741. if(lpDesc->lpszDescriptionA)
  742. {
  743. lReturn = RegSetValueExA(hkeyApp, "DescriptionA", 0, REG_SZ,
  744. lpDesc->lpszDescriptionA, lstrlenA(lpDesc->lpszDescriptionA));
  745. if(lReturn != ERROR_SUCCESS)
  746. {
  747. DPF_ERRVAL("Unable to register DescriptionA string, lReturn = %lu", lReturn);
  748. }
  749. }
  750. // Set the DescriptionW value (optional)
  751. if(lpDesc->lpszDescriptionW)
  752. {
  753. lReturn = RegSetValueEx(hkeyApp, SZ_DESCRIPTIONW, 0, REG_SZ,
  754. (LPBYTE)lpDesc->lpszDescriptionW,
  755. WSTRLEN_BYTES(lpDesc->lpszDescriptionW));
  756. if(lReturn != ERROR_SUCCESS)
  757. {
  758. DPF_ERRVAL("Unable to register DescriptionW string, lReturn = %lu", lReturn);
  759. }
  760. }
  761. // Set the LauncherName value (optional, DESC2 only)
  762. if(IS_DPLOBBY_APPLICATIONDESC2(lpDesc) && lpDesc2->lpszAppLauncherName){
  763. lReturn = RegSetValueEx(hkeyApp, SZ_LAUNCHER, 0, REG_SZ,
  764. (LPBYTE)lpDesc2->lpszAppLauncherName,
  765. WSTRLEN_BYTES(lpDesc2->lpszAppLauncherName));
  766. if(lReturn != ERROR_SUCCESS)
  767. {
  768. DPF_ERRVAL("Unable to register LauncherName string, lReturn = %lu", lReturn);
  769. }
  770. }
  771. // set the dwFlags field
  772. lReturn=RegSetValueEx(hkeyApp, SZ_DWFLAGS, 0, REG_DWORD, (CHAR *)&lpDesc->dwFlags,sizeof(DWORD));
  773. if(lReturn != ERROR_SUCCESS)
  774. {
  775. DPF_ERRVAL("Unable to write dwFlags field to registry, lReturn= %lu", lReturn);
  776. }
  777. // Close the two keys
  778. RegCloseKey(hkeyDPApps);
  779. RegCloseKey(hkeyApp);
  780. return DP_OK;
  781. ERROR_WRITEAPPINREGISTRYUNICODE:
  782. if(hkeyApp)
  783. {
  784. // Delete the key
  785. // REVIEW!!!! -- TODO
  786. // Now close the key
  787. RegCloseKey(hkeyApp);
  788. }
  789. if(hkeyDPApps)
  790. RegCloseKey(hkeyDPApps);
  791. return hr;
  792. } // PRV_WriteAppDescInRegistryUnicode
  793. #undef DPF_MODNAME
  794. #define DPF_MODNAME "DPL_RegisterApplication"
  795. HRESULT DPLAPI DPL_RegisterApplication(LPDIRECTPLAYLOBBY lpDPL,
  796. DWORD dwFlags, LPVOID lpvDesc)
  797. {
  798. LPDPLOBBYI_DPLOBJECT this;
  799. LPDPAPPLICATIONDESC lpDescA = NULL;
  800. HRESULT hr = DP_OK;
  801. LPDPAPPLICATIONDESC lpDesc=(LPDPAPPLICATIONDESC)lpvDesc;
  802. DPF(7, "Entering DPL_RegisterApplication");
  803. DPF(9, "Parameters: 0x%08x, 0x%08x, 0x%08x",
  804. lpDPL, dwFlags, lpDesc);
  805. ENTER_DPLOBBY();
  806. TRY
  807. {
  808. // We only need to validate the interface pointer here. Everything else
  809. // will get validated by the main function.
  810. if( !VALID_DPLOBBY_INTERFACE( lpDPL ))
  811. {
  812. LEAVE_DPLOBBY();
  813. return DPERR_INVALIDINTERFACE;
  814. }
  815. this = DPLOBJECT_FROM_INTERFACE(lpDPL);
  816. if( !VALID_DPLOBBY_PTR( this ) )
  817. {
  818. LEAVE_DPLOBBY();
  819. return DPERR_INVALIDOBJECT;
  820. }
  821. if(dwFlags)
  822. {
  823. LEAVE_DPLOBBY();
  824. return DPERR_INVALIDFLAGS;
  825. }
  826. // Validate the ApplicationDesc struct
  827. hr = PRV_ValidateDPAPPLICATIONDESC(lpDesc, FALSE);
  828. if(FAILED(hr))
  829. {
  830. LEAVE_DPLOBBY();
  831. DPF_ERR("Invalid DPAPPLICATIONDESC structure");
  832. return hr;
  833. }
  834. }
  835. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  836. {
  837. LEAVE_DPLOBBY();
  838. DPF_ERR( "Exception encountered validating parameters" );
  839. return DPERR_INVALIDPARAMS;
  840. }
  841. // If we're on a Unicode platform, just write the stuff in the registry.
  842. // If it's not, we need to convert the DPAPPLICATIONDESC struct to ANSI
  843. if(OS_IsPlatformUnicode())
  844. {
  845. // Just write to the registry
  846. hr = PRV_WriteAppDescInRegistryUnicode(lpDesc);
  847. }
  848. else
  849. {
  850. // Convert the APPDESC struct to ANSI
  851. hr = PRV_ConvertDPAPPLICATIONDESCToAnsi(lpDesc, &lpDescA);
  852. if(FAILED(hr))
  853. {
  854. DPF_ERRVAL("Unable to convert DPAPPLICATIONDESC to Ansi, hr = 0x%08x", hr);
  855. goto ERROR_REGISTERAPPLICATION;
  856. }
  857. // Write to the registry
  858. hr = PRV_WriteAppDescInRegistryAnsi(lpDescA);
  859. // Free our APPDESC structure
  860. PRV_FreeLocalDPAPPLICATIONDESC(lpDescA);
  861. }
  862. if(FAILED(hr))
  863. {
  864. DPF_ERRVAL("Failed writing ApplicationDesc to registry, hr = 0x%08x", hr);
  865. }
  866. ERROR_REGISTERAPPLICATION:
  867. LEAVE_DPLOBBY();
  868. return hr;
  869. } // DPL_RegisterApplication
  870. #undef DPF_MODNAME
  871. #define DPF_MODNAME "DPL_UnregisterApplication"
  872. HRESULT DPLAPI DPL_UnregisterApplication(LPDIRECTPLAYLOBBY lpDPL,
  873. DWORD dwFlags, REFGUID lpguid)
  874. {
  875. LPDPLOBBYI_DPLOBJECT this;
  876. HRESULT hr = DP_OK;
  877. DPF(7, "Entering DPL_UnregisterApplication");
  878. DPF(9, "Parameters: 0x%08x, 0x%08x, 0x%08x",
  879. lpDPL, dwFlags, lpguid);
  880. ENTER_DPLOBBY();
  881. TRY
  882. {
  883. // We only need to validate the interface pointer here. Everything else
  884. // will get validated by the main function.
  885. if( !VALID_DPLOBBY_INTERFACE( lpDPL ))
  886. {
  887. LEAVE_DPLOBBY();
  888. return DPERR_INVALIDINTERFACE;
  889. }
  890. this = DPLOBJECT_FROM_INTERFACE(lpDPL);
  891. if( !VALID_DPLOBBY_PTR( this ) )
  892. {
  893. LEAVE_DPLOBBY();
  894. return DPERR_INVALIDOBJECT;
  895. }
  896. if(dwFlags)
  897. {
  898. LEAVE_DPLOBBY();
  899. return DPERR_INVALIDFLAGS;
  900. }
  901. if(!VALID_READ_UUID_PTR(lpguid))
  902. {
  903. LEAVE_DPLOBBY();
  904. return DPERR_INVALIDPARAMS;
  905. }
  906. }
  907. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  908. {
  909. LEAVE_DPLOBBY();
  910. DPF_ERR( "Exception encountered validating parameters" );
  911. return DPERR_INVALIDPARAMS;
  912. }
  913. hr = PRV_DeleteAppKeyFromRegistry((LPGUID)lpguid);
  914. if(FAILED(hr))
  915. {
  916. DPF_ERRVAL("Unable to delete app key from registry, hr = 0x%08x", hr);
  917. }
  918. LEAVE_DPLOBBY();
  919. return hr;
  920. } // DPL_UnregisterApplication