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.

557 lines
14 KiB

  1. /*++
  2. Copyright (c) 1995-1997 Microsoft Corporation
  3. Module Name :
  4. wam.cpp
  5. Abstract:
  6. This module implements the exported routines for WAM object
  7. Author:
  8. David Kaplan ( DaveK ) 26-Feb-1997
  9. Environment:
  10. User Mode - Win32
  11. Project:
  12. Wam DLL
  13. --*/
  14. //
  15. // Following are the notes from the original MSDEV generated file
  16. // Note: Proxy/Stub Information
  17. // To merge the proxy/stub code into the object DLL, add the file
  18. // dlldatax.c to the project. Make sure precompiled headers
  19. // are turned off for this file, and add _MERGE_PROXYSTUB to the
  20. // defines for the project.
  21. //
  22. // If you are not running WinNT4.0 or Win95 with DCOM, then you
  23. // need to remove the following define from dlldatax.c
  24. // #define _WIN32_WINNT 0x0400
  25. //
  26. // Further, if you are running MIDL without /Oicf switch, you also
  27. // need to remove the following define from dlldatax.c.
  28. // #define USE_STUBLESS_PROXY
  29. //
  30. // Modify the custom build rule for Wam.idl by adding the following
  31. // files to the Outputs.
  32. // Wam_p.c
  33. // dlldata.c
  34. // To build a separate proxy/stub DLL,
  35. // run nmake -f Wamps.mk in the project directory.
  36. // BEGIN mods
  37. // Post-wizard mods appear within BEGIN mods ... END mods
  38. // END mods
  39. #include <isapip.hxx>
  40. #include "pudebug.h"
  41. #include "resource.h"
  42. #include "initguid.h"
  43. #include "wamobj.hxx"
  44. #include "Wam_i.c"
  45. // BEGIN mods
  46. #include <irtldbg.h>
  47. #include "setable.hxx"
  48. #include "wamccf.hxx"
  49. #include <ooptoken.h>
  50. #ifdef _ATL_STATIC_REGISTRY
  51. #include <statreg.h>
  52. #include <statreg.cpp>
  53. #endif
  54. #include <atlimpl.cpp>
  55. // END mods
  56. /************************************************************
  57. * Global Variables
  58. ************************************************************/
  59. const CHAR g_pszModuleName[] = "WAM";
  60. const CHAR g_pszWamRegLocation[] =
  61. "System\\CurrentControlSet\\Services\\W3Svc\\WAM";
  62. #ifdef _MERGE_PROXYSTUB
  63. extern "C" HINSTANCE hProxyDll;
  64. #endif
  65. CWamModule _Module;
  66. BEGIN_OBJECT_MAP(ObjectMap)
  67. OBJECT_ENTRY(CLSID_Wam, WAM)
  68. END_OBJECT_MAP()
  69. // BEGIN mods
  70. WAM_CCF_MODULE _WAMCCFModule; // Custom Class Factory Module
  71. DECLARE_PLATFORM_TYPE();
  72. #ifndef _NO_TRACING_
  73. #include <initguid.h>
  74. DEFINE_GUID(IisWamObjectGuid,
  75. 0x784d8909, 0xaa8c, 0x11d2, 0x92, 0x5e, 0x00, 0xc0, 0x4f, 0x72, 0xd9, 0x0e);
  76. #else
  77. DECLARE_DEBUG_VARIABLE();
  78. #endif
  79. DECLARE_DEBUG_PRINTS_OBJECT();
  80. BOOL g_fGlobalInitDone = FALSE;
  81. CRITICAL_SECTION g_csGlobalLock;
  82. BOOL g_fEnableTryExcept = TRUE;
  83. // WAM needs to ensure that IISRTL is fully initialized. This happens
  84. // automatically in infocomm when running in-process, but the following
  85. // hack is needed for OOP apps. InitializeIISRTL and TerminateIISRTL
  86. // use an internal refcount, so tying the initialization/termination to
  87. // _Module.GetLockCount works.
  88. LONG CWamModule::Lock()
  89. {
  90. IF_DEBUG( WAM_REFCOUNTS)
  91. DBGPRINTF((DBG_CONTEXT, "WamModule::Lock(%d)\n", GetLockCount()));
  92. InitializeIISRTL();
  93. AtqInitialize(0);
  94. return CComModule::Lock();
  95. }
  96. LONG CWamModule::Unlock()
  97. {
  98. IF_DEBUG( WAM_REFCOUNTS)
  99. DBGPRINTF((DBG_CONTEXT, "WamModule::Unlock(%d)\n", GetLockCount()));
  100. AtqTerminate();
  101. TerminateIISRTL();
  102. return CComModule::Unlock();
  103. }
  104. /************************************************************
  105. * Local Functions
  106. ************************************************************/
  107. static void
  108. WAMLoadNTApis(VOID);
  109. static void
  110. WAMUnloadNTApis(VOID);
  111. PFN_INTERLOCKED_COMPARE_EXCHANGE g_pfnInterlockedCompareExchange = NULL;
  112. // END mods
  113. /////////////////////////////////////////////////////////////////////////////
  114. // DLL Entry Point
  115. extern "C"
  116. BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
  117. {
  118. DWORD dwErr = NO_ERROR;
  119. #ifdef _MERGE_PROXYSTUB
  120. if (!PrxDllMain(hInstance, dwReason, lpReserved))
  121. return FALSE;
  122. #endif
  123. if (dwReason == DLL_PROCESS_ATTACH) {
  124. //
  125. // BEGIN mods
  126. //
  127. #ifdef _NO_TRACING_
  128. CREATE_DEBUG_PRINT_OBJECT( g_pszModuleName);
  129. #else
  130. CREATE_DEBUG_PRINT_OBJECT( g_pszModuleName, IisWamObjectGuid);
  131. #endif
  132. if ( !VALID_DEBUG_PRINT_OBJECT()) {
  133. return ( FALSE);
  134. }
  135. (VOID)IISGetPlatformType();
  136. #ifdef _NO_TRACING_
  137. LOAD_DEBUG_FLAGS_FROM_REG_STR( g_pszWamRegLocation,
  138. (DEBUG_ERROR | DEBUG_IID) );
  139. #endif
  140. INITIALIZE_PLATFORM_TYPE();
  141. DBG_ASSERT( IISIsValidPlatform());
  142. INITIALIZE_CRITICAL_SECTION( &g_csGlobalLock);
  143. WAMLoadNTApis();
  144. DBG_REQUIRE( WAM_EXEC_INFO::InitClass());
  145. dwErr = InitializeHseExtensions();
  146. if ( NOERROR == dwErr ) {
  147. IF_DEBUG( INIT_CLEAN) {
  148. DBGPRINTF((DBG_CONTEXT,
  149. " InitializeHseExtensions succeeded.\n" ) );
  150. }
  151. // From ATL generated
  152. _Module.Init(ObjectMap, hInstance);
  153. DisableThreadLibraryCalls(hInstance);
  154. // End of ATL generated
  155. _WAMCCFModule.Init(); // must be after _Module.Init()
  156. }
  157. else {
  158. dwErr = GetLastError();
  159. IF_DEBUG( ERROR ) {
  160. DBGPRINTF((DBG_CONTEXT,
  161. " InitializeHseExtensions failed. Error=%d.\n",
  162. dwErr) );
  163. }
  164. }
  165. // END mods
  166. } else if (dwReason == DLL_PROCESS_DETACH) {
  167. DBGPRINTF( (DBG_CONTEXT,
  168. " Termination of WAM.dll called with lpvReserved=%08x\n",
  169. lpReserved) );
  170. if ( NULL != lpReserved ) {
  171. //
  172. // Only cleanup if there is a FreeLibrary() call
  173. //
  174. return ( TRUE);
  175. }
  176. // BEGIN mods
  177. _WAMCCFModule.Term(); // must be before _Module.Term()
  178. // END mods
  179. _Module.Term();
  180. // BEGIN mods
  181. CleanupHseExtensions();
  182. WAM_EXEC_INFO::CleanupClass();
  183. DoGlobalCleanup();
  184. DeleteCriticalSection( &g_csGlobalLock);
  185. WAMUnloadNTApis();
  186. DELETE_DEBUG_PRINT_OBJECT();
  187. // END mods
  188. }
  189. return (dwErr == NO_ERROR);
  190. } // DllMain()
  191. /////////////////////////////////////////////////////////////////////////////
  192. // Used to determine whether the DLL can be unloaded by OLE
  193. STDAPI DllCanUnloadNow(void)
  194. {
  195. #ifdef _MERGE_PROXYSTUB
  196. if (PrxDllCanUnloadNow() != S_OK)
  197. return S_FALSE;
  198. #endif
  199. return (_Module.GetLockCount()==0) ? S_OK : S_FALSE;
  200. }
  201. /////////////////////////////////////////////////////////////////////////////
  202. // Returns a class factory to create an object of the requested type
  203. STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
  204. {
  205. HRESULT hr;
  206. if (ppv == NULL) {
  207. return ( NULL);
  208. }
  209. *ppv = NULL; // reset the value before getting inside.
  210. IF_DEBUG( IID)
  211. {
  212. DBGPRINTF(( DBG_CONTEXT,
  213. "GetClassObject( " GUID_FORMAT "," GUID_FORMAT ", %08x)\n",
  214. GUID_EXPAND( &rclsid),
  215. GUID_EXPAND( &riid),
  216. ppv));
  217. }
  218. if (ppv == NULL) {
  219. return ( E_POINTER);
  220. }
  221. *ppv = NULL; // set the incoming value to be invalid entry
  222. #ifdef _MERGE_PROXYSTUB
  223. if (PrxDllGetClassObject(rclsid, riid, ppv) == S_OK)
  224. return S_OK;
  225. #endif
  226. hr = _Module.GetClassObject(rclsid, riid, ppv);
  227. // BEGIN mods
  228. if (hr == CLASS_E_CLASSNOTAVAILABLE) {
  229. // If request for standard CF failed -> try custom
  230. IF_DEBUG( IID){
  231. DBGPRINTF(( DBG_CONTEXT, "Trying Custom CF GetClassObject()\n"));
  232. }
  233. #ifdef USE_DEFAULT_CF
  234. hr = _Module.GetClassObject(CLSID_Wam, riid, ppv);
  235. #else
  236. hr = _WAMCCFModule.GetClassObject(rclsid, riid, ppv);
  237. #endif
  238. }
  239. IF_DEBUG( IID)
  240. {
  241. DBGPRINTF(( DBG_CONTEXT,
  242. "GetClassObject() returns %08x. (*ppv=%08x)\n",
  243. hr, *ppv));
  244. }
  245. // END mods
  246. return ( hr);
  247. } // DllGetClassObject()
  248. /////////////////////////////////////////////////////////////////////////////
  249. // DllRegisterServer - Adds entries to the system registry
  250. STDAPI DllRegisterServer(void)
  251. {
  252. #ifdef _MERGE_PROXYSTUB
  253. HRESULT hRes = PrxDllRegisterServer();
  254. if (FAILED(hRes))
  255. return hRes;
  256. #endif
  257. // registers object, typelib and all interfaces in typelib
  258. return _Module.RegisterServer(TRUE);
  259. }
  260. /////////////////////////////////////////////////////////////////////////////
  261. // DllUnregisterServer - Removes entries from the system registry
  262. STDAPI DllUnregisterServer(void)
  263. {
  264. #ifdef _MERGE_PROXYSTUB
  265. PrxDllUnregisterServer();
  266. #endif
  267. _Module.UnregisterServer();
  268. return S_OK;
  269. }
  270. /************************************************************
  271. * Global Init/Cleanup functions
  272. ************************************************************/
  273. HRESULT
  274. DoGlobalInitializations(IN BOOL fInProc, IN BOOL fEnableTryExcept)
  275. /*++
  276. Description:
  277. This function is used to initialize the global state of various
  278. variable in use. RPC runtime runs into deadlocks with respect to the
  279. NT DLL loader lock. Eventlog for one uses RPC to establish the connections.
  280. Hence, we use this separate global initialize function to setup state
  281. outside the NT DLL loader lock boundary (outside the DllMain())
  282. Arguments:
  283. fInProc - Is this WAM instance running InProc?
  284. fEnableTryExcept - Catch exceptions in ISAPIs?
  285. Returns:
  286. HRESULT - NOERROR means success; otherwise returns custom error.
  287. --*/
  288. {
  289. HRESULT hr = NOERROR;
  290. //
  291. // Use Locks to ensure that only one guy is initializing the data
  292. //
  293. EnterCriticalSection( &g_csGlobalLock);
  294. if ( !g_fGlobalInitDone) {
  295. // remember fEnableTryExcept flag
  296. g_fEnableTryExcept = fEnableTryExcept;
  297. if( !fInProc )
  298. {
  299. hr = CWamOopTokenInfo::Create();
  300. DBG_ASSERT( SUCCEEDED(hr) );
  301. if( WAM_EXEC_INFO::sm_pSVCacheMap == NULL )
  302. {
  303. WAM_EXEC_INFO::sm_pSVCacheMap = new SV_CACHE_MAP();
  304. DBG_ASSERT( WAM_EXEC_INFO::sm_pSVCacheMap != NULL );
  305. if( WAM_EXEC_INFO::sm_pSVCacheMap != NULL )
  306. {
  307. DBG_REQUIRE( WAM_EXEC_INFO::sm_pSVCacheMap->Initialize() );
  308. }
  309. }
  310. }
  311. #ifndef _NO_TRACING_
  312. CREATE_INITIALIZE_DEBUG();
  313. #endif
  314. g_fGlobalInitDone = TRUE;
  315. }
  316. LeaveCriticalSection( &g_csGlobalLock);
  317. IF_DEBUG( INIT_CLEAN) {
  318. DBGPRINTF(( DBG_CONTEXT,
  319. " DoGlobalInitializations() returns hr = %08x\n",
  320. hr));
  321. }
  322. return ( hr);
  323. } // DoGlobalInitializations()
  324. HRESULT DoGlobalCleanup(VOID)
  325. {
  326. HRESULT hr = NOERROR;
  327. if ( !g_fGlobalInitDone) {
  328. return ( hr);
  329. }
  330. EnterCriticalSection( &g_csGlobalLock);
  331. if( CWamOopTokenInfo::HasInstance() )
  332. {
  333. CWamOopTokenInfo::Destroy();
  334. }
  335. delete WAM_EXEC_INFO::sm_pSVCacheMap;
  336. WAM_EXEC_INFO::sm_pSVCacheMap = NULL;
  337. g_fGlobalInitDone = FALSE;
  338. LeaveCriticalSection( &g_csGlobalLock);
  339. return ( hr);
  340. } // DoGlobalCleanup()
  341. /************************************************************
  342. * Thunks for Fake NT APIs
  343. ************************************************************/
  344. CRITICAL_SECTION g_csNonNTAPIs;
  345. LONG
  346. FakeInterlockedCompareExchange(
  347. LONG *Destination,
  348. LONG Exchange,
  349. LONG Comperand
  350. )
  351. /*++
  352. Description:
  353. This function fakes the interlocked compare exchange operation for non NT platforms
  354. See WAMLoadNTApis() for details
  355. Returns:
  356. returns the old value at Destination
  357. --*/
  358. {
  359. LONG oldValue;
  360. EnterCriticalSection( &g_csNonNTAPIs);
  361. oldValue = *Destination;
  362. if ( oldValue == Comperand ) {
  363. *Destination = Exchange;
  364. }
  365. LeaveCriticalSection( &g_csNonNTAPIs);
  366. return( oldValue);
  367. } // FakeInterlockedCompareExchange()
  368. static VOID
  369. WAMLoadNTApis(VOID)
  370. /*++
  371. Description:
  372. This function loads the entry point for functions from
  373. Kernel32.dll. If the entry point is missing, the function
  374. pointer will point to a fake routine which does nothing. Otherwise,
  375. it will point to the real function.
  376. It dynamically loads the kernel32.dll to find the entry ponit and then
  377. unloads it after getting the address. For the resulting function
  378. pointer to work correctly one has to ensure that the kernel32.dll is
  379. linked with the dll/exe which links to this file.
  380. --*/
  381. {
  382. // Initialize the critical section for non NT API support, in case if we need this
  383. INITIALIZE_CRITICAL_SECTION( &g_csNonNTAPIs);
  384. if ( g_pfnInterlockedCompareExchange == NULL ) {
  385. HINSTANCE tmpInstance;
  386. //
  387. // load kernel32 and get NT specific entry points
  388. //
  389. tmpInstance = LoadLibrary("kernel32.dll");
  390. if ( tmpInstance != NULL ) {
  391. // For some reason the original function is _InterlockedCompareExchange!
  392. g_pfnInterlockedCompareExchange = (PFN_INTERLOCKED_COMPARE_EXCHANGE )
  393. GetProcAddress( tmpInstance, "InterlockedCompareExchange");
  394. if ( g_pfnInterlockedCompareExchange == NULL ) {
  395. // the function is not available
  396. // Just thunk it.
  397. g_pfnInterlockedCompareExchange = FakeInterlockedCompareExchange;
  398. }
  399. //
  400. // We can free this because we are statically linked to it
  401. //
  402. FreeLibrary(tmpInstance);
  403. }
  404. }
  405. return;
  406. } // WAMLoadNTApis()
  407. static void
  408. WAMUnloadNTApis(VOID)
  409. {
  410. DeleteCriticalSection( &g_csNonNTAPIs);
  411. return;
  412. } // WAMUnloadNTApis()