Source code of Windows XP (NT5)
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.

961 lines
24 KiB

  1. /***************************************************************************
  2. *
  3. * Copyright (C) 2001-2002 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: dpnhpastdllmain.cpp
  6. *
  7. * Content: DPNHPAST DLL entry points.
  8. *
  9. * History:
  10. * Date By Reason
  11. * ======== ======== =========
  12. * 04/16/01 VanceO Split DPNATHLP into DPNHUPNP and DPNHPAST.
  13. *
  14. ***************************************************************************/
  15. #include "dpnhpasti.h"
  16. //=============================================================================
  17. // External globals
  18. //=============================================================================
  19. volatile LONG g_lOutstandingInterfaceCount = 0; // number of outstanding interfaces
  20. DNCRITICAL_SECTION g_csGlobalsLock; // lock protecting all of the following globals
  21. CBilink g_blNATHelpPASTObjs; // bilink of all the NATHelpPAST interface objects
  22. DWORD g_dwHoldRand; // current random number sequence
  23. DWORD g_dwPASTICSMode; // whether using PAST ICS is enabled or not
  24. DWORD g_dwPASTPFWMode; // whether using PAST PFW is enabled or not
  25. INT g_iUnicastTTL = 1; // unicast TTL value, or 0 to use default set by OS; normally we use 1
  26. DWORD g_dwDefaultGatewayV4 = INADDR_BROADCAST; // default to broadcasting when searching for PAST server
  27. DWORD g_dwSubnetMaskV4 = 0x00FFFFFF; // = 0xFFFFFF00 in Intel order = 255.255.255.0, a class C network
  28. DWORD g_dwNoActiveNotifyPollInterval = 25000; // start by polling every 25 seconds
  29. DWORD g_dwMinUpdateServerStatusInterval = 1000; // don't hit the network more often than every 1 second
  30. DWORD g_dwPollIntervalBackoff = 30000; // backoff an additional 0 to 30 seconds if no network changes occur
  31. DWORD g_dwMaxPollInterval = 300000; // don't go more than 5 minutes without polling
  32. BOOL g_fKeepPollingForRemoteGateway = FALSE; // whether to continue to search for new Internet gateway devices if none were found during startup
  33. DWORD g_dwReusePortTime = 60000; // how long to keep using the same port for polling remote Internet gateway devices (default is 1 minute)
  34. DWORD g_dwCacheLifeFound = 30000; // how long to cache QueryAddress results where the address was found
  35. DWORD g_dwCacheLifeNotFound = 30000; // how long to cache QueryAddress results where the address was not found
  36. //=============================================================================
  37. // Defines
  38. //=============================================================================
  39. #define REGKEY_VALUE_GUID L"Guid"
  40. #define REGKEY_VALUE_DIRECTPLAY8PRIORITY L"DirectPlay8Priority"
  41. #define REGKEY_VALUE_DIRECTPLAY8INITFLAGS L"DirectPlay8InitFlags"
  42. #define REGKEY_VALUE_PASTICSMODE L"PASTICSMode"
  43. #define REGKEY_VALUE_PASTPFWMODE L"PASTPFWMode"
  44. #define REGKEY_VALUE_UNICASTTTL L"UnicastTTL"
  45. #define REGKEY_VALUE_DEFAULTGATEWAYV4 L"GatewayV4"
  46. #define REGKEY_VALUE_SUBNETMASKV4 L"SubnetMaskV4"
  47. #define REGKEY_VALUE_NOACTIVENOTIFYPOLLINTERVAL L"NoActiveNotifyPollInterval"
  48. #define REGKEY_VALUE_MINUPDATESERVERSTATUSINTERVAL L"MinUpdateServerStatusInterval"
  49. #define REGKEY_VALUE_POLLINTERVALBACKOFF L"PollIntervalBackoff"
  50. #define REGKEY_VALUE_MAXPOLLINTERVAL L"MaxPollInterval"
  51. #define REGKEY_VALUE_KEEPPOLLINGFORREMOTEGATEWAY L"KeepPollingForRemoteGateway"
  52. #define REGKEY_VALUE_REUSEPORTTIME L"ReusePortTime"
  53. #define REGKEY_VALUE_CACHELIFEFOUND L"CacheLifeFound"
  54. #define REGKEY_VALUE_CACHELIFENOTFOUND L"CacheLifeNotFound"
  55. #define DEFAULT_DIRECTPLAY8PRIORITY 2
  56. #define DEFAULT_DIRECTPLAY8INITFLAGS DPNHINITIALIZE_DISABLELOCALFIREWALLSUPPORT
  57. //=============================================================================
  58. // Local prototypes
  59. //=============================================================================
  60. BOOL InitializeProcessGlobals(void);
  61. void CleanupProcessGlobals(void);
  62. void InitializeGlobalRand(const DWORD dwSeed);
  63. #undef DPF_MODNAME
  64. #define DPF_MODNAME "DllMain"
  65. //=============================================================================
  66. // DllMain
  67. //-----------------------------------------------------------------------------
  68. //
  69. // Description: DLL entry point.
  70. //
  71. // Arguments:
  72. // HANDLE hDllInst - Handle to this DLL module.
  73. // DWORD dwReason - Reason for calling this function.
  74. // LPVOID lpvReserved - Reserved.
  75. //
  76. // Returns: TRUE if all goes well, FALSE otherwise.
  77. //=============================================================================
  78. BOOL WINAPI DllMain(HANDLE hDllInst,
  79. DWORD dwReason,
  80. LPVOID lpvReserved)
  81. {
  82. BOOL fResult = TRUE;
  83. switch (dwReason)
  84. {
  85. case DLL_PROCESS_ATTACH:
  86. {
  87. DPFX(DPFPREP, 2, "====> ENTER: DLLMAIN(%p): Process Attach: %08lx, tid=%08lx",
  88. DllMain, GetCurrentProcessId(), GetCurrentThreadId());
  89. //
  90. // Ignore thread attach/detach messages.
  91. //
  92. DisableThreadLibraryCalls((HMODULE) hDllInst);
  93. //
  94. // Attempt to initialize the OS abstraction layer.
  95. //
  96. if (DNOSIndirectionInit(0))
  97. {
  98. //
  99. // Attempt to initialize process-global items.
  100. //
  101. if (! InitializeProcessGlobals())
  102. {
  103. DPFX(DPFPREP, 0, "Failed to initialize globals!");
  104. DNOSIndirectionDeinit();
  105. fResult = FALSE;
  106. }
  107. }
  108. else
  109. {
  110. DPFX(DPFPREP, 0, "Failed to initialize OS indirection layer!");
  111. fResult = FALSE;
  112. }
  113. break;
  114. }
  115. case DLL_THREAD_ATTACH:
  116. {
  117. //
  118. // Ignore.
  119. //
  120. break;
  121. }
  122. case DLL_THREAD_DETACH:
  123. {
  124. //
  125. // Ignore.
  126. //
  127. break;
  128. }
  129. case DLL_PROCESS_DETACH:
  130. {
  131. DPFX(DPFPREP, 2, "====> EXIT: DLLMAIN(%p): Process Detach %08lx, tid=%08lx",
  132. DllMain, GetCurrentProcessId(), GetCurrentThreadId());
  133. CleanupProcessGlobals();
  134. DNOSIndirectionDeinit();
  135. break;
  136. }
  137. default:
  138. {
  139. DNASSERT(FALSE);
  140. break;
  141. }
  142. }
  143. return fResult;
  144. } // DllMain
  145. #ifndef DPNBUILD_NOCOMREGISTER
  146. #undef DPF_MODNAME
  147. #define DPF_MODNAME "DllRegisterServer"
  148. //=============================================================================
  149. // DllRegisterServer
  150. //-----------------------------------------------------------------------------
  151. //
  152. // Description: Registers the DirectPlay NAT Helper PAST COM object.
  153. //
  154. // Arguments: None.
  155. //
  156. // Returns: HRESULT
  157. // S_OK - Successfully unregistered DirectPlay NAT Helper PAST.
  158. // E_FAIL - Failed unregistering DirectPlay NAT Helper PAST.
  159. //=============================================================================
  160. HRESULT WINAPI DllRegisterServer(void)
  161. {
  162. CRegistry RegObject;
  163. //
  164. // Register this COM object CLSID.
  165. //
  166. if (! CRegistry::Register(L"DirectPlayNATHelperPAST.1",
  167. L"DirectPlay NAT Helper PAST Object",
  168. L"dpnhpast.dll",
  169. &CLSID_DirectPlayNATHelpPAST,
  170. L"DirectPlayNATHelperPAST"))
  171. {
  172. DPFX(DPFPREP, 0, "Could not register DirectPlay NAT Helper PAST object!");
  173. return E_FAIL;
  174. }
  175. //
  176. // Write this object's GUID and DirectPlay8 availability to the registry.
  177. //
  178. if (! RegObject.Open(HKEY_LOCAL_MACHINE, DIRECTPLAYNATHELP_REGKEY L"\\" REGKEY_COMPONENTSUBKEY, FALSE, TRUE))
  179. {
  180. DPFX(DPFPREP, 0, "Couldn't create DirectPlay NAT Helper PAST key!");
  181. return E_FAIL;
  182. }
  183. if (! RegObject.WriteGUID(REGKEY_VALUE_GUID, CLSID_DirectPlayNATHelpPAST))
  184. {
  185. DPFX(DPFPREP, 0, "Couldn't write GUID to registry!");
  186. return E_FAIL;
  187. }
  188. if (! RegObject.WriteDWORD(REGKEY_VALUE_DIRECTPLAY8PRIORITY, DEFAULT_DIRECTPLAY8PRIORITY))
  189. {
  190. DPFX(DPFPREP, 0, "Couldn't write DirectPlay8 priority to registry!");
  191. return E_FAIL;
  192. }
  193. if (! RegObject.WriteDWORD(REGKEY_VALUE_DIRECTPLAY8INITFLAGS, DEFAULT_DIRECTPLAY8INITFLAGS))
  194. {
  195. DPFX(DPFPREP, 0, "Couldn't write DirectPlay8 init flags to registry!");
  196. return E_FAIL;
  197. }
  198. RegObject.Close();
  199. return S_OK;
  200. } // DllRegisterServer
  201. #undef DPF_MODNAME
  202. #define DPF_MODNAME "DllUnregisterServer"
  203. //=============================================================================
  204. // DllUnregisterServer
  205. //-----------------------------------------------------------------------------
  206. //
  207. // Description: Unregisters the DirectPlay NAT Helper PAST COM object.
  208. //
  209. // Arguments: None.
  210. //
  211. // Returns: HRESULT
  212. // S_OK - Successfully unregistered DirectPlay NAT Helper PAST.
  213. // E_FAIL - Failed unregistering DirectPlay NAT Helper PAST.
  214. //=============================================================================
  215. STDAPI DllUnregisterServer(void)
  216. {
  217. CRegistry RegObject;
  218. //
  219. // Unregister the class.
  220. //
  221. if (! CRegistry::UnRegister(&CLSID_DirectPlayNATHelpPAST))
  222. {
  223. DPFX(DPFPREP, 0, "Failed to unregister DirectPlay NAT Helper PAST object!");
  224. return E_FAIL;
  225. }
  226. //
  227. // Try removing all the subitems we registered.
  228. //
  229. if (! RegObject.Open(HKEY_LOCAL_MACHINE, DIRECTPLAYNATHELP_REGKEY L"\\" REGKEY_COMPONENTSUBKEY, FALSE, FALSE))
  230. {
  231. DPFX(DPFPREP, 0, "Couldn't open DirectPlay NAT Helper key! Ignoring.");
  232. }
  233. else
  234. {
  235. if (! RegObject.DeleteValue(REGKEY_VALUE_GUID))
  236. {
  237. DPFX(DPFPREP, 0, "Couldn't delete GUID registry value! Ignoring.");
  238. }
  239. if (! RegObject.DeleteValue(REGKEY_VALUE_DIRECTPLAY8PRIORITY))
  240. {
  241. DPFX(DPFPREP, 0, "Couldn't delete DirectPlay8 priority registry value! Ignoring.");
  242. }
  243. if (! RegObject.DeleteValue(REGKEY_VALUE_DIRECTPLAY8INITFLAGS))
  244. {
  245. DPFX(DPFPREP, 0, "Couldn't delete DirectPlay8 init flags registry value! Ignoring.");
  246. }
  247. RegObject.Close();
  248. }
  249. return S_OK;
  250. } // DllUnregisterServer
  251. #endif // !DPNBUILD_NOCOMREGISTER
  252. #ifndef WINCE
  253. #undef DPF_MODNAME
  254. #define DPF_MODNAME "DirectPlayNATHelpCreate"
  255. //=============================================================================
  256. // DirectPlayNATHelpCreate
  257. //-----------------------------------------------------------------------------
  258. //
  259. // Description: Creates an IDirectPlayNATHelp interface object.
  260. //
  261. // Arguments:
  262. // GUID * pIID - Pointer to IDirectPlayNATHelp interface GUID.
  263. // void ** ppvInterface - Place to store pointer to interface object
  264. // created.
  265. //
  266. // Returns: HRESULT
  267. // DPNH_OK - Creating the object was successful.
  268. // DPNHERR_INVALIDPOINTER - The destination pointer is invalid.
  269. // DPNHERR_OUTOFMEMORY - Not enough memory to create the object.
  270. // E_NOINTERFACE - The requested interface was invalid.
  271. //=============================================================================
  272. HRESULT WINAPI DirectPlayNATHelpCreate(const GUID * pIID, void ** ppvInterface)
  273. {
  274. HRESULT hr;
  275. DPFX(DPFPREP, 2, "Parameters: (0x%p, 0x%p)", pIID, ppvInterface);
  276. hr = DoCreateInstance(NULL, // no class factory object necessary
  277. NULL, // ?
  278. CLSID_DirectPlayNATHelpPAST, // DirectPlayNATHelp class
  279. (*pIID), // requested interface
  280. ppvInterface); // place to store interface
  281. DPFX(DPFPREP, 2, "Returning: [0x%lx]", hr);
  282. return hr;
  283. } // DirectPlayNATHelpCreate
  284. #endif // !WINCE
  285. #undef DPF_MODNAME
  286. #define DPF_MODNAME "InitializeProcessGlobals"
  287. //=============================================================================
  288. // InitializeProcessGlobals
  289. //-----------------------------------------------------------------------------
  290. //
  291. // Description: Initialize global items needed for the DLL to operate.
  292. //
  293. // Arguments: None.
  294. //
  295. // Returns: TRUE if successful, FALSE if an error occurred.
  296. //=============================================================================
  297. BOOL InitializeProcessGlobals(void)
  298. {
  299. BOOL fReturn = TRUE;
  300. if (! DNInitializeCriticalSection(&g_csGlobalsLock))
  301. {
  302. fReturn = FALSE;
  303. }
  304. //
  305. // Don't allow critical section reentry.
  306. //
  307. DebugSetCriticalSectionRecursionCount(&g_csGlobalsLock, 0);
  308. g_blNATHelpPASTObjs.Initialize();
  309. //
  310. // Seed the random number generator with the current time.
  311. //
  312. InitializeGlobalRand(GETTIMESTAMP());
  313. return fReturn;
  314. } // InitializeProcessGlobals
  315. #undef DPF_MODNAME
  316. #define DPF_MODNAME "CleanupProcessGlobals"
  317. //=============================================================================
  318. // CleanupProcessGlobals
  319. //-----------------------------------------------------------------------------
  320. //
  321. // Description: Releases global items used by DLL.
  322. //
  323. // Arguments: None.
  324. //
  325. // Returns: None.
  326. //=============================================================================
  327. void CleanupProcessGlobals(void)
  328. {
  329. CBilink * pBilink;
  330. CNATHelpPAST * pNATHelpPAST;
  331. if (! g_blNATHelpPASTObjs.IsEmpty())
  332. {
  333. //
  334. // This assert is far more descriptive than hitting one of those in the
  335. // cleanup code that complain about flags incorrectly being set.
  336. //
  337. DNASSERT(! "DPNHPAST.DLL unloading without all objects having been released! The caller's DirectPlayNATHelpPAST cleanup code needs to be fixed!");
  338. //
  339. // Force close all the objects still outstanding.
  340. //
  341. pBilink = g_blNATHelpPASTObjs.GetNext();
  342. while (pBilink != &g_blNATHelpPASTObjs)
  343. {
  344. pNATHelpPAST = NATHELPPAST_FROM_BILINK(pBilink);
  345. pBilink = pBilink->GetNext();
  346. DPFX(DPFPREP, 0, "Forcefully releasing object 0x%p!", pNATHelpPAST);
  347. pNATHelpPAST->Close(0); // ignore error
  348. //
  349. // Forcefully remove it from the list and delete it instead of
  350. // using pNATHelpPAST->Release().
  351. //
  352. pNATHelpPAST->m_blList.RemoveFromList();
  353. pNATHelpPAST->UninitializeObject();
  354. delete pNATHelpPAST;
  355. }
  356. }
  357. DNDeleteCriticalSection(&g_csGlobalsLock);
  358. } // CleanupProcessGlobals
  359. #undef DPF_MODNAME
  360. #define DPF_MODNAME "ReadRegistrySettings"
  361. //=============================================================================
  362. // ReadRegistrySettings
  363. //-----------------------------------------------------------------------------
  364. //
  365. // Description: Reads registry settings to override behavior of this DLL and to
  366. // turn on some debugging features.
  367. //
  368. // Arguments: None.
  369. //
  370. // Returns: None.
  371. //=============================================================================
  372. void ReadRegistrySettings(void)
  373. {
  374. CRegistry RegObject;
  375. DWORD dwNewValue;
  376. BOOL fNewValue;
  377. //
  378. // Try opening the registry key.
  379. //
  380. if (RegObject.Open(HKEY_LOCAL_MACHINE, DIRECTPLAYNATHELP_REGKEY L"\\" REGKEY_COMPONENTSUBKEY) != FALSE)
  381. {
  382. //
  383. // Lock out other interfaces from modifying the globals simultaneously.
  384. //
  385. DNEnterCriticalSection(&g_csGlobalsLock);
  386. //
  387. // If we successfully read a new mode, save it.
  388. //
  389. if (RegObject.ReadDWORD(REGKEY_VALUE_PASTICSMODE, &dwNewValue))
  390. {
  391. g_dwPASTICSMode = dwNewValue;
  392. DPFX(DPFPREP, 1, "Using PAST ICS mode %u.", g_dwPASTICSMode);
  393. }
  394. //
  395. // If we successfully read a new mode, save it.
  396. //
  397. if (RegObject.ReadDWORD(REGKEY_VALUE_PASTPFWMODE, &dwNewValue))
  398. {
  399. g_dwPASTPFWMode = dwNewValue;
  400. DPFX(DPFPREP, 1, "Using PAST PFW mode %u.", g_dwPASTPFWMode);
  401. }
  402. //
  403. // If we successfully read a new value, save it.
  404. //
  405. if (RegObject.ReadDWORD(REGKEY_VALUE_UNICASTTTL, &dwNewValue))
  406. {
  407. g_iUnicastTTL = dwNewValue;
  408. if (g_iUnicastTTL != 0)
  409. {
  410. DPFX(DPFPREP, 1, "Using unicast TTL of %i.", g_iUnicastTTL);
  411. }
  412. else
  413. {
  414. DPFX(DPFPREP, 1, "Using OS default unicast TTL.");
  415. }
  416. }
  417. //
  418. // If we successfully read a new default gateway, save it.
  419. //
  420. if (RegObject.ReadDWORD(REGKEY_VALUE_DEFAULTGATEWAYV4, &dwNewValue))
  421. {
  422. g_dwDefaultGatewayV4 = dwNewValue;
  423. DPFX(DPFPREP, 1, "Using default gateway 0x%08lx.", g_dwDefaultGatewayV4);
  424. }
  425. //
  426. // If we successfully read a new mask, save it.
  427. //
  428. if (RegObject.ReadDWORD(REGKEY_VALUE_SUBNETMASKV4, &dwNewValue))
  429. {
  430. g_dwSubnetMaskV4 = dwNewValue;
  431. DPFX(DPFPREP, 1, "Using subnet mask 0x%08lx.", g_dwSubnetMaskV4);
  432. }
  433. //
  434. // If we successfully read a new interval, save it.
  435. //
  436. if (RegObject.ReadDWORD(REGKEY_VALUE_NOACTIVENOTIFYPOLLINTERVAL, &dwNewValue))
  437. {
  438. g_dwNoActiveNotifyPollInterval = dwNewValue;
  439. DPFX(DPFPREP, 1, "Using no-active-notify recommended poll interval %u ms.", g_dwNoActiveNotifyPollInterval);
  440. }
  441. //
  442. // If we successfully read a new interval, save it.
  443. //
  444. if (RegObject.ReadDWORD(REGKEY_VALUE_MINUPDATESERVERSTATUSINTERVAL, &dwNewValue))
  445. {
  446. g_dwMinUpdateServerStatusInterval = dwNewValue;
  447. DPFX(DPFPREP, 1, "Using minimum update-server-status interval %u ms.", g_dwMinUpdateServerStatusInterval);
  448. }
  449. //
  450. // If we successfully read a new value, save it.
  451. //
  452. if (RegObject.ReadDWORD(REGKEY_VALUE_POLLINTERVALBACKOFF, &dwNewValue))
  453. {
  454. if (dwNewValue != 0)
  455. {
  456. g_dwPollIntervalBackoff = dwNewValue;
  457. DPFX(DPFPREP, 1, "Using poll interval backoff between 0 and %u ms.",
  458. g_dwPollIntervalBackoff);
  459. }
  460. else
  461. {
  462. DPFX(DPFPREP, 0, "Ignoring invalid poll interval backoff setting, using default between 0 and %u ms!",
  463. g_dwPollIntervalBackoff);
  464. }
  465. }
  466. //
  467. // If we successfully read a new interval, save it.
  468. //
  469. if (RegObject.ReadDWORD(REGKEY_VALUE_MAXPOLLINTERVAL, &dwNewValue))
  470. {
  471. //
  472. // Make sure the value is greater than the starting value.
  473. //
  474. if (dwNewValue >= g_dwNoActiveNotifyPollInterval)
  475. {
  476. g_dwMaxPollInterval = dwNewValue;
  477. DPFX(DPFPREP, 1, "Using max poll interval of %u ms.",
  478. g_dwMaxPollInterval);
  479. }
  480. else
  481. {
  482. g_dwMaxPollInterval = g_dwNoActiveNotifyPollInterval;
  483. DPFX(DPFPREP, 0, "Ignoring max poll interval of %u ms, the starting value is %u ms.",
  484. g_dwMaxPollInterval);
  485. }
  486. }
  487. else
  488. {
  489. //
  490. // Make sure the max poll interval default value is greater than
  491. // the starting value because we may have read in a new
  492. // g_dwNoActiveNotifyPollInterval that makes the default
  493. // g_dwMaxPollInterval invalid.
  494. //
  495. if (g_dwMaxPollInterval < g_dwNoActiveNotifyPollInterval)
  496. {
  497. g_dwMaxPollInterval = g_dwNoActiveNotifyPollInterval;
  498. DPFX(DPFPREP, 0, "Resetting max poll interval to %u ms so as to meet starting value.",
  499. g_dwMaxPollInterval);
  500. }
  501. }
  502. //
  503. // If we successfully read a new boolean, save it.
  504. //
  505. if (RegObject.ReadBOOL(REGKEY_VALUE_KEEPPOLLINGFORREMOTEGATEWAY, &fNewValue))
  506. {
  507. g_fKeepPollingForRemoteGateway = fNewValue;
  508. if (g_fKeepPollingForRemoteGateway)
  509. {
  510. DPFX(DPFPREP, 1, "Will continue to poll for remote gateways.");
  511. }
  512. else
  513. {
  514. //
  515. // This is actually default behavior, but print out a statement
  516. // anyway.
  517. //
  518. DPFX(DPFPREP, 1, "Continually polling for remote gateways is disallowed by registry key.");
  519. }
  520. }
  521. //
  522. // If we successfully read a new value, save it.
  523. //
  524. if (RegObject.ReadDWORD(REGKEY_VALUE_REUSEPORTTIME, &dwNewValue))
  525. {
  526. g_dwReusePortTime = dwNewValue;
  527. DPFX(DPFPREP, 1, "Reusing remote gateway discovery ports for %u ms.",
  528. g_dwReusePortTime);
  529. }
  530. //
  531. // If we successfully read a new value, save it.
  532. //
  533. if (RegObject.ReadDWORD(REGKEY_VALUE_CACHELIFEFOUND, &dwNewValue))
  534. {
  535. g_dwCacheLifeFound = dwNewValue;
  536. DPFX(DPFPREP, 1, "Caching found addresses for %u ms.",
  537. g_dwCacheLifeFound);
  538. }
  539. //
  540. // If we successfully read a new value, save it.
  541. //
  542. if (RegObject.ReadDWORD(REGKEY_VALUE_CACHELIFENOTFOUND, &dwNewValue))
  543. {
  544. g_dwCacheLifeNotFound = dwNewValue;
  545. DPFX(DPFPREP, 1, "Caching not-found addresses for %u ms.",
  546. g_dwCacheLifeNotFound);
  547. }
  548. //
  549. // Okay, we're done. Drop the lock.
  550. //
  551. DNLeaveCriticalSection(&g_csGlobalsLock);
  552. //
  553. // Done reading registry.
  554. //
  555. RegObject.Close();
  556. }
  557. } // ReadRegistrySettings
  558. #undef DPF_MODNAME
  559. #define DPF_MODNAME "InitializeGlobalRand"
  560. //=============================================================================
  561. // InitializeGlobalRand
  562. //-----------------------------------------------------------------------------
  563. //
  564. // Description: Initializes the fallback global psuedo-random number
  565. // generator, using the given seed value.
  566. //
  567. // Arguments:
  568. // DWORD dwSeed - Seed to use.
  569. //
  570. // Returns: None.
  571. //=============================================================================
  572. void InitializeGlobalRand(const DWORD dwSeed)
  573. {
  574. //
  575. // We don't need to hold a lock, since this should only be done once,
  576. // during initialization time.
  577. //
  578. g_dwHoldRand = dwSeed;
  579. } // InitializeGlobalRand
  580. #undef DPF_MODNAME
  581. #define DPF_MODNAME "GetGlobalRand"
  582. //=============================================================================
  583. // GetGlobalRand
  584. //-----------------------------------------------------------------------------
  585. //
  586. // Description: Generates a pseudo-random DWORD.
  587. //
  588. // Arguments: None.
  589. //
  590. // Returns: Pseudo-random number.
  591. //=============================================================================
  592. DWORD GetGlobalRand(void)
  593. {
  594. HCRYPTPROV hCryptProv;
  595. DWORD dwResult;
  596. WORD wResult1;
  597. WORD wResult2;
  598. #ifdef DBG
  599. DWORD dwError;
  600. #endif // DBG
  601. if (CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
  602. {
  603. if (CryptGenRandom(hCryptProv, sizeof(dwResult), (BYTE*) (&dwResult)))
  604. {
  605. CryptReleaseContext(hCryptProv, 0);
  606. return dwResult;
  607. }
  608. #ifdef DBG
  609. else
  610. {
  611. dwError = GetLastError();
  612. DPFX(DPFPREP, 0, "Crypto couldn't generate random number (err = %u)!",
  613. dwError);
  614. }
  615. #endif // DBG
  616. CryptReleaseContext(hCryptProv, 0);
  617. }
  618. #ifdef DBG
  619. else
  620. {
  621. dwError = GetLastError();
  622. DPFX(DPFPREP, 0, "Couldn't acquire crypto provider context (err = %u)!",
  623. dwError);
  624. }
  625. #endif // DBG
  626. //
  627. // We couldn't use the crypto API to generate a random number, so make
  628. // our own based off the C run time source.
  629. //
  630. DNEnterCriticalSection(&g_csGlobalsLock);
  631. g_dwHoldRand = ((g_dwHoldRand * 214013L + 2531011L) >> 16) & 0x7fff;
  632. wResult1 = (WORD) g_dwHoldRand;
  633. g_dwHoldRand = ((g_dwHoldRand * 214013L + 2531011L) >> 16) & 0x7fff;
  634. wResult2 = (WORD) g_dwHoldRand;
  635. DNLeaveCriticalSection(&g_csGlobalsLock);
  636. return MAKELONG(wResult1, wResult2);
  637. } // GetGlobalRand
  638. #undef DPF_MODNAME
  639. #define DPF_MODNAME "DoCreateInstance"
  640. //=============================================================================
  641. // DoCreateInstance
  642. //-----------------------------------------------------------------------------
  643. //
  644. // Description: Creates an instance of an interface. Required by the general
  645. // purpose class factory functions.
  646. //
  647. // Arguments:
  648. // LPCLASSFACTORY This - Pointer to class factory.
  649. // LPUNKNOWN pUnkOuter - Pointer to unknown interface.
  650. // REFCLSID rclsid - Reference of GUID of desired interface.
  651. // REFIID riid - Reference to another GUID?
  652. // LPVOID * ppvObj - Pointer to pointer to interface.
  653. //
  654. // Returns: HRESULT
  655. //=============================================================================
  656. HRESULT DoCreateInstance(LPCLASSFACTORY This,
  657. LPUNKNOWN pUnkOuter,
  658. REFCLSID rclsid,
  659. REFIID riid,
  660. LPVOID * ppvObj)
  661. {
  662. HRESULT hr;
  663. BOOL fNotCreatedWithCOM;
  664. CNATHelpPAST * pNATHelpPAST = NULL;
  665. DNASSERT(ppvObj != NULL);
  666. if (! IsEqualCLSID(rclsid, CLSID_DirectPlayNATHelpPAST))
  667. {
  668. //
  669. // This shouldn't happen if they called IClassFactory::CreateObject
  670. // correctly.
  671. //
  672. DNASSERT(FALSE);
  673. //
  674. // Return an error.
  675. //
  676. hr = E_UNEXPECTED;
  677. goto Failure;
  678. }
  679. //
  680. // If the class factory pointer is NULL, then we were called by the
  681. // DirectPlayNATHelpCreate function.
  682. //
  683. if (This == NULL)
  684. {
  685. fNotCreatedWithCOM = TRUE;
  686. }
  687. else
  688. {
  689. fNotCreatedWithCOM = FALSE;
  690. }
  691. //
  692. // Create the object instance.
  693. //
  694. pNATHelpPAST = new CNATHelpPAST(fNotCreatedWithCOM);
  695. if (pNATHelpPAST == NULL)
  696. {
  697. hr = E_OUTOFMEMORY;
  698. goto Failure;
  699. }
  700. //
  701. // Initialize the base object (which might fail).
  702. //
  703. hr = pNATHelpPAST->InitializeObject();
  704. if (hr != S_OK)
  705. {
  706. DPFX(DPFPREP, 0, "Couldn't initialize object!");
  707. delete pNATHelpPAST;
  708. pNATHelpPAST = NULL;
  709. goto Failure;
  710. }
  711. //
  712. // Add it to the global list.
  713. //
  714. DNEnterCriticalSection(&g_csGlobalsLock);
  715. pNATHelpPAST->m_blList.InsertBefore(&g_blNATHelpPASTObjs);
  716. g_lOutstandingInterfaceCount++; // update count so DllCanUnloadNow works correctly
  717. DNLeaveCriticalSection(&g_csGlobalsLock);
  718. //
  719. // Get the right interface for the caller and bump the refcount.
  720. //
  721. hr = pNATHelpPAST->QueryInterface(riid, ppvObj);
  722. if (hr != S_OK)
  723. {
  724. goto Failure;
  725. }
  726. Exit:
  727. //
  728. // Release the local reference to the object. If this function was
  729. // successful, there's still a reference in ppvObj.
  730. //
  731. if (pNATHelpPAST != NULL)
  732. {
  733. pNATHelpPAST->Release();
  734. pNATHelpPAST = NULL;
  735. }
  736. return hr;
  737. Failure:
  738. //
  739. // Make sure we don't hand back a pointer.
  740. //
  741. (*ppvObj) = NULL;
  742. goto Exit;
  743. } // DoCreateInstance
  744. #undef DPF_MODNAME
  745. #define DPF_MODNAME "IsClassImplemented"
  746. //=============================================================================
  747. // IsClassImplemented
  748. //-----------------------------------------------------------------------------
  749. //
  750. // Description: Determine if a class is implemented in this DLL. Required by
  751. // the general purpose class factory functions.
  752. //
  753. // Arguments:
  754. // REFCLSID rclsid - Reference to class GUID.
  755. //
  756. // Returns: BOOL
  757. // TRUE - This DLL implements the class.
  758. // FALSE - This DLL doesn't implement the class.
  759. //=============================================================================
  760. BOOL IsClassImplemented(REFCLSID rclsid)
  761. {
  762. return (IsEqualCLSID(rclsid, CLSID_DirectPlayNATHelpPAST));
  763. } // IsClassImplemented