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.

2944 lines
74 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1998-2002 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: Utils.cpp
  6. * Content: Serial service provider utility functions
  7. *
  8. *
  9. * History:
  10. * Date By Reason
  11. * ==== == ======
  12. * 11/25/98 jtk Created
  13. ***************************************************************************/
  14. #include "dnwsocki.h"
  15. //**********************************************************************
  16. // Constant definitions
  17. //**********************************************************************
  18. #define DEFAULT_THREADS_PER_PROCESSOR 3
  19. #define REGSUBKEY_DPNATHELP_DIRECTPLAY8PRIORITY L"DirectPlay8Priority"
  20. #define REGSUBKEY_DPNATHELP_DIRECTPLAY8INITFLAGS L"DirectPlay8InitFlags"
  21. #define REGSUBKEY_DPNATHELP_GUID L"Guid"
  22. //**********************************************************************
  23. // Macro definitions
  24. //**********************************************************************
  25. //**********************************************************************
  26. // Structure definitions
  27. //**********************************************************************
  28. //**********************************************************************
  29. // Variable definitions
  30. //**********************************************************************
  31. //
  32. // global variables that are unique for the process
  33. //
  34. #ifndef DPNBUILD_ONLYONETHREAD
  35. static DNCRITICAL_SECTION g_InterfaceGlobalsLock;
  36. #endif // !DPNBUILD_ONLYONETHREAD
  37. static volatile LONG g_iThreadPoolRefCount = 0;
  38. static CThreadPool * g_pThreadPool = NULL;
  39. static volatile LONG g_iWinsockRefCount = 0;
  40. #ifndef DPNBUILD_NONATHELP
  41. static volatile LONG g_iNATHelpRefCount = 0;
  42. #endif // ! DPNBUILD_NONATHELP
  43. #if ((defined(WINNT)) && (! defined(DPNBUILD_NOMULTICAST)))
  44. static volatile LONG g_iMadcapRefCount = 0;
  45. BYTE g_abClientID[MCAST_CLIENT_ID_LEN];
  46. #endif // WINNT and not DPNBUILD_NOMULTICAST
  47. //**********************************************************************
  48. // Function prototypes
  49. //**********************************************************************
  50. #ifndef DPNBUILD_NOREGISTRY
  51. static void ReadSettingsFromRegistry( void );
  52. static BOOL BannedIPv4AddressCompareFunction( PVOID pvKey1, PVOID pvKey2 );
  53. static DWORD BannedIPv4AddressHashFunction( PVOID pvKey, BYTE bBitDepth );
  54. static void ReadBannedIPv4Addresses( CRegistry * pRegObject );
  55. #endif // ! DPNBUILD_NOREGISTRY
  56. //**********************************************************************
  57. // Function definitions
  58. //**********************************************************************
  59. #if defined(WINCE) && !defined(_MAX_DRIVE)
  60. //typedef signed char _TSCHAR;
  61. #define _MAX_DRIVE 3 /* max. length of drive component */
  62. #define _MAX_DIR 256 /* max. length of path component */
  63. #define _MAX_FNAME 256 /* max. length of file name component */
  64. #define _MAX_EXT 256 /* max. length of extension component */
  65. void __cdecl _tsplitpath (
  66. register const _TSCHAR *path,
  67. _TSCHAR *drive,
  68. _TSCHAR *dir,
  69. _TSCHAR *fname,
  70. _TSCHAR *ext
  71. )
  72. {
  73. register _TSCHAR *p;
  74. _TSCHAR *last_slash = NULL, *dot = NULL;
  75. unsigned len;
  76. /* we assume that the path argument has the following form, where any
  77. * or all of the components may be missing.
  78. *
  79. * <drive><dir><fname><ext>
  80. *
  81. * and each of the components has the following expected form(s)
  82. *
  83. * drive:
  84. * 0 to _MAX_DRIVE-1 characters, the last of which, if any, is a
  85. * ':'
  86. * dir:
  87. * 0 to _MAX_DIR-1 characters in the form of an absolute path
  88. * (leading '/' or '\') or relative path, the last of which, if
  89. * any, must be a '/' or '\'. E.g -
  90. * absolute path:
  91. * \top\next\last\ ; or
  92. * /top/next/last/
  93. * relative path:
  94. * top\next\last\ ; or
  95. * top/next/last/
  96. * Mixed use of '/' and '\' within a path is also tolerated
  97. * fname:
  98. * 0 to _MAX_FNAME-1 characters not including the '.' character
  99. * ext:
  100. * 0 to _MAX_EXT-1 characters where, if any, the first must be a
  101. * '.'
  102. *
  103. */
  104. /* extract drive letter and :, if any */
  105. if ((_tcslen(path) >= (_MAX_DRIVE - 2)) && (*(path + _MAX_DRIVE - 2) == _T(':'))) {
  106. if (drive) {
  107. _tcsncpy(drive, path, _MAX_DRIVE - 1);
  108. *(drive + _MAX_DRIVE-1) = _T('\0');
  109. }
  110. path += _MAX_DRIVE - 1;
  111. }
  112. else if (drive) {
  113. *drive = _T('\0');
  114. }
  115. /* extract path string, if any. Path now points to the first character
  116. * of the path, if any, or the filename or extension, if no path was
  117. * specified. Scan ahead for the last occurence, if any, of a '/' or
  118. * '\' path separator character. If none is found, there is no path.
  119. * We will also note the last '.' character found, if any, to aid in
  120. * handling the extension.
  121. */
  122. for (last_slash = NULL, p = (_TSCHAR *)path; *p; p++) {
  123. #ifdef _MBCS
  124. if (_ISLEADBYTE (*p))
  125. p++;
  126. else {
  127. #endif /* _MBCS */
  128. if (*p == _T('/') || *p == _T('\\'))
  129. /* point to one beyond for later copy */
  130. last_slash = p + 1;
  131. else if (*p == _T('.'))
  132. dot = p;
  133. #ifdef _MBCS
  134. }
  135. #endif /* _MBCS */
  136. }
  137. if (last_slash) {
  138. /* found a path - copy up through last_slash or max. characters
  139. * allowed, whichever is smaller
  140. */
  141. if (dir) {
  142. len = __min(((char *)last_slash - (char *)path) / sizeof(_TSCHAR),
  143. (_MAX_DIR - 1));
  144. _tcsncpy(dir, path, len);
  145. *(dir + len) = _T('\0');
  146. }
  147. path = last_slash;
  148. }
  149. else if (dir) {
  150. /* no path found */
  151. *dir = _T('\0');
  152. }
  153. /* extract file name and extension, if any. Path now points to the
  154. * first character of the file name, if any, or the extension if no
  155. * file name was given. Dot points to the '.' beginning the extension,
  156. * if any.
  157. */
  158. if (dot && (dot >= path)) {
  159. /* found the marker for an extension - copy the file name up to
  160. * the '.'.
  161. */
  162. if (fname) {
  163. len = __min(((char *)dot - (char *)path) / sizeof(_TSCHAR),
  164. (_MAX_FNAME - 1));
  165. _tcsncpy(fname, path, len);
  166. *(fname + len) = _T('\0');
  167. }
  168. /* now we can get the extension - remember that p still points
  169. * to the terminating nul character of path.
  170. */
  171. if (ext) {
  172. len = __min(((char *)p - (char *)dot) / sizeof(_TSCHAR),
  173. (_MAX_EXT - 1));
  174. _tcsncpy(ext, dot, len);
  175. *(ext + len) = _T('\0');
  176. }
  177. }
  178. else {
  179. /* found no extension, give empty extension and copy rest of
  180. * string into fname.
  181. */
  182. if (fname) {
  183. len = __min(((char *)p - (char *)path) / sizeof(_TSCHAR),
  184. (_MAX_FNAME - 1));
  185. _tcsncpy(fname, path, len);
  186. *(fname + len) = _T('\0');
  187. }
  188. if (ext) {
  189. *ext = _T('\0');
  190. }
  191. }
  192. }
  193. #endif // WINCE
  194. #ifndef DPNBUILD_NOREGISTRY
  195. //**********************************************************************
  196. // ------------------------------
  197. // ReadSettingsFromRegistry - read custom registry keys
  198. //
  199. // Entry: Nothing
  200. //
  201. // Exit: Nothing
  202. // ------------------------------
  203. #undef DPF_MODNAME
  204. #define DPF_MODNAME "ReadSettingsFromRegistry"
  205. static void ReadSettingsFromRegistry( void )
  206. {
  207. CRegistry RegObject;
  208. CRegistry RegObjectTemp;
  209. CRegistry RegObjectAppEntry;
  210. DWORD dwRegValue;
  211. BOOL fGotPath;
  212. WCHAR wszExePath[_MAX_PATH];
  213. #ifndef UNICODE
  214. char szExePath[_MAX_PATH];
  215. #endif // !UNICODE
  216. if ( RegObject.Open( HKEY_LOCAL_MACHINE, g_RegistryBase ) != FALSE )
  217. {
  218. //
  219. // Find out the current process name.
  220. //
  221. #ifdef UNICODE
  222. if (GetModuleFileName(NULL, wszExePath, _MAX_PATH) > 0)
  223. {
  224. DPFX(DPFPREP, 3, "Loading DLL in process: %ls", wszExePath);
  225. _tsplitpath( wszExePath, NULL, NULL, wszExePath, NULL );
  226. fGotPath = TRUE;
  227. }
  228. #else // ! UNICODE
  229. if (GetModuleFileName(NULL, szExePath, _MAX_PATH) > 0)
  230. {
  231. HRESULT hr;
  232. DPFX(DPFPREP, 3, "Loading DLL in process: %hs", szExePath);
  233. _tsplitpath( szExePath, NULL, NULL, szExePath, NULL );
  234. dwRegValue = _MAX_PATH;
  235. hr = STR_AnsiToWide(szExePath, -1, wszExePath, &dwRegValue );
  236. if ( hr == DPN_OK )
  237. {
  238. //
  239. // Successfully converted ANSI path to Wide characters.
  240. //
  241. fGotPath = TRUE;
  242. }
  243. else
  244. {
  245. //
  246. // Couldn't convert ANSI path to Wide characters
  247. //
  248. fGotPath = FALSE;
  249. }
  250. }
  251. #endif // ! UNICODE
  252. else
  253. {
  254. //
  255. // Couldn't get current process path.
  256. //
  257. fGotPath = FALSE;
  258. }
  259. //
  260. // read receive buffer size
  261. //
  262. if ( RegObject.ReadDWORD( g_RegistryKeyReceiveBufferSize, &dwRegValue ) != FALSE )
  263. {
  264. g_fWinsockReceiveBufferSizeOverridden = TRUE;
  265. g_iWinsockReceiveBufferSize = dwRegValue;
  266. }
  267. #ifndef DPNBUILD_ONLYONETHREAD
  268. //
  269. // read default threads
  270. //
  271. if ( RegObject.ReadDWORD( g_RegistryKeyThreadCount, &dwRegValue ) != FALSE )
  272. {
  273. g_iThreadCount = dwRegValue;
  274. }
  275. //
  276. // if thread count is zero, use the 'default' for the system
  277. //
  278. if ( g_iThreadCount == 0 )
  279. {
  280. g_iThreadCount = DEFAULT_THREADS_PER_PROCESSOR;
  281. #ifndef DPNBUILD_ONLYONEPROCESSOR
  282. SYSTEM_INFO SystemInfo;
  283. GetSystemInfo(&SystemInfo);
  284. g_iThreadCount *= SystemInfo.dwNumberOfProcessors;
  285. #endif // ! DPNBUILD_ONLYONEPROCESSOR
  286. }
  287. #endif // ! DPNBUILD_ONLYONETHREAD
  288. #if ((! defined(DPNBUILD_NOWINSOCK2)) && (! defined(DPNBUILD_ONLYWINSOCK2)))
  289. //
  290. // Winsock2 9x option
  291. //
  292. if (RegObject.ReadDWORD( g_RegistryKeyWinsockVersion, &dwRegValue ))
  293. {
  294. switch (dwRegValue)
  295. {
  296. case 0:
  297. {
  298. DPFX(DPFPREP, 1, "Explicitly using available Winsock version.");
  299. g_dwWinsockVersion = dwRegValue;
  300. break;
  301. }
  302. case 1:
  303. {
  304. DPFX(DPFPREP, 1, "Explicitly using Winsock 1 only.");
  305. g_dwWinsockVersion = dwRegValue;
  306. break;
  307. }
  308. case 2:
  309. {
  310. DPFX(DPFPREP, 1, "Explicitly using Winsock 2 (when available).");
  311. g_dwWinsockVersion = dwRegValue;
  312. break;
  313. }
  314. default:
  315. {
  316. DPFX(DPFPREP, 0, "Ignoring invalid Winsock version setting (%u).", dwRegValue);
  317. break;
  318. }
  319. }
  320. }
  321. #endif // ! DPNBUILD_NOWINSOCK2 and ! DPNBUILD_ONLYWINSOCK2
  322. #ifndef DPNBUILD_NONATHELP
  323. //
  324. // get global NAT traversal disablers, ignore registry reading error
  325. //
  326. if (RegObject.ReadBOOL( g_RegistryKeyDisableDPNHGatewaySupport, &g_fDisableDPNHGatewaySupport ))
  327. {
  328. if (g_fDisableDPNHGatewaySupport)
  329. {
  330. DPFX(DPFPREP, 1, "Disabling NAT Help gateway support.");
  331. }
  332. else
  333. {
  334. DPFX(DPFPREP, 1, "Explicitly not disabling NAT Help gateway support.");
  335. }
  336. }
  337. if (RegObject.ReadBOOL( g_RegistryKeyDisableDPNHFirewallSupport, &g_fDisableDPNHFirewallSupport ))
  338. {
  339. if (g_fDisableDPNHFirewallSupport)
  340. {
  341. DPFX(DPFPREP, 1, "Disabling NAT Help firewall support.");
  342. }
  343. else
  344. {
  345. DPFX(DPFPREP, 1, "Explicitly not disabling NAT Help firewall support.");
  346. }
  347. }
  348. #endif // DPNBUILD_NONATHELP
  349. #if ((defined(WINNT)) && (! defined(DPNBUILD_NOMULTICAST)))
  350. //
  351. // get global MADCAP API disabler, ignore registry reading error
  352. //
  353. if (RegObject.ReadBOOL( g_RegistryKeyDisableMadcapSupport, &g_fDisableMadcapSupport ))
  354. {
  355. if (g_fDisableMadcapSupport)
  356. {
  357. DPFX(DPFPREP, 1, "Disabling MADCAP support.");
  358. }
  359. else
  360. {
  361. DPFX(DPFPREP, 1, "Explicitly not disabling MADCAP support.");
  362. }
  363. }
  364. #endif // WINNT and not DPNBUILD_NOMULTICAST
  365. //
  366. // If we have an app name, try opening the subkey and looking up the app
  367. // to see if enums are disabled, whether we should disconnect based on
  368. // ICMPs, and which IP protocol families to use.
  369. //
  370. if ( fGotPath )
  371. {
  372. if ( RegObjectTemp.Open( RegObject.GetHandle(), g_RegistryKeyAppsToIgnoreEnums, TRUE, FALSE ) )
  373. {
  374. RegObjectTemp.ReadBOOL( wszExePath, &g_fIgnoreEnums );
  375. RegObjectTemp.Close();
  376. if ( g_fIgnoreEnums )
  377. {
  378. DPFX(DPFPREP, 0, "Ignoring all enumerations (app = %ls).", wszExePath);
  379. }
  380. else
  381. {
  382. DPFX(DPFPREP, 2, "Not ignoring all enumerations (app = %ls).", wszExePath);
  383. }
  384. }
  385. if ( RegObjectTemp.Open( RegObject.GetHandle(), g_RegistryKeyAppsToDisconnectOnICMP, TRUE, FALSE ) )
  386. {
  387. RegObjectTemp.ReadBOOL( wszExePath, &g_fDisconnectOnICMP );
  388. RegObjectTemp.Close();
  389. if ( g_fDisconnectOnICMP )
  390. {
  391. DPFX(DPFPREP, 0, "Disconnecting upon receiving ICMP port not reachable messages (app = %ls).", wszExePath);
  392. }
  393. else
  394. {
  395. DPFX(DPFPREP, 2, "Not disconnecting upon receiving ICMP port not reachable messages (app = %ls).", wszExePath);
  396. }
  397. }
  398. #ifndef DPNBUILD_NONATHELP
  399. if ( RegObjectTemp.Open( RegObject.GetHandle(), g_RegistryKeyTraversalModeSettings, TRUE, FALSE ) )
  400. {
  401. //
  402. // Read the global default traversal mode.
  403. //
  404. if ( RegObjectTemp.ReadDWORD( g_RegistryKeyDefaultTraversalMode, &dwRegValue ) != FALSE )
  405. {
  406. switch (dwRegValue)
  407. {
  408. case DPNA_TRAVERSALMODE_NONE:
  409. case DPNA_TRAVERSALMODE_PORTREQUIRED:
  410. case DPNA_TRAVERSALMODE_PORTRECOMMENDED:
  411. {
  412. g_dwDefaultTraversalMode = dwRegValue;
  413. DPFX(DPFPREP, 1, "Using global default traversal mode %u.",
  414. g_dwDefaultTraversalMode);
  415. break;
  416. }
  417. case (DPNA_TRAVERSALMODE_NONE | FORCE_TRAVERSALMODE_BIT):
  418. case (DPNA_TRAVERSALMODE_PORTREQUIRED | FORCE_TRAVERSALMODE_BIT):
  419. case (DPNA_TRAVERSALMODE_PORTRECOMMENDED | FORCE_TRAVERSALMODE_BIT):
  420. {
  421. g_dwDefaultTraversalMode = dwRegValue;
  422. DPFX(DPFPREP, 1, "Forcing global traversal mode %u.",
  423. g_dwDefaultTraversalMode);
  424. break;
  425. }
  426. default:
  427. {
  428. DPFX(DPFPREP, 0, "Ignoring invalid global default traversal mode (%u).",
  429. dwRegValue);
  430. break;
  431. }
  432. }
  433. }
  434. //
  435. // Override with the per app setting.
  436. //
  437. if ( RegObjectTemp.ReadDWORD( wszExePath, &dwRegValue ) != FALSE )
  438. {
  439. switch (dwRegValue)
  440. {
  441. case DPNA_TRAVERSALMODE_NONE:
  442. case DPNA_TRAVERSALMODE_PORTREQUIRED:
  443. case DPNA_TRAVERSALMODE_PORTRECOMMENDED:
  444. {
  445. g_dwDefaultTraversalMode = dwRegValue;
  446. DPFX(DPFPREP, 1, "Using default traversal mode %u (app = %ls).",
  447. g_dwDefaultTraversalMode, wszExePath);
  448. break;
  449. }
  450. case (DPNA_TRAVERSALMODE_NONE | FORCE_TRAVERSALMODE_BIT):
  451. case (DPNA_TRAVERSALMODE_PORTREQUIRED | FORCE_TRAVERSALMODE_BIT):
  452. case (DPNA_TRAVERSALMODE_PORTRECOMMENDED | FORCE_TRAVERSALMODE_BIT):
  453. {
  454. g_dwDefaultTraversalMode = dwRegValue;
  455. DPFX(DPFPREP, 1, "Forcing traversal mode %u (app = %ls).",
  456. g_dwDefaultTraversalMode, wszExePath);
  457. break;
  458. }
  459. default:
  460. {
  461. DPFX(DPFPREP, 0, "Ignoring invalid default traversal mode (%u, app %ls).",
  462. dwRegValue, wszExePath);
  463. break;
  464. }
  465. }
  466. }
  467. RegObjectTemp.Close();
  468. }
  469. #endif // DPNBUILD_NONATHELP
  470. #ifndef DPNBUILD_NOIPV6
  471. if ( RegObjectTemp.Open( RegObject.GetHandle(), g_RegistryKeyIPAddressFamilySettings, TRUE, FALSE ) )
  472. {
  473. //
  474. // Read the global IP address family setting.
  475. //
  476. if ( RegObjectTemp.ReadDWORD( g_RegistryKeyDefaultIPAddressFamily, &dwRegValue ) != FALSE )
  477. {
  478. switch (dwRegValue)
  479. {
  480. case PF_UNSPEC:
  481. case PF_INET:
  482. case PF_INET6:
  483. {
  484. g_iIPAddressFamily = dwRegValue;
  485. DPFX(DPFPREP, 1, "Using IP address family %i global setting.",
  486. g_iIPAddressFamily);
  487. break;
  488. }
  489. default:
  490. {
  491. DPFX(DPFPREP, 0, "Ignoring invalid IP address family global setting (%u).",
  492. dwRegValue);
  493. break;
  494. }
  495. }
  496. }
  497. //
  498. // Override with the per app setting.
  499. //
  500. if ( RegObjectTemp.ReadDWORD( wszExePath, &dwRegValue ) != FALSE )
  501. {
  502. switch (dwRegValue)
  503. {
  504. case PF_UNSPEC:
  505. case PF_INET:
  506. case PF_INET6:
  507. {
  508. g_iIPAddressFamily = dwRegValue;
  509. DPFX(DPFPREP, 1, "Using IP address family %i (app = %ls).",
  510. g_iIPAddressFamily, wszExePath);
  511. break;
  512. }
  513. default:
  514. {
  515. DPFX(DPFPREP, 0, "Ignoring invalid IP address family setting (%u, app %ls).",
  516. dwRegValue, wszExePath);
  517. break;
  518. }
  519. }
  520. }
  521. RegObjectTemp.Close();
  522. }
  523. #endif // ! DPNBUILD_NOIPV6
  524. }
  525. //
  526. // Get the proxy support options, ignore registry reading error.
  527. //
  528. #ifndef DPNBUILD_NOWINSOCK2
  529. if (RegObject.ReadBOOL( g_RegistryKeyDontAutoDetectProxyLSP, &g_fDontAutoDetectProxyLSP ))
  530. {
  531. if (g_fDontAutoDetectProxyLSP)
  532. {
  533. DPFX(DPFPREP, 1, "Not auto-detected ISA Proxy LSP.");
  534. }
  535. else
  536. {
  537. DPFX(DPFPREP, 1, "Explicitly allowing auto-detection of ISA Proxy LSP.");
  538. }
  539. }
  540. #endif // !DPNBUILD_NOWINSOCK2
  541. if (RegObject.ReadBOOL( g_RegistryKeyTreatAllResponsesAsProxied, &g_fTreatAllResponsesAsProxied ))
  542. {
  543. if (g_fTreatAllResponsesAsProxied)
  544. {
  545. DPFX(DPFPREP, 1, "Treating all responses as proxied.");
  546. }
  547. else
  548. {
  549. DPFX(DPFPREP, 1, "Explicitly not treating all responses as proxied.");
  550. }
  551. }
  552. //
  553. // read MTU overrides
  554. //
  555. if ( RegObject.ReadDWORD( g_RegistryKeyMaxUserDataSize, &dwRegValue ) != FALSE )
  556. {
  557. if ((dwRegValue >= MIN_SEND_FRAME_SIZE) && (dwRegValue <= MAX_SEND_FRAME_SIZE))
  558. {
  559. //
  560. // If the new user data size is smaller than the the default enum setting,
  561. // shrink the enum size as well. It can be explicitly overridden below.
  562. //
  563. if (dwRegValue < g_dwMaxEnumDataSize)
  564. {
  565. g_dwMaxUserDataSize = dwRegValue;
  566. g_dwMaxEnumDataSize = g_dwMaxUserDataSize - ENUM_PAYLOAD_HEADER_SIZE;
  567. DPFX(DPFPREP, 1, "Max user data size is set to %u, assuming enum payload is %u.",
  568. g_dwMaxUserDataSize, g_dwMaxEnumDataSize);
  569. }
  570. else
  571. {
  572. g_dwMaxUserDataSize = dwRegValue;
  573. DPFX(DPFPREP, 1, "Max user data size is set to %u.",
  574. g_dwMaxUserDataSize);
  575. }
  576. }
  577. else
  578. {
  579. DPFX(DPFPREP, 0, "Ignoring invalid max user data size setting (%u).",
  580. dwRegValue);
  581. }
  582. }
  583. if ( RegObject.ReadDWORD( g_RegistryKeyMaxEnumDataSize, &dwRegValue ) != FALSE )
  584. {
  585. if ((dwRegValue >= (MIN_SEND_FRAME_SIZE - ENUM_PAYLOAD_HEADER_SIZE)) &&
  586. (dwRegValue <= (MAX_SEND_FRAME_SIZE - ENUM_PAYLOAD_HEADER_SIZE)))
  587. {
  588. DPFX(DPFPREP, 1, "Max user data size is set to %u.",
  589. dwRegValue);
  590. g_dwMaxEnumDataSize = dwRegValue;
  591. }
  592. else
  593. {
  594. DPFX(DPFPREP, 0, "Ignoring invalid max user data size setting (%u).",
  595. dwRegValue);
  596. }
  597. }
  598. //
  599. // read default port range
  600. //
  601. if ( RegObject.ReadDWORD( g_RegistryKeyBaseDPlayPort, &dwRegValue ) != FALSE )
  602. {
  603. if (dwRegValue < (WORD_MAX - 100)) // cannot be 65435 or above
  604. {
  605. g_wBaseDPlayPort = (WORD) dwRegValue;
  606. DPFX(DPFPREP, 1, "Base DPlay default port set to %u.",
  607. g_wBaseDPlayPort);
  608. }
  609. else
  610. {
  611. DPFX(DPFPREP, 0, "Ignoring invalid base DPlay default port setting (%u).",
  612. dwRegValue);
  613. }
  614. }
  615. if ( RegObject.ReadDWORD( g_RegistryKeyMaxDPlayPort, &dwRegValue ) != FALSE )
  616. {
  617. if (dwRegValue <= WORD_MAX) // cannot be greater than 65535
  618. {
  619. g_wMaxDPlayPort = (WORD) dwRegValue;
  620. DPFX(DPFPREP, 1, "Max DPlay default port set to %u.",
  621. g_wMaxDPlayPort);
  622. }
  623. else
  624. {
  625. DPFX(DPFPREP, 0, "Ignoring invalid max DPlay default port setting (%u).",
  626. dwRegValue);
  627. }
  628. }
  629. if (g_wMaxDPlayPort <= g_wBaseDPlayPort)
  630. {
  631. DPFX(DPFPREP, 1, "Max DPlay default port %u is less than or equal to base %u, setting to %u.",
  632. g_wMaxDPlayPort, g_wBaseDPlayPort, (g_wBaseDPlayPort + 100));
  633. g_wMaxDPlayPort = g_wBaseDPlayPort + 100;
  634. }
  635. RegObject.Close();
  636. }
  637. #pragma TODO(vanceo, "Be able to read while session is still running")
  638. if ( RegObject.Open( HKEY_LOCAL_MACHINE, g_RegistryBase, TRUE, FALSE ) != FALSE )
  639. {
  640. if ( RegObjectTemp.Open( RegObject.GetHandle(), g_RegistryKeyBannedIPv4Addresses, TRUE, FALSE ) )
  641. {
  642. DPFX(DPFPREP, 1, "Reading banned IPv4 addresses for all users.");
  643. ReadBannedIPv4Addresses(&RegObjectTemp);
  644. }
  645. RegObject.Close();
  646. }
  647. if ( RegObject.Open( HKEY_CURRENT_USER, g_RegistryBase, TRUE, FALSE ) != FALSE )
  648. {
  649. if ( RegObjectTemp.Open( RegObject.GetHandle(), g_RegistryKeyBannedIPv4Addresses, TRUE, FALSE ) )
  650. {
  651. DPFX(DPFPREP, 1, "Reading banned IPv4 addresses for current user.");
  652. ReadBannedIPv4Addresses(&RegObjectTemp);
  653. }
  654. RegObject.Close();
  655. }
  656. }
  657. //**********************************************************************
  658. //**********************************************************************
  659. // ------------------------------
  660. // BannedIPv4AddressCompareFunction - compare against another address
  661. //
  662. // Entry: Addresses to compare
  663. //
  664. // Exit: Bool indicating equality of two addresses
  665. // ------------------------------
  666. #undef DPF_MODNAME
  667. #define DPF_MODNAME "BannedIPv4AddressCompareFunction"
  668. static BOOL BannedIPv4AddressCompareFunction( PVOID pvKey1, PVOID pvKey2 )
  669. {
  670. DWORD dwAddr1;
  671. DWORD dwAddr2;
  672. dwAddr1 = (DWORD) ((DWORD_PTR) pvKey1);
  673. dwAddr2 = (DWORD) ((DWORD_PTR) pvKey2);
  674. if (dwAddr1 == dwAddr2)
  675. {
  676. return TRUE;
  677. }
  678. return FALSE;
  679. }
  680. //**********************************************************************
  681. //**********************************************************************
  682. // ------------------------------
  683. // BannedIPv4AddressHashFunction - hash address to N bits
  684. //
  685. // Entry: Count of bits to hash to
  686. //
  687. // Exit: Hashed value
  688. // ------------------------------
  689. #undef DPF_MODNAME
  690. #define DPF_MODNAME "BannedIPv4AddressHashFunction"
  691. static DWORD BannedIPv4AddressHashFunction( PVOID pvKey, BYTE bBitDepth )
  692. {
  693. DWORD dwReturn;
  694. UINT_PTR Temp;
  695. DNASSERT( bBitDepth != 0 );
  696. //
  697. // initialize
  698. //
  699. dwReturn = 0;
  700. //
  701. // hash IP address
  702. //
  703. Temp = (DWORD) ((DWORD_PTR) pvKey);
  704. do
  705. {
  706. dwReturn ^= Temp & ( ( 1 << bBitDepth ) - 1 );
  707. Temp >>= bBitDepth;
  708. } while ( Temp != 0 );
  709. return dwReturn;
  710. }
  711. //**********************************************************************
  712. //**********************************************************************
  713. // ------------------------------
  714. // ReadBannedIPv4Addresses - reads in additional banned IPv4 addresses from the registry
  715. //
  716. // Entry: Pointer to registry object with values to read
  717. //
  718. // Exit: None
  719. // ------------------------------
  720. #undef DPF_MODNAME
  721. #define DPF_MODNAME "ReadBannedIPv4Addresses"
  722. static void ReadBannedIPv4Addresses( CRegistry * pRegObject )
  723. {
  724. WCHAR wszIPAddress[16]; // nnn.nnn.nnn.nnn + NULL termination
  725. char szIPAddress[16]; // nnn.nnn.nnn.nnn + NULL termination
  726. DWORD dwSize;
  727. DWORD dwIndex;
  728. DWORD dwMask;
  729. DWORD dwBit;
  730. PVOID pvMask;
  731. CSocketAddress SocketAddressTemp;
  732. SOCKADDR_IN * psaddrinTemp;
  733. memset(&SocketAddressTemp, 0, sizeof(SocketAddressTemp));
  734. psaddrinTemp = (SOCKADDR_IN*) SocketAddressTemp.GetWritableAddress();
  735. psaddrinTemp->sin_family = AF_INET;
  736. psaddrinTemp->sin_port = 0xAAAA; // doesn't matter, just anything valid for IsValidUnicastAddress()
  737. //
  738. // Create the banned IPv4 addresses hash table, if we don't have it already.
  739. //
  740. if (g_pHashBannedIPv4Addresses == NULL)
  741. {
  742. g_pHashBannedIPv4Addresses = (CHashTable*) DNMalloc(sizeof(CHashTable));
  743. if (g_pHashBannedIPv4Addresses == NULL)
  744. {
  745. DPFX(DPFPREP, 0, "Couldn't allocate banned IPv4 addresses hash table!");
  746. goto Failure;
  747. }
  748. //
  749. // Initialize the banned address hash with 2 entries and grow by a factor of 2.
  750. //
  751. if (! g_pHashBannedIPv4Addresses->Initialize(1,
  752. #ifndef DPNBUILD_PREALLOCATEDMEMORYMODEL
  753. 1,
  754. #endif // ! DPNBUILD_PREALLOCATEDMEMORYMODEL
  755. BannedIPv4AddressCompareFunction,
  756. BannedIPv4AddressHashFunction))
  757. {
  758. DPFX(DPFPREP, 0, "Couldn't initialize banned IPv4 addresses hash table!");
  759. goto Failure;
  760. }
  761. }
  762. dwIndex = 0;
  763. do
  764. {
  765. dwSize = 16;
  766. if (! pRegObject->EnumValues( wszIPAddress, &dwSize, dwIndex ))
  767. {
  768. break;
  769. }
  770. //
  771. // Read the mask associated with the IP address.
  772. //
  773. if ( pRegObject->ReadDWORD(wszIPAddress, &dwMask))
  774. {
  775. //
  776. // Convert the IP address string to binary.
  777. //
  778. if (STR_jkWideToAnsi(szIPAddress, wszIPAddress, 16) == DPN_OK)
  779. {
  780. //
  781. // Convert the IP address string to binary.
  782. //
  783. psaddrinTemp->sin_addr.S_un.S_addr = inet_addr(szIPAddress);
  784. if (SocketAddressTemp.IsValidUnicastAddress(FALSE))
  785. {
  786. //
  787. // Find the first mask bit. We expect the network byte order of
  788. // the IP address to be opposite of host byte order.
  789. //
  790. dwBit = 0x80000000;
  791. while (! (dwBit & dwMask))
  792. {
  793. psaddrinTemp->sin_addr.S_un.S_addr &= ~dwBit;
  794. dwBit >>= 1;
  795. if (dwBit <= 0x80)
  796. {
  797. break;
  798. }
  799. }
  800. if (dwBit & dwMask)
  801. {
  802. //
  803. // If the masked address is already in the hash, update the mask.
  804. // This allows bans to be listed more than once.
  805. //
  806. if (g_pHashBannedIPv4Addresses->Find((PVOID) ((DWORD_PTR) psaddrinTemp->sin_addr.S_un.S_addr), &pvMask))
  807. {
  808. if (! g_pHashBannedIPv4Addresses->Remove((PVOID) ((DWORD_PTR) psaddrinTemp->sin_addr.S_un.S_addr)))
  809. {
  810. DPFX(DPFPREP, 0, "Couldn't remove masked IPv4 entry %u.%u.%u.%u from ban hash.",
  811. psaddrinTemp->sin_addr.S_un.S_un_b.s_b1,
  812. psaddrinTemp->sin_addr.S_un.S_un_b.s_b2,
  813. psaddrinTemp->sin_addr.S_un.S_un_b.s_b3,
  814. psaddrinTemp->sin_addr.S_un.S_un_b.s_b4);
  815. dwMask = dwBit;
  816. }
  817. else
  818. {
  819. dwMask = ((DWORD) ((DWORD_PTR) pvMask)) | dwBit;
  820. }
  821. }
  822. else
  823. {
  824. dwMask = dwBit;
  825. }
  826. //
  827. // Add (or readd) the masked address to the hash.
  828. //
  829. if (g_pHashBannedIPv4Addresses->Insert((PVOID) ((DWORD_PTR) psaddrinTemp->sin_addr.S_un.S_addr), (PVOID) ((DWORD_PTR) dwMask)))
  830. {
  831. g_dwBannedIPv4Masks |= dwBit;
  832. DPFX(DPFPREP, 5, "Added (or readded) %ls (bits = 0x%08x, masked IPv4 entry %u.%u.%u.%u) to ban hash.",
  833. wszIPAddress,
  834. dwMask,
  835. psaddrinTemp->sin_addr.S_un.S_un_b.s_b1,
  836. psaddrinTemp->sin_addr.S_un.S_un_b.s_b2,
  837. psaddrinTemp->sin_addr.S_un.S_un_b.s_b3,
  838. psaddrinTemp->sin_addr.S_un.S_un_b.s_b4);
  839. }
  840. else
  841. {
  842. DPFX(DPFPREP, 0, "Couldn't add %ls (bits = 0x%08x, masked IPv4 entry %u.%u.%u.%u) to ban hash!",
  843. wszIPAddress,
  844. dwMask,
  845. psaddrinTemp->sin_addr.S_un.S_un_b.s_b1,
  846. psaddrinTemp->sin_addr.S_un.S_un_b.s_b2,
  847. psaddrinTemp->sin_addr.S_un.S_un_b.s_b3,
  848. psaddrinTemp->sin_addr.S_un.S_un_b.s_b4);
  849. }
  850. }
  851. else
  852. {
  853. DPFX(DPFPREP, 0, "Ignoring invalid banned IPv4 entry \"%ls\" (mask = 0x%08x)!",
  854. wszIPAddress, dwMask);
  855. }
  856. }
  857. else
  858. {
  859. DPFX(DPFPREP, 0, "Ignoring invalid banned IPv4 entry \"%ls\" (mask = 0x%08x)!",
  860. wszIPAddress, dwMask);
  861. }
  862. }
  863. else
  864. {
  865. DPFX(DPFPREP, 0, "Couldn't convert banned IPv4 entry \"%ls\" (mask = 0x%08x) to ANSI!",
  866. wszIPAddress, dwMask);
  867. }
  868. }
  869. else
  870. {
  871. DPFX(DPFPREP, 0, "Couldn't read banned IPv4 entry \"%ls\"!", wszIPAddress);
  872. }
  873. dwIndex++;
  874. }
  875. while (TRUE);
  876. DPFX(DPFPREP, 2, "There are now a total of %u IPv4 addresses to ban, mask bits = 0x%08x.",
  877. g_pHashBannedIPv4Addresses->GetEntryCount(),
  878. g_dwBannedIPv4Masks);
  879. Exit:
  880. return;
  881. Failure:
  882. goto Exit;
  883. }
  884. //**********************************************************************
  885. #endif // ! DPNBUILD_NOREGISTRY
  886. //**********************************************************************
  887. // ------------------------------
  888. // InitProcessGlobals - initialize the global items needed for the SP to operate
  889. //
  890. // Entry: Nothing
  891. //
  892. // Exit: Boolean indicating success
  893. // TRUE = success
  894. // FALSE = failure
  895. // ------------------------------
  896. #undef DPF_MODNAME
  897. #define DPF_MODNAME "InitProcessGlobals"
  898. BOOL InitProcessGlobals( void )
  899. {
  900. BOOL fReturn;
  901. BOOL fCriticalSectionInitialized;
  902. #ifdef _XBOX
  903. BOOL fRefcountXnKeysInitted;
  904. #endif // _XBOX
  905. //
  906. // initialize
  907. //
  908. fReturn = TRUE;
  909. fCriticalSectionInitialized = FALSE;
  910. #ifdef _XBOX
  911. fRefcountXnKeysInitted = FALSE;
  912. #endif // _XBOX
  913. #ifdef DBG
  914. g_blDPNWSockCritSecsHeld.Initialize();
  915. #endif // DBG
  916. #ifndef DPNBUILD_NOREGISTRY
  917. ReadSettingsFromRegistry();
  918. #endif // ! DPNBUILD_NOREGISTRY
  919. if ( DNInitializeCriticalSection( &g_InterfaceGlobalsLock ) == FALSE )
  920. {
  921. fReturn = FALSE;
  922. goto Failure;
  923. }
  924. DebugSetCriticalSectionGroup( &g_InterfaceGlobalsLock, &g_blDPNWSockCritSecsHeld ); // separate dpnwsock CSes from the rest of DPlay's CSes
  925. fCriticalSectionInitialized = TRUE;
  926. if ( InitializePools() == FALSE )
  927. {
  928. fReturn = FALSE;
  929. goto Failure;
  930. }
  931. #ifdef _XBOX
  932. #pragma BUGBUG(vanceo, "Find way to retrieve value from XNet")
  933. if ( InitializeRefcountXnKeys(4) == FALSE )
  934. {
  935. fReturn = FALSE;
  936. goto Failure;
  937. }
  938. fRefcountXnKeysInitted = TRUE;
  939. #endif // _XBOX
  940. DNASSERT( g_pThreadPool == NULL );
  941. Exit:
  942. return fReturn;
  943. Failure:
  944. #ifdef _XBOX
  945. if ( fRefcountXnKeysInitted )
  946. {
  947. CleanupRefcountXnKeys();
  948. fRefcountXnKeysInitted = FALSE;
  949. }
  950. #endif // _XBOX
  951. DeinitializePools();
  952. if ( fCriticalSectionInitialized != FALSE )
  953. {
  954. DNDeleteCriticalSection( &g_InterfaceGlobalsLock );
  955. fCriticalSectionInitialized = FALSE;
  956. }
  957. goto Exit;
  958. }
  959. //**********************************************************************
  960. //**********************************************************************
  961. // ------------------------------
  962. // DeinitProcessGlobals - deinitialize the global items
  963. //
  964. // Entry: Nothing
  965. //
  966. // Exit: Nothing
  967. // ------------------------------
  968. #undef DPF_MODNAME
  969. #define DPF_MODNAME "DeinitProcessGlobals"
  970. void DeinitProcessGlobals( void )
  971. {
  972. DNASSERT( g_pThreadPool == NULL );
  973. DNASSERT( g_iThreadPoolRefCount == 0 );
  974. #ifndef DPNBUILD_NOREGISTRY
  975. if (g_pHashBannedIPv4Addresses != NULL)
  976. {
  977. g_pHashBannedIPv4Addresses->RemoveAll();
  978. g_pHashBannedIPv4Addresses->Deinitialize();
  979. DNFree(g_pHashBannedIPv4Addresses);
  980. g_pHashBannedIPv4Addresses = NULL;
  981. g_dwBannedIPv4Masks = 0;
  982. }
  983. #endif // ! DPNBUILD_NOREGISTRY
  984. #ifdef _XBOX
  985. CleanupRefcountXnKeys();
  986. #endif // _XBOX
  987. DeinitializePools();
  988. DNDeleteCriticalSection( &g_InterfaceGlobalsLock );
  989. }
  990. //**********************************************************************
  991. //**********************************************************************
  992. // ------------------------------
  993. // LoadWinsock - load Winsock module into memory
  994. //
  995. // Entry: Nothing
  996. //
  997. // Exit: Boolean indicating success
  998. // ------------------------------
  999. #undef DPF_MODNAME
  1000. #define DPF_MODNAME "LoadWinsock"
  1001. BOOL LoadWinsock( void )
  1002. {
  1003. BOOL fReturn = TRUE;
  1004. int iResult;
  1005. DNEnterCriticalSection( &g_InterfaceGlobalsLock );
  1006. if ( g_iWinsockRefCount == 0 )
  1007. {
  1008. //
  1009. // initialize the bindings to Winsock
  1010. //
  1011. iResult = DWSInitWinSock();
  1012. if ( iResult != 0 ) // failure
  1013. {
  1014. DPFX(DPFPREP, 0, "Problem binding dynamic winsock function (err = %i)!", iResult );
  1015. fReturn = FALSE;
  1016. goto Failure;
  1017. }
  1018. DPFX(DPFPREP, 6, "Successfully bound dynamic WinSock functions." );
  1019. }
  1020. DNASSERT(g_iWinsockRefCount >= 0);
  1021. DNInterlockedIncrement( const_cast<LONG*>(&g_iWinsockRefCount) );
  1022. Exit:
  1023. DNLeaveCriticalSection( &g_InterfaceGlobalsLock );
  1024. return fReturn;
  1025. Failure:
  1026. goto Exit;
  1027. }
  1028. //**********************************************************************
  1029. //**********************************************************************
  1030. // ------------------------------
  1031. // UnloadWinsock - unload Winsock module
  1032. //
  1033. // Entry: Nothing
  1034. //
  1035. // Exit: Nothing
  1036. // ------------------------------
  1037. #undef DPF_MODNAME
  1038. #define DPF_MODNAME "UnloadWinsock"
  1039. void UnloadWinsock( void )
  1040. {
  1041. DNEnterCriticalSection( &g_InterfaceGlobalsLock );
  1042. DNASSERT(g_iWinsockRefCount > 0);
  1043. if ( DNInterlockedDecrement( const_cast<LONG*>(&g_iWinsockRefCount) ) == 0 )
  1044. {
  1045. DPFX(DPFPREP, 6, "Unbinding dynamic WinSock functions.");
  1046. DWSFreeWinSock();
  1047. }
  1048. DNLeaveCriticalSection( &g_InterfaceGlobalsLock );
  1049. }
  1050. //**********************************************************************
  1051. #ifndef DPNBUILD_NONATHELP
  1052. //**********************************************************************
  1053. // ------------------------------
  1054. // LoadNATHelp - create and initialize NAT Help object(s)
  1055. //
  1056. // Entry: Nothing
  1057. //
  1058. // Exit: TRUE if some objects were successfully loaded, FALSE otherwise
  1059. // ------------------------------
  1060. #undef DPF_MODNAME
  1061. #define DPF_MODNAME "LoadNATHelp"
  1062. BOOL LoadNATHelp(void)
  1063. {
  1064. BOOL fReturn;
  1065. HRESULT hr;
  1066. #ifndef DPNBUILD_ONLYONENATHELP
  1067. CRegistry RegEntry;
  1068. CRegistry RegSubentry;
  1069. DWORD dwMaxKeyLen;
  1070. WCHAR * pwszKeyName = NULL;
  1071. DWORD dwEnumIndex;
  1072. DWORD dwKeyLen;
  1073. GUID guid;
  1074. #endif // ! DPNBUILD_ONLYONENATHELP
  1075. DWORD dwDirectPlay8Priority;
  1076. DWORD dwDirectPlay8InitFlags;
  1077. DWORD dwNumLoaded;
  1078. DNEnterCriticalSection(&g_InterfaceGlobalsLock);
  1079. if ( g_iNATHelpRefCount == 0 )
  1080. {
  1081. #ifndef DPNBUILD_ONLYONENATHELP
  1082. //
  1083. // Enumerate all the DirectPlayNAT Helpers.
  1084. //
  1085. if (! RegEntry.Open(HKEY_LOCAL_MACHINE, DIRECTPLAYNATHELP_REGKEY, TRUE, FALSE))
  1086. {
  1087. DPFX(DPFPREP, 0, "Couldn't open DirectPlayNATHelp registry key!");
  1088. goto Failure;
  1089. }
  1090. //
  1091. // Find length of largest subkey.
  1092. //
  1093. if (!RegEntry.GetMaxKeyLen(&dwMaxKeyLen))
  1094. {
  1095. DPFERR("RegistryEntry.GetMaxKeyLen() failed!");
  1096. goto Failure;
  1097. }
  1098. dwMaxKeyLen++; // Null terminator
  1099. DPFX(DPFPREP, 9, "dwMaxKeyLen = %ld", dwMaxKeyLen);
  1100. pwszKeyName = (WCHAR*) DNMalloc(dwMaxKeyLen * sizeof(WCHAR));
  1101. if (pwszKeyName == NULL)
  1102. {
  1103. DPFERR("Allocating key name buffer failed!");
  1104. goto Failure;
  1105. }
  1106. #endif // ! DPNBUILD_ONLYONENATHELP
  1107. //
  1108. // Allocate an array to hold the helper objects.
  1109. //
  1110. g_papNATHelpObjects = (IDirectPlayNATHelp**) DNMalloc(MAX_NUM_DIRECTPLAYNATHELPERS * sizeof(IDirectPlayNATHelp*));
  1111. if (g_papNATHelpObjects == NULL)
  1112. {
  1113. DPFERR("DNMalloc() failed");
  1114. goto Failure;
  1115. }
  1116. ZeroMemory(g_papNATHelpObjects,
  1117. (MAX_NUM_DIRECTPLAYNATHELPERS * sizeof(IDirectPlayNATHelp*)));
  1118. #ifndef DPNBUILD_ONLYONENATHELP
  1119. dwEnumIndex = 0;
  1120. #endif // ! DPNBUILD_ONLYONENATHELP
  1121. dwNumLoaded = 0;
  1122. //
  1123. // Enumerate the DirectPlay NAT helpers.
  1124. //
  1125. do
  1126. {
  1127. #ifdef DPNBUILD_ONLYONENATHELP
  1128. WCHAR * pwszKeyName;
  1129. pwszKeyName = L"UPnP";
  1130. dwDirectPlay8Priority = 1;
  1131. dwDirectPlay8InitFlags = 0; // default UPnP flags
  1132. #else // ! DPNBUILD_ONLYONENATHELP
  1133. dwKeyLen = dwMaxKeyLen;
  1134. if (! RegEntry.EnumKeys(pwszKeyName, &dwKeyLen, dwEnumIndex))
  1135. {
  1136. break;
  1137. }
  1138. dwEnumIndex++;
  1139. DPFX(DPFPREP, 8, "%ld - %ls (%ld)", dwEnumIndex, pwszKeyName, dwKeyLen);
  1140. if (!RegSubentry.Open(RegEntry, pwszKeyName, TRUE, FALSE))
  1141. {
  1142. DPFX(DPFPREP, 0, "Couldn't open subentry \"%ls\"! Skipping.", pwszKeyName);
  1143. continue;
  1144. }
  1145. //
  1146. // Read the DirectPlay8 priority
  1147. //
  1148. if (!RegSubentry.ReadDWORD(REGSUBKEY_DPNATHELP_DIRECTPLAY8PRIORITY, &dwDirectPlay8Priority))
  1149. {
  1150. DPFX(DPFPREP, 0, "RegSubentry.ReadDWORD \"%ls\\%ls\" failed! Skipping.",
  1151. pwszKeyName, REGSUBKEY_DPNATHELP_DIRECTPLAY8PRIORITY);
  1152. RegSubentry.Close();
  1153. continue;
  1154. }
  1155. //
  1156. // Read the DirectPlay8 initialization flags
  1157. //
  1158. if (!RegSubentry.ReadDWORD(REGSUBKEY_DPNATHELP_DIRECTPLAY8INITFLAGS, &dwDirectPlay8InitFlags))
  1159. {
  1160. DPFX(DPFPREP, 0, "RegSubentry.ReadDWORD \"%ls\\%ls\" failed! Defaulting to 0.",
  1161. pwszKeyName, REGSUBKEY_DPNATHELP_DIRECTPLAY8INITFLAGS);
  1162. dwDirectPlay8InitFlags = 0;
  1163. }
  1164. //
  1165. // Read the object's CLSID.
  1166. //
  1167. if (!RegSubentry.ReadGUID(REGSUBKEY_DPNATHELP_GUID, &guid))
  1168. {
  1169. DPFX(DPFPREP, 0,"RegSubentry.ReadGUID \"%ls\\%ls\" failed! Skipping.",
  1170. pwszKeyName, REGSUBKEY_DPNATHELP_GUID);
  1171. RegSubentry.Close();
  1172. continue;
  1173. }
  1174. //
  1175. // Close the subkey.
  1176. //
  1177. RegSubentry.Close();
  1178. //
  1179. // If this helper should be loaded, do so.
  1180. //
  1181. if (dwDirectPlay8Priority == 0)
  1182. {
  1183. DPFX(DPFPREP, 1, "DirectPlay NAT Helper \"%ls\" is not enabled for DirectPlay8.", pwszKeyName);
  1184. }
  1185. else
  1186. #endif // ! DPNBUILD_ONLYONENATHELP
  1187. {
  1188. #ifdef DPNBUILD_ONLYONENATHELP
  1189. //
  1190. // Try to create the NAT Help object. COM should have been
  1191. // initialized by now by someone else.
  1192. //
  1193. hr = COM_CoCreateInstance(CLSID_DirectPlayNATHelpUPnP,
  1194. NULL,
  1195. CLSCTX_INPROC_SERVER,
  1196. IID_IDirectPlayNATHelp,
  1197. (LPVOID*) (&g_papNATHelpObjects[dwDirectPlay8Priority - 1]), FALSE);
  1198. #else // ! DPNBUILD_ONLYONENATHELP
  1199. //
  1200. // Make sure this priority is valid.
  1201. //
  1202. if (dwDirectPlay8Priority > MAX_NUM_DIRECTPLAYNATHELPERS)
  1203. {
  1204. DPFX(DPFPREP, 0, "Ignoring DirectPlay NAT helper \"%ls\" with invalid priority level set too high (%u > %u).",
  1205. pwszKeyName, dwDirectPlay8Priority, MAX_NUM_DIRECTPLAYNATHELPERS);
  1206. continue;
  1207. }
  1208. //
  1209. // Make sure this priority hasn't already been taken.
  1210. //
  1211. if (g_papNATHelpObjects[dwDirectPlay8Priority - 1] != NULL)
  1212. {
  1213. DPFX(DPFPREP, 0, "Ignoring DirectPlay NAT helper \"%ls\" with duplicate priority level %u (existing object = 0x%p).",
  1214. pwszKeyName, dwDirectPlay8Priority,
  1215. g_papNATHelpObjects[dwDirectPlay8Priority - 1]);
  1216. continue;
  1217. }
  1218. //
  1219. // Try to create the NAT Help object. COM should have been
  1220. // initialized by now by someone else.
  1221. //
  1222. hr = COM_CoCreateInstance(guid,
  1223. NULL,
  1224. CLSCTX_INPROC_SERVER,
  1225. IID_IDirectPlayNATHelp,
  1226. (LPVOID*) (&g_papNATHelpObjects[dwDirectPlay8Priority - 1]), FALSE);
  1227. #endif // ! DPNBUILD_ONLYONENATHELP
  1228. if ( hr != S_OK )
  1229. {
  1230. DNASSERT( g_papNATHelpObjects[dwDirectPlay8Priority - 1] == NULL );
  1231. DPFX(DPFPREP, 0, "Failed to create \"%ls\" IDirectPlayNATHelp interface (error = 0x%lx)! Skipping.",
  1232. pwszKeyName, hr);
  1233. continue;
  1234. }
  1235. //
  1236. // Initialize NAT Help.
  1237. //
  1238. #ifndef DPNBUILD_NOREGISTRY
  1239. DNASSERT((! g_fDisableDPNHGatewaySupport) || (! g_fDisableDPNHFirewallSupport));
  1240. if (g_fDisableDPNHGatewaySupport)
  1241. {
  1242. dwDirectPlay8InitFlags |= DPNHINITIALIZE_DISABLEGATEWAYSUPPORT;
  1243. }
  1244. if (g_fDisableDPNHFirewallSupport)
  1245. {
  1246. dwDirectPlay8InitFlags |= DPNHINITIALIZE_DISABLELOCALFIREWALLSUPPORT;
  1247. }
  1248. #endif // ! DPNBUILD_NOREGISTRY
  1249. //
  1250. // Make sure the flags we're passing are valid.
  1251. //
  1252. if ((dwDirectPlay8InitFlags & (DPNHINITIALIZE_DISABLEGATEWAYSUPPORT | DPNHINITIALIZE_DISABLELOCALFIREWALLSUPPORT)) == (DPNHINITIALIZE_DISABLEGATEWAYSUPPORT | DPNHINITIALIZE_DISABLELOCALFIREWALLSUPPORT))
  1253. {
  1254. DPFX(DPFPREP, 1, "Not loading NAT Help \"%ls\" because both DISABLEGATEWAYSUPPORT and DISABLELOCALFIREWALLSUPPORT would have been specified (priority = %u, flags = 0x%lx).",
  1255. pwszKeyName, dwDirectPlay8Priority, dwDirectPlay8InitFlags);
  1256. IDirectPlayNATHelp_Release(g_papNATHelpObjects[dwDirectPlay8Priority - 1]);
  1257. g_papNATHelpObjects[dwDirectPlay8Priority - 1] = NULL;
  1258. continue;
  1259. }
  1260. hr = IDirectPlayNATHelp_Initialize(g_papNATHelpObjects[dwDirectPlay8Priority - 1], dwDirectPlay8InitFlags);
  1261. if (hr != DPNH_OK)
  1262. {
  1263. DPFX(DPFPREP, 0, "Couldn't initialize NAT Help \"%ls\" (error = 0x%lx)! Skipping.",
  1264. pwszKeyName, hr);
  1265. IDirectPlayNATHelp_Release(g_papNATHelpObjects[dwDirectPlay8Priority - 1]);
  1266. g_papNATHelpObjects[dwDirectPlay8Priority - 1] = NULL;
  1267. continue;
  1268. }
  1269. DPFX(DPFPREP, 8, "Initialized NAT Help \"%ls\" (priority = %u, flags = 0x%lx, object = 0x%p).",
  1270. pwszKeyName, dwDirectPlay8Priority, dwDirectPlay8InitFlags, g_papNATHelpObjects[dwDirectPlay8Priority - 1]);
  1271. dwNumLoaded++;
  1272. }
  1273. }
  1274. #ifdef DPNBUILD_ONLYONENATHELP
  1275. while (FALSE);
  1276. #else // ! DPNBUILD_ONLYONENATHELP
  1277. while (TRUE);
  1278. #endif // ! DPNBUILD_ONLYONENATHELP
  1279. //
  1280. // If we didn't load any NAT helper objects, free up the memory.
  1281. //
  1282. if (dwNumLoaded == 0)
  1283. {
  1284. DNFree(g_papNATHelpObjects);
  1285. g_papNATHelpObjects = NULL;
  1286. //
  1287. // We never got anything. Fail.
  1288. //
  1289. goto Failure;
  1290. }
  1291. DPFX(DPFPREP, 8, "Loaded %u DirectPlay NAT Helper objects.", dwNumLoaded);
  1292. }
  1293. else
  1294. {
  1295. DPFX(DPFPREP, 8, "Already loaded NAT Help objects.");
  1296. }
  1297. //
  1298. // We have the interface globals lock, don't need DNInterlockedIncrement.
  1299. //
  1300. g_iNATHelpRefCount++;
  1301. //
  1302. // We succeeded.
  1303. //
  1304. fReturn = TRUE;
  1305. Exit:
  1306. DNLeaveCriticalSection(&g_InterfaceGlobalsLock);
  1307. #ifndef DPNBUILD_ONLYONENATHELP
  1308. if (pwszKeyName != NULL)
  1309. {
  1310. DNFree(pwszKeyName);
  1311. pwszKeyName = NULL;
  1312. }
  1313. #endif // ! DPNBUILD_ONLYONENATHELP
  1314. return fReturn;
  1315. Failure:
  1316. //
  1317. // We can only fail during the first initialize, so therefore we will never be freeing
  1318. // g_papNATHelpObjects when we didn't allocate it in this function.
  1319. //
  1320. if (g_papNATHelpObjects != NULL)
  1321. {
  1322. DNFree(g_papNATHelpObjects);
  1323. g_papNATHelpObjects = NULL;
  1324. }
  1325. fReturn = FALSE;
  1326. goto Exit;
  1327. }
  1328. //**********************************************************************
  1329. //**********************************************************************
  1330. // ------------------------------
  1331. // UnloadNATHelp - release the NAT Help object
  1332. //
  1333. // Entry: Nothing
  1334. //
  1335. // Exit: Nothing
  1336. // ------------------------------
  1337. #undef DPF_MODNAME
  1338. #define DPF_MODNAME "UnloadNATHelp"
  1339. void UnloadNATHelp(void)
  1340. {
  1341. DWORD dwTemp;
  1342. DNEnterCriticalSection(&g_InterfaceGlobalsLock);
  1343. //
  1344. // We have the interface globals lock, don't need DNInterlockedDecrement.
  1345. //
  1346. DNASSERT(g_iNATHelpRefCount > 0);
  1347. g_iNATHelpRefCount--;
  1348. if (g_iNATHelpRefCount == 0 )
  1349. {
  1350. HRESULT hr;
  1351. DNASSERT(g_papNATHelpObjects != NULL);
  1352. for(dwTemp = 0; dwTemp < MAX_NUM_DIRECTPLAYNATHELPERS; dwTemp++)
  1353. {
  1354. if (g_papNATHelpObjects[dwTemp] != NULL)
  1355. {
  1356. DPFX(DPFPREP, 8, "Closing NAT Help object priority %u (0x%p).",
  1357. dwTemp, g_papNATHelpObjects[dwTemp]);
  1358. hr = IDirectPlayNATHelp_Close(g_papNATHelpObjects[dwTemp], 0);
  1359. if (hr != DPNH_OK)
  1360. {
  1361. DPFX(DPFPREP, 0, "Problem closing NAT Help object %u (error = 0x%lx), continuing.",
  1362. dwTemp, hr);
  1363. }
  1364. IDirectPlayNATHelp_Release(g_papNATHelpObjects[dwTemp]);
  1365. g_papNATHelpObjects[dwTemp] = NULL;
  1366. }
  1367. }
  1368. DNFree(g_papNATHelpObjects);
  1369. g_papNATHelpObjects = NULL;
  1370. }
  1371. else
  1372. {
  1373. DPFX(DPFPREP, 8, "NAT Help object(s) still have %i references.",
  1374. g_iNATHelpRefCount);
  1375. }
  1376. DNLeaveCriticalSection( &g_InterfaceGlobalsLock );
  1377. }
  1378. //**********************************************************************
  1379. #endif // DPNBUILD_NONATHELP
  1380. #if ((defined(WINNT)) && (! defined(DPNBUILD_NOMULTICAST)))
  1381. //**********************************************************************
  1382. // ------------------------------
  1383. // LoadMADCAP - create and initialize MADCAP API
  1384. //
  1385. // Entry: Nothing
  1386. //
  1387. // Exit: TRUE if the API was successfully loaded, FALSE otherwise
  1388. // ------------------------------
  1389. #undef DPF_MODNAME
  1390. #define DPF_MODNAME "LoadMadcap"
  1391. BOOL LoadMadcap(void)
  1392. {
  1393. BOOL fReturn;
  1394. DWORD dwError;
  1395. DWORD dwMadcapVersion;
  1396. #ifndef DPNBUILD_NOREGISTRY
  1397. DNASSERT(! g_fDisableMadcapSupport);
  1398. #endif // ! DPNBUILD_NOREGISTRY
  1399. DNEnterCriticalSection(&g_InterfaceGlobalsLock);
  1400. if ( g_iMadcapRefCount == 0 )
  1401. {
  1402. //
  1403. // Initialize the MADCAP API.
  1404. //
  1405. dwMadcapVersion = MCAST_API_CURRENT_VERSION;
  1406. dwError = McastApiStartup(&dwMadcapVersion);
  1407. if (dwError != ERROR_SUCCESS)
  1408. {
  1409. DPFX(DPFPREP, 0, "Failed starting MADCAP version %u (err = %u)!",
  1410. MCAST_API_CURRENT_VERSION, dwError);
  1411. goto Failure;
  1412. }
  1413. DPFX(DPFPREP, 5, "Using MADCAP version %u (supported version = %u).",
  1414. MCAST_API_CURRENT_VERSION, dwMadcapVersion);
  1415. //
  1416. // Create a unique client ID.
  1417. //
  1418. g_mcClientUid.ClientUID = g_abClientID;
  1419. g_mcClientUid.ClientUIDLength = sizeof(g_abClientID);
  1420. dwError = McastGenUID(&g_mcClientUid);
  1421. if (dwError != ERROR_SUCCESS)
  1422. {
  1423. DPFX(DPFPREP, 0, "Failed creating MADCAP client ID (err = %u)!",
  1424. dwError);
  1425. goto Failure;
  1426. }
  1427. }
  1428. else
  1429. {
  1430. DPFX(DPFPREP, 8, "Already loaded MADCAP.");
  1431. }
  1432. //
  1433. // We have the interface globals lock, don't need DNInterlockedIncrement.
  1434. //
  1435. g_iMadcapRefCount++;
  1436. //
  1437. // We succeeded.
  1438. //
  1439. fReturn = TRUE;
  1440. Exit:
  1441. DNLeaveCriticalSection(&g_InterfaceGlobalsLock);
  1442. return fReturn;
  1443. Failure:
  1444. fReturn = FALSE;
  1445. goto Exit;
  1446. }
  1447. //**********************************************************************
  1448. //**********************************************************************
  1449. // ------------------------------
  1450. // UnloadMadcap - release the MADCAP interface
  1451. //
  1452. // Entry: Nothing
  1453. //
  1454. // Exit: Nothing
  1455. // ------------------------------
  1456. #undef DPF_MODNAME
  1457. #define DPF_MODNAME "UnloadMadcap"
  1458. void UnloadMadcap(void)
  1459. {
  1460. DNEnterCriticalSection(&g_InterfaceGlobalsLock);
  1461. //
  1462. // We have the interface globals lock, don't need DNInterlockedDecrement.
  1463. //
  1464. DNASSERT(g_iMadcapRefCount > 0);
  1465. g_iMadcapRefCount--;
  1466. if (g_iMadcapRefCount == 0 )
  1467. {
  1468. DPFX(DPFPREP, 5, "Unloading MADCAP API.");
  1469. McastApiCleanup();
  1470. }
  1471. else
  1472. {
  1473. DPFX(DPFPREP, 8, "MADCAP API still has %i references.",
  1474. g_iMadcapRefCount);
  1475. }
  1476. DNLeaveCriticalSection( &g_InterfaceGlobalsLock );
  1477. }
  1478. //**********************************************************************
  1479. #endif // WINNT and not DPNBUILD_NOMULTICAST
  1480. //**********************************************************************
  1481. // ------------------------------
  1482. // CreateSPData - create instance data for SP
  1483. //
  1484. // Entry: Pointer to pointer to SPData
  1485. // Interface type
  1486. // Pointer to COM interface vtable
  1487. //
  1488. // Exit: Error code
  1489. // ------------------------------
  1490. #undef DPF_MODNAME
  1491. #define DPF_MODNAME "CreateSPData"
  1492. HRESULT CreateSPData( CSPData **const ppSPData,
  1493. #if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
  1494. const short sSPType,
  1495. #endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
  1496. #ifdef DPNBUILD_PREALLOCATEDMEMORYMODEL
  1497. const XDP8CREATE_PARAMS * const pDP8CreateParams,
  1498. #endif // DPNBUILD_PREALLOCATEDMEMORYMODEL
  1499. IDP8ServiceProviderVtbl *const pVtbl )
  1500. {
  1501. HRESULT hr;
  1502. CSPData *pSPData;
  1503. DNASSERT( ppSPData != NULL );
  1504. #ifdef DPNBUILD_PREALLOCATEDMEMORYMODEL
  1505. DNASSERT( pDP8CreateParams != NULL );
  1506. #endif // DPNBUILD_PREALLOCATEDMEMORYMODEL
  1507. DNASSERT( pVtbl != NULL );
  1508. //
  1509. // initialize
  1510. //
  1511. hr = DPN_OK;
  1512. *ppSPData = NULL;
  1513. pSPData = NULL;
  1514. //
  1515. // create data
  1516. //
  1517. pSPData = (CSPData*) DNMalloc(sizeof(CSPData));
  1518. if ( pSPData == NULL )
  1519. {
  1520. hr = DPNERR_OUTOFMEMORY;
  1521. DPFX(DPFPREP, 0, "Cannot create data for Winsock interface!" );
  1522. goto Failure;
  1523. }
  1524. hr = pSPData->Initialize( pVtbl
  1525. #if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
  1526. ,sSPType
  1527. #endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
  1528. #ifdef DPNBUILD_PREALLOCATEDMEMORYMODEL
  1529. ,pDP8CreateParams
  1530. #endif // DPNBUILD_PREALLOCATEDMEMORYMODEL
  1531. );
  1532. if ( hr != DPN_OK )
  1533. {
  1534. DPFX(DPFPREP, 0, "Failed to intialize SP data!" );
  1535. DisplayDNError( 0, hr );
  1536. goto Failure;
  1537. }
  1538. DPFX(DPFPREP, 6, "Created SP Data object 0x%p.", pSPData);
  1539. pSPData->AddRef(); // reference is now 1
  1540. *ppSPData = pSPData;
  1541. Exit:
  1542. return hr;
  1543. Failure:
  1544. if ( pSPData != NULL )
  1545. {
  1546. DNFree(pSPData);
  1547. pSPData = NULL;
  1548. }
  1549. DPFX(DPFPREP, 0, "Problem with CreateSPData (err = 0x%lx)!", hr);
  1550. DisplayDNError( 0, hr );
  1551. goto Exit;
  1552. }
  1553. //**********************************************************************
  1554. //**********************************************************************
  1555. // ------------------------------
  1556. // InitializeInterfaceGlobals - perform global initialization for an interface.
  1557. //
  1558. // Entry: Pointer to SPData
  1559. //
  1560. // Exit: Error code
  1561. // ------------------------------
  1562. #undef DPF_MODNAME
  1563. #define DPF_MODNAME "InitializeInterfaceGlobals"
  1564. HRESULT InitializeInterfaceGlobals( CSPData *const pSPData )
  1565. {
  1566. HRESULT hr;
  1567. CThreadPool *pThreadPool;
  1568. DNASSERT( pSPData != NULL );
  1569. //
  1570. // initialize
  1571. //
  1572. hr = DPN_OK;
  1573. pThreadPool = NULL;
  1574. DNEnterCriticalSection( &g_InterfaceGlobalsLock );
  1575. if ( g_pThreadPool == NULL )
  1576. {
  1577. DNASSERT( g_iThreadPoolRefCount == 0 );
  1578. g_pThreadPool = (CThreadPool*)g_ThreadPoolPool.Get();
  1579. if ( g_pThreadPool != NULL )
  1580. {
  1581. hr = g_pThreadPool->Initialize();
  1582. if ( hr != DPN_OK )
  1583. {
  1584. DPFX(DPFPREP, 0, "Initializing thread pool failed (err = 0x%lx)!", hr);
  1585. g_ThreadPoolPool.Release(g_pThreadPool);
  1586. g_pThreadPool = NULL;
  1587. hr = DPNERR_OUTOFMEMORY;
  1588. goto Failure;
  1589. }
  1590. else
  1591. {
  1592. g_pThreadPool->AddRef();
  1593. g_iThreadPoolRefCount++;
  1594. pThreadPool = g_pThreadPool;
  1595. }
  1596. }
  1597. }
  1598. else
  1599. {
  1600. DNASSERT( g_iThreadPoolRefCount != 0 );
  1601. g_iThreadPoolRefCount++;
  1602. g_pThreadPool->AddRef();
  1603. pThreadPool = g_pThreadPool;
  1604. }
  1605. Exit:
  1606. DNLeaveCriticalSection( &g_InterfaceGlobalsLock );
  1607. pSPData->SetThreadPool( g_pThreadPool );
  1608. return hr;
  1609. Failure:
  1610. goto Exit;
  1611. }
  1612. //**********************************************************************
  1613. //**********************************************************************
  1614. // ------------------------------
  1615. // DeinitializeInterfaceGlobals - deinitialize thread pool and Rsip
  1616. //
  1617. // Entry: Pointer to service provider
  1618. //
  1619. // Exit: Nothing
  1620. // ------------------------------
  1621. #undef DPF_MODNAME
  1622. #define DPF_MODNAME "DeinitializeInterfaceGlobals"
  1623. void DeinitializeInterfaceGlobals( CSPData *const pSPData )
  1624. {
  1625. CThreadPool *pThreadPool;
  1626. DNASSERT( pSPData != NULL );
  1627. //
  1628. // initialize
  1629. //
  1630. pThreadPool = NULL;
  1631. //
  1632. // Process as little as possible inside the lock. If any of the items
  1633. // need to be released, pointers to them will be set.
  1634. //
  1635. DNEnterCriticalSection( &g_InterfaceGlobalsLock );
  1636. DNASSERT( g_pThreadPool != NULL );
  1637. DNASSERT( g_iThreadPoolRefCount != 0 );
  1638. DNASSERT( g_pThreadPool == pSPData->GetThreadPool() );
  1639. pThreadPool = pSPData->GetThreadPool();
  1640. //
  1641. // remove thread pool reference
  1642. //
  1643. DNASSERT( pThreadPool != NULL );
  1644. g_iThreadPoolRefCount--;
  1645. if ( g_iThreadPoolRefCount == 0 )
  1646. {
  1647. g_pThreadPool = NULL;
  1648. }
  1649. else
  1650. {
  1651. pThreadPool = NULL;
  1652. }
  1653. DNLeaveCriticalSection( &g_InterfaceGlobalsLock );
  1654. //
  1655. // The thread pool will be cleaned up when all of the outstanding interfaces
  1656. // close.
  1657. //
  1658. }
  1659. //**********************************************************************
  1660. #ifndef DPNBUILD_NOIPV6
  1661. //**********************************************************************
  1662. // ------------------------------
  1663. // DNIpv6AddressToStringW - Stolen from RtlIpv6AddressToString
  1664. //
  1665. // Generates an IPv6 string literal corresponding to the address Addr.
  1666. // The shortened canonical forms are used (RFC 1884 etc).
  1667. // The basic string representation consists of 8 hex numbers
  1668. // separated by colons, with a couple embellishments:
  1669. // - a string of zero numbers (at most one) is replaced
  1670. // with a double-colon.
  1671. // - the last 32 bits are represented in IPv4-style dotted-octet notation
  1672. // if the address is a v4-compatible or ISATAP address.
  1673. //
  1674. // For example,
  1675. // ::
  1676. // ::1
  1677. // ::157.56.138.30
  1678. // ::ffff:156.56.136.75
  1679. // ff01::
  1680. // ff02::2
  1681. // 0:1:2:3:4:5:6:7
  1682. //
  1683. // Entry: S - Receives a pointer to the buffer in which to place the string literal
  1684. // Addr - Receives the IPv6 address
  1685. //
  1686. // Exit: Pointer to the null byte at the end of the string inserted.
  1687. // This can be used by the caller to easily append more information
  1688. // ------------------------------
  1689. #undef DPF_MODNAME
  1690. #define DPF_MODNAME "DNIpv6AddressToStringW"
  1691. LPWSTR DNIpv6AddressToStringW(const struct in6_addr *Addr, LPWSTR S)
  1692. {
  1693. int maxFirst, maxLast;
  1694. int curFirst, curLast;
  1695. int i;
  1696. int endHex = 8;
  1697. // Check for IPv6-compatible, IPv4-mapped, and IPv4-translated
  1698. // addresses
  1699. if ((Addr->s6_words[0] == 0) && (Addr->s6_words[1] == 0) &&
  1700. (Addr->s6_words[2] == 0) && (Addr->s6_words[3] == 0) &&
  1701. (Addr->s6_words[6] != 0)) {
  1702. if ((Addr->s6_words[4] == 0) &&
  1703. ((Addr->s6_words[5] == 0) || (Addr->s6_words[5] == 0xffff)))
  1704. {
  1705. // compatible or mapped
  1706. S += _stprintf(S, _T("::%hs%u.%u.%u.%u"),
  1707. Addr->s6_words[5] == 0 ? "" : "ffff:",
  1708. Addr->s6_bytes[12], Addr->s6_bytes[13],
  1709. Addr->s6_bytes[14], Addr->s6_bytes[15]);
  1710. return S;
  1711. }
  1712. else if ((Addr->s6_words[4] == 0xffff) && (Addr->s6_words[5] == 0)) {
  1713. // translated
  1714. S += _stprintf(S, _T("::ffff:0:%u.%u.%u.%u"),
  1715. Addr->s6_bytes[12], Addr->s6_bytes[13],
  1716. Addr->s6_bytes[14], Addr->s6_bytes[15]);
  1717. return S;
  1718. }
  1719. }
  1720. // Find largest contiguous substring of zeroes
  1721. // A substring is [First, Last), so it's empty if First == Last.
  1722. maxFirst = maxLast = 0;
  1723. curFirst = curLast = 0;
  1724. // ISATAP EUI64 starts with 00005EFE (or 02005EFE)...
  1725. if (((Addr->s6_words[4] & 0xfffd) == 0) && (Addr->s6_words[5] == 0xfe5e)) {
  1726. endHex = 6;
  1727. }
  1728. for (i = 0; i < endHex; i++) {
  1729. if (Addr->s6_words[i] == 0) {
  1730. // Extend current substring
  1731. curLast = i+1;
  1732. // Check if current is now largest
  1733. if (curLast - curFirst > maxLast - maxFirst) {
  1734. maxFirst = curFirst;
  1735. maxLast = curLast;
  1736. }
  1737. }
  1738. else {
  1739. // Start a new substring
  1740. curFirst = curLast = i+1;
  1741. }
  1742. }
  1743. // Ignore a substring of length 1.
  1744. if (maxLast - maxFirst <= 1)
  1745. maxFirst = maxLast = 0;
  1746. // Write colon-separated words.
  1747. // A double-colon takes the place of the longest string of zeroes.
  1748. // All zeroes is just "::".
  1749. for (i = 0; i < endHex; i++) {
  1750. // Skip over string of zeroes
  1751. if ((maxFirst <= i) && (i < maxLast)) {
  1752. S += _stprintf(S, _T("::"));
  1753. i = maxLast-1;
  1754. continue;
  1755. }
  1756. // Need colon separator if not at beginning
  1757. if ((i != 0) && (i != maxLast))
  1758. S += _stprintf(S, _T(":"));
  1759. S += _stprintf(S, _T("%x"), NTOHS(Addr->s6_words[i])); // swap bytes
  1760. }
  1761. if (endHex < 8) {
  1762. S += _stprintf(S, _T(":%u.%u.%u.%u"),
  1763. Addr->s6_bytes[12], Addr->s6_bytes[13],
  1764. Addr->s6_bytes[14], Addr->s6_bytes[15]);
  1765. }
  1766. return S;
  1767. }
  1768. #endif // ! DPNBUILD_NOIPV6
  1769. //**********************************************************************
  1770. // ------------------------------
  1771. // AddInfoToBuffer - add an adapter info/multicast scope info structure to a packed buffer
  1772. //
  1773. // Entry: Pointer to packed buffer
  1774. // Pointer to adapter/scope name
  1775. // Pointer to adapter/scope guid
  1776. //
  1777. // Exit: Error code
  1778. // ------------------------------
  1779. #undef DPF_MODNAME
  1780. #define DPF_MODNAME "AddInfoToBuffer"
  1781. HRESULT AddInfoToBuffer( CPackedBuffer *const pPackedBuffer,
  1782. const WCHAR *const pwszInfoName,
  1783. const GUID *const pInfoGUID,
  1784. const DWORD dwFlags )
  1785. {
  1786. HRESULT hr;
  1787. DPN_SERVICE_PROVIDER_INFO AdapterInfo;
  1788. #ifndef DPNBUILD_NOMULTICAST
  1789. DBG_CASSERT( sizeof( DPN_SERVICE_PROVIDER_INFO ) == sizeof( DPN_MULTICAST_SCOPE_INFO ) );
  1790. DBG_CASSERT( OFFSETOF( DPN_SERVICE_PROVIDER_INFO, dwFlags ) == OFFSETOF( DPN_MULTICAST_SCOPE_INFO, dwFlags ) );
  1791. DBG_CASSERT( OFFSETOF( DPN_SERVICE_PROVIDER_INFO, guid ) == OFFSETOF( DPN_MULTICAST_SCOPE_INFO, guid ) );
  1792. DBG_CASSERT( OFFSETOF( DPN_SERVICE_PROVIDER_INFO, pwszName ) == OFFSETOF( DPN_MULTICAST_SCOPE_INFO, pwszName ) );
  1793. DBG_CASSERT( OFFSETOF( DPN_SERVICE_PROVIDER_INFO, pvReserved ) == OFFSETOF( DPN_MULTICAST_SCOPE_INFO, pvReserved ) );
  1794. DBG_CASSERT( OFFSETOF( DPN_SERVICE_PROVIDER_INFO, dwReserved ) == OFFSETOF( DPN_MULTICAST_SCOPE_INFO, dwReserved ) );
  1795. #endif // ! DPNBUILD_NOMULTICAST
  1796. DNASSERT( pPackedBuffer != NULL );
  1797. DNASSERT( pwszInfoName != NULL );
  1798. DNASSERT( pInfoGUID != NULL );
  1799. //
  1800. // initialize
  1801. //
  1802. hr = DPN_OK;
  1803. memset( &AdapterInfo, 0x00, sizeof( AdapterInfo ) );
  1804. AdapterInfo.dwFlags = dwFlags;
  1805. AdapterInfo.guid = *pInfoGUID;
  1806. hr = pPackedBuffer->AddWCHARStringToBack( pwszInfoName );
  1807. if ( ( hr != DPNERR_BUFFERTOOSMALL ) && ( hr != DPN_OK ) )
  1808. {
  1809. DPFX(DPFPREP, 0, "Failed to add info name to buffer!" );
  1810. goto Failure;
  1811. }
  1812. AdapterInfo.pwszName = static_cast<WCHAR*>( pPackedBuffer->GetTailAddress() );
  1813. hr = pPackedBuffer->AddToFront( &AdapterInfo, sizeof( AdapterInfo ) );
  1814. Exit:
  1815. return hr;
  1816. Failure:
  1817. goto Exit;
  1818. }
  1819. //**********************************************************************
  1820. #ifdef _XBOX
  1821. typedef struct _REFCOUNTXNKEY
  1822. {
  1823. LONG lRefCount;
  1824. XNKID xnkid;
  1825. XNKEY xnkey;
  1826. } REFCOUNTXNKEY;
  1827. REFCOUNTXNKEY * g_paRefcountXnKeys = NULL;
  1828. DWORD g_dwMaxNumRefcountXnKeys = 0;
  1829. #undef DPF_MODNAME
  1830. #define DPF_MODNAME "InitializeRefcountXnKeys"
  1831. BOOL InitializeRefcountXnKeys(const DWORD dwKeyRegMax)
  1832. {
  1833. BOOL fResult;
  1834. DPFX(DPFPREP, 3, "Parameters: (%u)", dwKeyRegMax);
  1835. DNASSERT(dwKeyRegMax != 0);
  1836. DNASSERT(g_paRefcountXnKeys == NULL);
  1837. g_paRefcountXnKeys = (REFCOUNTXNKEY*) DNMalloc(dwKeyRegMax * sizeof(REFCOUNTXNKEY));
  1838. if (g_paRefcountXnKeys == NULL)
  1839. {
  1840. g_dwMaxNumRefcountXnKeys = 0;
  1841. fResult = FALSE;
  1842. }
  1843. else
  1844. {
  1845. memset(g_paRefcountXnKeys, 0, (dwKeyRegMax * sizeof(REFCOUNTXNKEY)));
  1846. g_dwMaxNumRefcountXnKeys = dwKeyRegMax;
  1847. fResult = TRUE;
  1848. }
  1849. DPFX(DPFPREP, 3, "Returning: [%i]", fResult);
  1850. return fResult;
  1851. }
  1852. #undef DPF_MODNAME
  1853. #define DPF_MODNAME "CleanupRefcountXnKeys"
  1854. void WINAPI CleanupRefcountXnKeys(void)
  1855. {
  1856. #ifdef DBG
  1857. DWORD dwTemp;
  1858. DPFX(DPFPREP, 3, "Enter");
  1859. DNASSERT(g_paRefcountXnKeys != NULL);
  1860. for(dwTemp = 0; dwTemp < g_dwMaxNumRefcountXnKeys; dwTemp++)
  1861. {
  1862. DNASSERT(g_paRefcountXnKeys[dwTemp].lRefCount == 0);
  1863. }
  1864. #endif // DBG
  1865. DNFree(g_paRefcountXnKeys);
  1866. g_paRefcountXnKeys = NULL;
  1867. g_dwMaxNumRefcountXnKeys = 0;
  1868. DPFX(DPFPREP, 3, "Leave");
  1869. }
  1870. #undef DPF_MODNAME
  1871. #define DPF_MODNAME "RegisterRefcountXnKey"
  1872. INT WINAPI RegisterRefcountXnKey(const XNKID * pxnkid, const XNKEY * pxnkey)
  1873. {
  1874. int iReturn;
  1875. DWORD dwTemp;
  1876. DWORD dwIndex = -1;
  1877. DPFX(DPFPREP, 3, "Parameters: (0x%p, 0x%p)", pxnkid, pxnkey);
  1878. DNASSERT(pxnkid != NULL);
  1879. DNASSERT(pxnkey != NULL);
  1880. DNASSERT(g_paRefcountXnKeys != NULL);
  1881. for(dwTemp = 0; dwTemp < g_dwMaxNumRefcountXnKeys; dwTemp++)
  1882. {
  1883. if (g_paRefcountXnKeys[dwTemp].lRefCount > 0)
  1884. {
  1885. if (memcmp(pxnkid, &g_paRefcountXnKeys[dwTemp].xnkid, sizeof(XNKID)) == 0)
  1886. {
  1887. DPFX(DPFPREP, 1, "Key has already been registered.");
  1888. g_paRefcountXnKeys[dwTemp].lRefCount++;
  1889. iReturn = 0;
  1890. goto Exit;
  1891. }
  1892. }
  1893. else
  1894. {
  1895. DNASSERT(g_paRefcountXnKeys[dwTemp].lRefCount == 0);
  1896. if (dwIndex == -1)
  1897. {
  1898. dwIndex = dwTemp;
  1899. }
  1900. }
  1901. }
  1902. if (dwIndex == -1)
  1903. {
  1904. DPFX(DPFPREP, 0, "No more keys can be registered!");
  1905. DNASSERTX(! "No more keys can be registered!", 2);
  1906. iReturn = WSAENOBUFS;
  1907. goto Exit;
  1908. }
  1909. iReturn = XNetRegisterKey(pxnkid, pxnkey);
  1910. if (iReturn != 0)
  1911. {
  1912. DPFX(DPFPREP, 0, "Registering key failed!");
  1913. goto Exit;
  1914. }
  1915. DNASSERT(g_paRefcountXnKeys[dwIndex].lRefCount == 0);
  1916. g_paRefcountXnKeys[dwIndex].lRefCount = 1;
  1917. memcpy(&g_paRefcountXnKeys[dwIndex].xnkid, pxnkid, sizeof(XNKID));
  1918. memcpy(&g_paRefcountXnKeys[dwIndex].xnkey, pxnkey, sizeof(XNKEY));
  1919. Exit:
  1920. DPFX(DPFPREP, 3, "Returning: [%i]", iReturn);
  1921. return iReturn;
  1922. }
  1923. #undef DPF_MODNAME
  1924. #define DPF_MODNAME "UnregisterRefcountXnKey"
  1925. INT WINAPI UnregisterRefcountXnKey(const XNKID * pxnkid)
  1926. {
  1927. int iReturn;
  1928. DWORD dwTemp;
  1929. DPFX(DPFPREP, 3, "Parameters: (0x%p)", pxnkid);
  1930. DNASSERT(pxnkid != NULL);
  1931. DNASSERT(g_paRefcountXnKeys != NULL);
  1932. for(dwTemp = 0; dwTemp < g_dwMaxNumRefcountXnKeys; dwTemp++)
  1933. {
  1934. if (g_paRefcountXnKeys[dwTemp].lRefCount > 0)
  1935. {
  1936. if (memcmp(pxnkid, &g_paRefcountXnKeys[dwTemp].xnkid, sizeof(XNKID)) == 0)
  1937. {
  1938. g_paRefcountXnKeys[dwTemp].lRefCount--;
  1939. if (g_paRefcountXnKeys[dwTemp].lRefCount == 0)
  1940. {
  1941. iReturn = XNetUnregisterKey(pxnkid);
  1942. if (iReturn != 0)
  1943. {
  1944. DPFX(DPFPREP, 0, "Unregistering key failed!");
  1945. }
  1946. }
  1947. else
  1948. {
  1949. iReturn = 0;
  1950. }
  1951. goto Exit;
  1952. }
  1953. }
  1954. else
  1955. {
  1956. DNASSERT(g_paRefcountXnKeys[dwTemp].lRefCount == 0);
  1957. }
  1958. }
  1959. DPFX(DPFPREP, 0, "Key has not been registered!");
  1960. DNASSERTX(! "Key has not been registered!", 2);
  1961. iReturn = -1;
  1962. Exit:
  1963. DPFX(DPFPREP, 3, "Returning: [%i]", iReturn);
  1964. return iReturn;
  1965. }
  1966. #ifdef XBOX_ON_DESKTOP
  1967. typedef struct _SECURITYASSOCIATION
  1968. {
  1969. BOOL fInUse;
  1970. XNADDR xnaddr;
  1971. IN_ADDR inaddr;
  1972. } SECURITYASSOCIATION;
  1973. typedef struct _KEYENTRY
  1974. {
  1975. BOOL fInUse;
  1976. XNKID xnkid;
  1977. XNKEY xnkey;
  1978. SECURITYASSOCIATION * paSecurityAssociations;
  1979. } KEYENTRY;
  1980. KEYENTRY * g_paKeys = NULL;
  1981. DWORD g_dwMaxNumKeys = 0;
  1982. DWORD g_dwMaxNumAssociations = 0;
  1983. #undef DPF_MODNAME
  1984. #define DPF_MODNAME "XNetStartup"
  1985. INT WINAPI XNetStartup(const XNetStartupParams * pxnsp)
  1986. {
  1987. int iReturn;
  1988. XNetStartupParams StartupParamsCapped;
  1989. DWORD dwTemp;
  1990. #ifdef DBG
  1991. //DPFX(DPFPREP, 3, "Parameters: (0x%p)", pxnsp);
  1992. // Not using DNASSERT because DPlay may not be initted yet.
  1993. if (! (g_paKeys == NULL))
  1994. {
  1995. OutputDebugString("Assert failed (g_paKeys == NULL)\n");
  1996. DebugBreak();
  1997. }
  1998. #endif // DBG
  1999. if (pxnsp == NULL)
  2000. {
  2001. memset(&StartupParamsCapped, 0, sizeof(StartupParamsCapped));
  2002. }
  2003. else
  2004. {
  2005. memcpy(&StartupParamsCapped, pxnsp, sizeof(StartupParamsCapped));
  2006. }
  2007. if (StartupParamsCapped.cfgKeyRegMax == 0)
  2008. {
  2009. StartupParamsCapped.cfgKeyRegMax = 4;
  2010. }
  2011. if (StartupParamsCapped.cfgSecRegMax == 0)
  2012. {
  2013. StartupParamsCapped.cfgSecRegMax = 32;
  2014. }
  2015. // Not using DNMalloc because DPlay may not be initted yet.
  2016. g_paKeys = (KEYENTRY*) HeapAlloc(GetProcessHeap(), 0, StartupParamsCapped.cfgKeyRegMax * sizeof(KEYENTRY));
  2017. if (g_paKeys == NULL)
  2018. {
  2019. iReturn = -1;
  2020. goto Failure;
  2021. }
  2022. memset(g_paKeys, 0, (StartupParamsCapped.cfgKeyRegMax * sizeof(KEYENTRY)));
  2023. for(dwTemp = 0; dwTemp < StartupParamsCapped.cfgKeyRegMax; dwTemp++)
  2024. {
  2025. // Not using DNMalloc because DPlay may not be initted yet.
  2026. g_paKeys[dwTemp].paSecurityAssociations = (SECURITYASSOCIATION*) HeapAlloc(GetProcessHeap(), 0, StartupParamsCapped.cfgSecRegMax * sizeof(SECURITYASSOCIATION));
  2027. if (g_paKeys == NULL)
  2028. {
  2029. iReturn = -1;
  2030. goto Failure;
  2031. }
  2032. memset(g_paKeys[dwTemp].paSecurityAssociations, 0, (StartupParamsCapped.cfgSecRegMax * sizeof(SECURITYASSOCIATION)));
  2033. }
  2034. g_dwMaxNumKeys = StartupParamsCapped.cfgKeyRegMax;
  2035. g_dwMaxNumAssociations = StartupParamsCapped.cfgSecRegMax;
  2036. iReturn = 0;
  2037. Exit:
  2038. //DPFX(DPFPREP, 3, "Returning: [%i]", iReturn);
  2039. return iReturn;
  2040. Failure:
  2041. if (g_paKeys != NULL)
  2042. {
  2043. for(dwTemp = 0; dwTemp < StartupParamsCapped.cfgKeyRegMax; dwTemp++)
  2044. {
  2045. if (g_paKeys[dwTemp].paSecurityAssociations != NULL)
  2046. {
  2047. HeapFree(GetProcessHeap(), 0, g_paKeys[dwTemp].paSecurityAssociations);
  2048. g_paKeys[dwTemp].paSecurityAssociations = NULL;
  2049. }
  2050. }
  2051. HeapFree(GetProcessHeap(), 0, g_paKeys);
  2052. g_paKeys = NULL;
  2053. }
  2054. g_dwMaxNumKeys = 0;
  2055. g_dwMaxNumAssociations = 0;
  2056. goto Exit;
  2057. }
  2058. #undef DPF_MODNAME
  2059. #define DPF_MODNAME "XNetCleanup"
  2060. INT WINAPI XNetCleanup(void)
  2061. {
  2062. int iReturn;
  2063. DWORD dwTemp;
  2064. #ifdef DBG
  2065. //DPFX(DPFPREP, 3, "Enter");
  2066. // Not using DNASSERT because DPlay may not be initted anymore.
  2067. if (! (g_paKeys != NULL))
  2068. {
  2069. OutputDebugString("Assert failed (g_paKeys != NULL)\n");
  2070. DebugBreak();
  2071. }
  2072. #endif // DBG
  2073. for(dwTemp = 0; dwTemp < g_dwMaxNumKeys; dwTemp++)
  2074. {
  2075. if (g_paKeys[dwTemp].paSecurityAssociations != NULL)
  2076. {
  2077. HeapFree(GetProcessHeap(), 0, g_paKeys[dwTemp].paSecurityAssociations);
  2078. g_paKeys[dwTemp].paSecurityAssociations = NULL;
  2079. }
  2080. }
  2081. HeapFree(GetProcessHeap(), 0, g_paKeys);
  2082. g_paKeys = NULL;
  2083. g_dwMaxNumKeys = 0;
  2084. g_dwMaxNumAssociations = 0;
  2085. iReturn = 0;
  2086. //DPFX(DPFPREP, 3, "Returning: [%i]", iReturn);
  2087. return iReturn;
  2088. }
  2089. #undef DPF_MODNAME
  2090. #define DPF_MODNAME "XNetRegisterKey"
  2091. INT WINAPI XNetRegisterKey(const XNKID * pxnkid, const XNKEY * pxnkey)
  2092. {
  2093. int iReturn;
  2094. DWORD dwTemp;
  2095. DWORD dwIndex = -1;
  2096. DPFX(DPFPREP, 3, "Parameters: (0x%p, 0x%p)", pxnkid, pxnkey);
  2097. DNASSERT(pxnkid != NULL);
  2098. DNASSERT(pxnkey != NULL);
  2099. for(dwTemp = 0; dwTemp < g_dwMaxNumKeys; dwTemp++)
  2100. {
  2101. if (g_paKeys[dwTemp].fInUse)
  2102. {
  2103. if (memcmp(pxnkid, &g_paKeys[dwTemp].xnkid, sizeof(XNKID)) == 0)
  2104. {
  2105. DPFX(DPFPREP, 2, "Key has already been registered.");
  2106. iReturn = WSAEALREADY;
  2107. goto Exit;
  2108. }
  2109. }
  2110. else
  2111. {
  2112. if (dwIndex == -1)
  2113. {
  2114. dwIndex = dwTemp;
  2115. }
  2116. }
  2117. }
  2118. if (dwIndex == -1)
  2119. {
  2120. DPFX(DPFPREP, 0, "No more keys can be registered!");
  2121. iReturn = WSAENOBUFS;
  2122. goto Exit;
  2123. }
  2124. g_paKeys[dwIndex].fInUse = TRUE;
  2125. memcpy(&g_paKeys[dwIndex].xnkid, pxnkid, sizeof(XNKID));
  2126. memcpy(&g_paKeys[dwIndex].xnkey, pxnkey, sizeof(XNKEY));
  2127. iReturn = 0;
  2128. Exit:
  2129. DPFX(DPFPREP, 3, "Returning: [%i]", iReturn);
  2130. return iReturn;
  2131. }
  2132. #undef DPF_MODNAME
  2133. #define DPF_MODNAME "XNetUnregisterKey"
  2134. INT WINAPI XNetUnregisterKey(const XNKID * pxnkid)
  2135. {
  2136. int iReturn;
  2137. DWORD dwTemp;
  2138. DPFX(DPFPREP, 3, "Parameters: (0x%p)", pxnkid);
  2139. DNASSERT(pxnkid != NULL);
  2140. for(dwTemp = 0; dwTemp < g_dwMaxNumKeys; dwTemp++)
  2141. {
  2142. if (g_paKeys[dwTemp].fInUse)
  2143. {
  2144. if (memcmp(pxnkid, &g_paKeys[dwTemp].xnkid, sizeof(XNKID)) == 0)
  2145. {
  2146. g_paKeys[dwTemp].fInUse = FALSE;
  2147. iReturn = 0;
  2148. goto Exit;
  2149. }
  2150. }
  2151. }
  2152. DPFX(DPFPREP, 0, "Key has not been registered!");
  2153. DNASSERTX(! "Key has not been registered!", 2);
  2154. iReturn = -1;
  2155. Exit:
  2156. DPFX(DPFPREP, 3, "Returning: [%i]", iReturn);
  2157. return iReturn;
  2158. }
  2159. #undef DPF_MODNAME
  2160. #define DPF_MODNAME "XNetXnAddrToInAddr"
  2161. INT WINAPI XNetXnAddrToInAddr(const XNADDR * pxna, const XNKID * pxnkid, IN_ADDR * pina)
  2162. {
  2163. int iReturn;
  2164. DWORD dwKey;
  2165. DWORD dwAssociation;
  2166. DWORD dwIndex;
  2167. DPFX(DPFPREP, 3, "Parameters: (0x%p, 0x%p, 0x%p)", pxna, pxnkid, pina);
  2168. DNASSERT(pxna != NULL);
  2169. DNASSERT(pxnkid != NULL);
  2170. DNASSERT(pina != NULL);
  2171. for(dwKey = 0; dwKey < g_dwMaxNumKeys; dwKey++)
  2172. {
  2173. if ((g_paKeys[dwKey].fInUse) &&
  2174. (memcmp(pxnkid, &g_paKeys[dwKey].xnkid, sizeof(XNKID)) == 0))
  2175. {
  2176. dwIndex = -1;
  2177. for(dwAssociation = 0; dwAssociation < g_dwMaxNumAssociations; dwAssociation++)
  2178. {
  2179. if (g_paKeys[dwKey].paSecurityAssociations[dwAssociation].fInUse)
  2180. {
  2181. if (memcmp(pxna, &g_paKeys[dwKey].paSecurityAssociations[dwAssociation].xnaddr, sizeof(XNADDR)) == 0)
  2182. {
  2183. memcpy(pina, &g_paKeys[dwKey].paSecurityAssociations[dwAssociation].inaddr, sizeof(IN_ADDR));
  2184. iReturn = 0;
  2185. goto Exit;
  2186. }
  2187. }
  2188. else
  2189. {
  2190. if (dwIndex == -1)
  2191. {
  2192. dwIndex = dwAssociation;
  2193. }
  2194. }
  2195. }
  2196. if (dwIndex == -1)
  2197. {
  2198. DPFX(DPFPREP, 0, "No more security associations can be made!");
  2199. iReturn = WSAENOBUFS;
  2200. goto Exit;
  2201. }
  2202. g_paKeys[dwKey].paSecurityAssociations[dwIndex].fInUse = TRUE;
  2203. memcpy(&g_paKeys[dwKey].paSecurityAssociations[dwIndex].xnaddr, pxna, sizeof(XNADDR));
  2204. DBG_CASSERT(sizeof(pxna->abEnet) > (sizeof(IN_ADDR) + 1));
  2205. memcpy(&g_paKeys[dwKey].paSecurityAssociations[dwIndex].inaddr, &pxna->abEnet[1], sizeof(IN_ADDR));
  2206. memcpy(pina, &g_paKeys[dwKey].paSecurityAssociations[dwIndex].inaddr, sizeof(IN_ADDR));
  2207. iReturn = 0;
  2208. goto Exit;
  2209. }
  2210. }
  2211. DPFX(DPFPREP, 0, "Key has not been registered!");
  2212. DNASSERTX(! "Key has not been registered!", 2);
  2213. iReturn = -1;
  2214. Exit:
  2215. DPFX(DPFPREP, 3, "Returning: [%i]", iReturn);
  2216. return iReturn;
  2217. }
  2218. #undef DPF_MODNAME
  2219. #define DPF_MODNAME "XNetInAddrToXnAddr"
  2220. INT WINAPI XNetInAddrToXnAddr(const IN_ADDR ina, XNADDR * pxna, XNKID * pxnkid)
  2221. {
  2222. int iReturn;
  2223. DWORD dwKey;
  2224. DWORD dwAssociation;
  2225. DPFX(DPFPREP, 3, "Parameters: (%u.%u.%u.%u, 0x%p, 0x%p)",
  2226. ina.S_un.S_un_b.s_b1, ina.S_un.S_un_b.s_b2, ina.S_un.S_un_b.s_b3, ina.S_un.S_un_b.s_b4, pxna, pxnkid);
  2227. //
  2228. // Special case the loopback address, that just means the title address.
  2229. //
  2230. if (ina.S_un.S_addr == IP_LOOPBACK_ADDRESS)
  2231. {
  2232. if (pxna != NULL)
  2233. {
  2234. iReturn = XNetGetTitleXnAddr(pxna);
  2235. DNASSERT((iReturn != XNET_GET_XNADDR_PENDING) && (iReturn != XNET_GET_XNADDR_NONE));
  2236. }
  2237. if (pxnkid != NULL)
  2238. {
  2239. memset(pxnkid, 0, sizeof(XNKID));
  2240. }
  2241. iReturn = 0;
  2242. goto Exit;
  2243. }
  2244. for(dwKey = 0; dwKey < g_dwMaxNumKeys; dwKey++)
  2245. {
  2246. if (g_paKeys[dwKey].fInUse)
  2247. {
  2248. for(dwAssociation = 0; dwAssociation < g_dwMaxNumAssociations; dwAssociation++)
  2249. {
  2250. if (g_paKeys[dwKey].paSecurityAssociations[dwAssociation].fInUse)
  2251. {
  2252. if (memcmp(&ina, &g_paKeys[dwKey].paSecurityAssociations[dwAssociation].inaddr, sizeof(IN_ADDR)) == 0)
  2253. {
  2254. if (pxna != NULL)
  2255. {
  2256. memcpy(pxna, &g_paKeys[dwKey].paSecurityAssociations[dwAssociation].xnaddr, sizeof(XNADDR));
  2257. }
  2258. if (pxnkid != NULL)
  2259. {
  2260. memcpy(pxnkid, &g_paKeys[dwKey].xnkid, sizeof(XNKID));
  2261. }
  2262. iReturn = 0;
  2263. goto Exit;
  2264. }
  2265. }
  2266. }
  2267. }
  2268. }
  2269. DPFX(DPFPREP, 0, "No security association for IN_ADDR specified!");
  2270. DNASSERTX(! "No security association for IN_ADDR specified!", 2);
  2271. iReturn = -1;
  2272. Exit:
  2273. DPFX(DPFPREP, 3, "Returning: [%i]", iReturn);
  2274. return iReturn;
  2275. }
  2276. #undef DPF_MODNAME
  2277. #define DPF_MODNAME "XNetGetTitleXnAddr"
  2278. DWORD WINAPI XNetGetTitleXnAddr(XNADDR * pxna)
  2279. {
  2280. DWORD dwReturn;
  2281. char szBuffer[256];
  2282. PHOSTENT phostent;
  2283. IN_ADDR * pinaddr;
  2284. DPFX(DPFPREP, 3, "Parameters: (0x%p)", pxna);
  2285. DNASSERT(pxna != NULL);
  2286. if (gethostname(szBuffer, sizeof(szBuffer)) == SOCKET_ERROR)
  2287. {
  2288. #ifdef DBG
  2289. dwReturn = WSAGetLastError();
  2290. DPFX(DPFPREP, 0, "Failed to get host name into fixed size buffer (err = %i)!", dwReturn);
  2291. DisplayWinsockError(0, dwReturn);
  2292. #endif // DBG
  2293. dwReturn = XNET_GET_XNADDR_NONE;
  2294. goto Exit;
  2295. }
  2296. phostent = gethostbyname(szBuffer);
  2297. if (phostent == NULL)
  2298. {
  2299. #ifdef DBG
  2300. dwReturn = WSAGetLastError();
  2301. DPFX(DPFPREP, 0, "Failed to get host data (err = %i)!", dwReturn);
  2302. DisplayWinsockError(0, dwReturn);
  2303. #endif // DBG
  2304. dwReturn = XNET_GET_XNADDR_NONE;
  2305. goto Exit;
  2306. }
  2307. memset(pxna, 0, sizeof(XNADDR));
  2308. //
  2309. // We'll use the first address returned.
  2310. //
  2311. pinaddr = (IN_ADDR*) phostent->h_addr_list[0];
  2312. DNASSERT(pinaddr != NULL);
  2313. DBG_CASSERT(sizeof(pxna->abEnet) > (sizeof(IN_ADDR) + 1));
  2314. memset(&pxna->abEnet, 0xFF, sizeof(pxna->abEnet));
  2315. memcpy(&pxna->abEnet[1], pinaddr, sizeof(IN_ADDR));
  2316. memcpy(&pxna->ina, pinaddr, sizeof(IN_ADDR));
  2317. //
  2318. // Pretend it's always DHCP.
  2319. //
  2320. dwReturn = XNET_GET_XNADDR_DHCP;
  2321. Exit:
  2322. DPFX(DPFPREP, 3, "Returning: [%u]", dwReturn);
  2323. return dwReturn;
  2324. }
  2325. #undef DPF_MODNAME
  2326. #define DPF_MODNAME "XNetGetEthernetLinkStatus"
  2327. DWORD WINAPI XNetGetEthernetLinkStatus(void)
  2328. {
  2329. DWORD dwReturn;
  2330. DPFX(DPFPREP, 3, "Enter");
  2331. //
  2332. // Hard code an active 10 Mbit link.
  2333. //
  2334. dwReturn = XNET_ETHERNET_LINK_ACTIVE | XNET_ETHERNET_LINK_10MBPS;
  2335. DPFX(DPFPREP, 3, "Returning: [0x%x]", dwReturn);
  2336. return dwReturn;
  2337. }
  2338. #undef DPF_MODNAME
  2339. #define DPF_MODNAME "XNetPrivCreateAssociation"
  2340. INT WINAPI XNetPrivCreateAssociation(const XNKID * pxnkid, const CSocketAddress * const pSocketAddress)
  2341. {
  2342. int iReturn;
  2343. SOCKADDR_IN * psockaddrin;
  2344. DWORD dwKey;
  2345. DWORD dwAssociation;
  2346. DWORD dwIndex;
  2347. DPFX(DPFPREP, 3, "Parameters: (0x%p, 0x%p)", pxnkid, pSocketAddress);
  2348. DNASSERT(pxnkid != NULL);
  2349. DNASSERT(pSocketAddress != NULL);
  2350. DNASSERT(pSocketAddress->GetFamily() == AF_INET);
  2351. psockaddrin = (SOCKADDR_IN*) pSocketAddress->GetAddress();
  2352. for(dwKey = 0; dwKey < g_dwMaxNumKeys; dwKey++)
  2353. {
  2354. if ((g_paKeys[dwKey].fInUse) &&
  2355. (memcmp(pxnkid, &g_paKeys[dwKey].xnkid, sizeof(XNKID)) == 0))
  2356. {
  2357. dwIndex = -1;
  2358. for(dwAssociation = 0; dwAssociation < g_dwMaxNumAssociations; dwAssociation++)
  2359. {
  2360. if (g_paKeys[dwKey].paSecurityAssociations[dwAssociation].fInUse)
  2361. {
  2362. if (memcmp(&psockaddrin->sin_addr, &g_paKeys[dwKey].paSecurityAssociations[dwAssociation].xnaddr, sizeof(psockaddrin->sin_addr)) == 0)
  2363. {
  2364. DPFX(DPFPREP, 2, "Security association already made.");
  2365. iReturn = 0;
  2366. goto Exit;
  2367. }
  2368. }
  2369. else
  2370. {
  2371. if (dwIndex == -1)
  2372. {
  2373. dwIndex = dwAssociation;
  2374. }
  2375. }
  2376. }
  2377. if (dwIndex == -1)
  2378. {
  2379. DPFX(DPFPREP, 0, "No more security associations can be made!");
  2380. iReturn = WSAENOBUFS;
  2381. goto Exit;
  2382. }
  2383. g_paKeys[dwKey].paSecurityAssociations[dwIndex].fInUse = TRUE;
  2384. memset(&g_paKeys[dwKey].paSecurityAssociations[dwIndex].xnaddr, 0, sizeof(XNADDR));
  2385. memset(&g_paKeys[dwKey].paSecurityAssociations[dwIndex].xnaddr.abEnet, 0xFF,
  2386. sizeof(g_paKeys[dwKey].paSecurityAssociations[dwIndex].xnaddr.abEnet));
  2387. DBG_CASSERT(sizeof(g_paKeys[dwKey].paSecurityAssociations[dwIndex].xnaddr.abEnet) > (sizeof(IN_ADDR) + 1));
  2388. memcpy(&g_paKeys[dwKey].paSecurityAssociations[dwIndex].xnaddr.abEnet[1],
  2389. &psockaddrin->sin_addr, sizeof(IN_ADDR));
  2390. memcpy(&g_paKeys[dwKey].paSecurityAssociations[dwIndex].inaddr, &psockaddrin->sin_addr, sizeof(IN_ADDR));
  2391. iReturn = 0;
  2392. goto Exit;
  2393. }
  2394. }
  2395. DPFX(DPFPREP, 0, "Key has not been registered!");
  2396. DNASSERTX(! "Key has not been registered!", 2);
  2397. iReturn = -1;
  2398. Exit:
  2399. DPFX(DPFPREP, 3, "Returning: [%i]", iReturn);
  2400. return iReturn;
  2401. }
  2402. #endif // XBOX_ON_DESKTOP
  2403. #endif // _XBOX