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.

995 lines
23 KiB

  1. /***************************************************************************
  2. *
  3. * Copyright (C) 2001-2002 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: dp8simdllmain.cpp
  6. *
  7. * Content: DP8SIM DLL entry points.
  8. *
  9. * History:
  10. * Date By Reason
  11. * ======== ======== =========
  12. * 04/23/01 VanceO Created.
  13. *
  14. ***************************************************************************/
  15. #include "dp8simi.h"
  16. //=============================================================================
  17. // External globals
  18. //=============================================================================
  19. volatile LONG g_lOutstandingInterfaceCount = 0; // number of outstanding interfaces
  20. HINSTANCE g_hDLLInstance = NULL; // handle to this DLL instance
  21. DNCRITICAL_SECTION g_csGlobalsLock; // lock protecting all of the following globals
  22. CBilink g_blDP8SimSPObjs; // bilink of all the DP8SimSP interface objects
  23. CBilink g_blDP8SimControlObjs; // bilink of all the DP8SimControl interface objects
  24. UINT g_uiRandShr3 = 0; // global holding value for Shr3 random number sequence generator
  25. UINT g_uiRandCong = 0; // global holding value for congruential random number sequence generator
  26. //=============================================================================
  27. // Supported SPs table
  28. //=============================================================================
  29. typedef struct _SUPPORTEDSP
  30. {
  31. const CLSID * pclsidFakeSP; // pointer to class ID for fake SP
  32. const CLSID * pclsidRealSP; // pointer to class ID for real SP
  33. const WCHAR * pwszVerIndProgID; // version independent prog ID for fake SP COM object, must match the sub key for pwszServiceProviderKey
  34. const WCHAR * pwszProgID; // prog ID for fake SP COM object
  35. const WCHAR * pwszDesc; // description for fake SP COM object
  36. const WCHAR * pwszServiceProviderKey; // service provider key string, sub key must match pwszVerIndProgID
  37. UINT uiFriendlyNameResourceID; // ID of fake SP's name string resource
  38. } SUPPORTEDSP;
  39. const SUPPORTEDSP c_aSupportedSPs[] =
  40. {
  41. {
  42. (&CLSID_NETWORKSIMULATOR_DP8SP_TCPIP),
  43. (&CLSID_DP8SP_TCPIP),
  44. L"DP8SimTCPIP",
  45. L"DP8SimTCPIP.1",
  46. L"DirectPlay8 Network Simulator TCP/IP Service Provider",
  47. DPN_REG_LOCAL_SP_SUBKEY L"\\DP8SimTCPIP",
  48. IDS_FRIENDLYNAME_TCPIP,
  49. },
  50. };
  51. #define NUM_SUPPORTED_SPS (sizeof(c_aSupportedSPs) / sizeof(c_aSupportedSPs[0]))
  52. //=============================================================================
  53. // Defines
  54. //=============================================================================
  55. #define MAX_RESOURCE_STRING_LENGTH _MAX_PATH
  56. //=============================================================================
  57. // Macros
  58. //=============================================================================
  59. // 3-shift register generator
  60. //
  61. // Original comments:
  62. // SHR3 is a 3-shift-register generator with period 2^32-1. It uses
  63. // y(n)=y(n-1)(I+L^17)(I+R^13)(I+L^5), with the y's viewed as binary vectors,
  64. // L the 32x32 binary matrix that shifts a vector left 1, and R its transpose.
  65. // SHR3 seems to pass all except those related to the binary rank test, since
  66. // 32 successive values, as binary vectors, must be linearly independent,
  67. // while 32 successive truly random 32-bit integers, viewed as binary vectors,
  68. // will be linearly independent only about 29% of the time.
  69. #define RANDALG_SHR3() (g_uiRandShr3 = g_uiRandShr3 ^ (g_uiRandShr3 << 17), g_uiRandShr3 = g_uiRandShr3 ^ (g_uiRandShr3 >> 13), g_uiRandShr3 = g_uiRandShr3 ^ (g_uiRandShr3 << 5))
  70. // Congruential generator
  71. //
  72. // Original comments:
  73. // CONG is a congruential generator with the widely used 69069 multiplier:
  74. // x(n)=69069x(n-1)+1234567. It has period 2^32. The leading half of its 32
  75. // bits seem to pass tests, but bits in the last half are too regular.
  76. #define RANDALG_CONG() (g_uiRandCong = 69069UL * g_uiRandCong + 1234567UL)
  77. //=============================================================================
  78. // Local prototypes
  79. //=============================================================================
  80. BOOL InitializeProcessGlobals(void);
  81. void CleanupProcessGlobals(void);
  82. HRESULT LoadAndAllocString(UINT uiResourceID, WCHAR ** pwszString);
  83. #undef DPF_MODNAME
  84. #define DPF_MODNAME "DllMain"
  85. //=============================================================================
  86. // DllMain
  87. //-----------------------------------------------------------------------------
  88. //
  89. // Description: DLL entry point.
  90. //
  91. // Arguments:
  92. // HINSTANCE hDllInst - Handle to this DLL module.
  93. // DWORD dwReason - Reason for calling this function.
  94. // LPVOID lpvReserved - Reserved.
  95. //
  96. // Returns: TRUE if all goes well, FALSE otherwise.
  97. //=============================================================================
  98. BOOL WINAPI DllMain(HINSTANCE hDllInst,
  99. DWORD dwReason,
  100. LPVOID lpvReserved)
  101. {
  102. switch (dwReason)
  103. {
  104. case DLL_PROCESS_ATTACH:
  105. {
  106. DPFX(DPFPREP, 2, "====> ENTER: DLLMAIN(%p): Process Attach: %08lx, tid=%08lx",
  107. DllMain, GetCurrentProcessId(), GetCurrentThreadId());
  108. DNASSERT(g_hDLLInstance == NULL);
  109. g_hDLLInstance = hDllInst;
  110. //
  111. // Attempt to initialize the OS abstraction layer.
  112. //
  113. if (! DNOSIndirectionInit(0))
  114. {
  115. DPFX(DPFPREP, 0, "Failed to initialize OS indirection layer!");
  116. return FALSE;
  117. }
  118. //
  119. // Attempt to initialize COM.
  120. //
  121. if (FAILED(COM_Init()))
  122. {
  123. DPFX(DPFPREP, 0, "Failed to initialize COM indirection layer!");
  124. DNOSIndirectionDeinit();
  125. return FALSE;
  126. }
  127. //
  128. // Attempt to initialize process-global items.
  129. //
  130. if (! InitializeProcessGlobals())
  131. {
  132. DPFX(DPFPREP, 0, "Failed to initialize globals!");
  133. COM_Free();
  134. DNOSIndirectionDeinit();
  135. return FALSE;
  136. }
  137. //
  138. // We don't need thread attach/detach messages.
  139. //
  140. DisableThreadLibraryCalls(hDllInst);
  141. return TRUE;
  142. break;
  143. }
  144. case DLL_PROCESS_DETACH:
  145. {
  146. DPFX(DPFPREP, 2, "====> EXIT: DLLMAIN(%p): Process Detach %08lx, tid=%08lx",
  147. DllMain, GetCurrentProcessId(), GetCurrentThreadId());
  148. DNASSERT(g_hDLLInstance != NULL);
  149. g_hDLLInstance = NULL;
  150. CleanupProcessGlobals();
  151. COM_Free();
  152. DNOSIndirectionDeinit();
  153. return TRUE;
  154. break;
  155. }
  156. default:
  157. {
  158. DNASSERT(FALSE);
  159. break;
  160. }
  161. }
  162. return FALSE;
  163. } // DllMain
  164. #undef DPF_MODNAME
  165. #define DPF_MODNAME "DllRegisterServer"
  166. //=============================================================================
  167. // DllRegisterServer
  168. //-----------------------------------------------------------------------------
  169. //
  170. // Description: Registers the DP8Sim COM object.
  171. //
  172. // Arguments: None.
  173. //
  174. // Returns: HRESULT
  175. // S_OK - Successfully registered DP8Sim.
  176. // E_FAIL - Failed registering DP8Sim.
  177. //=============================================================================
  178. HRESULT WINAPI DllRegisterServer(void)
  179. {
  180. HRESULT hr;
  181. CRegistry RegObject;
  182. DWORD dwLength;
  183. DWORD dwSimulatedSP;
  184. char szLocalPath[_MAX_PATH + 1];
  185. WCHAR wszLocalPath[_MAX_PATH + 1];
  186. WCHAR * pwszFriendlyName = NULL;
  187. //
  188. // Retrieve the location of this DLL.
  189. //
  190. dwLength = GetModuleFileNameA(g_hDLLInstance, szLocalPath, _MAX_PATH);
  191. if (dwLength == 0)
  192. {
  193. DPFX(DPFPREP, 0, "Couldn't read local path!");
  194. hr = E_FAIL;
  195. goto Failure;
  196. }
  197. //
  198. // Include NULL termination.
  199. //
  200. szLocalPath[dwLength] = '\0';
  201. dwLength++;
  202. //
  203. // Convert it to Unicode.
  204. //
  205. hr = STR_AnsiToWide(szLocalPath, dwLength, wszLocalPath, &dwLength);
  206. if (hr != S_OK)
  207. {
  208. DPFX(DPFPREP, 0, "Could not convert ANSI path to Unicode!");
  209. goto Failure;
  210. }
  211. //
  212. // Register the control COM object CLSID.
  213. //
  214. if (! RegObject.Register(L"DP8SimControl.1",
  215. L"DirectPlay8 Network Simulator Control Object",
  216. wszLocalPath,
  217. &CLSID_DP8SimControl,
  218. L"DP8SimControl"))
  219. {
  220. DPFX(DPFPREP, 0, "Could not register DP8SimControl object!");
  221. hr = E_FAIL;
  222. goto Failure;
  223. }
  224. //
  225. // Register all of the simulated SPs.
  226. //
  227. for(dwSimulatedSP = 0; dwSimulatedSP < NUM_SUPPORTED_SPS; dwSimulatedSP++)
  228. {
  229. if (! RegObject.Register(c_aSupportedSPs[dwSimulatedSP].pwszProgID,
  230. c_aSupportedSPs[dwSimulatedSP].pwszDesc,
  231. wszLocalPath,
  232. c_aSupportedSPs[dwSimulatedSP].pclsidFakeSP,
  233. c_aSupportedSPs[dwSimulatedSP].pwszVerIndProgID))
  234. {
  235. DPFX(DPFPREP, 0, "Could not register simulated SP %u object!",
  236. dwSimulatedSP);
  237. hr = E_FAIL;
  238. goto Failure;
  239. }
  240. hr = LoadAndAllocString(c_aSupportedSPs[dwSimulatedSP].uiFriendlyNameResourceID,
  241. &pwszFriendlyName);
  242. if (FAILED(hr))
  243. {
  244. DPFX(DPFPREP, 0, "Could not load friendly name string (err = 0x%lx)!", hr);
  245. goto Failure;
  246. }
  247. if (! RegObject.Open(HKEY_LOCAL_MACHINE, c_aSupportedSPs[dwSimulatedSP].pwszServiceProviderKey, FALSE, TRUE))
  248. {
  249. DPFX(DPFPREP, 0, "Could not open service provider key!");
  250. hr = E_FAIL;
  251. goto Failure;
  252. }
  253. RegObject.WriteString(DPN_REG_KEYNAME_FRIENDLY_NAME, pwszFriendlyName);
  254. RegObject.WriteGUID(DPN_REG_KEYNAME_GUID, *(c_aSupportedSPs[dwSimulatedSP].pclsidFakeSP));
  255. RegObject.Close();
  256. DNFree(pwszFriendlyName);
  257. pwszFriendlyName = NULL;
  258. }
  259. hr = S_OK;
  260. Exit:
  261. return hr;
  262. Failure:
  263. if (pwszFriendlyName != NULL)
  264. {
  265. DNFree(pwszFriendlyName);
  266. pwszFriendlyName = NULL;
  267. }
  268. goto Exit;
  269. } // DllRegisterServer
  270. #undef DPF_MODNAME
  271. #define DPF_MODNAME "DllUnregisterServer"
  272. //=============================================================================
  273. // DllUnregisterServer
  274. //-----------------------------------------------------------------------------
  275. //
  276. // Description: Unregisters the DP8Sim COM object.
  277. //
  278. // Arguments: None.
  279. //
  280. // Returns: HRESULT
  281. // S_OK - Successfully unregistered DP8Sim.
  282. // E_FAIL - Failed unregistering DP8Sim.
  283. //=============================================================================
  284. STDAPI DllUnregisterServer(void)
  285. {
  286. HRESULT hr;
  287. CRegistry RegObject;
  288. DWORD dwSimulatedSP;
  289. //
  290. // Unregister the control class.
  291. //
  292. if (! RegObject.UnRegister(&CLSID_DP8SimControl))
  293. {
  294. DPFX(DPFPREP, 0, "Failed to unregister DP8Sim control object!");
  295. hr = E_FAIL;
  296. goto Failure;
  297. }
  298. //
  299. // Unregister all of the simulated SPs.
  300. //
  301. if (! RegObject.Open(HKEY_LOCAL_MACHINE, DPN_REG_LOCAL_SP_SUBKEY, FALSE, FALSE, FALSE))
  302. {
  303. DPFX(DPFPREP, 0, "Could not open HKEY_LOCAL_MACHINE!");
  304. hr = E_FAIL;
  305. goto Failure;
  306. }
  307. for(dwSimulatedSP = 0; dwSimulatedSP < NUM_SUPPORTED_SPS; dwSimulatedSP++)
  308. {
  309. if (! RegObject.UnRegister(c_aSupportedSPs[dwSimulatedSP].pclsidFakeSP))
  310. {
  311. DPFX(DPFPREP, 0, "Could not unregister simulated SP %u object!",
  312. dwSimulatedSP);
  313. hr = E_FAIL;
  314. goto Failure;
  315. }
  316. if (! RegObject.DeleteSubKey(c_aSupportedSPs[dwSimulatedSP].pwszVerIndProgID))
  317. {
  318. DPFX(DPFPREP, 0, "Could not delete simulated SP %u's key!",
  319. dwSimulatedSP);
  320. hr = E_FAIL;
  321. goto Failure;
  322. }
  323. }
  324. RegObject.Close();
  325. hr = S_OK;
  326. Exit:
  327. return hr;
  328. Failure:
  329. //
  330. // Rely on RegObject destructure to close registry key.
  331. //
  332. goto Exit;
  333. } // DllUnregisterServer
  334. #undef DPF_MODNAME
  335. #define DPF_MODNAME "InitializeProcessGlobals"
  336. //=============================================================================
  337. // InitializeProcessGlobals
  338. //-----------------------------------------------------------------------------
  339. //
  340. // Description: Initialize global items needed for the DLL to operate.
  341. //
  342. // Arguments: None.
  343. //
  344. // Returns: TRUE if successful, FALSE if an error occurred.
  345. //=============================================================================
  346. BOOL InitializeProcessGlobals(void)
  347. {
  348. BOOL fReturn = TRUE;
  349. BOOL fInittedGlobalLock = FALSE;
  350. if (! DNInitializeCriticalSection(&g_csGlobalsLock))
  351. {
  352. DPFX(DPFPREP, 0, "Failed to initialize global lock!");
  353. goto Failure;
  354. }
  355. fInittedGlobalLock = TRUE;
  356. //
  357. // Don't allow critical section reentry.
  358. //
  359. DebugSetCriticalSectionRecursionCount(&g_csGlobalsLock, 0);
  360. if (!InitializePools())
  361. {
  362. DPFX(DPFPREP, 0, "Failed initializing pools!");
  363. goto Failure;
  364. }
  365. g_blDP8SimSPObjs.Initialize();
  366. g_blDP8SimControlObjs.Initialize();
  367. //
  368. // Seed the random number generator with the current time.
  369. //
  370. InitializeGlobalRand(GETTIMESTAMP());
  371. Exit:
  372. return fReturn;
  373. Failure:
  374. if (fInittedGlobalLock)
  375. {
  376. DNDeleteCriticalSection(&g_csGlobalsLock);
  377. }
  378. fReturn = FALSE;
  379. goto Exit;
  380. } // InitializeProcessGlobals
  381. #undef DPF_MODNAME
  382. #define DPF_MODNAME "CleanupProcessGlobals"
  383. //=============================================================================
  384. // CleanupProcessGlobals
  385. //-----------------------------------------------------------------------------
  386. //
  387. // Description: Releases global items used by DLL.
  388. //
  389. // Arguments: None.
  390. //
  391. // Returns: None.
  392. //=============================================================================
  393. void CleanupProcessGlobals(void)
  394. {
  395. CBilink * pBilink;
  396. CDP8SimSP * pDP8SimSP;
  397. CDP8SimControl * pDP8SimControl;
  398. if (! g_blDP8SimSPObjs.IsEmpty())
  399. {
  400. DNASSERT(! "DP8Sim DLL unloading without all SP objects having been released!");
  401. //
  402. // Force close all the objects still outstanding.
  403. //
  404. pBilink = g_blDP8SimSPObjs.GetNext();
  405. while (pBilink != &g_blDP8SimSPObjs)
  406. {
  407. pDP8SimSP = DP8SIMSP_FROM_BILINK(pBilink);
  408. pBilink = pBilink->GetNext();
  409. DPFX(DPFPREP, 0, "Forcefully releasing SP object 0x%p!", pDP8SimSP);
  410. pDP8SimSP->Close(); // ignore error
  411. //
  412. // Forcefully remove it from the list and delete it instead of
  413. // using pDP8SimSP->Release().
  414. //
  415. pDP8SimSP->m_blList.RemoveFromList();
  416. pDP8SimSP->UninitializeObject();
  417. delete pDP8SimSP;
  418. }
  419. }
  420. if (! g_blDP8SimControlObjs.IsEmpty())
  421. {
  422. DNASSERT(! "DP8Sim DLL unloading without all Control objects having been released!");
  423. //
  424. // Force close all the objects still outstanding.
  425. //
  426. pBilink = g_blDP8SimControlObjs.GetNext();
  427. while (pBilink != &g_blDP8SimControlObjs)
  428. {
  429. pDP8SimControl = DP8SIMCONTROL_FROM_BILINK(pBilink);
  430. pBilink = pBilink->GetNext();
  431. DPFX(DPFPREP, 0, "Forcefully releasing Control object 0x%p!", pDP8SimControl);
  432. pDP8SimControl->Close(0); // ignore error
  433. //
  434. // Forcefully remove it from the list and delete it instead of
  435. // using pDP8SimControl->Release().
  436. //
  437. pDP8SimControl->m_blList.RemoveFromList();
  438. pDP8SimControl->UninitializeObject();
  439. delete pDP8SimControl;
  440. }
  441. }
  442. CleanupPools();
  443. DNDeleteCriticalSection(&g_csGlobalsLock);
  444. } // CleanupProcessGlobals
  445. #undef DPF_MODNAME
  446. #define DPF_MODNAME "LoadAndAllocString"
  447. //=============================================================================
  448. // LoadAndAllocString
  449. //-----------------------------------------------------------------------------
  450. //
  451. // Description: DNMallocs a wide character string from the given resource ID.
  452. //
  453. // Arguments:
  454. // UINT uiResourceID - Resource ID to load.
  455. // WCHAR ** pwszString - Place to store pointer to allocated string.
  456. //
  457. // Returns: HRESULT
  458. //=============================================================================
  459. HRESULT LoadAndAllocString(UINT uiResourceID, WCHAR ** pwszString)
  460. {
  461. HRESULT hr = DPN_OK;
  462. int iLength;
  463. if (DNGetOSType() == VER_PLATFORM_WIN32_NT)
  464. {
  465. WCHAR wszTmpBuffer[MAX_RESOURCE_STRING_LENGTH];
  466. iLength = LoadStringW(g_hDLLInstance, uiResourceID, wszTmpBuffer, MAX_RESOURCE_STRING_LENGTH );
  467. if (iLength == 0)
  468. {
  469. hr = GetLastError();
  470. DPFX(DPFPREP, 0, "Unable to load resource ID %d error 0x%x", uiResourceID, hr);
  471. (*pwszString) = NULL;
  472. goto Exit;
  473. }
  474. (*pwszString) = (WCHAR*) DNMalloc((iLength + 1) * sizeof(WCHAR));
  475. if ((*pwszString) == NULL)
  476. {
  477. DPFX(DPFPREP, 0, "Memory allocation failure!");
  478. hr = DPNERR_OUTOFMEMORY;
  479. goto Exit;
  480. }
  481. wcscpy((*pwszString), wszTmpBuffer);
  482. }
  483. else
  484. {
  485. char szTmpBuffer[MAX_RESOURCE_STRING_LENGTH];
  486. iLength = LoadStringA(g_hDLLInstance, uiResourceID, szTmpBuffer, MAX_RESOURCE_STRING_LENGTH );
  487. if (iLength == 0)
  488. {
  489. hr = GetLastError();
  490. DPFX(DPFPREP, 0, "Unable to load resource ID %u (err =0x%lx)!", uiResourceID, hr);
  491. (*pwszString) = NULL;
  492. goto Exit;
  493. }
  494. (*pwszString) = (WCHAR*) DNMalloc((iLength + 1) * sizeof(WCHAR));
  495. if ((*pwszString) == NULL)
  496. {
  497. DPFX(DPFPREP, 0, "Memory allocation failure!");
  498. hr = DPNERR_OUTOFMEMORY;
  499. goto Exit;
  500. }
  501. hr = STR_jkAnsiToWide((*pwszString), szTmpBuffer, (iLength + 1));
  502. if (hr == DPN_OK)
  503. {
  504. hr = GetLastError();
  505. DPFX(DPFPREP, 0, "Unable to convert from ANSI to Unicode (err =0x%lx)!", hr);
  506. goto Exit;
  507. }
  508. }
  509. Exit:
  510. return hr;
  511. } // LoadAndAllocString
  512. #undef DPF_MODNAME
  513. #define DPF_MODNAME "InitializeGlobalRand"
  514. //=============================================================================
  515. // InitializeGlobalRand
  516. //-----------------------------------------------------------------------------
  517. //
  518. // Description: Initializes the global psuedo-random number generator, using
  519. // the given seed value.
  520. //
  521. // Based off algorithms posted to usenet by George Marsaglia.
  522. //
  523. // Arguments:
  524. // DWORD dwSeed - Seed to use.
  525. //
  526. // Returns: None.
  527. //=============================================================================
  528. void InitializeGlobalRand(const DWORD dwSeed)
  529. {
  530. //
  531. // We don't need to hold a lock, since this should only be done once,
  532. // during initialization time.
  533. //
  534. g_uiRandShr3 = dwSeed;
  535. g_uiRandCong = dwSeed;
  536. } // InitializeGlobalRand
  537. #undef DPF_MODNAME
  538. #define DPF_MODNAME "GetGlobalRand"
  539. //=============================================================================
  540. // GetGlobalRand
  541. //-----------------------------------------------------------------------------
  542. //
  543. // Description: Generates a pseudo-random positive double between 0.0 and
  544. // 1.0, inclusive.
  545. //
  546. // Based off algorithms posted to usenet by George Marsaglia.
  547. //
  548. // Arguments: None.
  549. //
  550. // Returns: Pseudo-random number.
  551. //=============================================================================
  552. double GetGlobalRand(void)
  553. {
  554. double dResult;
  555. DNEnterCriticalSection(&g_csGlobalsLock);
  556. dResult = (RANDALG_CONG() + RANDALG_SHR3()) * 2.328306e-10f;
  557. DNLeaveCriticalSection(&g_csGlobalsLock);
  558. return dResult;
  559. } // GetGlobalRand
  560. #undef DPF_MODNAME
  561. #define DPF_MODNAME "DoCreateInstance"
  562. //=============================================================================
  563. // DoCreateInstance
  564. //-----------------------------------------------------------------------------
  565. //
  566. // Description: Creates an instance of an interface. Required by the general
  567. // purpose class factory functions.
  568. //
  569. // Arguments:
  570. // LPCLASSFACTORY This - Pointer to class factory.
  571. // LPUNKNOWN pUnkOuter - Pointer to unknown interface.
  572. // REFCLSID rclsid - Reference of GUID of desired interface.
  573. // REFIID riid - Reference to another GUID?
  574. // LPVOID * ppvObj - Pointer to pointer to interface.
  575. //
  576. // Returns: HRESULT
  577. //=============================================================================
  578. HRESULT DoCreateInstance(LPCLASSFACTORY This,
  579. LPUNKNOWN pUnkOuter,
  580. REFCLSID rclsid,
  581. REFIID riid,
  582. LPVOID * ppvObj)
  583. {
  584. HRESULT hr;
  585. CDP8SimSP * pDP8SimSP = NULL;
  586. CDP8SimControl * pDP8SimControl = NULL;
  587. DWORD dwSimulatedSP;
  588. DNASSERT(ppvObj != NULL);
  589. //
  590. // See if it's the control object.
  591. //
  592. if (IsEqualCLSID(rclsid, CLSID_DP8SimControl))
  593. {
  594. //
  595. // Create the object instance.
  596. //
  597. pDP8SimControl = new CDP8SimControl;
  598. if (pDP8SimControl == NULL)
  599. {
  600. hr = E_OUTOFMEMORY;
  601. goto Failure;
  602. }
  603. //
  604. // Initialize the base object (which might fail).
  605. //
  606. hr = pDP8SimControl->InitializeObject();
  607. if (hr != S_OK)
  608. {
  609. delete pDP8SimControl;
  610. pDP8SimControl = NULL;
  611. goto Failure;
  612. }
  613. //
  614. // Add it to the global list.
  615. //
  616. DNEnterCriticalSection(&g_csGlobalsLock);
  617. pDP8SimControl->m_blList.InsertBefore(&g_blDP8SimControlObjs);
  618. g_lOutstandingInterfaceCount++; // update count so DllCanUnloadNow works correctly
  619. DNLeaveCriticalSection(&g_csGlobalsLock);
  620. //
  621. // Get the right interface for the caller and bump the refcount.
  622. //
  623. hr = pDP8SimControl->QueryInterface(riid, ppvObj);
  624. if (hr != S_OK)
  625. {
  626. goto Failure;
  627. }
  628. }
  629. else
  630. {
  631. //
  632. // Look up the real SP we're replacing.
  633. //
  634. for(dwSimulatedSP = 0; dwSimulatedSP < NUM_SUPPORTED_SPS; dwSimulatedSP++)
  635. {
  636. if (IsEqualCLSID(rclsid, *(c_aSupportedSPs[dwSimulatedSP].pclsidFakeSP)))
  637. {
  638. break;
  639. }
  640. }
  641. //
  642. // If we didn't find it
  643. //
  644. if (dwSimulatedSP >= NUM_SUPPORTED_SPS)
  645. {
  646. DPFX(DPFPREP, 0, "Unrecognized service provider class ID!");
  647. hr = E_UNEXPECTED;
  648. goto Failure;
  649. }
  650. //
  651. // Create the object instance.
  652. //
  653. pDP8SimSP = new CDP8SimSP(c_aSupportedSPs[dwSimulatedSP].pclsidFakeSP,
  654. c_aSupportedSPs[dwSimulatedSP].pclsidRealSP);
  655. if (pDP8SimSP == NULL)
  656. {
  657. hr = E_OUTOFMEMORY;
  658. goto Failure;
  659. }
  660. //
  661. // Initialize the base object (which might fail).
  662. //
  663. hr = pDP8SimSP->InitializeObject();
  664. if (hr != S_OK)
  665. {
  666. DPFX(DPFPREP, 0, "Couldn't initialize object!");
  667. delete pDP8SimSP;
  668. pDP8SimSP = NULL;
  669. goto Failure;
  670. }
  671. //
  672. // Add it to the global list.
  673. //
  674. DNEnterCriticalSection(&g_csGlobalsLock);
  675. pDP8SimSP->m_blList.InsertBefore(&g_blDP8SimSPObjs);
  676. g_lOutstandingInterfaceCount++; // update count so DllCanUnloadNow works correctly
  677. DNLeaveCriticalSection(&g_csGlobalsLock);
  678. //
  679. // Get the right interface for the caller and bump the refcount.
  680. //
  681. hr = pDP8SimSP->QueryInterface(riid, ppvObj);
  682. if (hr != S_OK)
  683. {
  684. goto Failure;
  685. }
  686. }
  687. Exit:
  688. //
  689. // Release the local reference to the objec(s)t. If this function was
  690. // successful, there's still a reference in ppvObj.
  691. //
  692. if (pDP8SimSP != NULL)
  693. {
  694. pDP8SimSP->Release();
  695. pDP8SimSP = NULL;
  696. }
  697. if (pDP8SimControl != NULL)
  698. {
  699. pDP8SimControl->Release();
  700. pDP8SimControl = NULL;
  701. }
  702. return hr;
  703. Failure:
  704. //
  705. // Make sure we don't hand back a pointer.
  706. //
  707. (*ppvObj) = NULL;
  708. goto Exit;
  709. } // DoCreateInstance
  710. #undef DPF_MODNAME
  711. #define DPF_MODNAME "IsClassImplemented"
  712. //=============================================================================
  713. // IsClassImplemented
  714. //-----------------------------------------------------------------------------
  715. //
  716. // Description: Determine if a class is implemented in this DLL. Required by
  717. // the general purpose class factory functions.
  718. //
  719. // Arguments:
  720. // REFCLSID rclsid - Reference to class GUID.
  721. //
  722. // Returns: BOOL
  723. // TRUE - This DLL implements the class.
  724. // FALSE - This DLL doesn't implement the class.
  725. //=============================================================================
  726. BOOL IsClassImplemented(REFCLSID rclsid)
  727. {
  728. DWORD dwSimulatedSP;
  729. if (IsEqualCLSID(rclsid, CLSID_DP8SimControl))
  730. {
  731. return TRUE;
  732. }
  733. //
  734. // Check if this is a valid simulated SP.
  735. //
  736. for(dwSimulatedSP = 0; dwSimulatedSP < NUM_SUPPORTED_SPS; dwSimulatedSP++)
  737. {
  738. if (IsEqualCLSID(rclsid, *(c_aSupportedSPs[dwSimulatedSP].pclsidFakeSP)))
  739. {
  740. return TRUE;
  741. }
  742. }
  743. return FALSE;
  744. } // IsClassImplemented