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.

1071 lines
29 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1996-1997 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: dplenum.c
  6. * Content: Methods for enumeration
  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. * 12/10/96 myronth Fixed bugs #4622 and #5043
  14. * 2/12/97 myronth Mass DX5 changes
  15. * 3/4/97 myronth Fixed enum size bug #6149
  16. * 3/12/97 myronth Added EnumConnections
  17. * 3/25/97 kipo EnumConnections takes a const *GUID now
  18. * 4/7/97 myronth Fixed PRV_EnumConnections to use CreateCompoundAddress
  19. * 5/10/97 kipo added GUID to EnumConnections callback
  20. * 5/14/97 myronth Check for valid guid in EnumLocalApps, bug #7695
  21. * 5/17/97 myronth Fixed bug #8506 (return bogus error if last app
  22. * is invalid), fixed more GUIDFromString bugs
  23. * 8/22/97 myronth Added registry support for Description and Private
  24. * values, also cleaned up LP enumeration code
  25. * 11/20/97 myronth Made EnumConnections & DirectPlayEnumerate
  26. * drop the lock before calling the callback (#15208)
  27. * 12/2/97 myronth Changed EnumLocalApp to use Desc fields (#15448)
  28. * 01/20/98 sohailm Don't free sp list after EnumConnections (#17006)
  29. * 10/22/99 aarono Add support to hide apps from enum calls
  30. ***************************************************************************/
  31. #include "dplobpr.h"
  32. //--------------------------------------------------------------------------
  33. //
  34. // Definitions
  35. //
  36. //--------------------------------------------------------------------------
  37. //--------------------------------------------------------------------------
  38. //
  39. // Globals
  40. //
  41. //--------------------------------------------------------------------------
  42. LPLSPNODE glpLSPHead = NULL;
  43. //--------------------------------------------------------------------------
  44. //
  45. // Functions
  46. //
  47. //--------------------------------------------------------------------------
  48. #undef DPF_MODNAME
  49. #define DPF_MODNAME "PRV_CallEnumAddressTypesCallback"
  50. HRESULT PRV_CallEnumAddressTypesCallback(HKEY hkeySP,
  51. LPDPLENUMADDRESSTYPESCALLBACK lpfnEnumCallback,
  52. LPVOID lpContext)
  53. {
  54. HRESULT hr;
  55. WCHAR wszGuidStr[GUID_STRING_SIZE];
  56. DWORD dwGuidStrSize = sizeof(wszGuidStr)/sizeof(WCHAR);
  57. GUID guidAddressType;
  58. HKEY hkeyAddressTypes;
  59. DWORD dwIndex = 0;
  60. LONG lReturn;
  61. BOOL bReturn = TRUE;
  62. DPF(7, "Entering PRV_CallEnumAddressTypesCallback");
  63. DPF(9, "Parameters: 0x%08x, 0x%08x, 0x%08x",
  64. hkeySP, lpfnEnumCallback, lpContext);
  65. ASSERT(hkeySP);
  66. // Get the Address Type registry key
  67. lReturn = OS_RegOpenKeyEx(hkeySP, SZ_ADDRESS_TYPES, 0,
  68. KEY_READ, &hkeyAddressTypes);
  69. if(lReturn != ERROR_SUCCESS)
  70. {
  71. DPF_ERR("No Address Types found for the Service Provider!");
  72. return DP_OK;
  73. }
  74. // Walk the list of Address Types in the registry, looking for the GUID passed in
  75. while((ERROR_NO_MORE_ITEMS != OS_RegEnumKeyEx(hkeyAddressTypes, dwIndex++,
  76. (LPWSTR)wszGuidStr, &dwGuidStrSize, NULL, NULL, NULL, NULL)) && bReturn)
  77. {
  78. // Convert the string to a real GUID
  79. hr = GUIDFromString(wszGuidStr, &guidAddressType);
  80. if(FAILED(hr))
  81. {
  82. DPF_ERR("Couldn't convert Address Type string to GUID");
  83. dwGuidStrSize = sizeof(wszGuidStr)/sizeof(WCHAR);
  84. continue;
  85. }
  86. // Call the callback
  87. bReturn = ((LPDPLENUMADDRESSTYPESCALLBACK)lpfnEnumCallback)
  88. (&guidAddressType, lpContext, 0L);
  89. // Reset the size variable in the success case
  90. dwGuidStrSize = sizeof(wszGuidStr)/sizeof(WCHAR);
  91. }
  92. // Close the Address Types key
  93. RegCloseKey(hkeyAddressTypes);
  94. return DP_OK;
  95. } // PRV_CallEnumAddressTypesCallback
  96. #undef DPF_MODNAME
  97. #define DPF_MODNAME "PRV_EnumAddressTypes"
  98. HRESULT PRV_EnumAddressTypes(LPDIRECTPLAYLOBBY lpDPL,
  99. LPDPLENUMADDRESSTYPESCALLBACK lpfnEnumCallback,
  100. REFGUID guidSPIn, LPVOID lpContext, DWORD dwFlags)
  101. {
  102. LPDPLOBBYI_DPLOBJECT this;
  103. HRESULT hr = DP_OK;
  104. HKEY hkeySPHead, hkeySP;
  105. DWORD dwIndex = 0;
  106. DWORD dwNameSize;
  107. WCHAR wszSPName[DPLOBBY_REGISTRY_NAMELEN];
  108. WCHAR wszGuidStr[GUID_STRING_SIZE];
  109. DWORD dwGuidStrSize = sizeof(wszGuidStr)/sizeof(WCHAR);
  110. DWORD dwType = REG_SZ;
  111. GUID guidSP;
  112. LONG lReturn;
  113. BOOL bFound = FALSE;
  114. DPF(7, "Entering PRV_EnumAddressTypes");
  115. DPF(9, "Parameters: 0x%08x, 0x%08x, guid, 0x%08x, 0x%08x",
  116. lpDPL, lpfnEnumCallback, lpContext, dwFlags);
  117. TRY
  118. {
  119. if( !VALID_DPLOBBY_INTERFACE( lpDPL ))
  120. {
  121. return DPERR_INVALIDINTERFACE;
  122. }
  123. this = DPLOBJECT_FROM_INTERFACE(lpDPL);
  124. if( !VALID_DPLOBBY_PTR( this ) )
  125. {
  126. return DPERR_INVALIDOBJECT;
  127. }
  128. if( !VALIDEX_CODE_PTR( lpfnEnumCallback ) )
  129. {
  130. return DPERR_INVALIDPARAMS;
  131. }
  132. if (!VALID_READ_PTR(guidSPIn, sizeof(GUID)))
  133. {
  134. DPF_ERR("Invalid SP GUID pointer");
  135. return DPERR_INVALIDPARAMS;
  136. }
  137. // There are no flags defined for DX3
  138. if( dwFlags )
  139. {
  140. return DPERR_INVALIDPARAMS;
  141. }
  142. }
  143. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  144. {
  145. DPF_ERR( "Exception encountered validating parameters" );
  146. return DPERR_INVALIDPARAMS;
  147. }
  148. // Open the Service Providers key
  149. lReturn = OS_RegOpenKeyEx(HKEY_LOCAL_MACHINE, SZ_DPLAY_SP_KEY, 0,
  150. KEY_READ, &hkeySPHead);
  151. if(lReturn != ERROR_SUCCESS)
  152. {
  153. // This just means that the Service Providers key doesn't exist (most
  154. // likely), so in that case, there are no SP's to enumerate.
  155. DPF_ERR("There are no Service Providers registered");
  156. return DP_OK;
  157. }
  158. // Walk the list of SP's in the registry, looking for the GUID passed in
  159. while(!bFound)
  160. {
  161. // Get the next SP in the list
  162. dwNameSize = DPLOBBY_REGISTRY_NAMELEN;
  163. lReturn = OS_RegEnumKeyEx(hkeySPHead, dwIndex++, (LPWSTR)wszSPName,
  164. &dwNameSize, NULL, NULL, NULL, NULL);
  165. // If lReturn is ERROR_NO_MORE_ITEMS, we want to end on this iteration
  166. if(lReturn == ERROR_NO_MORE_ITEMS)
  167. break;;
  168. // Open the SP key
  169. lReturn = OS_RegOpenKeyEx(hkeySPHead, (LPWSTR)wszSPName, 0,
  170. KEY_READ, &hkeySP);
  171. if(lReturn != ERROR_SUCCESS)
  172. {
  173. DPF_ERR("Unable to open key for Service Provider!");
  174. continue;
  175. }
  176. // Get the GUID of the SP
  177. dwGuidStrSize = GUID_STRING_SIZE;
  178. lReturn = OS_RegQueryValueEx(hkeySP, SZ_GUID, NULL, &dwType,
  179. (LPBYTE)wszGuidStr, &dwGuidStrSize);
  180. if(lReturn != ERROR_SUCCESS)
  181. {
  182. RegCloseKey(hkeySP);
  183. DPF_ERR("Unable to query GUID key value!");
  184. continue;
  185. }
  186. // Convert the string to a real GUID
  187. hr = GUIDFromString(wszGuidStr, &guidSP);
  188. if(FAILED(hr))
  189. {
  190. DPF_ERRVAL("Invalid SP guid -- skipping SP, hr = 0x%08x", hr);
  191. RegCloseKey(hkeySP);
  192. // Set the hresult back to DP_OK in case this is the last
  193. // SP in the registry -- we want the method call
  194. // to succeed if we got this far, we just don't want to
  195. // call the callback for this particular SP
  196. hr = DP_OK;
  197. continue;
  198. }
  199. // If we match the GUID passed in, then enumerate them
  200. if(IsEqualGUID(guidSPIn, &guidSP))
  201. {
  202. // Enumerate the Address Types for this SP
  203. hr = PRV_CallEnumAddressTypesCallback(hkeySP,
  204. lpfnEnumCallback, lpContext);
  205. bFound = TRUE;
  206. }
  207. // Close the SP key
  208. RegCloseKey(hkeySP);
  209. }
  210. // Close the DPlay Apps key
  211. RegCloseKey(hkeySPHead);
  212. // If we didn't find the SP, return an error
  213. // REVIEW!!!! -- Is this really the error we want here????
  214. if(!bFound)
  215. return DPERR_UNAVAILABLE;
  216. return hr;
  217. } // PRV_EnumAddressTypes
  218. #undef DPF_MODNAME
  219. #define DPF_MODNAME "DPL_EnumAddressTypes"
  220. HRESULT DPLAPI DPL_EnumAddressTypes(LPDIRECTPLAYLOBBY lpDPL,
  221. LPDPLENUMADDRESSTYPESCALLBACK lpfnEnumCallback,
  222. REFGUID guidSP, LPVOID lpContext, DWORD dwFlags)
  223. {
  224. HRESULT hr;
  225. DPF(7, "Entering DPL_EnumAddressTypes");
  226. DPF(9, "Parameters: 0x%08x, 0x%08x, guid, 0x%08x, 0x%08x",
  227. lpDPL, lpfnEnumCallback, lpContext, dwFlags);
  228. ENTER_DPLOBBY();
  229. // Set the ANSI flag to TRUE and call the internal function
  230. hr = PRV_EnumAddressTypes(lpDPL, lpfnEnumCallback, guidSP, lpContext, dwFlags);
  231. LEAVE_DPLOBBY();
  232. return hr;
  233. } // DPL_EnumAddressTypes
  234. #undef DPF_MODNAME
  235. #define DPF_MODNAME "PRV_FreeLSPNode"
  236. void PRV_FreeLSPNode(LPLSPNODE lpNode)
  237. {
  238. DPF(7, "Entering PRV_FreeLSPNode");
  239. if(!lpNode)
  240. return;
  241. if(lpNode->lpwszName)
  242. DPMEM_FREE(lpNode->lpwszName);
  243. if(lpNode->lpwszPath)
  244. DPMEM_FREE(lpNode->lpwszPath);
  245. if(lpNode->lpszDescA)
  246. DPMEM_FREE(lpNode->lpszDescA);
  247. if(lpNode->lpwszDesc)
  248. DPMEM_FREE(lpNode->lpwszDesc);
  249. DPMEM_FREE(lpNode);
  250. } // PRV_FreeLSPNode
  251. #undef DPF_MODNAME
  252. #define DPF_MODNAME "PRV_FreeLSPList"
  253. void PRV_FreeLSPList(LPLSPNODE lpLSPHead)
  254. {
  255. LPLSPNODE lpTemp;
  256. DPF(7, "Entering PRV_FreeLSPList");
  257. DPF(9, "Parameters: 0x%08x", lpLSPHead);
  258. // Walk the list and free each node
  259. while(lpLSPHead)
  260. {
  261. // Save the next one
  262. lpTemp = lpLSPHead->lpNext;
  263. // Free all of the members
  264. PRV_FreeLSPNode(lpLSPHead);
  265. // Move to the next one
  266. lpLSPHead = lpTemp;
  267. }
  268. } // PRV_FreeLSPList
  269. #undef DPF_MODNAME
  270. #define DPF_MODNAME "PRV_AddLSPNode"
  271. HRESULT PRV_AddLSPNode(LPWSTR lpwszName, LPWSTR lpwszPath, LPWSTR lpwszDesc,
  272. LPSTR lpszDescA, LPWSTR lpwszGuid, DWORD dwReserved1,
  273. DWORD dwReserved2, DWORD dwNodeFlags)
  274. {
  275. LPLSPNODE lpLSPNode = NULL;
  276. DWORD dwDescASize;
  277. HRESULT hr;
  278. DPF(7, "Entering PRV_AddLSPNode");
  279. DPF(9, "Parameters: 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, %lu, %lu, 0x%08x",
  280. lpwszName, lpwszPath, lpwszDesc, lpszDescA, lpwszGuid, dwReserved1,
  281. dwReserved2, dwNodeFlags);
  282. // Allocate memory for the node
  283. lpLSPNode = DPMEM_ALLOC(sizeof(LSPNODE));
  284. if(!lpLSPNode)
  285. {
  286. DPF_ERR("Failed to allocate memory for Lobby Provider node, skipping LP");
  287. return DPERR_OUTOFMEMORY;
  288. }
  289. // Allocate memory for the Name string and copy it
  290. hr = GetString(&lpLSPNode->lpwszName, lpwszName);
  291. if(FAILED(hr))
  292. {
  293. DPF_ERR("Unable to allocate memory for Lobby Provider Name string, skipping provider");
  294. hr = DPERR_OUTOFMEMORY;
  295. goto ERROR_ADDLSPNODE;
  296. }
  297. // Allocate memory for the Path string and copy it
  298. hr = GetString(&lpLSPNode->lpwszPath, lpwszPath);
  299. if(FAILED(hr))
  300. {
  301. DPF_ERR("Unable to allocate memory for Lobby Provider Path string, skipping provider");
  302. hr = DPERR_OUTOFMEMORY;
  303. goto ERROR_ADDLSPNODE;
  304. }
  305. if(dwNodeFlags & LSPNODE_DESCRIPTION)
  306. {
  307. // Allocate memory for the DescriptionA string and copy it
  308. dwDescASize = lstrlenA(lpszDescA)+1;
  309. lpLSPNode->lpszDescA = DPMEM_ALLOC(dwDescASize);
  310. if(!lpLSPNode->lpszDescA)
  311. {
  312. DPF_ERR("Unable to allocate memory for Lobby Provider Path string, skipping provider");
  313. hr = DPERR_OUTOFMEMORY;
  314. goto ERROR_ADDLSPNODE;
  315. }
  316. memcpy(lpLSPNode->lpszDescA, lpszDescA, dwDescASize);
  317. // Allocate memory for the DescriptionW string and copy it
  318. hr = GetString(&lpLSPNode->lpwszDesc, lpwszDesc);
  319. if(FAILED(hr))
  320. {
  321. DPF_ERR("Unable to allocate memory for Lobby Provider DescriptionW string, skipping provider");
  322. hr = DPERR_OUTOFMEMORY;
  323. goto ERROR_ADDLSPNODE;
  324. }
  325. }
  326. // Convert the string to a real GUID
  327. hr = GUIDFromString(lpwszGuid, &lpLSPNode->guid);
  328. if(FAILED(hr))
  329. {
  330. DPF_ERRVAL("Invalid LP guid -- skipping LP, hr = 0x%08x", hr);
  331. goto ERROR_ADDLSPNODE;
  332. }
  333. // Finish setting up the node
  334. lpLSPNode->dwReserved1 = dwReserved1;
  335. lpLSPNode->dwReserved2 = dwReserved2;
  336. lpLSPNode->dwNodeFlags = dwNodeFlags;
  337. // Add the node to the list
  338. lpLSPNode->lpNext = glpLSPHead;
  339. glpLSPHead = lpLSPNode;
  340. return DP_OK;
  341. ERROR_ADDLSPNODE:
  342. if(lpLSPNode->lpwszName)
  343. DPMEM_FREE(lpLSPNode->lpwszName);
  344. if(lpLSPNode->lpwszPath)
  345. DPMEM_FREE(lpLSPNode->lpwszPath);
  346. if(lpLSPNode->lpwszDesc)
  347. DPMEM_FREE(lpLSPNode->lpwszDesc);
  348. if(lpLSPNode->lpszDescA)
  349. DPMEM_FREE(lpLSPNode->lpszDescA);
  350. DPMEM_FREE(lpLSPNode);
  351. return hr;
  352. } // PRV_AddLSPNode
  353. #undef DPF_MODNAME
  354. #define DPF_MODNAME "PRV_BuildLSPList"
  355. HRESULT PRV_BuildLSPList()
  356. {
  357. HKEY hkeyLobbySP, hkeySP;
  358. WCHAR szSPName[DPLOBBY_REGISTRY_NAMELEN];
  359. WCHAR szSPPath[DPLOBBY_REGISTRY_NAMELEN];
  360. WCHAR szSPDescW[DPLOBBY_REGISTRY_NAMELEN];
  361. CHAR szSPDescA[DPLOBBY_REGISTRY_NAMELEN];
  362. WCHAR wszGuidStr[GUID_STRING_SIZE];
  363. DWORD dwSize;
  364. DWORD dwGuidStrSize = GUID_STRING_SIZE;
  365. DWORD dwType = REG_SZ;
  366. DWORD dwIndex = 0;
  367. DWORD dwReserved1, dwReserved2, dwReservedSize;
  368. LONG lReturn;
  369. DWORD dwError;
  370. HRESULT hr;
  371. DWORD dwNodeFlags = 0;
  372. DPF(7, "Entering PRV_BuildLSPList");
  373. if(glpLSPHead)
  374. {
  375. return DP_OK;
  376. }
  377. // Open the DPLobby SP key
  378. lReturn = OS_RegOpenKeyEx(HKEY_LOCAL_MACHINE, SZ_DPLOBBY_SP_KEY, 0,
  379. KEY_READ, &hkeyLobbySP);
  380. if(lReturn != ERROR_SUCCESS)
  381. {
  382. // This just means that the DPLobby SP key doesn't exist (most
  383. // likely), so in that case, there are no Lobby SP's to enumerate.
  384. return DP_OK;
  385. }
  386. // Walk the list of Lobby SP's in the registry, enumerating them
  387. while(1)
  388. {
  389. // Get the next LSP Name
  390. dwSize = sizeof(szSPName)/sizeof(TCHAR);
  391. lReturn = OS_RegEnumKeyEx(hkeyLobbySP, dwIndex++, szSPName,
  392. &dwSize, NULL, NULL, NULL, NULL);
  393. if(lReturn == ERROR_NO_MORE_ITEMS)
  394. break;
  395. else if(lReturn != ERROR_SUCCESS)
  396. {
  397. dwError = GetLastError();
  398. DPF_ERRVAL("Unable to get Lobby Provider name from the registry -- dwError = %u -- skipping provider", dwError);
  399. continue;
  400. }
  401. // Open the subkey
  402. lReturn = OS_RegOpenKeyEx(hkeyLobbySP, szSPName, 0, KEY_READ, &hkeySP);
  403. if(lReturn != ERROR_SUCCESS)
  404. {
  405. dwError = GetLastError();
  406. DPF_ERRVAL("Unable to open Lobby Provider key in the registry -- dwError = %u -- skipping provider", dwError);
  407. continue;
  408. }
  409. // First see if the "Private" key exists. If it does, then set the flag
  410. // so that it will get skipped during enumeration
  411. lReturn = OS_RegQueryValueEx(hkeySP, SZ_PRIVATE, NULL, &dwType, NULL, &dwSize);
  412. if (ERROR_SUCCESS == lReturn)
  413. {
  414. // The key exists, so set the flag so we don't enumerate it
  415. dwNodeFlags |= LSPNODE_PRIVATE;
  416. }
  417. // Get the LSP Path
  418. dwSize = sizeof(szSPPath);
  419. lReturn = OS_RegQueryValueEx(hkeySP, SZ_PATH, NULL, &dwType,
  420. (LPBYTE)szSPPath, &dwSize);
  421. if(lReturn != ERROR_SUCCESS)
  422. {
  423. dwError = GetLastError();
  424. DPF_ERRVAL("Unable to get Lobby Provider path from the registry -- dwError = %u -- skipping provider", dwError);
  425. RegCloseKey(hkeySP);
  426. continue;
  427. }
  428. // Get the LSP Descriptions
  429. // If the DescriptionA value doesn't exist, then don't worry about
  430. // getting the DescriptionW value. If the DescriptionA value exits,
  431. // but the DescriptionW value does not, convert the DescriptionA
  432. // value to Unicode and store it in DescriptionW.
  433. // NOTE: We always assume the DescriptionA value is an ANSI string,
  434. // even if it's stored in a Unicode format on NT & Memphis. So we
  435. // always retrieve this as an ANSI string
  436. dwSize = sizeof(szSPDescA);
  437. lReturn = RegQueryValueExA(hkeySP, "DescriptionA", NULL, &dwType,
  438. (LPBYTE)szSPDescA, &dwSize);
  439. if(lReturn == ERROR_SUCCESS)
  440. {
  441. // Save the description flag
  442. dwNodeFlags |= LSPNODE_DESCRIPTION;
  443. // Get the DescriptionW value
  444. dwSize = sizeof(szSPDescW);
  445. lReturn = OS_RegQueryValueEx(hkeySP, SZ_DESCRIPTIONW, NULL, &dwType,
  446. (LPBYTE)szSPDescW, &dwSize);
  447. if(lReturn != ERROR_SUCCESS)
  448. {
  449. // Convert the ANSI Description string to Unicode and store it
  450. AnsiToWide(szSPDescW, szSPDescA, (lstrlenA(szSPDescA)+1));
  451. }
  452. }
  453. // Get the GUID of the LSP
  454. dwGuidStrSize = GUID_STRING_SIZE;
  455. lReturn = OS_RegQueryValueEx(hkeySP, SZ_GUID, NULL, &dwType,
  456. (LPBYTE)wszGuidStr, &dwGuidStrSize);
  457. if(lReturn != ERROR_SUCCESS)
  458. {
  459. RegCloseKey(hkeySP);
  460. DPF_ERR("Unable to query GUID key value for Lobby Provider!");
  461. continue;
  462. }
  463. // Get the Reserved1 dword (we don't care if it fails)
  464. dwType = REG_DWORD;
  465. dwReservedSize = sizeof(DWORD);
  466. dwReserved1 = 0;
  467. OS_RegQueryValueEx(hkeySP, SZ_DWRESERVED1, NULL, &dwType,
  468. (LPBYTE)&dwReserved1, &dwReservedSize);
  469. // Get the Reserved1 dword (we don't care if it fails)
  470. dwReservedSize = sizeof(DWORD);
  471. dwReserved2 = 0;
  472. OS_RegQueryValueEx(hkeySP, SZ_DWRESERVED1, NULL, &dwType,
  473. (LPBYTE)&dwReserved2, &dwReservedSize);
  474. // Add the node to the list
  475. hr = PRV_AddLSPNode(szSPName, szSPPath, szSPDescW, szSPDescA,
  476. wszGuidStr, dwReserved1, dwReserved2, dwNodeFlags);
  477. if(FAILED(hr))
  478. {
  479. DPF_ERRVAL("Failed adding Lobby Provider to internal list, hr = 0x%08x", hr);
  480. }
  481. // Close the SP key
  482. RegCloseKey(hkeySP);
  483. }
  484. // Close the Lobby SP key
  485. RegCloseKey(hkeyLobbySP);
  486. return DP_OK;
  487. } // PRV_BuildLSPList
  488. #undef DPF_MODNAME
  489. #define DPF_MODNAME "PRV_EnumConnections"
  490. HRESULT PRV_EnumConnections(LPCGUID lpGuid, LPDPENUMCONNECTIONSCALLBACK lpCallback,
  491. LPVOID lpContext, DWORD dwFlags, BOOL bAnsi)
  492. {
  493. LPLSPNODE lpLSPNode, lpLSPHead;
  494. BOOL bContinue = TRUE;
  495. DPNAME name;
  496. HRESULT hr = DP_OK;
  497. DPCOMPOUNDADDRESSELEMENT AddrOnly;
  498. LPDPADDRESS lpAddress = NULL;
  499. DWORD dwAddressSize;
  500. DWORD dwAddressSizeSave;
  501. LPWSTR lpwszName = NULL;
  502. DPF(7, "Entering PRV_EnumConnections");
  503. DPF(9, "Parameters: ");
  504. // Rebuild the LSP List
  505. PRV_BuildLSPList();
  506. // If we don't have any entries, just bail here
  507. if(!glpLSPHead)
  508. return DP_OK;
  509. // Get a pointer to the first lobby provider, and store our head pointer
  510. lpLSPHead = glpLSPHead;
  511. lpLSPNode = glpLSPHead;
  512. // Setup the unfinished address
  513. memset(&AddrOnly, 0, sizeof(DPCOMPOUNDADDRESSELEMENT));
  514. AddrOnly.guidDataType = DPAID_LobbyProvider;
  515. AddrOnly.dwDataSize = sizeof(GUID);
  516. AddrOnly.lpData = &lpLSPNode->guid;
  517. // Calculate the size of the finished address
  518. hr = InternalCreateCompoundAddress(&AddrOnly, 1, NULL, &dwAddressSize);
  519. if(hr != DPERR_BUFFERTOOSMALL)
  520. {
  521. DPF_ERRVAL("Failed to retrieve the size of the output address buffer, hr = 0x%08x", hr);
  522. return hr;
  523. }
  524. // Allocate the buffer for the finished address
  525. lpAddress = DPMEM_ALLOC(dwAddressSize);
  526. if(!lpAddress)
  527. {
  528. DPF_ERR("Unable to allocate memory for temporary address structure");
  529. return DPERR_OUTOFMEMORY;
  530. }
  531. // Clear the DPNAME struct
  532. memset(&name,0,sizeof(name));
  533. name.dwSize = sizeof(name);
  534. // now, we have a list of SP's. walk the list, and call the app back
  535. // run through what we found...
  536. dwAddressSizeSave = dwAddressSize;
  537. // Drop the locks
  538. LEAVE_ALL();
  539. while ((lpLSPNode) && (bContinue))
  540. {
  541. // If the private flag is set, don't enumerate it
  542. if(!(lpLSPNode->dwNodeFlags & LSPNODE_PRIVATE))
  543. {
  544. // Create the real DPADDRESS
  545. dwAddressSize = dwAddressSizeSave;
  546. AddrOnly.lpData = &lpLSPNode->guid;
  547. hr = InternalCreateCompoundAddress(&AddrOnly, 1, lpAddress,
  548. &dwAddressSize);
  549. if(SUCCEEDED(hr))
  550. {
  551. // Call the callback
  552. // If the caller is ANSI, convert the string
  553. if (bAnsi)
  554. {
  555. // If we have a description string, use it, and we already
  556. // have an ANSI version to use
  557. if(lpLSPNode->dwNodeFlags & LSPNODE_DESCRIPTION)
  558. {
  559. name.lpszShortNameA = lpLSPNode->lpszDescA;
  560. // Call the app's callback
  561. bContinue= lpCallback(&lpLSPNode->guid, lpAddress, dwAddressSize, &name,
  562. DPCONNECTION_DIRECTPLAYLOBBY, lpContext);
  563. }
  564. else
  565. {
  566. hr = GetAnsiString(&(name.lpszShortNameA), lpLSPNode->lpwszName);
  567. if(SUCCEEDED(hr))
  568. {
  569. // Call the app's callback
  570. bContinue= lpCallback(&lpLSPNode->guid, lpAddress, dwAddressSize, &name,
  571. DPCONNECTION_DIRECTPLAYLOBBY, lpContext);
  572. // Free our short name buffer
  573. DPMEM_FREE(name.lpszShortNameA);
  574. }
  575. else
  576. {
  577. DPF_ERR("Unable to allocate memory for temporary name string, skipping Connection");
  578. }
  579. }
  580. }
  581. else
  582. {
  583. // If we have a description, use it
  584. if(lpLSPNode->dwNodeFlags & LSPNODE_DESCRIPTION)
  585. lpwszName = lpLSPNode->lpwszDesc;
  586. else
  587. lpwszName = lpLSPNode->lpwszName;
  588. name.lpszShortName = lpwszName;
  589. // Call the app's callback
  590. bContinue= lpCallback(&lpLSPNode->guid, lpAddress, dwAddressSize, &name,
  591. DPCONNECTION_DIRECTPLAYLOBBY, lpContext);
  592. }
  593. }
  594. else
  595. {
  596. DPF(2, "Failed to create DPADDRESS structure, skipping this Connection, hr = 0x%08x", hr);
  597. }
  598. }
  599. lpLSPNode = lpLSPNode->lpNext;
  600. } // while
  601. // Take the locks back
  602. ENTER_ALL();
  603. // Free our temporary address struct
  604. DPMEM_FREE(lpAddress);
  605. return DP_OK;
  606. } // PRV_EnumConnections
  607. #undef DPF_MODNAME
  608. #define DPF_MODNAME "PRV_CallEnumLocalAppCallback"
  609. HRESULT PRV_CallEnumLocalAppCallback(LPWSTR lpwszAppName, LPGUID lpguidApp,
  610. LPDPLENUMLOCALAPPLICATIONSCALLBACK lpfnEnumCallback,
  611. LPVOID lpContext, BOOL bAnsi, LPSTR lpszDescA,
  612. LPWSTR lpwszDescW)
  613. {
  614. LPDPLAPPINFO lpai = NULL;
  615. LPSTR lpszAppName = NULL;
  616. BOOL bReturn;
  617. DPF(7, "Entering PRV_CallEnumLocalAppCallback");
  618. DPF(9, "Parameters: 0x%08x, 0x%08x, 0x%08x, 0x%08x, %lu, 0x%08x, 0x%08x",
  619. lpwszAppName, lpguidApp, lpfnEnumCallback, lpContext, bAnsi,
  620. lpszDescA, lpwszDescW);
  621. // Allocate memory for the AppInfo struct
  622. lpai = DPMEM_ALLOC(sizeof(DPLAPPINFO));
  623. if(!lpai)
  624. {
  625. DPF_ERR("Unable to allocate memory for AppInfo structure!");
  626. return DPERR_OUTOFMEMORY;
  627. }
  628. // Set the size
  629. lpai->dwSize = sizeof(DPLAPPINFO);
  630. // If the description strings exist, use them
  631. // NOTE: We can assume that if the DescriptionA string exists,
  632. // they both do.
  633. if(lpszDescA)
  634. {
  635. if(bAnsi)
  636. lpai->lpszAppNameA = lpszDescA;
  637. else
  638. lpai->lpszAppName = lpwszDescW;
  639. }
  640. else
  641. {
  642. // If we're ANSI, convert the string
  643. if(bAnsi)
  644. {
  645. if(FAILED(GetAnsiString(&lpszAppName, lpwszAppName)))
  646. {
  647. DPMEM_FREE(lpai);
  648. DPF_ERR("Unable to allocate memory for temporary string!");
  649. return DPERR_OUTOFMEMORY;
  650. }
  651. lpai->lpszAppNameA = lpszAppName;
  652. }
  653. else
  654. {
  655. lpai->lpszAppName = lpwszAppName;
  656. }
  657. }
  658. // Set the GUID
  659. lpai->guidApplication = *lpguidApp;
  660. // Call the callback
  661. bReturn = ((LPDPLENUMLOCALAPPLICATIONSCALLBACK)lpfnEnumCallback)
  662. (lpai, lpContext, 0L);
  663. // Free all of our memory
  664. if(lpszAppName)
  665. DPMEM_FREE(lpszAppName);
  666. DPMEM_FREE(lpai);
  667. // Set our HRESULT return value
  668. if(bReturn)
  669. return DP_OK;
  670. else
  671. return DPLOBBYPR_CALLBACKSTOP;
  672. } // PRV_CallEnumLocalAppCallback
  673. #undef DPF_MODNAME
  674. #define DPF_MODNAME "PRV_EnumLocalApplications"
  675. HRESULT PRV_EnumLocalApplications(LPDIRECTPLAYLOBBY lpDPL,
  676. LPDPLENUMLOCALAPPLICATIONSCALLBACK lpfnEnumCallback,
  677. LPVOID lpContext, DWORD dwFlags, BOOL bAnsi)
  678. {
  679. LPDPLOBBYI_DPLOBJECT this;
  680. HRESULT hr = DP_OK;
  681. HKEY hkeyDPApps, hkeyApp;
  682. WCHAR wszAppName[DPLOBBY_REGISTRY_NAMELEN];
  683. DWORD dwIndex = 0;
  684. DWORD dwNameSize;
  685. WCHAR wszGuidStr[GUID_STRING_SIZE];
  686. DWORD dwGuidStrSize = sizeof(wszGuidStr)/sizeof(WCHAR);
  687. DWORD dwType = REG_SZ;
  688. GUID guidApp;
  689. LONG lReturn;
  690. CHAR szDescA[DPLOBBY_REGISTRY_NAMELEN];
  691. WCHAR wszDescW[DPLOBBY_REGISTRY_NAMELEN];
  692. DWORD dwDescSize;
  693. BOOL bDesc = FALSE;
  694. LPSTR lpszDescA = NULL;
  695. LPWSTR lpwszDescW = NULL;
  696. BOOL bHide;
  697. DWORD dwRegFlags;
  698. DWORD dwRegFlagsSize;
  699. DPF(7, "Entering PRV_EnumLocalApplications");
  700. DPF(9, "Parameters: 0x%08x, 0x%08x, 0x%08x, 0x%08x, %lu",
  701. lpDPL, lpfnEnumCallback, lpContext, dwFlags, bAnsi);
  702. TRY
  703. {
  704. if( !VALID_DPLOBBY_INTERFACE( lpDPL ))
  705. {
  706. return DPERR_INVALIDINTERFACE;
  707. }
  708. this = DPLOBJECT_FROM_INTERFACE(lpDPL);
  709. if( !VALID_DPLOBBY_PTR( this ) )
  710. {
  711. return DPERR_INVALIDOBJECT;
  712. }
  713. if( !VALIDEX_CODE_PTR( lpfnEnumCallback ) )
  714. {
  715. return DPERR_INVALIDPARAMS;
  716. }
  717. if( dwFlags )
  718. {
  719. return DPERR_INVALIDPARAMS;
  720. }
  721. }
  722. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  723. {
  724. LEAVE_DPLOBBY();
  725. DPF_ERR( "Exception encountered validating parameters" );
  726. return DPERR_INVALIDPARAMS;
  727. }
  728. // Open the Applications key
  729. lReturn = OS_RegOpenKeyEx(HKEY_LOCAL_MACHINE, SZ_DPLAY_APPS_KEY, 0,
  730. KEY_READ, &hkeyDPApps);
  731. if(lReturn != ERROR_SUCCESS)
  732. {
  733. // This just means that the application key doesn't exist (most
  734. // likely), so in that case, there are no apps to enumerate.
  735. return DP_OK;
  736. }
  737. // Walk the list of DPlay games in the registry, enumerating them
  738. while(1)
  739. {
  740. // Reset the pointers and the flag
  741. lpszDescA = NULL;
  742. lpwszDescW = NULL;
  743. bDesc = FALSE;
  744. bHide = FALSE;
  745. // Get the next app in the list
  746. dwNameSize = DPLOBBY_REGISTRY_NAMELEN;
  747. lReturn = OS_RegEnumKeyEx(hkeyDPApps, dwIndex++, (LPWSTR)wszAppName,
  748. &dwNameSize, NULL, NULL, NULL, NULL);
  749. // If lReturn is ERROR_NO_MORE_ITEMS, we want this to be the last iteration
  750. if(lReturn == ERROR_NO_MORE_ITEMS)
  751. break;
  752. // Open the app key
  753. lReturn = OS_RegOpenKeyEx(hkeyDPApps, (LPWSTR)wszAppName, 0,
  754. KEY_READ, &hkeyApp);
  755. if(lReturn != ERROR_SUCCESS)
  756. {
  757. DPF_ERR("Unable to open app key!");
  758. continue;
  759. }
  760. // see if we should even report this game (its hidden)
  761. dwRegFlags = 0;
  762. dwRegFlagsSize = sizeof(dwRegFlags);
  763. lReturn = OS_RegQueryValueEx(hkeyApp, SZ_DWFLAGS, NULL, &dwType, (CHAR *)&dwRegFlags, &dwRegFlagsSize);
  764. if(lReturn == ERROR_SUCCESS && dwRegFlags & DPLAPP_NOENUM){
  765. // application is hidden, don't report it back to the application.
  766. bHide = TRUE;
  767. } else {
  768. // Get the GUID of the Game
  769. dwGuidStrSize = GUID_STRING_SIZE;
  770. lReturn = OS_RegQueryValueEx(hkeyApp, SZ_GUID, NULL, &dwType,
  771. (LPBYTE)wszGuidStr, &dwGuidStrSize);
  772. if(lReturn != ERROR_SUCCESS)
  773. {
  774. RegCloseKey(hkeyApp);
  775. DPF_ERR("Unable to query GUID key value!");
  776. continue;
  777. }
  778. // Convert the string to a real GUID
  779. hr = GUIDFromString(wszGuidStr, &guidApp);
  780. if(FAILED(hr))
  781. {
  782. DPF_ERRVAL("Invalid game guid -- skipping game, hr = 0x%08x", hr);
  783. RegCloseKey(hkeyApp);
  784. // Set the hresult back to DP_OK in case this is the last
  785. // application in the registry -- we want the method call
  786. // to succeed if we got this far, we just don't want to
  787. // call the callback for this particular application
  788. hr = DP_OK;
  789. continue;
  790. }
  791. // Get the Description strings
  792. dwDescSize = sizeof(szDescA);
  793. lReturn = RegQueryValueExA(hkeyApp, "DescriptionA", NULL, &dwType,
  794. (LPBYTE)szDescA, &dwDescSize);
  795. if(lReturn != ERROR_SUCCESS)
  796. {
  797. DPF(5,"Could not read Description lReturn = %d\n",lReturn);
  798. // it's ok if the app doesn't have one of these...
  799. }
  800. else
  801. {
  802. DPF(5,"Got DescriptionA = %s\n",szDescA);
  803. // Set our description flag
  804. bDesc = TRUE;
  805. // Now try to get the DescriptionW string if one exists. If for some
  806. // reason a DescriptionW string exists, but the DescriptionA does not,
  807. // we pretend the DescriptionW string doesn't exist either.
  808. // NOTE: We always assume the DescriptionW string is a Unicode string,
  809. // even on Win95. On Win95, this will be of the type REG_BINARY, but
  810. // it is really just a Unicode string.
  811. dwDescSize = sizeof(wszDescW);
  812. lReturn = OS_RegQueryValueEx(hkeyApp, SZ_DESCRIPTIONW, NULL,
  813. &dwType, (LPBYTE)wszDescW, &dwDescSize);
  814. if(lReturn != ERROR_SUCCESS)
  815. {
  816. DPF(5,"Could not get DescriptionW, converting DescriptionA");
  817. // We couldn't get DescriptionW, so convert DescriptionA...
  818. AnsiToWide(wszDescW,szDescA,(lstrlenA(szDescA)+1));
  819. }
  820. else
  821. {
  822. DPF(5,"Got DescriptionW = %ls\n",wszDescW);
  823. }
  824. }
  825. }
  826. // Close the App key
  827. RegCloseKey(hkeyApp);
  828. // Setup the description pointers if they are valid
  829. if(bDesc)
  830. {
  831. lpszDescA = (LPSTR)szDescA;
  832. lpwszDescW = (LPWSTR)wszDescW;
  833. }
  834. if(bHide){
  835. // not calling back for this hidden application
  836. hr=DP_OK;
  837. } else {
  838. // Call the callback
  839. hr = PRV_CallEnumLocalAppCallback(wszAppName, &guidApp,
  840. lpfnEnumCallback, lpContext, bAnsi,
  841. lpszDescA, lpwszDescW);
  842. }
  843. if(hr == DPLOBBYPR_CALLBACKSTOP)
  844. {
  845. hr = DP_OK;
  846. break;
  847. }
  848. else
  849. {
  850. if(FAILED(hr))
  851. break;
  852. else
  853. continue;
  854. }
  855. }
  856. // Close the DPlay Apps key
  857. RegCloseKey(hkeyDPApps);
  858. dwNameSize = DPLOBBY_REGISTRY_NAMELEN;
  859. return hr;
  860. } // PRV_EnumLocalApplications
  861. #undef DPF_MODNAME
  862. #define DPF_MODNAME "DPL_EnumLocalApplications"
  863. HRESULT DPLAPI DPL_EnumLocalApplications(LPDIRECTPLAYLOBBY lpDPL,
  864. LPDPLENUMLOCALAPPLICATIONSCALLBACK lpfnEnumCallback,
  865. LPVOID lpContext, DWORD dwFlags)
  866. {
  867. HRESULT hr;
  868. DPF(7, "Entering DPL_EnumLocalApplications");
  869. DPF(9, "Parameters: 0x%08x, 0x%08x, 0x%08x, 0x%08x",
  870. lpDPL, lpfnEnumCallback, lpContext, dwFlags);
  871. ENTER_DPLOBBY();
  872. // Set the ANSI flag to TRUE and call the internal function
  873. hr = PRV_EnumLocalApplications(lpDPL, lpfnEnumCallback, lpContext,
  874. dwFlags, FALSE);
  875. LEAVE_DPLOBBY();
  876. return hr;
  877. } // DPL_EnumLocalApplications