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.

1599 lines
46 KiB

  1. /*===================================================================
  2. Microsoft Denali
  3. Microsoft Confidential.
  4. Copyright 1996-1999 Microsoft Corporation. All Rights Reserved.
  5. Component: Main
  6. File: denali.cpp
  7. Owner: AndyMorr
  8. This file contains the I S A P I C A L L B A C K A P I S
  9. ===================================================================*/
  10. #include "denpre.h"
  11. #pragma hdrstop
  12. #undef DEFAULT_TRACE_FLAGS
  13. #define DEFAULT_TRACE_FLAGS (DEBUG_ERROR)
  14. #include "gip.h"
  15. #include "mtacb.h"
  16. #include "perfdata.h"
  17. #include "activdbg.h"
  18. #include "debugger.h"
  19. #include "dbgutil.h"
  20. #include "randgen.h"
  21. #include "aspdmon.h"
  22. #include "tlbcache.h"
  23. #include "thrdgate.h"
  24. #include "ie449.h"
  25. #include "memcls.h"
  26. #include "memchk.h"
  27. // Globals
  28. BOOL g_fShutDownInProgress = FALSE;
  29. BOOL g_fInitStarted = FALSE;
  30. char g_szExtensionDesc[] = "Microsoft Active Server Pages 2.0";
  31. GLOB gGlob;
  32. BOOL g_fFirstHit = TRUE;
  33. char g_pszASPModuleName[] = "ASP";
  34. DECLARE_DEBUG_PRINTS_OBJECT();
  35. #ifdef _NO_TRACING_
  36. DECLARE_DEBUG_VARIABLE();
  37. #else
  38. #include <initguid.h>
  39. DEFINE_GUID(IisAspGuid,
  40. 0x784d8902, 0xaa8c, 0x11d2, 0x92, 0x5e, 0x00, 0xc0, 0x4f, 0x72, 0xd9, 0x0e);
  41. #endif
  42. DECLARE_PLATFORM_TYPE();
  43. // Out of process flag
  44. BOOL g_fOOP = FALSE;
  45. // session id cookie
  46. char g_szSessionIDCookieName[CCH_SESSION_ID_COOKIE+1];
  47. CRITICAL_SECTION g_csEventlogLock;
  48. CRITICAL_SECTION g_csFirstHitLock;
  49. HINSTANCE g_hODBC32Lib;
  50. // Added to support CacheExtensions
  51. HINSTANCE g_hDenali = (HINSTANCE)0;
  52. HINSTANCE g_hinstDLL = (HINSTANCE)0;
  53. extern LONG g_nSessionObjectsActive;
  54. // Cached BSTRs
  55. BSTR g_bstrApplication = NULL;
  56. BSTR g_bstrRequest = NULL;
  57. BSTR g_bstrResponse = NULL;
  58. BSTR g_bstrServer = NULL;
  59. BSTR g_bstrCertificate = NULL;
  60. BSTR g_bstrSession = NULL;
  61. BSTR g_bstrScriptingNamespace = NULL;
  62. BSTR g_bstrObjectContext = NULL;
  63. extern IASPObjectContext *g_pIASPDummyObjectContext;
  64. // Forward references
  65. HRESULT GlobInit();
  66. HRESULT GlobUnInit();
  67. HRESULT CacheStdTypeInfos();
  68. HRESULT UnCacheStdTypeInfos();
  69. HRESULT InitCachedBSTRs();
  70. HRESULT UnInitCachedBSTRs();
  71. HRESULT ShutDown();
  72. HRESULT SendHtmlSubstitute(CIsapiReqInfo *pIReq);
  73. void MakeAspCookieName(char *);
  74. BOOL FirstHitInit(CIsapiReqInfo *pIReq);
  75. // ATL support
  76. #if _IIS_5_1
  77. CWamModule _Module;
  78. #elif _IIS_6_0
  79. CComModule _Module;
  80. #else
  81. #error "Neither _IIS_6_0 nor _IIS_5_1 is defined"
  82. #endif
  83. BEGIN_OBJECT_MAP(ObjectMap)
  84. END_OBJECT_MAP()
  85. /*===================================================================
  86. DllMain - Moved from clsfctry.cpp
  87. Main entry point into the DLL. Called by system on DLL load
  88. and unload.
  89. Returns:
  90. TRUE on success
  91. Side effects:
  92. None.
  93. ===================================================================*/
  94. BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpvReserved)
  95. {
  96. /* Obsolete
  97. // Let the Proxy code get a crack at it
  98. if (!PrxDllMain(hinstDLL, dwReason, lpvReserved))
  99. return FALSE;
  100. */
  101. switch(dwReason)
  102. {
  103. case DLL_PROCESS_ATTACH:
  104. // hang onto the hinstance so we can use it to get to our string resources
  105. //
  106. g_hinstDLL = hinstDLL;
  107. // Here's an interesting optimization:
  108. // The following tells the system NOT to call us for Thread attach/detach
  109. // since we dont handle those calls anyway, this will speed things up a bit.
  110. // If this turns out to be a problem for some reason (cant imagine why),
  111. // just remove this again.
  112. DisableThreadLibraryCalls(hinstDLL);
  113. break;
  114. case DLL_PROCESS_DETACH:
  115. break;
  116. case DLL_THREAD_ATTACH:
  117. break;
  118. case DLL_THREAD_DETACH:
  119. break;
  120. }
  121. return TRUE;
  122. }
  123. /*===================================================================
  124. DWORD HandleHit
  125. Given the CIsapiReqInfo construct a hit object to be queued
  126. for execution
  127. Parameters:
  128. pIReq - CIsapiReqInfo
  129. Returns:
  130. HSE_STATUS_PENDING if function is successful in queuing request
  131. HSE_STATUS_ERROR if not successful
  132. ===================================================================*/
  133. DWORD HandleHit(CIsapiReqInfo *pIReq)
  134. {
  135. int errorId = 0;
  136. BOOL fRejected = FALSE;
  137. BOOL fCompleted = FALSE;
  138. HRESULT hr = S_OK;
  139. /*
  140. * We cant read the metabase until we have the WAM_EXEC_INFO, which
  141. * we dont have at DllInit time. Therefore, we postpone reading the
  142. * metabase until now, but we do it only on the first hit.
  143. */
  144. if (g_fFirstHit)
  145. {
  146. EnterCriticalSection(&g_csFirstHitLock);
  147. // If someone initied while we were waiting for the CS,
  148. // then noop
  149. if (g_fFirstHit)
  150. {
  151. BOOL fT;
  152. fT = FirstHitInit(pIReq);
  153. Assert(fT);
  154. g_fFirstHit = FALSE;
  155. }
  156. LeaveCriticalSection(&g_csFirstHitLock);
  157. }
  158. #ifndef PERF_DISABLE
  159. if (!g_fPerfInited) // Init PERFMON data on first request
  160. {
  161. // FYI: leverage same CS as first hit lock
  162. EnterCriticalSection(&g_csFirstHitLock);
  163. // If someone initied while we were waiting for the CS,
  164. // then noop
  165. if (!g_fPerfInited)
  166. {
  167. if (SUCCEEDED(InitPerfDataOnFirstRequest(pIReq)))
  168. {
  169. g_fPerfInited = TRUE;
  170. }
  171. else
  172. {
  173. g_fPerfInited = FALSE;
  174. // call this again since InitPerfDataOnFirstRequest will uninit
  175. // and erase the criticalsection which will then AV when we try to increment counters
  176. PreInitPerfData();
  177. }
  178. }
  179. LeaveCriticalSection(&g_csFirstHitLock);
  180. }
  181. g_PerfData.Incr_REQTOTAL();
  182. #endif
  183. if (Glob(fNeedUpdate))
  184. {
  185. if (SUCCEEDED(StartISAThreadBracket(pIReq)))
  186. {
  187. // Update uses pIReq - need to bracket
  188. gGlob.Update(pIReq);
  189. EndISAThreadBracket(pIReq);
  190. }
  191. }
  192. if (IsShutDownInProgress())
  193. hr = E_FAIL;
  194. // Enforce the limit of concurrent browser requests
  195. if (SUCCEEDED(hr) && Glob(dwRequestQueueMax) &&
  196. (*g_PerfData.PDWCounter(ID_REQCURRENT) >= Glob(dwRequestQueueMax)))
  197. {
  198. hr = E_FAIL;
  199. fRejected = TRUE;
  200. }
  201. if (SUCCEEDED(hr))
  202. hr = CHitObj::NewBrowserRequest(pIReq, &fRejected, &fCompleted, &errorId);
  203. if (SUCCEEDED(hr))
  204. return fCompleted ? HSE_STATUS_SUCCESS_AND_KEEP_CONN : HSE_STATUS_PENDING;
  205. if (fRejected)
  206. {
  207. if (Glob(fEnableAspHtmlFallBack))
  208. {
  209. // Instead of rejecting the request try to find
  210. // XXX_ASP.HTM file in the same directory and dump its contents
  211. hr = SendHtmlSubstitute(pIReq);
  212. if (hr == S_OK)
  213. return HSE_STATUS_SUCCESS_AND_KEEP_CONN; // HTML substitute sent
  214. else if (FAILED(hr))
  215. return HSE_STATUS_ERROR; // error sending
  216. // HTML substitute not found
  217. }
  218. errorId = IDE_SERVER_TOO_BUSY;
  219. #ifndef PERF_DISABLE
  220. g_PerfData.Incr_REQREJECTED();
  221. #endif
  222. }
  223. if (SUCCEEDED(StartISAThreadBracket(pIReq)))
  224. {
  225. // Uses pIReq -- need to bracket
  226. Handle500Error(errorId, pIReq);
  227. EndISAThreadBracket(pIReq);
  228. }
  229. return HSE_STATUS_ERROR;
  230. }
  231. /*===================================================================
  232. BOOL DllInit
  233. Initialize Denali if not invoked by RegSvr32. Only do inits here
  234. that dont require Glob values loaded from the metabase. For any
  235. inits that require values loaded into Glob from the metabase, use
  236. FirstHitInit.
  237. Returns:
  238. TRUE on successful initialization
  239. ===================================================================*/
  240. BOOL DllInit()
  241. {
  242. HRESULT hr;
  243. const CHAR szASPDebugRegLocation[] =
  244. "System\\CurrentControlSet\\Services\\W3Svc\\ASP";
  245. #if _IIS_5_1
  246. InitializeIISRTL();
  247. DBGPRINTF((DBG_CONTEXT, "ASP Init -- IISRTL\n"));
  248. #endif
  249. #ifndef _NO_TRACING_
  250. CREATE_DEBUG_PRINT_OBJECT( g_pszASPModuleName, IisAspGuid);
  251. #else
  252. CREATE_DEBUG_PRINT_OBJECT( g_pszASPModuleName);
  253. #endif
  254. if ( !VALID_DEBUG_PRINT_OBJECT())
  255. {
  256. return ( FALSE);
  257. }
  258. #ifdef _NO_TRACING_
  259. LOAD_DEBUG_FLAGS_FROM_REG_STR(szASPDebugRegLocation, (DEBUG_ERROR));
  260. #endif
  261. #ifdef SCRIPT_STATS
  262. ReadRegistrySettings();
  263. #endif // SCRIPT_STATS
  264. // Create ASP RefTrace Logs
  265. IF_DEBUG(TEMPLATE) CTemplate::gm_pTraceLog = CreateRefTraceLog(5000, 0);
  266. IF_DEBUG(SESSION) CSession::gm_pTraceLog = CreateRefTraceLog(5000, 0);
  267. IF_DEBUG(APPLICATION) CAppln::gm_pTraceLog = CreateRefTraceLog(5000, 0);
  268. IF_DEBUG(FCN) CASPDirMonitorEntry::gm_pTraceLog = CreateRefTraceLog(500, 0);
  269. CAppln::gm_pTraceLog = CreateRefTraceLog(5000, 0);
  270. if (FAILED(PreInitPerfData()))
  271. return FALSE;
  272. DBGPRINTF((DBG_CONTEXT, "ASP Init -- PerfMon Data PreInit\n"));
  273. ErrInitCriticalSection( &g_csEventlogLock, hr );
  274. if (FAILED(hr))
  275. return FALSE;
  276. ErrInitCriticalSection( &g_csFirstHitLock, hr );
  277. if (FAILED(hr))
  278. return FALSE;
  279. #ifdef DENALI_MEMCHK
  280. if (FAILED(DenaliMemoryInit()))
  281. return FALSE;
  282. #else
  283. if (FAILED(AspMemInit()))
  284. return FALSE;
  285. #endif
  286. DBGPRINTF((DBG_CONTEXT, "ASP Init -- Denali Memory Init\n"));
  287. g_pDirMonitor = new CDirMonitor;
  288. if (g_pDirMonitor == NULL) {
  289. return FALSE;
  290. }
  291. _Module.Init(ObjectMap, g_hinstDLL, &LIBID_ASPTypeLibrary);
  292. #if _IIS_5_1
  293. if (AtqInitialize(0) == FALSE)
  294. return FALSE;
  295. DBGPRINTF((DBG_CONTEXT, "ASP Init -- ATQ Initialized\n"));
  296. #endif
  297. if (FAILED(GlobInit()))
  298. return FALSE;
  299. DBGPRINTF((DBG_CONTEXT, "ASP Init -- Glob Init\n"));
  300. if (FAILED(InitMemCls()))
  301. return FALSE;
  302. DBGPRINTF((DBG_CONTEXT, "ASP Init -- Per-Class Cache Init\n"));
  303. if (FAILED(InitCachedBSTRs()))
  304. return FALSE;
  305. DBGPRINTF((DBG_CONTEXT, "ASP Init -- Cached BSTRs Init\n"));
  306. if (FAILED(CacheStdTypeInfos()))
  307. return FALSE;
  308. DBGPRINTF((DBG_CONTEXT, "ASP Init -- Cache Std TypeInfos\n"));
  309. if (FAILED(g_TypelibCache.Init()))
  310. return FALSE;
  311. DBGPRINTF((DBG_CONTEXT, "ASP Init -- Typelib Cache Init\n"));
  312. if (FAILED(ErrHandleInit()))
  313. return FALSE;
  314. DBGPRINTF((DBG_CONTEXT, "ASP Init -- Err Handler Init\n"));
  315. srand( (unsigned int) time(NULL) );
  316. if (FAILED(g_SessionIdGenerator.Init())) // seed session id
  317. return FALSE;
  318. // Init new Exposed Session Id variable
  319. if (FAILED(g_ExposedSessionIdGenerator.Init(g_SessionIdGenerator))) // seed exposed session id
  320. return FALSE;
  321. DBGPRINTF((DBG_CONTEXT, "ASP Init -- SessionID Generator Init\n"));
  322. MakeAspCookieName(g_szSessionIDCookieName);
  323. if (FAILED(InitRandGenerator()))
  324. return FALSE;
  325. DBGPRINTF((DBG_CONTEXT, "ASP Init -- RandGen Init\n"));
  326. if (FAILED(g_ApplnMgr.Init()))
  327. return FALSE;
  328. DBGPRINTF((DBG_CONTEXT, "ASP Init -- Appln Mgr Init\n"));
  329. if (FAILED(Init449()))
  330. return FALSE;
  331. DBGPRINTF((DBG_CONTEXT, "ASP Init -- 449 Mgr Init\n"));
  332. // Note: Template cache manager is inited in two phases. Do first here.
  333. if (FAILED(g_TemplateCache.Init()))
  334. return FALSE;
  335. DBGPRINTF((DBG_CONTEXT, "ASP Init -- Template Cache Init\n"));
  336. if (FAILED(g_IncFileMap.Init()))
  337. return FALSE;
  338. DBGPRINTF((DBG_CONTEXT, "ASP Init -- Inc File Users Init\n"));
  339. if (FIsWinNT()) // No Change notification on Windows 95
  340. {
  341. if (FAILED(g_FileAppMap.Init()))
  342. return FALSE;
  343. DBGPRINTF((DBG_CONTEXT, "ASP Init -- File-Application Map Init\n"));
  344. }
  345. if (FAILED(g_ScriptManager.Init()))
  346. return FALSE;
  347. DBGPRINTF((DBG_CONTEXT, "ASP Init -- Script Manager Init\n"));
  348. if (FAILED(CTemplate::InitClass()))
  349. return FALSE;
  350. DBGPRINTF((DBG_CONTEXT, "ASP Init -- CTemplate Init Class\n"));
  351. if (FIsWinNT()) // No GIPs on Win95
  352. {
  353. if (FAILED(g_GIPAPI.Init()))
  354. return FALSE;
  355. DBGPRINTF((DBG_CONTEXT, "ASP Init -- Global Interface API Init\n"));
  356. }
  357. if (FAILED(InitMTACallbacks()))
  358. return FALSE;
  359. DBGPRINTF((DBG_CONTEXT, "ASP Init -- MTA Callbacks Init\n"));
  360. if (!RequestSupportInit())
  361. return FALSE;
  362. DBGPRINTF((DBG_CONTEXT, "ASP Init -- Request Support Init\n"));
  363. DBGPRINTF((DBG_CONTEXT, "ASP Init -- Denali DLL Initialized\n"));
  364. #ifdef LOG_FCNOTIFICATIONS
  365. LfcnCreateLogFile();
  366. #endif //LOG_FCNOTIFICATIONS
  367. return TRUE;
  368. }
  369. /*===================================================================
  370. BOOL FirstHitInit
  371. Initialize any ASP values that can not be inited at DllInit time.
  372. Returns:
  373. TRUE on successful initialization
  374. ===================================================================*/
  375. BOOL FirstHitInit
  376. (
  377. CIsapiReqInfo *pIReq
  378. )
  379. {
  380. HRESULT hr;
  381. /*
  382. * In the out of proc case, being able to call the metabase relies on having
  383. * told WAM that we are a "smart" client
  384. */
  385. if (SUCCEEDED(StartISAThreadBracket(pIReq)))
  386. {
  387. // ReadConfigFromMD uses pIReq - need to bracket
  388. hr = ReadConfigFromMD(pIReq, NULL, TRUE);
  389. // Initialize Debugging
  390. if (FIsWinNT() && RevertToSelf()) // No Debugging on Win95
  391. {
  392. // Don't care whether debugging initializaiton succeeds or not. The most likely
  393. // falure is debugger not installed on the machine.
  394. //
  395. if (SUCCEEDED(InitDebugging(pIReq)))
  396. {
  397. DBGPRINTF((DBG_CONTEXT, "FirstHitInit: Debugging Initialized\n"));
  398. }
  399. else
  400. {
  401. DBGPRINTF((DBG_CONTEXT, "FirstHitInit: Debugger Initialization Failed\n"));
  402. }
  403. DBG_REQUIRE( SetThreadToken(NULL, pIReq->QueryImpersonationToken()) );
  404. }
  405. EndISAThreadBracket(pIReq);
  406. }
  407. else
  408. {
  409. hr = E_FAIL;
  410. }
  411. if (FAILED(hr))
  412. goto LExit;
  413. DBGPRINTF((DBG_CONTEXT, "FirstHitInit: Metadata loaded successfully\n"));
  414. // Do FirstHitInit for the Template Cache Manager. Primarily initializes
  415. // the Persisted Template Cache
  416. if (FAILED(hr = g_TemplateCache.FirstHitInit()))
  417. goto LExit;
  418. DBGPRINTF((DBG_CONTEXT, "FirstHitInit: Template Cache Initialized\n"));
  419. // Configure MTS
  420. if (FAILED(hr = ViperConfigure(Glob(dwProcessorThreadMax), Glob(fAllowOutOfProcCmpnts))))
  421. goto LExit;
  422. DBGPRINTF((DBG_CONTEXT, "FirstHitInit: MTS configured\n"));
  423. // Configure Thread Gate
  424. THREADGATE_CONFIG tgc;
  425. tgc.fEnabled = Glob(fThreadGateEnabled);
  426. tgc.msTimeSlice = Glob(dwThreadGateTimeSlice);
  427. tgc.msSleepDelay = Glob(dwThreadGateSleepDelay);
  428. tgc.nSleepMax = Glob(dwThreadGateSleepMax);
  429. tgc.nLoadLow = Glob(dwThreadGateLoadLow);
  430. tgc.nLoadHigh = Glob(dwThreadGateLoadHigh);
  431. tgc.nMinProcessorThreads = 1;
  432. tgc.nMaxProcessorThreads = Glob(dwProcessorThreadMax);
  433. if (FAILED(hr = InitThreadGate(&tgc)))
  434. goto LExit;
  435. DBGPRINTF((DBG_CONTEXT, "Thread Gate Init\n"));
  436. DBGPRINTF((DBG_CONTEXT, "ASP First Hit Initialization complete\n"));
  437. LExit:
  438. Assert(SUCCEEDED(hr));
  439. return SUCCEEDED(hr);
  440. }
  441. /*===================================================================
  442. void DllUnInit
  443. UnInitialize Denali DLL if not invoked by RegSvr32
  444. Returns:
  445. NONE
  446. Side effects:
  447. NONE
  448. ===================================================================*/
  449. void DllUnInit( void )
  450. {
  451. DBGPRINTF((DBG_CONTEXT, "ASP UnInit -- %d Apps %d Sessions %d Requests\n",
  452. g_nApplications, g_nSessions, g_nBrowserRequests));
  453. g_fShutDownInProgress = TRUE;
  454. ShutDown();
  455. DBGPRINTF((DBG_CONTEXT, "ASP UnInit -- ShutDown Processing\n" ));
  456. UnInitMTACallbacks();
  457. DBGPRINTF((DBG_CONTEXT, "ASP UnInit -- MTA Callbacks\n" ));
  458. UnInitRandGenerator();
  459. DBGPRINTF((DBG_CONTEXT, "ASP UnInit -- RandGen\n"));
  460. UnInitThreadGate();
  461. DBGPRINTF((DBG_CONTEXT, "ASP UnInit -- Thread Gate\n"));
  462. UnInit449();
  463. DBGPRINTF((DBG_CONTEXT, "ASP UnInit -- 449 Mgr\n"));
  464. g_ApplnMgr.UnInit();
  465. DBGPRINTF((DBG_CONTEXT, "ASP UnInit -- Application Manager\n" ));
  466. g_ScriptManager.UnInit();
  467. DBGPRINTF((DBG_CONTEXT, "ASP UnInit -- Script Manager\n" ));
  468. g_TemplateCache.UnInit();
  469. DBGPRINTF((DBG_CONTEXT, "ASP UnInit -- Template Cache\n" ));
  470. g_IncFileMap.UnInit();
  471. DBGPRINTF((DBG_CONTEXT, "ASP UnInit -- IncFileMap\n" ));
  472. if (FIsWinNT()) {
  473. // No change notification on windows 95
  474. g_FileAppMap.UnInit();
  475. DBGPRINTF((DBG_CONTEXT, "ASP UnInit -- File-Application Map\n" ));
  476. if (g_pDirMonitor) {
  477. g_pDirMonitor->Cleanup();
  478. DBGPRINTF((DBG_CONTEXT, "ASP UNInit -- Directory Monitor\n" ));
  479. }
  480. }
  481. CTemplate::UnInitClass();
  482. DBGPRINTF((DBG_CONTEXT, "ASP UnInit -- CTemplate\n" ));
  483. g_TypelibCache.UnInit();
  484. DBGPRINTF((DBG_CONTEXT, "ASP UnInit -- Typelib Cache\n"));
  485. UnCacheStdTypeInfos();
  486. DBGPRINTF((DBG_CONTEXT, "ASP UnInit -- TypeInfos\n" ));
  487. if (FIsWinNT())
  488. {
  489. // No GIPs on Win95
  490. g_GIPAPI.UnInit();
  491. DBGPRINTF((DBG_CONTEXT, "ASP UnInit -- GIP\n" ));
  492. }
  493. ErrHandleUnInit();
  494. DBGPRINTF((DBG_CONTEXT, "ASP UnInit -- ErrHandler\n" ));
  495. GlobUnInit();
  496. DBGPRINTF((DBG_CONTEXT, "ASP UnInit -- Glob\n" ));
  497. UnInitCachedBSTRs();
  498. DBGPRINTF((DBG_CONTEXT, "ASP UnInit -- Cached BSTRs\n" ));
  499. //////////////////////////////////////////////////////////
  500. // Wait for the actual session objects to be destroyed.
  501. // The g_nSessions global tracks the init/uninit of session
  502. // objects but not the memory itself. This presents a
  503. // problem when something outside of ASP holds a reference
  504. // to a session object or one of the contained intrinsics.
  505. // One case of this is the revoking of a git'd transaction
  506. // object. Turns out the revoke can happen asynchronously.
  507. //
  508. // NOTE!!! - This needs to be done BEFORE uniniting the
  509. // mem classes since these objects are in the acache.
  510. LONG lastCount = g_nSessionObjectsActive;
  511. DWORD loopCount = 50;
  512. while( (g_nSessionObjectsActive > 0) && (loopCount--) )
  513. {
  514. if (lastCount != g_nSessionObjectsActive) {
  515. lastCount = g_nSessionObjectsActive;
  516. loopCount = 50;
  517. }
  518. Sleep( 100 );
  519. }
  520. UnInitMemCls();
  521. DBGPRINTF((DBG_CONTEXT, "ASP UnInit -- Per-Class Cache\n" ));
  522. #if _IIS_5_1
  523. AtqTerminate();
  524. DBGPRINTF((DBG_CONTEXT, "ASP UnInit -- ATQ\n" ));
  525. #endif
  526. // Destroy ASP RefTrace Logs
  527. IF_DEBUG(TEMPLATE) DestroyRefTraceLog(CTemplate::gm_pTraceLog);
  528. IF_DEBUG(SESSION) DestroyRefTraceLog(CSession::gm_pTraceLog);
  529. IF_DEBUG(APPLICATION) DestroyRefTraceLog(CAppln::gm_pTraceLog);
  530. IF_DEBUG(FCN) DestroyRefTraceLog(CASPDirMonitorEntry::gm_pTraceLog);
  531. if (g_pIASPDummyObjectContext)
  532. g_pIASPDummyObjectContext->Release();
  533. _Module.Term();
  534. delete g_pDirMonitor;
  535. g_pDirMonitor = NULL;
  536. // UnInitODBC();
  537. // Note: the memmgr uses perf counters, so must be uninited before the perf counters are uninited
  538. #ifdef DENALI_MEMCHK
  539. DenaliMemoryUnInit();
  540. #else
  541. AspMemUnInit();
  542. #endif
  543. DBGPRINTF((DBG_CONTEXT, "ASP UnInit -- Memory Manager\n" ));
  544. UnInitPerfData();
  545. DBGPRINTF((DBG_CONTEXT, "ASP UnInit -- Perf Counters\n" ));
  546. #if _IIS_5_1
  547. TerminateIISRTL();
  548. DBGPRINTF((DBG_CONTEXT, "ASP UnInit -- IISRTL\n" ));
  549. #endif
  550. DBGPRINTF((DBG_CONTEXT, "ASP Uninitialized\n" ));
  551. #ifdef LOG_FCNOTIFICATIONS
  552. LfcnUnmapLogFile();
  553. #endif //LOG_FCNOTIFICATIONS
  554. // Deleting the following CS's must be last. Dont put anything after this
  555. DeleteCriticalSection( &g_csFirstHitLock );
  556. DeleteCriticalSection( &g_csEventlogLock );
  557. DELETE_DEBUG_PRINT_OBJECT();
  558. }
  559. /*===================================================================
  560. GetExtensionVersion
  561. Mandatory server extension call which returns the version number of
  562. the ISAPI spec that we were built with.
  563. Returns:
  564. TRUE on success
  565. Side effects:
  566. None.
  567. ===================================================================*/
  568. BOOL WINAPI GetExtensionVersion(HSE_VERSION_INFO *pextver)
  569. {
  570. // This DLL can be inited only once
  571. if (g_fShutDownInProgress ||
  572. InterlockedExchange((LPLONG)&g_fInitStarted, TRUE))
  573. {
  574. SetLastError(ERROR_BUSY);
  575. return FALSE;
  576. }
  577. if (!DllInit())
  578. {
  579. SetLastError(ERROR_BUSY);
  580. return FALSE;
  581. }
  582. pextver->dwExtensionVersion =
  583. MAKELONG(HSE_VERSION_MAJOR, HSE_VERSION_MINOR);
  584. strcpy(pextver->lpszExtensionDesc, g_szExtensionDesc);
  585. return TRUE;
  586. }
  587. /*===================================================================
  588. HttpExtensionProc
  589. Main entry point into the DLL for the (ActiveX) Internet Information Server.
  590. Returns:
  591. DWord indicating status of request.
  592. HSE_STATUS_PENDING for normal return
  593. (This indicates that we will process the request, but havent yet.)
  594. Side effects:
  595. None.
  596. ===================================================================*/
  597. DWORD WINAPI HttpExtensionProc(EXTENSION_CONTROL_BLOCK *pECB)
  598. {
  599. #ifdef SCRIPT_STATS
  600. InterlockedIncrement(&g_cHttpExtensionsExecuting);
  601. #endif // SCRIPT_STATS
  602. CIsapiReqInfo *pIReq = new CIsapiReqInfo(pECB);
  603. if (pIReq == NULL) {
  604. SetLastError(ERROR_OUTOFMEMORY);
  605. return HSE_STATUS_ERROR;
  606. }
  607. #ifndef PERF_DISABLE
  608. g_PerfData.Add_REQTOTALBYTEIN
  609. (
  610. pIReq->QueryCchQueryString()
  611. #if _IIS_5_1
  612. + pIReq->QueryCchPathTranslated()
  613. #elif _IIS_6_0
  614. + strlen( pIReq->ECB()->lpszPathTranslated )
  615. #endif
  616. + pIReq->QueryCbTotalBytes()
  617. );
  618. #endif
  619. DWORD dw = HandleHit(pIReq);
  620. #ifdef SCRIPT_STATS
  621. InterlockedDecrement(&g_cHttpExtensionsExecuting);
  622. #endif // SCRIPT_STATS
  623. pIReq->Release();
  624. return dw;
  625. }
  626. /*===================================================================
  627. TerminateExtension
  628. IIS is supposed to call this entry point to unload ISAPI DLLs.
  629. Returns:
  630. NONE
  631. Side effects:
  632. Uninitializes the Denali ISAPI DLL if asked to.
  633. ===================================================================*/
  634. BOOL WINAPI TerminateExtension( DWORD dwFlag )
  635. {
  636. if ( dwFlag == HSE_TERM_ADVISORY_UNLOAD )
  637. return TRUE;
  638. if ( dwFlag == HSE_TERM_MUST_UNLOAD )
  639. {
  640. // If already shutdown don't uninit twice.
  641. if (g_fShutDownInProgress)
  642. return TRUE;
  643. // make sure this is a CoInitialize()'d thread
  644. HRESULT hr = CoInitialize(NULL);
  645. if (hr == RPC_E_CHANGED_MODE)
  646. {
  647. // already coinitialized MUTLITREADED - OK
  648. DllUnInit();
  649. }
  650. else if (SUCCEEDED(hr))
  651. {
  652. DllUnInit();
  653. // need to CoUninit() because CoInit() Succeeded
  654. CoUninitialize();
  655. }
  656. return TRUE;
  657. }
  658. return FALSE;
  659. }
  660. /*===================================================================
  661. HRESULT ShutDown
  662. ASP Processing ShutDown logic. (Moved from ThreadManager::UnInit())
  663. Returns:
  664. HRESULT - S_OK on success
  665. Side effects:
  666. May be slow. Kills all requests/sessions/applications
  667. ===================================================================*/
  668. HRESULT ShutDown()
  669. {
  670. long iT;
  671. const DWORD dwtLongWait = 1000; // 1 sec
  672. const DWORD dwtShortWait = 100; // 1/10 sec
  673. DBGPRINTF((DBG_CONTEXT, "ASP Shutdown: %d apps (%d restarting), %d sessions\n",
  674. g_nApplications, g_nApplicationsRestarting, g_nSessions ));
  675. //////////////////////////////////////////////////////////
  676. // Stop change notification on files in template cache
  677. if (FIsWinNT())
  678. {
  679. g_TemplateCache.ShutdownCacheChangeNotification();
  680. }
  681. //////////////////////////////////////////////////////////
  682. // Shut down debugging, which will have the effect of
  683. // resuming scripts stopped at a breakpoint.
  684. //
  685. // (otherwise stopping running scripts will hang later)
  686. if (g_pPDM)
  687. {
  688. g_TemplateCache.RemoveApplicationFromDebuggerUI(NULL); // remove all document nodes
  689. UnInitDebugging(); // kill PDM
  690. DBGPRINTF((DBG_CONTEXT, "ASP Shutdown: PDM Closed\n" ));
  691. }
  692. //////////////////////////////////////////////////////////
  693. // Drain down all pending browser requests
  694. if (g_nBrowserRequests > 0)
  695. {
  696. // Give them a little time each
  697. for (iT = 2*g_nBrowserRequests; g_nBrowserRequests > 0 && iT > 0; iT--)
  698. Sleep(dwtShortWait);
  699. if (g_nBrowserRequests > 0)
  700. {
  701. // Still there - kill scripts and wait again
  702. g_ScriptManager.EmptyRunningScriptList();
  703. for (iT = 2*g_nBrowserRequests; g_nBrowserRequests > 0 && iT > 0; iT--)
  704. Sleep(dwtShortWait);
  705. }
  706. }
  707. DBGPRINTF((DBG_CONTEXT, "ASP Shutdown: Requests drained: %d remaining\n",
  708. g_nBrowserRequests));
  709. //////////////////////////////////////////////////////////
  710. // Kill any remaining engines running scripts
  711. g_ScriptManager.EmptyRunningScriptList();
  712. DBGPRINTF((DBG_CONTEXT, "ASP Shutdown: Scripts killed\n"));
  713. //////////////////////////////////////////////////////////
  714. // Wait till there are no appications restarting
  715. g_ApplnMgr.Lock();
  716. while (g_nApplicationsRestarting > 0)
  717. {
  718. g_ApplnMgr.UnLock();
  719. Sleep(dwtShortWait);
  720. g_ApplnMgr.Lock();
  721. }
  722. g_ApplnMgr.UnLock();
  723. DBGPRINTF((DBG_CONTEXT, "ASP Shutdown: 0 applications restarting\n"));
  724. //////////////////////////////////////////////////////////
  725. // Make this thread's priority higher than that of worker threads
  726. SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
  727. //////////////////////////////////////////////////////////
  728. // For each application queue up all its sessions for deletion
  729. CApplnIterator ApplnIterator;
  730. ApplnIterator.Start();
  731. CAppln *pAppln;
  732. while (pAppln = ApplnIterator.Next())
  733. {
  734. // remove link to ATQ scheduler (even if killing of sessions fails)
  735. pAppln->PSessionMgr()->UnScheduleSessionKiller();
  736. for (iT = pAppln->GetNumSessions(); iT > 0; iT--)
  737. {
  738. pAppln->PSessionMgr()->DeleteAllSessions(TRUE);
  739. if (pAppln->GetNumSessions() == 0) // all gone?
  740. break;
  741. Sleep(dwtShortWait);
  742. }
  743. }
  744. ApplnIterator.Stop();
  745. DBGPRINTF((DBG_CONTEXT, "ASP Shutdown: All sessions queued up for deletion. nSessions=%d\n",
  746. g_nSessions));
  747. //////////////////////////////////////////////////////////
  748. // Wait till all sessions are gone (UnInited)
  749. while (g_nSessions > 0)
  750. {
  751. // Wait for a maximum of 0.1 sec x # of sessions
  752. for (iT = g_nSessions; g_nSessions > 0 && iT > 0; iT--)
  753. Sleep(dwtShortWait);
  754. if (g_nSessions > 0)
  755. g_ScriptManager.EmptyRunningScriptList(); // Kill runaway Session_OnEnd scripts
  756. }
  757. DBGPRINTF((DBG_CONTEXT, "ASP Shutdown: Finished waiting for sessions to go away. nSessions=%d\n",
  758. g_nSessions));
  759. //////////////////////////////////////////////////////////
  760. // Queue up all application objects for deletion
  761. g_ApplnMgr.DeleteAllApplications();
  762. DBGPRINTF((DBG_CONTEXT, "ASP Shutdown: All applications queued up for deletion. nApplications=%d\n",
  763. g_nApplications));
  764. //////////////////////////////////////////////////////////
  765. // Wait till all applications are gone (UnInited)
  766. while (g_nApplications > 0)
  767. {
  768. // Wait for a maximum of 1 sec x # of applications
  769. for (iT = g_nApplications; g_nApplications > 0 && iT > 0; iT--)
  770. Sleep(dwtLongWait);
  771. if (g_nApplications > 0)
  772. g_ScriptManager.EmptyRunningScriptList(); // Kill runaway Applications_OnEnd scripts
  773. }
  774. DBGPRINTF((DBG_CONTEXT, "ASP Shutdown: Finished waiting for applications to go away. nApplications=%d\n",
  775. g_nApplications));
  776. /////////////////////////////////////////////////////////
  777. // Wait on the CViperAsyncRequest objects. COM holds the
  778. // final reference to these so we need to let the activity
  779. // threads release any outstanding references before we
  780. // exit.
  781. while( g_nViperRequests > 0 )
  782. {
  783. Sleep( dwtShortWait );
  784. }
  785. //////////////////////////////////////////////////////////
  786. // Free up libraries to force call of DllCanUnloadNow()
  787. // Component writers should put cleanup code in the DllCanUnloadNow() entry point.
  788. CoFreeUnusedLibraries();
  789. //////////////////////////////////////////////////////////
  790. // Kill Debug Activity if any
  791. if (g_pDebugActivity)
  792. delete g_pDebugActivity;
  793. DBGPRINTF((DBG_CONTEXT, "ASP Shutdown: Debug Activity destroyed\n"));
  794. //////////////////////////////////////////////////////////
  795. return S_OK;
  796. }
  797. /*===================================================================
  798. HRESULT GlobInit
  799. Get all interesting global values (mostly from registry)
  800. Returns:
  801. HRESULT - S_OK on success
  802. Side effects:
  803. fills in glob. May be slow
  804. ===================================================================*/
  805. HRESULT GlobInit()
  806. {
  807. //
  808. // BUGBUG - This really needs to be provided either through
  809. // a server support function or via the wamexec
  810. //
  811. char szModule[MAX_PATH+1];
  812. if (GetModuleFileNameA(NULL, szModule, MAX_PATH) > 0)
  813. {
  814. int cch = strlen(szModule);
  815. if (cch > 12 && stricmp(szModule+cch-12, "inetinfo.exe") == 0)
  816. {
  817. g_fOOP = FALSE;
  818. }
  819. else if ( cch > 8 && stricmp( szModule+cch-8, "w3wp.exe" ) == 0 )
  820. {
  821. g_fOOP = FALSE;
  822. }
  823. else
  824. {
  825. g_fOOP = TRUE;
  826. }
  827. }
  828. // Init gGlob
  829. return gGlob.GlobInit();
  830. }
  831. /*===================================================================
  832. GlobUnInit
  833. It is a macro now. see glob.h
  834. Returns:
  835. HRESULT - S_OK on success
  836. Side effects:
  837. memory freed.
  838. ===================================================================*/
  839. HRESULT GlobUnInit()
  840. {
  841. return gGlob.GlobUnInit();
  842. }
  843. /*===================================================================
  844. InitCachedBSTRs
  845. Pre-create frequently used BSTRs
  846. ===================================================================*/
  847. HRESULT InitCachedBSTRs()
  848. {
  849. g_bstrApplication = SysAllocString(WSZ_OBJ_APPLICATION);
  850. g_bstrRequest = SysAllocString(WSZ_OBJ_REQUEST);
  851. g_bstrResponse = SysAllocString(WSZ_OBJ_RESPONSE);
  852. g_bstrServer = SysAllocString(WSZ_OBJ_SERVER);
  853. g_bstrCertificate = SysAllocString(WSZ_OBJ_CERTIFICATE);
  854. g_bstrSession = SysAllocString(WSZ_OBJ_SESSION);
  855. g_bstrScriptingNamespace = SysAllocString(WSZ_OBJ_SCRIPTINGNAMESPACE);
  856. g_bstrObjectContext = SysAllocString(WSZ_OBJ_OBJECTCONTEXT);
  857. return
  858. (
  859. g_bstrApplication &&
  860. g_bstrRequest &&
  861. g_bstrResponse &&
  862. g_bstrServer &&
  863. g_bstrCertificate &&
  864. g_bstrSession &&
  865. g_bstrScriptingNamespace &&
  866. g_bstrObjectContext
  867. )
  868. ? S_OK : E_OUTOFMEMORY;
  869. }
  870. /*===================================================================
  871. UnInitCachedBSTRs
  872. Delete frequently used BSTRs
  873. ===================================================================*/
  874. HRESULT UnInitCachedBSTRs()
  875. {
  876. if (g_bstrApplication)
  877. {
  878. SysFreeString(g_bstrApplication);
  879. g_bstrApplication = NULL;
  880. }
  881. if (g_bstrRequest)
  882. {
  883. SysFreeString(g_bstrRequest);
  884. g_bstrRequest = NULL;
  885. }
  886. if (g_bstrResponse)
  887. {
  888. SysFreeString(g_bstrResponse);
  889. g_bstrResponse = NULL;
  890. }
  891. if (g_bstrServer)
  892. {
  893. SysFreeString(g_bstrServer);
  894. g_bstrServer = NULL;
  895. }
  896. if (g_bstrCertificate)
  897. {
  898. SysFreeString(g_bstrCertificate);
  899. g_bstrCertificate = NULL;
  900. }
  901. if (g_bstrSession)
  902. {
  903. SysFreeString(g_bstrSession);
  904. g_bstrSession = NULL;
  905. }
  906. if (g_bstrScriptingNamespace)
  907. {
  908. SysFreeString(g_bstrScriptingNamespace);
  909. g_bstrScriptingNamespace = NULL;
  910. }
  911. if (g_bstrObjectContext)
  912. {
  913. SysFreeString(g_bstrObjectContext);
  914. g_bstrObjectContext = NULL;
  915. }
  916. return S_OK;
  917. }
  918. // Cached typeinfo's
  919. ITypeInfo *g_ptinfoIDispatch = NULL; // Cache IDispatch typeinfo
  920. ITypeInfo *g_ptinfoIUnknown = NULL; // Cache IUnknown typeinfo
  921. ITypeInfo *g_ptinfoIStringList = NULL; // Cache IStringList typeinfo
  922. ITypeInfo *g_ptinfoIRequestDictionary = NULL; // Cache IRequestDictionary typeinfo
  923. ITypeInfo *g_ptinfoIReadCookie = NULL; // Cache IReadCookie typeinfo
  924. ITypeInfo *g_ptinfoIWriteCookie = NULL; // Cache IWriteCookie typeinfo
  925. /*===================================================================
  926. CacheStdTypeInfos
  927. This is kindofa funny OA-threading bug workaround and perf improvement.
  928. Because we know that they typinfo's for IUnknown and IDispatch are
  929. going to be used like mad, we will load them on startup and keep
  930. them addref'ed. Without this, OA would be loading and unloading
  931. their typeinfos on almost every Invoke.
  932. Also, cache denali's typelib so everyone can get at it, and
  933. cache tye typeinfo's of all our non-top-level intrinsics.
  934. Returns:
  935. HRESULT - S_OK on success
  936. Side effects:
  937. ===================================================================*/
  938. HRESULT CacheStdTypeInfos()
  939. {
  940. HRESULT hr = S_OK;
  941. ITypeLib *pITypeLib = NULL;
  942. CMBCSToWChar convStr;
  943. /*
  944. * Load the typeinfos for IUnk and IDisp
  945. */
  946. hr = LoadRegTypeLib(IID_StdOle,
  947. STDOLE2_MAJORVERNUM,
  948. STDOLE2_MINORVERNUM,
  949. STDOLE2_LCID,
  950. &pITypeLib);
  951. if (hr != S_OK)
  952. {
  953. hr = LoadTypeLibEx(OLESTR("stdole2.tlb"), REGKIND_DEFAULT, &pITypeLib);
  954. }
  955. hr = pITypeLib->GetTypeInfoOfGuid(IID_IDispatch, &g_ptinfoIDispatch);
  956. if (SUCCEEDED(hr))
  957. {
  958. hr = pITypeLib->GetTypeInfoOfGuid(IID_IUnknown, &g_ptinfoIUnknown);
  959. }
  960. pITypeLib->Release();
  961. pITypeLib = NULL;
  962. if (FAILED(hr))
  963. goto LFail;
  964. /*
  965. * Load denali's typelibs. Save them in Glob.
  966. */
  967. /*
  968. * The type libraries are registered under 0 (neutral),
  969. * and 9 (English) with no specific sub-language, which
  970. * would make them 407 or 409 and such.
  971. * If we become sensitive to sub-languages, then use the
  972. * full LCID instead of just the LANGID as done here.
  973. */
  974. char szPath[MAX_PATH + 4];
  975. // Get the path for denali so we can look for the TLB there.
  976. if (!GetModuleFileNameA(g_hinstDLL, szPath, MAX_PATH))
  977. return E_FAIL;
  978. if (FAILED(hr = convStr.Init(szPath)))
  979. goto LFail;
  980. hr = LoadTypeLibEx(convStr.GetString(), REGKIND_DEFAULT, &pITypeLib);
  981. // Since it's presumably in our DLL, make sure that we loaded it.
  982. Assert (SUCCEEDED(hr));
  983. if (FAILED(hr))
  984. goto LFail;
  985. // Save it in Glob
  986. gGlob.m_pITypeLibDenali = pITypeLib;
  987. // now load the txn type lib
  988. strcat(szPath, "\\2");
  989. if (FAILED(hr = convStr.Init(szPath)))
  990. goto LFail;
  991. hr = LoadTypeLibEx(convStr.GetString(), REGKIND_DEFAULT, &pITypeLib);
  992. // Since it's presumably in our DLL, make sure that we loaded it.
  993. Assert (SUCCEEDED(hr));
  994. if (FAILED(hr))
  995. goto LFail;
  996. // Save it in Glob
  997. gGlob.m_pITypeLibTxn = pITypeLib;
  998. /*
  999. * Now cache the typeinfo's of all non-top-level intrinsics
  1000. * This is for the OA workaround and for performance.
  1001. */
  1002. hr = gGlob.m_pITypeLibDenali->GetTypeInfoOfGuid(IID_IStringList, &g_ptinfoIStringList);
  1003. if (FAILED(hr))
  1004. goto LFail;
  1005. hr = gGlob.m_pITypeLibDenali->GetTypeInfoOfGuid(IID_IRequestDictionary, &g_ptinfoIRequestDictionary);
  1006. if (FAILED(hr))
  1007. goto LFail;
  1008. hr = gGlob.m_pITypeLibDenali->GetTypeInfoOfGuid(IID_IReadCookie, &g_ptinfoIReadCookie);
  1009. if (FAILED(hr))
  1010. goto LFail;
  1011. hr = gGlob.m_pITypeLibDenali->GetTypeInfoOfGuid(IID_IWriteCookie, &g_ptinfoIWriteCookie);
  1012. if (FAILED(hr))
  1013. goto LFail;
  1014. LFail:
  1015. return(hr);
  1016. }
  1017. /*===================================================================
  1018. UnCacheStdTypeInfos
  1019. Release the typeinfo's we have cached for IUnknown and IDispatch
  1020. and the denali typelib and the other cached stuff.
  1021. Returns:
  1022. HRESULT - S_OK on success
  1023. Side effects:
  1024. ===================================================================*/
  1025. HRESULT UnCacheStdTypeInfos()
  1026. {
  1027. ITypeInfo **ppTypeInfo;
  1028. // Release the typeinfos for IUnk and IDisp
  1029. if (g_ptinfoIDispatch)
  1030. {
  1031. g_ptinfoIDispatch->Release();
  1032. g_ptinfoIDispatch = NULL;
  1033. }
  1034. if (g_ptinfoIUnknown)
  1035. {
  1036. g_ptinfoIUnknown->Release();
  1037. g_ptinfoIDispatch = NULL;
  1038. }
  1039. // Let go of the cached Denali typelibs
  1040. Glob(pITypeLibDenali)->Release();
  1041. Glob(pITypeLibTxn)->Release();
  1042. // Let go of other cached typeinfos
  1043. g_ptinfoIStringList->Release();
  1044. g_ptinfoIRequestDictionary->Release();
  1045. g_ptinfoIReadCookie->Release();
  1046. g_ptinfoIWriteCookie->Release();
  1047. return(S_OK);
  1048. }
  1049. /*===================================================================
  1050. InitODBC
  1051. Based on the registry Entry value for StartConnectionPool
  1052. we will initialize the ODBC Connection Pool.
  1053. This initialization requires no un-init call
  1054. StartConnectionPool = TRUE - turn on connection pooling
  1055. StartConnectionPool = FALSE
  1056. Returns:
  1057. Void - no return value
  1058. ===================================================================*/
  1059. /*void InitODBC(void)
  1060. {
  1061. if (!Glob(fStartConnectionPool))
  1062. return;
  1063. signed short rc;
  1064. // define the function pointer type
  1065. typedef signed short(CALLBACK *PFNSQLSetEnvAttr)
  1066. (
  1067. DWORD, DWORD, void*, DWORD
  1068. );
  1069. // declare the function pointer
  1070. PFNSQLSetEnvAttr pfnSQLSetEnvAttr;
  1071. g_hODBC32Lib = LoadLibrary("odbc32.dll");
  1072. if(g_hODBC32Lib)
  1073. {
  1074. pfnSQLSetEnvAttr = (PFNSQLSetEnvAttr) GetProcAddress(g_hODBC32Lib, "SQLSetEnvAttr");
  1075. if (pfnSQLSetEnvAttr)
  1076. rc = (*pfnSQLSetEnvAttr)(0UL, 201UL, (void*)2UL, 0UL);
  1077. // rc = SQLSetEnvAttr(SQL_NULL_HENV, SQL_ATTR_CONNECTION_POOLING, (void*)SQL_CP_ONE_PER_HENV,0)
  1078. // I did not want to include all of the SQL h files so I hard-coded the values
  1079. // for the constants
  1080. }
  1081. }
  1082. */
  1083. /*===================================================================
  1084. UnInitODBC
  1085. Based on the registry Entry value for StartConnectionPool
  1086. we will free the odbc32.dll that was loaded with InitODBC
  1087. StartConnectionPool = TRUE - turn on connection pooling
  1088. StartConnectionPool = FALSE
  1089. Returns:
  1090. Void - no return value
  1091. ===================================================================*/
  1092. /*
  1093. void UnInitODBC(void)
  1094. {
  1095. if (!Glob(fStartConnectionPool))
  1096. return;
  1097. if (g_hODBC32Lib)
  1098. FreeLibrary(g_hODBC32Lib);
  1099. }
  1100. */
  1101. /*===================================================================
  1102. MakeAspCookieName
  1103. Creates the asp cookie name as concatination of standard prefix and
  1104. current process id.
  1105. This function is called once per ASP.DLL (oon DllInit())
  1106. Parameters:
  1107. szCookie [out] Put cookie name here
  1108. Returns:
  1109. NOTHING
  1110. ===================================================================*/
  1111. static void MakeAspCookieName(char *szCookie)
  1112. {
  1113. // Standard prefix
  1114. strcpy(szCookie, SZ_SESSION_ID_COOKIE_PREFIX);
  1115. szCookie += CCH_SESSION_ID_COOKIE_PREFIX;
  1116. // Process ID
  1117. sprintf(szCookie, "%08x", GetCurrentProcessId());
  1118. // Uppercase
  1119. strupr(szCookie);
  1120. // Change digits to letters
  1121. static const char *pszDigitsToLetters[2] = {"GHIJKLMNOP","QRSTUVWXYZ"};
  1122. for (int i = 0; i < 8; i++)
  1123. {
  1124. int ch = szCookie[i];
  1125. if (ch >= '0' && ch <= '9')
  1126. szCookie[i] = pszDigitsToLetters[rand() % 2][ch - '0'];
  1127. }
  1128. }
  1129. /*===================================================================
  1130. SendHtmlSubstitute
  1131. Send the html file named XXX_ASP.HTM instead of rejecting the
  1132. request.
  1133. Parameters:
  1134. pIReq CIsapiReqInfo
  1135. Returns:
  1136. HRESULT (S_FALSE = no html substitute found)
  1137. ===================================================================*/
  1138. HRESULT SendHtmlSubstitute(CIsapiReqInfo *pIReq)
  1139. {
  1140. TCHAR *szAspPath = pIReq->QueryPszPathTranslated();
  1141. DWORD cchAspPath = pIReq->QueryCchPathTranslated();
  1142. // verify file name
  1143. if (cchAspPath < 4 || cchAspPath > MAX_PATH ||
  1144. _tcsicmp(szAspPath + cchAspPath - 4, _T(".asp")) != 0)
  1145. {
  1146. return S_FALSE;
  1147. }
  1148. // construct path of the html file
  1149. TCHAR szHtmPath[MAX_PATH+5];
  1150. DWORD cchHtmPath = cchAspPath + 4;
  1151. _tcscpy(szHtmPath, szAspPath);
  1152. szHtmPath[cchAspPath - 4] = _T('_');
  1153. _tcscpy(szHtmPath + cchAspPath, _T(".htm"));
  1154. // check if the html file exists
  1155. if (FAILED(AspGetFileAttributes(szHtmPath)))
  1156. return S_FALSE;
  1157. return CResponse::SyncWriteFile(pIReq, szHtmPath);
  1158. }
  1159. #ifdef LOG_FCNOTIFICATIONS
  1160. // UNDONE get this from registry
  1161. LPSTR g_szNotifyLogFile = "C:\\Temp\\AspNotify.Log";
  1162. HANDLE g_hfileNotifyLog;
  1163. HANDLE g_hmapNotifyLog;
  1164. char* g_pchNotifyLogStart;
  1165. char* g_pchNotifyLogCurrent;
  1166. LPSTR g_szNotifyPrefix = "File change notification: ";
  1167. LPSTR g_szCreateHandlePrefix = "Create handle: ";
  1168. void LfcnCreateLogFile()
  1169. {
  1170. DWORD dwErrCode;
  1171. if(INVALID_HANDLE_VALUE != (g_hfileNotifyLog =
  1172. CreateFile(
  1173. g_szNotifyLogFile, // file name
  1174. GENERIC_READ | GENERIC_WRITE, // access (read-write) mode
  1175. FILE_SHARE_READ, // share mode
  1176. NULL, // pointer to security descriptor
  1177. CREATE_ALWAYS, // how to create
  1178. FILE_ATTRIBUTE_NORMAL, // file attributes
  1179. NULL // handle to file with attributes to copy
  1180. )))
  1181. {
  1182. BYTE rgb[0x10000];
  1183. DWORD cb = sizeof( rgb );
  1184. DWORD cbWritten = 0;
  1185. // FillMemory( rgb, cb, 0xAB );
  1186. WriteFile(
  1187. g_hfileNotifyLog, // handle to file to write to
  1188. rgb, // pointer to data to write to file
  1189. cb, // number of bytes to write
  1190. &cbWritten, // pointer to number of bytes written
  1191. NULL // pointer to structure needed for overlapped I/O
  1192. );
  1193. if(NULL != (g_hmapNotifyLog =
  1194. CreateFileMapping(
  1195. g_hfileNotifyLog, // handle to file to map
  1196. NULL, // optional security attributes
  1197. PAGE_READWRITE, // protection for mapping object
  1198. 0, // high-order 32 bits of object size
  1199. 100, // low-order 32 bits of object size
  1200. NULL // name of file-mapping object
  1201. )))
  1202. {
  1203. if(NULL != (g_pchNotifyLogStart =
  1204. (char*) MapViewOfFile(
  1205. g_hmapNotifyLog, // file-mapping object to map into address space
  1206. FILE_MAP_WRITE, // access mode
  1207. 0, // high-order 32 bits of file offset
  1208. 0, // low-order 32 bits of file offset
  1209. 0 // number of bytes to map
  1210. )))
  1211. {
  1212. *g_pchNotifyLogStart = '\0';
  1213. g_pchNotifyLogCurrent = g_pchNotifyLogStart;
  1214. LfcnAppendLog( "ASP change-notifications log file \r\n" );
  1215. LfcnAppendLog( "================================= \r\n" );
  1216. DBGPRINTF((DBG_CONTEXT, "Notifications log file created and mapped.\r\n" ));
  1217. return;
  1218. }
  1219. }
  1220. }
  1221. dwErrCode = GetLastError();
  1222. DBGERROR((DBG_CONTEXT, "Failed to create notifications log file; last error was %d\r\n", szErrCode));
  1223. }
  1224. void LfcnCopyAdvance(char** ppchDest, const char* sz)
  1225. {
  1226. // UNDONE make this robust (WriteFile to extend file?)
  1227. strcpy( *ppchDest, sz );
  1228. *ppchDest += strlen( sz );
  1229. }
  1230. void LfcnAppendLog(const char* sz)
  1231. {
  1232. LfcnCopyAdvance( &g_pchNotifyLogCurrent, sz );
  1233. DBGPRINTF((DBG_CONTEXT, "%s", sz));
  1234. }
  1235. void LfcnLogNotification(char* szFile)
  1236. {
  1237. LfcnAppendLog( g_szNotifyPrefix );
  1238. LfcnAppendLog( szFile );
  1239. LfcnAppendLog( "\r\n" );
  1240. }
  1241. void LfcnLogHandleCreation(int i, char* szApp)
  1242. {
  1243. char szIndex[5];
  1244. _itoa( i, szIndex, 10);
  1245. LfcnAppendLog( g_szCreateHandlePrefix );
  1246. LfcnAppendLog( szIndex );
  1247. LfcnAppendLog( "\t" );
  1248. LfcnAppendLog( szApp );
  1249. LfcnAppendLog( "\r\n" );
  1250. }
  1251. void LfcnUnmapLogFile()
  1252. {
  1253. if(g_pchNotifyLogStart != NULL)
  1254. UnmapViewOfFile(g_pchNotifyLogStart);
  1255. if(g_hmapNotifyLog!= NULL)
  1256. CloseHandle(g_hmapNotifyLog);
  1257. if(g_hfileNotifyLog != NULL && g_hfileNotifyLog != INVALID_HANDLE_VALUE)
  1258. CloseHandle( g_hfileNotifyLog );
  1259. g_pchNotifyLogStart = NULL;
  1260. g_hmapNotifyLog = NULL;
  1261. g_hfileNotifyLog = NULL;
  1262. }
  1263. #endif //LOG_FCNOTIFICATIONS
  1264. #if _IIS_5_1
  1265. LONG CWamModule::Lock()
  1266. {
  1267. return CComModule::Lock();
  1268. }
  1269. LONG CWamModule::Unlock()
  1270. {
  1271. return CComModule::Unlock();
  1272. }
  1273. #endif