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.

478 lines
13 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1996-1997 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: server.c
  6. * Content: Methods for connecting and interrogating a lobby server
  7. *
  8. * History:
  9. * Date By Reason
  10. * ======= ======= ======
  11. * 10/25/96 myronth Created it
  12. * 11/20/96 myronth Implemented Logon/LogoffServer
  13. * 2/12/97 myronth Mass DX5 changes
  14. * 2/26/97 myronth #ifdef'd out DPASYNCDATA stuff (removed dependency)
  15. * 3/12/97 myronth Fixed LoadSP code for DPlay3, reg & DPF bug fixes
  16. * 3/13/97 myronth Save hInstance handle for LP DLL
  17. * 4/3/97 myronth Changed CALLSP macro to CALL_LP
  18. * 4/9/97 myronth Fixed structure passed to LP at DPLSPInit
  19. * 5/8/97 myronth Purged dead code
  20. * 6/19/97 myronth Moved setting of DPLOBBYPR_SPINTERFACE flag (#10118)
  21. * 7/28/97 sohailm PRV_FindLPGUIDInAddressCallback was assuming pointers
  22. * were valid after duration of call.
  23. * 10/3/97 myronth Bumped version to DX6, added it to DPLSPInit struct (#12667)
  24. * 10/7/97 myronth Save the LP version in the lobby struct for later use
  25. * 11/6/97 myronth Added version existence flag and dwReserved values
  26. * to SPDATA_INIT (#12916, #12917)
  27. ***************************************************************************/
  28. #include "dplobpr.h"
  29. //--------------------------------------------------------------------------
  30. //
  31. // Definitions
  32. //
  33. //--------------------------------------------------------------------------
  34. #define NUM_CALLBACKS( ptr ) ((ptr->dwSize-2*sizeof( DWORD ))/ sizeof( LPVOID ))
  35. typedef struct LOOKFORSP
  36. {
  37. LPGUID lpguid;
  38. LPBOOL lpbSuccess;
  39. } LOOKFORSP, FAR * LPLOOKFORSP;
  40. //--------------------------------------------------------------------------
  41. //
  42. // Functions
  43. //
  44. //--------------------------------------------------------------------------
  45. #undef DPF_MODNAME
  46. #define DPF_MODNAME "PRV_VerifySPCallbacks"
  47. HRESULT PRV_VerifySPCallbacks(LPDPLOBBYI_DPLOBJECT this)
  48. {
  49. LPDWORD lpCallback;
  50. int nCallbacks = NUM_CALLBACKS(((LPSP_CALLBACKS)this->pcbSPCallbacks));
  51. int i;
  52. DPF(2,"Verifying %d callbacks\n",nCallbacks);
  53. DPF(7, "Entering PRV_VerifySPCallbacks");
  54. DPF(9, "Parameters: 0x%08x", this);
  55. lpCallback = (LPDWORD)this->pcbSPCallbacks + 2; // + 1 for dwSize, + 1 for dwFlags
  56. for (i=0;i<nCallbacks ;i++ )
  57. {
  58. if ((lpCallback) && !VALIDEX_CODE_PTR(lpCallback))
  59. {
  60. DPF_ERR("SP provided bad callback pointer!");
  61. return E_FAIL;
  62. }
  63. lpCallback++;
  64. }
  65. return DP_OK;
  66. } // PRV_VerifySPCallbacks
  67. #undef DPF_MODNAME
  68. #define DPF_MODNAME "PRV_LookForSPCallback"
  69. BOOL FAR PASCAL PRV_LookForSPCallback(LPGUID lpguidSP, LPWSTR lpSPName,
  70. DWORD dwMajorVersion, DWORD dwMinorVersion, LPVOID lpContext)
  71. {
  72. LPLOOKFORSP lplook = (LPLOOKFORSP)lpContext;
  73. ASSERT(lpguidSP);
  74. ASSERT(lplook);
  75. // Check the guid and see if they match
  76. if(IsEqualGUID(lpguidSP, lplook->lpguid))
  77. {
  78. // Set the flag to true and stop enumerating
  79. *(lplook->lpbSuccess) = TRUE;
  80. return FALSE;
  81. }
  82. return TRUE;
  83. } // PRV_LookForSPCallback
  84. #undef DPF_MODNAME
  85. #define DPF_MODNAME "PRV_FindSPName"
  86. HRESULT PRV_FindSPName(LPGUID lpguidSP, LPWSTR * lplpName,
  87. LPDWORD lpdwReserved1, LPDWORD lpdwReserved2)
  88. {
  89. HKEY hkeyLobbySP=NULL, hkeySP;
  90. WCHAR wszSPName[DPLOBBY_REGISTRY_NAMELEN];
  91. DWORD dwIndex = 0, dwSPNameSize;
  92. WCHAR wszGuidStr[GUID_STRING_SIZE];
  93. DWORD dwGuidStrSize = sizeof(wszGuidStr)/sizeof(WCHAR);
  94. DWORD dwFileStrSize = 0;
  95. DWORD dwType = REG_SZ;
  96. LPWSTR lpwszFile = NULL;
  97. GUID guidSP;
  98. LOOKFORSP look;
  99. LONG lReturn;
  100. BOOL bFound = FALSE;
  101. DWORD dwError;
  102. HRESULT hr;
  103. DWORD dwSize;
  104. DPF(7, "Entering PRV_FindSPName");
  105. DPF(9, "Parameters: 0x%08x, 0x%08x", lpguidSP, lplpName);
  106. ASSERT(lpguidSP);
  107. ASSERT(lplpName);
  108. // First see if it is a Lobby SP
  109. // Open the DPLobby SP key
  110. lReturn = OS_RegOpenKeyEx(HKEY_LOCAL_MACHINE, SZ_DPLOBBY_SP_KEY, 0,
  111. KEY_READ, &hkeyLobbySP);
  112. // If this fails, it just means that the DPLobby SP key doesn't exist (most
  113. // likely), so in that case, there are no Lobby SP's to enumerate.
  114. if(lReturn == ERROR_SUCCESS)
  115. {
  116. // Walk the list of Lobby SP's in the registry, enumerating them
  117. while(!bFound)
  118. {
  119. // Get the next key's name
  120. dwSPNameSize = DPLOBBY_REGISTRY_NAMELEN;
  121. lReturn = OS_RegEnumKeyEx(hkeyLobbySP, dwIndex++, (LPWSTR)wszSPName,
  122. &dwSPNameSize, NULL, NULL, NULL, NULL);
  123. if(ERROR_NO_MORE_ITEMS == lReturn)
  124. break;
  125. else if(lReturn != ERROR_SUCCESS)
  126. {
  127. dwError = GetLastError();
  128. DPF(2, "Unable to get Lobby Provider name -- skipping provider -- dwError = %u", dwError);
  129. continue;
  130. }
  131. // Open the key
  132. lReturn = OS_RegOpenKeyEx(hkeyLobbySP, (LPWSTR)wszSPName, 0,
  133. KEY_READ, &hkeySP);
  134. if(lReturn != ERROR_SUCCESS)
  135. {
  136. DPF_ERR("Unable to open Lobby Service Provider key in the registry!");
  137. continue;
  138. }
  139. // Get the GUID of the SP
  140. dwGuidStrSize = GUID_STRING_SIZE;
  141. lReturn = OS_RegQueryValueEx(hkeySP, SZ_GUID, NULL, &dwType,
  142. (LPBYTE)wszGuidStr, &dwGuidStrSize);
  143. if(lReturn != ERROR_SUCCESS)
  144. {
  145. RegCloseKey(hkeySP);
  146. DPF_ERR("Unable to query GUID key value!");
  147. continue;
  148. }
  149. // Convert the string to a real GUID
  150. GUIDFromString(wszGuidStr, &guidSP);
  151. // Check to see if the guid is the one we are looking for
  152. if(IsEqualGUID(&guidSP, lpguidSP))
  153. {
  154. // Allocate memory for the filename string
  155. lReturn = OS_RegQueryValueEx(hkeySP, SZ_PATH, NULL, &dwType,
  156. NULL, &dwFileStrSize);
  157. if(lReturn != ERROR_SUCCESS)
  158. {
  159. RegCloseKey(hkeySP);
  160. DPF_ERR("Unable to get the size of the SP Path string");
  161. continue;
  162. }
  163. // Allocate memory for the string
  164. lpwszFile = DPMEM_ALLOC(dwFileStrSize);
  165. if(!lpwszFile)
  166. {
  167. RegCloseKey(hkeySP);
  168. DPF_ERR("Unable to allocate memory for temporary file string");
  169. continue;
  170. }
  171. // Get the filename string
  172. lReturn = OS_RegQueryValueEx(hkeySP, SZ_PATH, NULL, &dwType,
  173. (LPBYTE)lpwszFile, &dwFileStrSize);
  174. if(lReturn != ERROR_SUCCESS)
  175. {
  176. RegCloseKey(hkeySP);
  177. DPF_ERR("Unable to get filename string from registry");
  178. continue;
  179. }
  180. // Get the Reserved1 value
  181. dwSize = sizeof(DWORD);
  182. lReturn = OS_RegQueryValueEx(hkeySP, SZ_DWRESERVED1, NULL,
  183. &dwType, (LPBYTE)lpdwReserved1, &dwSize);
  184. if (lReturn != ERROR_SUCCESS)
  185. {
  186. DPF(0,"Could not read dwReserved1 lReturn = %d\n", lReturn);
  187. // It's ok if LP doesn't have one of these...
  188. }
  189. // Get the Reserved2 value
  190. dwSize = sizeof(DWORD);
  191. lReturn = OS_RegQueryValueEx(hkeySP, SZ_DWRESERVED2, NULL,
  192. &dwType, (LPBYTE)lpdwReserved2, &dwSize);
  193. if (lReturn != ERROR_SUCCESS)
  194. {
  195. DPF(0,"Could not read dwReserved2 lReturn = %d\n", lReturn);
  196. // It's ok if LP doesn't have one of these...
  197. }
  198. // We've got our information, so set the flag and bail
  199. bFound = TRUE;
  200. RegCloseKey(hkeySP);
  201. break;
  202. }
  203. // Close the SP key
  204. RegCloseKey(hkeySP);
  205. }
  206. }
  207. // Close the Lobby SP key
  208. if(hkeyLobbySP)
  209. {
  210. RegCloseKey(hkeyLobbySP);
  211. }
  212. // If we haven't found the SP, start checking the DPlay SP's for it
  213. if(!bFound)
  214. {
  215. // Set up a struct containing the guid and a success flag
  216. look.lpguid = lpguidSP;
  217. look.lpbSuccess = &bFound;
  218. // Call DirectPlayEnumerate and look for our SP
  219. hr = DirectPlayEnumerate(PRV_LookForSPCallback, &look);
  220. if(FAILED(hr))
  221. {
  222. DPF_ERR("Unable to enumerate DirectPlay Service Providers");
  223. }
  224. // If the flag is TRUE, that means we found it, so set the output
  225. // pointer to a string containing our LobbySP for DPlay
  226. if(bFound)
  227. {
  228. hr = GetString(&lpwszFile, SZ_SP_FOR_DPLAY);
  229. if(FAILED(hr))
  230. {
  231. DPF_ERR("Unable to allocate temporary string for filename");
  232. }
  233. }
  234. }
  235. // If we haven't found the filename, return an error
  236. if(!bFound)
  237. return DPERR_GENERIC;
  238. // Set the output parameter
  239. *lplpName = lpwszFile;
  240. return DP_OK;
  241. } // PRV_FindSPName
  242. #undef DPF_MODNAME
  243. #define DPF_MODNAME "PRV_LoadSP"
  244. HRESULT PRV_LoadSP(LPDPLOBBYI_DPLOBJECT this, LPGUID lpguidSP,
  245. LPVOID lpAddress, DWORD dwAddressSize)
  246. {
  247. SPDATA_INIT sd;
  248. SPDATA_SHUTDOWN sdd;
  249. LPDPLOBBYSP lpISP = NULL;
  250. LPWSTR lpwszSP = NULL;
  251. HANDLE hModule = NULL;
  252. HRESULT hr;
  253. HRESULT (WINAPI *SPInit)(LPSPDATA_INIT pSD);
  254. DWORD dwError;
  255. DWORD dwReserved1 = 0;
  256. DWORD dwReserved2 = 0;
  257. DPF(7, "Entering PRV_LoadSP");
  258. DPF(9, "Parameters: 0x%08x, 0x%08x, 0x%08x",
  259. this, lpguidSP, lpAddress);
  260. ASSERT(this);
  261. ASSERT(lpguidSP);
  262. // Find the requested Service Provider
  263. hr = PRV_FindSPName(lpguidSP, &lpwszSP, &dwReserved1, &dwReserved2);
  264. if(FAILED(hr))
  265. {
  266. DPF_ERR("Unabled to find requested LobbyProvider");
  267. hr = DPERR_GENERIC;
  268. goto ERROR_EXIT_LOADSP;
  269. }
  270. // Try to load the specified sp
  271. hModule = OS_LoadLibrary(lpwszSP);
  272. if (!hModule)
  273. {
  274. dwError = GetLastError();
  275. DPF_ERR("Could not load service provider\n");
  276. DPF(0, "GetLastError returned dwError = %d\n", dwError);
  277. hr = DPERR_GENERIC;
  278. goto ERROR_EXIT_LOADSP;
  279. }
  280. // Free the name string
  281. DPMEM_FREE(lpwszSP);
  282. lpwszSP = NULL;
  283. // Get our DPLSPInit entry point
  284. (FARPROC)SPInit = OS_GetProcAddress(hModule, "DPLSPInit");
  285. if (!SPInit)
  286. {
  287. DPF(0,"Could not find service provider entry point");
  288. hr = DPERR_GENERIC;
  289. goto ERROR_EXIT_LOADSP;
  290. }
  291. // Get an IDPLobbySP to pass it
  292. hr = PRV_GetInterface(this, (LPDPLOBBYI_INTERFACE *)&lpISP, &dplCallbacksSP);
  293. if (FAILED(hr))
  294. {
  295. DPF(0,"Unable to get an IDPLobbySP interface. hr = 0x%08lx\n",hr);
  296. hr = DPERR_GENERIC;
  297. goto ERROR_EXIT_LOADSP;
  298. }
  299. // Alloc the callbacks
  300. this->pcbSPCallbacks = DPMEM_ALLOC(sizeof(SP_CALLBACKS));
  301. if (!this->pcbSPCallbacks)
  302. {
  303. DPF_ERR("Unable to allocate memory for SPCallback structure");
  304. LEAVE_DPLOBBY();
  305. hr = DPERR_OUTOFMEMORY;
  306. goto ERROR_EXIT_LOADSP;
  307. }
  308. // Set up the init data struct
  309. memset(&sd,0,sizeof(sd));
  310. sd.lpCB = this->pcbSPCallbacks;
  311. sd.lpCB->dwSize = sizeof(SP_CALLBACKS);
  312. sd.lpCB->dwDPlayVersion = DPLSP_MAJORVERSION;
  313. sd.lpISP = lpISP;
  314. sd.lpAddress = lpAddress;
  315. sd.dwReserved1 = dwReserved1;
  316. sd.dwReserved2 = dwReserved2;
  317. hr = SPInit(&sd);
  318. if (FAILED(hr))
  319. {
  320. DPF_ERR("Could not start up service provider!");
  321. goto ERROR_EXIT_LOADSP;
  322. }
  323. // Verify the callbacks are valid
  324. hr = PRV_VerifySPCallbacks(this);
  325. if (FAILED(hr))
  326. {
  327. DPF_ERR("Invalid callbacks from service provider!");
  328. goto ERROR_EXIT_LOADSP;
  329. }
  330. // Make sure the SP version is valid
  331. if (sd.dwSPVersion < DPLSP_DX5VERSION)
  332. {
  333. DPF_ERR("Incompatible version returned from lobby provider!");
  334. // Since the init succeeded, try to call shutdown
  335. memset(&sdd, 0, sizeof(SPDATA_SHUTDOWN));
  336. // REVIEW!!!! -- Should we pass a valid interface pointer
  337. // to the shutdown callback? If so, which one?
  338. if (CALLBACK_EXISTS(Shutdown))
  339. {
  340. sdd.lpISP = PRV_GetDPLobbySPInterface(this);
  341. hr = CALL_LP(this, Shutdown, &sdd);
  342. if (FAILED(hr))
  343. {
  344. DPF_ERR("Could not invoke shutdown on the Lobby Provider");
  345. }
  346. }
  347. else
  348. {
  349. ASSERT(FALSE);
  350. }
  351. hr = DPERR_UNAVAILABLE;
  352. goto ERROR_EXIT_LOADSP;
  353. }
  354. else
  355. {
  356. // Save the version of the lobby provider
  357. this->dwLPVersion = sd.dwSPVersion;
  358. }
  359. // Set the flag which tells us we have an IDPLobbySP interface
  360. this->dwFlags |= DPLOBBYPR_SPINTERFACE;
  361. // Save the hInstance for the LP's DLL
  362. this->hInstanceLP = hModule;
  363. return DP_OK;
  364. ERROR_EXIT_LOADSP:
  365. // If the LP DLL was loaded, unload it
  366. if(hModule)
  367. {
  368. if(!FreeLibrary(hModule))
  369. {
  370. dwError = GetLastError();
  371. DPF_ERRVAL("Unable to free Lobby Provider DLL, dwError = %lu", dwError);
  372. ASSERT(FALSE);
  373. }
  374. }
  375. // Free our allocated callback table
  376. if(this->pcbSPCallbacks)
  377. {
  378. DPMEM_FREE(this->pcbSPCallbacks);
  379. this->pcbSPCallbacks = NULL;
  380. }
  381. return hr;
  382. } // PRV_LoadSP
  383. #undef DPF_MODNAME
  384. #define DPF_MODNAME "PRV_FindLPGUIDInAddressCallback"
  385. BOOL FAR PASCAL PRV_FindLPGUIDInAddressCallback(REFGUID lpguidDataType, DWORD dwDataSize,
  386. LPCVOID lpData, LPVOID lpContext)
  387. {
  388. // See if this chunk is our LobbyProvider GUID
  389. if (IsEqualGUID(lpguidDataType, &DPAID_LobbyProvider))
  390. {
  391. // We found it, so we can stop enumerating chunks
  392. *((LPGUID)lpContext) = *((LPGUID)lpData);
  393. return FALSE;
  394. }
  395. // Try the next chunk
  396. return TRUE;
  397. } // PRV_FindLPGUIDInAddressCallback