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.

2265 lines
66 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 "ie449.h"
  24. #include "memcls.h"
  25. #include "memchk.h"
  26. #include "etwtrace.hxx"
  27. // Globals
  28. BOOL g_fShutDownInProgress = FALSE;
  29. BOOL g_fInitStarted = FALSE;
  30. BOOL g_fTerminateExtension = FALSE;
  31. DWORD g_nIllStatesReported = 0;
  32. LONG g_nOOMErrors = 0;
  33. BOOL g_fOOMRecycleDisabled = FALSE;
  34. BOOL g_fLazyContentPropDisabled = FALSE;
  35. BOOL g_fUNCChangeNotificationEnabled = FALSE;
  36. DWORD g_dwFileMonitoringTimeoutSecs = 5; // Default 5 Seconds Time to Live (TTL) for monitoring files.
  37. char g_szExtensionDesc[] = "Microsoft Active Server Pages 2.0";
  38. GLOB gGlob;
  39. BOOL g_fFirstHit = TRUE;
  40. DWORD g_fFirstHitFailed = 0;
  41. LONG g_fUnhealthyReported = 0;
  42. char g_pszASPModuleName[] = "ASP";
  43. enum g_eInitCompletions {
  44. eInitMDReadConfigFail = 1,
  45. eInitTemplateCacheFail,
  46. eInitViperConfigFail,
  47. eInitViperReqMgrFail,
  48. eInitMBListenerFail
  49. };
  50. DECLARE_DEBUG_PRINTS_OBJECT();
  51. DECLARE_PLATFORM_TYPE();
  52. //
  53. // Etw Tracing
  54. //
  55. #define ASP_TRACE_MOF_FILE L"AspMofResource"
  56. #define ASP_IMAGE_PATH L"Asp.dll"
  57. CEtwTracer * g_pEtwTracer = NULL;
  58. HRESULT AdjustProcessSecurityToAllowPowerUsersToWait();
  59. // Out of process flag
  60. BOOL g_fOOP = FALSE;
  61. // session id cookie
  62. char g_szSessionIDCookieName[CCH_SESSION_ID_COOKIE+1];
  63. CRITICAL_SECTION g_csEventlogLock;
  64. CRITICAL_SECTION g_csFirstHitLock;
  65. CRITICAL_SECTION g_csFirstMTAHitLock;
  66. CRITICAL_SECTION g_csFirstSTAHitLock;
  67. HINSTANCE g_hODBC32Lib;
  68. // Added to support CacheExtensions
  69. HINSTANCE g_hDenali = (HINSTANCE)0;
  70. HINSTANCE g_hinstDLL = (HINSTANCE)0;
  71. HMODULE g_hResourceDLL = (HMODULE)0;
  72. extern LONG g_nSessionObjectsActive;
  73. extern DWORD g_nApplicationObjectsActive;
  74. extern LONG g_nRequestsHung;
  75. extern LONG g_nThreadsExecuting;
  76. DWORD g_nConsecutiveIllStates = 0;
  77. DWORD g_nRequestSamples[3] = {0,0,0};
  78. class CHangDetectConfig {
  79. public:
  80. CHangDetectConfig() {
  81. dwRequestThreshold = 1000;
  82. dwThreadsHungThreshold = 50;
  83. dwConsecIllStatesThreshold = 3;
  84. dwHangDetectionEnabled = TRUE;
  85. }
  86. void Init() {
  87. dwRequestThreshold = Glob(dwRequestQueueMax)/3;
  88. ReadRegistryValues();
  89. }
  90. DWORD dwRequestThreshold;
  91. DWORD dwThreadsHungThreshold;
  92. DWORD dwConsecIllStatesThreshold;
  93. DWORD dwHangDetectionEnabled;
  94. private:
  95. void ReadRegistryValues() {
  96. DWORD dwValue;
  97. if (SUCCEEDED(g_AspRegistryParams.GetHangDetRequestThreshold(&dwValue)))
  98. dwRequestThreshold = dwValue;
  99. if (SUCCEEDED(g_AspRegistryParams.GetHangDetThreadHungThreshold(&dwValue)))
  100. dwThreadsHungThreshold = dwValue;
  101. if (SUCCEEDED(g_AspRegistryParams.GetHangDetConsecIllStatesThreshold(&dwValue)))
  102. dwConsecIllStatesThreshold = dwValue;
  103. if (SUCCEEDED(g_AspRegistryParams.GetHangDetEnabled(&dwValue)))
  104. dwHangDetectionEnabled = dwValue;
  105. }
  106. };
  107. CHangDetectConfig g_HangDetectConfig;
  108. // Cached BSTRs
  109. BSTR g_bstrApplication = NULL;
  110. BSTR g_bstrRequest = NULL;
  111. BSTR g_bstrResponse = NULL;
  112. BSTR g_bstrServer = NULL;
  113. BSTR g_bstrCertificate = NULL;
  114. BSTR g_bstrSession = NULL;
  115. BSTR g_bstrScriptingNamespace = NULL;
  116. BSTR g_bstrObjectContext = NULL;
  117. extern IASPObjectContext *g_pIASPDummyObjectContext;
  118. // Forward references
  119. HRESULT GlobInit();
  120. HRESULT GlobUnInit();
  121. HRESULT CacheStdTypeInfos();
  122. HRESULT UnCacheStdTypeInfos();
  123. HRESULT InitCachedBSTRs();
  124. HRESULT UnInitCachedBSTRs();
  125. HRESULT ShutDown();
  126. HRESULT SendHtmlSubstitute(CIsapiReqInfo *pIReq);
  127. void DoHangDetection(CIsapiReqInfo *pIReq, DWORD totalReqs);
  128. void DoOOMDetection(CIsapiReqInfo *pIReq, DWORD totalReqs);
  129. BOOL FReportUnhealthy();
  130. BOOL FirstHitInit(CIsapiReqInfo *pIReq);
  131. // ATL support
  132. CComModule _Module;
  133. BEGIN_OBJECT_MAP(ObjectMap)
  134. END_OBJECT_MAP()
  135. /*===================================================================
  136. DllMain - Moved from clsfctry.cpp
  137. Main entry point into the DLL. Called by system on DLL load
  138. and unload.
  139. Returns:
  140. TRUE on success
  141. Side effects:
  142. None.
  143. ===================================================================*/
  144. BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpvReserved)
  145. {
  146. /* Obsolete
  147. // Let the Proxy code get a crack at it
  148. if (!PrxDllMain(hinstDLL, dwReason, lpvReserved))
  149. return FALSE;
  150. */
  151. switch(dwReason)
  152. {
  153. case DLL_PROCESS_ATTACH:
  154. // hang onto the hinstance so we can use it to get to our string resources
  155. //
  156. g_hinstDLL = hinstDLL;
  157. // Here's an interesting optimization:
  158. // The following tells the system NOT to call us for Thread attach/detach
  159. // since we dont handle those calls anyway, this will speed things up a bit.
  160. // If this turns out to be a problem for some reason (cant imagine why),
  161. // just remove this again.
  162. DisableThreadLibraryCalls(hinstDLL);
  163. break;
  164. case DLL_PROCESS_DETACH:
  165. break;
  166. case DLL_THREAD_ATTACH:
  167. break;
  168. case DLL_THREAD_DETACH:
  169. break;
  170. }
  171. return TRUE;
  172. }
  173. /*===================================================================
  174. DWORD HandleHit
  175. Given the CIsapiReqInfo construct a hit object to be queued
  176. for execution
  177. Parameters:
  178. pIReq - CIsapiReqInfo
  179. Returns:
  180. HSE_STATUS_PENDING if function is successful in queuing request
  181. HSE_STATUS_ERROR if not successful
  182. ===================================================================*/
  183. DWORD HandleHit(CIsapiReqInfo *pIReq)
  184. {
  185. int errorId = 0;
  186. BOOL fRejected = FALSE;
  187. BOOL fCompleted = FALSE;
  188. HRESULT hr = S_OK;
  189. DWORD totalReqs;
  190. /*
  191. * We cant read the metabase until we have the WAM_EXEC_INFO, which
  192. * we dont have at DllInit time. Therefore, we postpone reading the
  193. * metabase until now, but we do it only on the first hit.
  194. */
  195. if (g_fFirstHit)
  196. {
  197. EnterCriticalSection(&g_csFirstHitLock);
  198. // If someone initied while we were waiting for the CS,
  199. // then noop
  200. if (g_fFirstHit)
  201. {
  202. BOOL fT;
  203. fT = FirstHitInit(pIReq);
  204. Assert(fT);
  205. g_fFirstHit = FALSE;
  206. // Log error to the NT EventLog
  207. if (!fT)
  208. {
  209. // Log event to EventLog
  210. MSG_Error(IDS_FIRSTHIT_INIT_FAILED_STR);
  211. }
  212. }
  213. LeaveCriticalSection(&g_csFirstHitLock);
  214. }
  215. if (g_fFirstHitFailed)
  216. {
  217. // return 500 error.
  218. errorId = IDE_500_SERVER_ERROR;
  219. Handle500Error(errorId, pIReq);
  220. // We cannot return HSE_STATUS_ERROR because of a race condition.
  221. // We have queued the response for Async Completion (in Handle500Error).
  222. // It is the duty of the Async Completion routine to flag DONE_WITH_SESSION
  223. return pIReq->GetRequestStatus();
  224. }
  225. #ifndef PERF_DISABLE
  226. if (!g_fPerfInited) // Init PERFMON data on first request
  227. {
  228. // FYI: leverage same CS as first hit lock
  229. EnterCriticalSection(&g_csFirstHitLock);
  230. // If someone initied while we were waiting for the CS,
  231. // then noop
  232. if (!g_fPerfInited)
  233. {
  234. if (SUCCEEDED(InitPerfDataOnFirstRequest(pIReq)))
  235. {
  236. g_fPerfInited = TRUE;
  237. }
  238. else
  239. {
  240. g_fPerfInited = FALSE;
  241. }
  242. }
  243. LeaveCriticalSection(&g_csFirstHitLock);
  244. }
  245. totalReqs = g_PerfData.Incr_REQTOTAL();
  246. #endif
  247. if (Glob(fNeedUpdate))
  248. gGlob.Update(pIReq);
  249. if (IsShutDownInProgress())
  250. hr = E_FAIL;
  251. // Do hang detection tests
  252. DoHangDetection(pIReq, totalReqs);
  253. DoOOMDetection(pIReq, totalReqs);
  254. // Enforce the limit of concurrent browser requests
  255. if (SUCCEEDED(hr) && Glob(dwRequestQueueMax) &&
  256. (g_nBrowserRequests >= Glob(dwRequestQueueMax)))
  257. {
  258. hr = E_FAIL;
  259. fRejected = TRUE;
  260. }
  261. if (SUCCEEDED(hr))
  262. hr = CHitObj::NewBrowserRequest(pIReq, &fRejected, &fCompleted, &errorId);
  263. if (SUCCEEDED(hr))
  264. return pIReq->GetRequestStatus();
  265. if (fRejected)
  266. {
  267. if (Glob(fEnableAspHtmlFallBack))
  268. {
  269. // Instead of rejecting the request try to find
  270. // XXX_ASP.HTM file in the same directory and dump its contents
  271. hr = SendHtmlSubstitute(pIReq);
  272. if (hr == S_OK)
  273. {
  274. #ifndef PERF_DISABLE
  275. //
  276. // Counts as request succeeded
  277. //
  278. g_PerfData.Incr_REQSUCCEEDED();
  279. #endif
  280. //
  281. // HTML substitute sent
  282. //
  283. return pIReq->GetRequestStatus();
  284. }
  285. //
  286. // HTML substitute not found
  287. //
  288. }
  289. errorId = IDE_SERVER_TOO_BUSY;
  290. #ifndef PERF_DISABLE
  291. g_PerfData.Incr_REQREJECTED();
  292. #endif
  293. }
  294. Handle500Error(errorId, pIReq);
  295. return pIReq->GetRequestStatus();
  296. }
  297. /*===================================================================
  298. BOOL DllInit
  299. Initialize Denali if not invoked by RegSvr32. Only do inits here
  300. that dont require Glob values loaded from the metabase. For any
  301. inits that require values loaded into Glob from the metabase, use
  302. FirstHitInit.
  303. Returns:
  304. TRUE on successful initialization
  305. ===================================================================*/
  306. BOOL DllInit()
  307. {
  308. HRESULT hr;
  309. const CHAR szASPDebugRegLocation[] =
  310. "System\\CurrentControlSet\\Services\\W3Svc\\ASP";
  311. DWORD initStatus = 0;
  312. enum eInitCompletions {
  313. eInitResourceDll = 1,
  314. eInitDebugPrintObject,
  315. eInitTraceLogs,
  316. eInitPerfData,
  317. eInitEventLogCS,
  318. eInitFirstHitCS,
  319. eInitFirstMTAHitCS,
  320. eInitFirstSTAHitCS,
  321. eInitDenaliMemory,
  322. eInitDirMonitor,
  323. eInitGlob,
  324. eInitMemCls,
  325. eInitCachedBSTRs,
  326. eInitCacheStdTypeInfos,
  327. eInitTypelibCache,
  328. eInitErrHandle,
  329. eInitRandGenerator,
  330. eInitApplnMgr,
  331. eInit449,
  332. eInitTemplateCache,
  333. eInitIncFileMap,
  334. eInitFileAppMap,
  335. eInitScriptMgr,
  336. eInitTemplate__InitClass,
  337. eInitGIPAPI,
  338. eInitMTACallbacks
  339. };
  340. hr = InitializeResourceDll();
  341. if (FAILED(hr))
  342. {
  343. return FALSE;
  344. }
  345. initStatus = eInitResourceDll;
  346. CREATE_DEBUG_PRINT_OBJECT( g_pszASPModuleName);
  347. if ( !VALID_DEBUG_PRINT_OBJECT())
  348. goto errExit;
  349. initStatus = eInitDebugPrintObject;
  350. LOAD_DEBUG_FLAGS_FROM_REG_STR(szASPDebugRegLocation, 0);
  351. #ifdef SCRIPT_STATS
  352. ReadRegistrySettings();
  353. #endif // SCRIPT_STATS
  354. // Create ASP RefTrace Logs
  355. IF_DEBUG(TEMPLATE) CTemplate::gm_pTraceLog = CreateRefTraceLog(5000, 0);
  356. IF_DEBUG(SESSION) CSession::gm_pTraceLog = CreateRefTraceLog(5000, 0);
  357. IF_DEBUG(APPLICATION) CAppln::gm_pTraceLog = CreateRefTraceLog(5000, 0);
  358. IF_DEBUG(FCN) CASPDirMonitorEntry::gm_pTraceLog = CreateRefTraceLog(500, 0);
  359. initStatus = eInitTraceLogs;
  360. if (FAILED(PreInitPerfData()))
  361. goto errExit;
  362. initStatus = eInitPerfData;
  363. DBGPRINTF((DBG_CONTEXT, "ASP Init -- PerfMon Data PreInit\n"));
  364. ErrInitCriticalSection( &g_csEventlogLock, hr );
  365. if (FAILED(hr))
  366. goto errExit;
  367. initStatus = eInitEventLogCS;
  368. ErrInitCriticalSection( &g_csFirstHitLock, hr );
  369. if (FAILED(hr))
  370. goto errExit;
  371. initStatus = eInitFirstHitCS;
  372. ErrInitCriticalSection( &g_csFirstMTAHitLock, hr );
  373. if (FAILED(hr))
  374. goto errExit;
  375. initStatus = eInitFirstMTAHitCS;
  376. ErrInitCriticalSection( &g_csFirstSTAHitLock, hr );
  377. if (FAILED(hr))
  378. goto errExit;
  379. initStatus = eInitFirstSTAHitCS;
  380. #ifdef DENALI_MEMCHK
  381. if (FAILED(DenaliMemoryInit()))
  382. goto errExit;
  383. #else
  384. if (FAILED(AspMemInit()))
  385. goto errExit;
  386. #endif
  387. DBGPRINTF((DBG_CONTEXT, "ASP Init -- Denali Memory Init\n"));
  388. initStatus = eInitDenaliMemory;
  389. g_pDirMonitor = new CDirMonitor;
  390. if (g_pDirMonitor == NULL) {
  391. goto errExit;
  392. }
  393. initStatus = eInitDirMonitor;
  394. _Module.Init(ObjectMap, g_hinstDLL, &LIBID_ASPTypeLibrary);
  395. if (FAILED(GlobInit()))
  396. goto errExit;
  397. DBGPRINTF((DBG_CONTEXT, "ASP Init -- Glob Init\n"));
  398. initStatus = eInitGlob;
  399. DWORD dwData = 0;
  400. if (SUCCEEDED(g_AspRegistryParams.GetDisableOOMRecycle(&dwData)))
  401. g_fOOMRecycleDisabled = dwData;
  402. if (SUCCEEDED(g_AspRegistryParams.GetDisableLazyContentPropagation(&dwData)))
  403. g_fLazyContentPropDisabled = dwData;
  404. if (SUCCEEDED(g_AspRegistryParams.GetChangeNotificationForUNCEnabled(&dwData)))
  405. g_fUNCChangeNotificationEnabled = dwData;
  406. // Read the Registry to see if a timeout value has been added.
  407. if (SUCCEEDED(g_AspRegistryParams.GetFileMonitoringTimeout(&dwData)))
  408. g_dwFileMonitoringTimeoutSecs = dwData;
  409. if (FAILED(InitMemCls()))
  410. goto errExit;
  411. DBGPRINTF((DBG_CONTEXT, "ASP Init -- Per-Class Cache Init\n"));
  412. initStatus = eInitMemCls;
  413. if (FAILED(InitCachedBSTRs()))
  414. goto errExit;
  415. DBGPRINTF((DBG_CONTEXT, "ASP Init -- Cached BSTRs Init\n"));
  416. initStatus = eInitCachedBSTRs;
  417. if (FAILED(CacheStdTypeInfos()))
  418. goto errExit;
  419. DBGPRINTF((DBG_CONTEXT, "ASP Init -- Cache Std TypeInfos\n"));
  420. initStatus = eInitCacheStdTypeInfos;
  421. if (FAILED(g_TypelibCache.Init()))
  422. goto errExit;
  423. DBGPRINTF((DBG_CONTEXT, "ASP Init -- Typelib Cache Init\n"));
  424. initStatus = eInitTypelibCache;
  425. if (FAILED(ErrHandleInit()))
  426. goto errExit;
  427. DBGPRINTF((DBG_CONTEXT, "ASP Init -- Err Handler Init\n"));
  428. initStatus = eInitErrHandle;
  429. srand( (unsigned int) time(NULL) );
  430. if (FAILED(g_SessionIdGenerator.Init())) // seed session id
  431. goto errExit;
  432. // Init new Exposed Session Id variable
  433. if (FAILED(g_ExposedSessionIdGenerator.Init(g_SessionIdGenerator))) // seed exposed session id
  434. goto errExit;
  435. DBGPRINTF((DBG_CONTEXT, "ASP Init -- SessionID Generator Init\n"));
  436. if (FAILED(InitRandGenerator()))
  437. goto errExit;
  438. DBGPRINTF((DBG_CONTEXT, "ASP Init -- RandGen Init\n"));
  439. initStatus = eInitRandGenerator;
  440. if (FAILED(g_ApplnMgr.Init()))
  441. goto errExit;
  442. DBGPRINTF((DBG_CONTEXT, "ASP Init -- Appln Mgr Init\n"));
  443. initStatus = eInitApplnMgr;
  444. if (FAILED(Init449()))
  445. goto errExit;
  446. DBGPRINTF((DBG_CONTEXT, "ASP Init -- 449 Mgr Init\n"));
  447. initStatus = eInit449;
  448. // Note: Template cache manager is inited in two phases. Do first here.
  449. if (FAILED(g_TemplateCache.Init()))
  450. goto errExit;
  451. DBGPRINTF((DBG_CONTEXT, "ASP Init -- Template Cache Init\n"));
  452. initStatus = eInitTemplateCache;
  453. if (FAILED(g_IncFileMap.Init()))
  454. goto errExit;
  455. DBGPRINTF((DBG_CONTEXT, "ASP Init -- Inc File Users Init\n"));
  456. initStatus = eInitIncFileMap;
  457. if (FAILED(g_FileAppMap.Init()))
  458. goto errExit;
  459. DBGPRINTF((DBG_CONTEXT, "ASP Init -- File-Application Map Init\n"));
  460. initStatus = eInitFileAppMap;
  461. if (FAILED(g_ScriptManager.Init()))
  462. goto errExit;
  463. DBGPRINTF((DBG_CONTEXT, "ASP Init -- Script Manager Init\n"));
  464. initStatus = eInitScriptMgr;
  465. if (FAILED(CTemplate::InitClass()))
  466. goto errExit;
  467. DBGPRINTF((DBG_CONTEXT, "ASP Init -- CTemplate Init Class\n"));
  468. initStatus = eInitTemplate__InitClass;
  469. if (FAILED(g_GIPAPI.Init()))
  470. goto errExit;
  471. DBGPRINTF((DBG_CONTEXT, "ASP Init -- Global Interface API Init\n"));
  472. initStatus = eInitGIPAPI;
  473. if (FAILED(InitMTACallbacks()))
  474. goto errExit;
  475. DBGPRINTF((DBG_CONTEXT, "ASP Init -- MTA Callbacks Init\n"));
  476. initStatus = eInitMTACallbacks;
  477. if (!RequestSupportInit())
  478. goto errExit;
  479. DBGPRINTF((DBG_CONTEXT, "ASP Init -- Request Support Init\n"));
  480. //
  481. // Intialize Trace
  482. //
  483. g_pEtwTracer = new CEtwTracer();
  484. if (g_pEtwTracer != NULL)
  485. {
  486. DWORD Status;
  487. Status = g_pEtwTracer->Register(&AspControlGuid,
  488. ASP_IMAGE_PATH,
  489. ASP_TRACE_MOF_FILE );
  490. if (Status != ERROR_SUCCESS)
  491. {
  492. delete g_pEtwTracer;
  493. g_pEtwTracer = NULL;
  494. }
  495. }
  496. DBGPRINTF((DBG_CONTEXT, "ASP Init -- Event Tracer Init\n"));
  497. AdjustProcessSecurityToAllowPowerUsersToWait();
  498. DBGPRINTF((DBG_CONTEXT, "ASP Init -- Denali DLL Initialized\n"));
  499. #ifdef LOG_FCNOTIFICATIONS
  500. LfcnCreateLogFile();
  501. #endif //LOG_FCNOTIFICATIONS
  502. return TRUE;
  503. errExit:
  504. // we should never be here. If we do get here, in checked builds we should break.
  505. DBGPRINTF((DBG_CONTEXT, "ASP Init -- Error in DllInit. initStatus = %d\n", initStatus));
  506. Assert(0);
  507. switch (initStatus) {
  508. case eInitMTACallbacks:
  509. UnInitMTACallbacks();
  510. case eInitGIPAPI:
  511. g_GIPAPI.UnInit();
  512. case eInitTemplate__InitClass:
  513. CTemplate::UnInitClass();
  514. case eInitScriptMgr:
  515. g_ScriptManager.UnInit();
  516. case eInitFileAppMap:
  517. g_FileAppMap.UnInit();
  518. if (g_pDirMonitor) {
  519. g_pDirMonitor->Cleanup();
  520. }
  521. case eInitIncFileMap:
  522. g_IncFileMap.UnInit();
  523. case eInitTemplateCache:
  524. g_TemplateCache.UnInit();
  525. case eInit449:
  526. UnInit449();
  527. case eInitApplnMgr:
  528. g_ApplnMgr.UnInit();
  529. case eInitRandGenerator:
  530. UnInitRandGenerator();
  531. case eInitErrHandle:
  532. ErrHandleUnInit();
  533. case eInitTypelibCache:
  534. g_TypelibCache.UnInit();
  535. case eInitCacheStdTypeInfos:
  536. UnCacheStdTypeInfos();
  537. case eInitCachedBSTRs:
  538. UnInitCachedBSTRs();
  539. case eInitMemCls:
  540. UnInitMemCls();
  541. case eInitGlob:
  542. GlobUnInit();
  543. case eInitDirMonitor:
  544. delete g_pDirMonitor;
  545. g_pDirMonitor = NULL;
  546. case eInitDenaliMemory:
  547. #ifdef DENALI_MEMCHK
  548. DenaliMemoryUnInit();
  549. #else
  550. AspMemUnInit();
  551. #endif
  552. case eInitFirstSTAHitCS:
  553. DeleteCriticalSection( &g_csFirstSTAHitLock );
  554. case eInitFirstMTAHitCS:
  555. DeleteCriticalSection( &g_csFirstMTAHitLock );
  556. case eInitFirstHitCS:
  557. DeleteCriticalSection( &g_csFirstHitLock );
  558. case eInitEventLogCS:
  559. DeleteCriticalSection( &g_csEventlogLock );
  560. case eInitTraceLogs:
  561. IF_DEBUG(TEMPLATE) DestroyRefTraceLog(CTemplate::gm_pTraceLog);
  562. IF_DEBUG(SESSION) DestroyRefTraceLog(CSession::gm_pTraceLog);
  563. IF_DEBUG(APPLICATION) DestroyRefTraceLog(CAppln::gm_pTraceLog);
  564. IF_DEBUG(FCN) DestroyRefTraceLog(CASPDirMonitorEntry::gm_pTraceLog);
  565. case eInitDebugPrintObject:
  566. DELETE_DEBUG_PRINT_OBJECT();
  567. case eInitResourceDll:
  568. UninitializeResourceDll();
  569. }
  570. return FALSE;
  571. }
  572. /*===================================================================
  573. BOOL FirstHitInit
  574. Initialize any ASP values that can not be inited at DllInit time.
  575. Returns:
  576. TRUE on successful initialization
  577. ===================================================================*/
  578. BOOL FirstHitInit
  579. (
  580. CIsapiReqInfo *pIReq
  581. )
  582. {
  583. HRESULT hr;
  584. DWORD FirstHitInitStatus = 0;;
  585. /*
  586. * In the out of proc case, being able to call the metabase relies on having
  587. * told WAM that we are a "smart" client
  588. */
  589. // ReadConfigFromMD uses pIReq - need to bracket
  590. hr = ReadConfigFromMD(pIReq, NULL, TRUE);
  591. if (FAILED(hr))
  592. FirstHitInitStatus = eInitMDReadConfigFail;
  593. // Initialize Debugging
  594. if (RevertToSelf()) // No Debugging on Win95
  595. {
  596. // Don't care whether debugging initializaiton succeeds or not. The most likely
  597. // falure is debugger not installed on the machine.
  598. //
  599. if (SUCCEEDED(InitDebugging(pIReq)))
  600. {
  601. DBGPRINTF((DBG_CONTEXT, "FirstHitInit: Debugging Initialized\n"));
  602. }
  603. else
  604. {
  605. DBGPRINTF((DBG_CONTEXT, "FirstHitInit: Debugger Initialization Failed\n"));
  606. }
  607. DBG_REQUIRE( SetThreadToken(NULL, pIReq->QueryImpersonationToken()) );
  608. }
  609. if (FAILED(hr))
  610. goto LExit;
  611. DBGPRINTF((DBG_CONTEXT, "FirstHitInit: Metadata loaded successfully\n"));
  612. // Do FirstHitInit for the Template Cache Manager. Primarily initializes
  613. // the Persisted Template Cache
  614. if (FAILED(hr = g_TemplateCache.FirstHitInit(pIReq)))
  615. {
  616. FirstHitInitStatus = eInitTemplateCacheFail;
  617. goto LExit;
  618. }
  619. DBGPRINTF((DBG_CONTEXT, "FirstHitInit: Template Cache Initialized\n"));
  620. // Configure MTS
  621. if (FAILED(hr = ViperConfigure()))
  622. {
  623. FirstHitInitStatus = eInitViperConfigFail;
  624. goto LExit;
  625. }
  626. DBGPRINTF((DBG_CONTEXT, "FirstHitInit: MTS configured\n"));
  627. //
  628. // we need to initialize the CViperReqManager here because it needs some metabase props
  629. //
  630. if (FAILED(hr = g_ViperReqMgr.Init()))
  631. {
  632. FirstHitInitStatus = eInitViperReqMgrFail;
  633. goto LExit;
  634. }
  635. DBGPRINTF((DBG_CONTEXT, "FirstHitInit: CViperReqManager configured\n"));
  636. //
  637. // Initialize Hang Detection Configuration
  638. //
  639. g_HangDetectConfig.Init();
  640. DBGPRINTF((DBG_CONTEXT, "FirstHitInit: Hang Detection configured\n"));
  641. //
  642. // Initialize ApplnMgr to listen to Metabase changes.
  643. //
  644. if (FAILED(hr = g_ApplnMgr.InitMBListener()))
  645. {
  646. FirstHitInitStatus = eInitMBListenerFail;
  647. goto LExit;
  648. }
  649. DBGPRINTF((DBG_CONTEXT, "FirstHitInit: ApplnMgr Metabase Listener configured\n"));
  650. DBGPRINTF((DBG_CONTEXT, "ASP First Hit Initialization complete\n"));
  651. LExit:
  652. if (FAILED(hr))
  653. g_fFirstHitFailed = FirstHitInitStatus;
  654. Assert(SUCCEEDED(hr));
  655. return SUCCEEDED(hr);
  656. }
  657. /*===================================================================
  658. void DllUnInit
  659. UnInitialize Denali DLL if not invoked by RegSvr32
  660. Returns:
  661. NONE
  662. Side effects:
  663. NONE
  664. ===================================================================*/
  665. void DllUnInit( void )
  666. {
  667. DBGPRINTF((DBG_CONTEXT, "ASP UnInit -- %d Apps %d Sessions %d Requests\n",
  668. g_nApplications, g_nSessions, g_nBrowserRequests));
  669. g_fShutDownInProgress = TRUE;
  670. ShutDown();
  671. DBGPRINTF((DBG_CONTEXT, "ASP UnInit -- ShutDown Processing\n" ));
  672. UnInitMTACallbacks();
  673. DBGPRINTF((DBG_CONTEXT, "ASP UnInit -- MTA Callbacks\n" ));
  674. UnInitRandGenerator();
  675. DBGPRINTF((DBG_CONTEXT, "ASP UnInit -- RandGen\n"));
  676. UnInit449();
  677. DBGPRINTF((DBG_CONTEXT, "ASP UnInit -- 449 Mgr\n"));
  678. g_ApplnMgr.UnInit();
  679. DBGPRINTF((DBG_CONTEXT, "ASP UnInit -- Application Manager\n" ));
  680. g_ScriptManager.UnInit();
  681. DBGPRINTF((DBG_CONTEXT, "ASP UnInit -- Script Manager\n" ));
  682. if (!g_fFirstHitFailed || g_fFirstHitFailed > eInitViperConfigFail)
  683. {
  684. g_TemplateCache.UnInit();
  685. DBGPRINTF((DBG_CONTEXT, "ASP UnInit -- Template Cache\n" ));
  686. }
  687. g_IncFileMap.UnInit();
  688. DBGPRINTF((DBG_CONTEXT, "ASP UnInit -- IncFileMap\n" ));
  689. g_FileAppMap.UnInit();
  690. DBGPRINTF((DBG_CONTEXT, "ASP UnInit -- File-Application Map\n" ));
  691. if (g_pDirMonitor) {
  692. g_pDirMonitor->Cleanup();
  693. DBGPRINTF((DBG_CONTEXT, "ASP UNInit -- Directory Monitor\n" ));
  694. }
  695. CTemplate::UnInitClass();
  696. DBGPRINTF((DBG_CONTEXT, "ASP UnInit -- CTemplate\n" ));
  697. g_TypelibCache.UnInit();
  698. DBGPRINTF((DBG_CONTEXT, "ASP UnInit -- Typelib Cache\n"));
  699. UnCacheStdTypeInfos();
  700. DBGPRINTF((DBG_CONTEXT, "ASP UnInit -- TypeInfos\n" ));
  701. g_GIPAPI.UnInit();
  702. DBGPRINTF((DBG_CONTEXT, "ASP UnInit -- GIP\n" ));
  703. ErrHandleUnInit();
  704. DBGPRINTF((DBG_CONTEXT, "ASP UnInit -- ErrHandler\n" ));
  705. GlobUnInit();
  706. DBGPRINTF((DBG_CONTEXT, "ASP UnInit -- Glob\n" ));
  707. UnInitCachedBSTRs();
  708. DBGPRINTF((DBG_CONTEXT, "ASP UnInit -- Cached BSTRs\n" ));
  709. //////////////////////////////////////////////////////////
  710. // Wait for the actual session or Application objects to be destroyed.
  711. // The g_nSessions global tracks the init/uninit of session
  712. // objects but not the memory itself. This presents a
  713. // problem when something outside of ASP holds a reference
  714. // to a session object or one of the contained intrinsics.
  715. // One case of this is the revoking of a git'd transaction
  716. // object. Turns out the revoke can happen asynchronously.
  717. //
  718. // NOTE!!! - This needs to be done BEFORE uniniting the
  719. // mem classes since these objects are in the acache.
  720. // Wait for Sessions objects to shutdown.
  721. LONG lastCount = g_nSessionObjectsActive;
  722. DWORD loopCount = 50;
  723. while( (g_nSessionObjectsActive > 0) && (loopCount--) )
  724. {
  725. if (lastCount != g_nSessionObjectsActive)
  726. {
  727. lastCount = g_nSessionObjectsActive;
  728. loopCount = 50;
  729. }
  730. Sleep (100);
  731. }
  732. // Wait for Application objects to shutdown.
  733. lastCount = g_nApplicationObjectsActive;
  734. loopCount = 50;
  735. while( (g_nApplicationObjectsActive > 0) && (loopCount--) )
  736. {
  737. if (lastCount != g_nApplicationObjectsActive)
  738. {
  739. lastCount = g_nApplicationObjectsActive;
  740. loopCount = 50;
  741. }
  742. Sleep (100);
  743. }
  744. // We have waited too long. Proceed with shutdown.
  745. UnInitMemCls();
  746. DBGPRINTF((DBG_CONTEXT, "ASP UnInit -- Per-Class Cache\n" ));
  747. // Destroy ASP RefTrace Logs
  748. IF_DEBUG(TEMPLATE) DestroyRefTraceLog(CTemplate::gm_pTraceLog);
  749. IF_DEBUG(SESSION) DestroyRefTraceLog(CSession::gm_pTraceLog);
  750. IF_DEBUG(APPLICATION) DestroyRefTraceLog(CAppln::gm_pTraceLog);
  751. IF_DEBUG(FCN) DestroyRefTraceLog(CASPDirMonitorEntry::gm_pTraceLog);
  752. if (g_pIASPDummyObjectContext)
  753. g_pIASPDummyObjectContext->Release();
  754. _Module.Term();
  755. delete g_pDirMonitor;
  756. g_pDirMonitor = NULL;
  757. if (g_pEtwTracer != NULL) {
  758. g_pEtwTracer->UnRegister();
  759. delete g_pEtwTracer;
  760. g_pEtwTracer = NULL;
  761. }
  762. // UnInitODBC();
  763. // Note: the memmgr uses perf counters, so must be uninited before the perf counters are uninited
  764. #ifdef DENALI_MEMCHK
  765. DenaliMemoryUnInit();
  766. #else
  767. AspMemUnInit();
  768. #endif
  769. DBGPRINTF((DBG_CONTEXT, "ASP UnInit -- Memory Manager\n" ));
  770. UnInitPerfData();
  771. DBGPRINTF((DBG_CONTEXT, "ASP UnInit -- Perf Counters\n" ));
  772. UnPreInitPerfData();
  773. DBGPRINTF((DBG_CONTEXT, "ASP UnInit -- Perf Counters\n" ));
  774. // Viper Request manager is the last to be initialized. So if anything failed dont Uninitialize.
  775. if (!g_fFirstHitFailed)
  776. {
  777. g_ViperReqMgr.UnInit();
  778. DBGPRINTF((DBG_CONTEXT, "ASP UnInit -- CViperReqManager\n" ));
  779. }
  780. DBGPRINTF((DBG_CONTEXT, "ASP Uninitialized\n" ));
  781. #ifdef LOG_FCNOTIFICATIONS
  782. LfcnUnmapLogFile();
  783. #endif //LOG_FCNOTIFICATIONS
  784. // Deleting the following CS's must be last. Dont put anything after this
  785. DeleteCriticalSection( &g_csFirstMTAHitLock );
  786. DeleteCriticalSection( &g_csFirstSTAHitLock );
  787. DeleteCriticalSection( &g_csFirstHitLock );
  788. DeleteCriticalSection( &g_csEventlogLock );
  789. DELETE_DEBUG_PRINT_OBJECT();
  790. UninitializeResourceDll();
  791. }
  792. /*===================================================================
  793. GetExtensionVersion
  794. Mandatory server extension call which returns the version number of
  795. the ISAPI spec that we were built with.
  796. Returns:
  797. TRUE on success
  798. Side effects:
  799. None.
  800. ===================================================================*/
  801. BOOL WINAPI GetExtensionVersion(HSE_VERSION_INFO *pextver)
  802. {
  803. // This DLL can be inited only once
  804. if (g_fShutDownInProgress ||
  805. InterlockedExchange((LPLONG)&g_fInitStarted, TRUE))
  806. {
  807. SetLastError(ERROR_BUSY);
  808. return FALSE;
  809. }
  810. if (!DllInit())
  811. {
  812. SetLastError(ERROR_BUSY);
  813. return FALSE;
  814. }
  815. pextver->dwExtensionVersion =
  816. MAKELONG(HSE_VERSION_MAJOR, HSE_VERSION_MINOR);
  817. strcpy(pextver->lpszExtensionDesc, g_szExtensionDesc);
  818. return TRUE;
  819. }
  820. /*===================================================================
  821. HttpExtensionProc
  822. Main entry point into the DLL for the (ActiveX) Internet Information Server.
  823. Returns:
  824. DWord indicating status of request.
  825. HSE_STATUS_PENDING for normal return
  826. (This indicates that we will process the request, but havent yet.)
  827. Side effects:
  828. None.
  829. ===================================================================*/
  830. DWORD WINAPI HttpExtensionProc(EXTENSION_CONTROL_BLOCK *pECB)
  831. {
  832. #ifdef SCRIPT_STATS
  833. InterlockedIncrement(&g_cHttpExtensionsExecuting);
  834. #endif // SCRIPT_STATS
  835. CIsapiReqInfo *pIReq = new CIsapiReqInfo(pECB);
  836. if (pIReq == NULL) {
  837. SetLastError(ERROR_OUTOFMEMORY);
  838. return HSE_STATUS_ERROR;
  839. }
  840. #ifndef PERF_DISABLE
  841. g_PerfData.Add_REQTOTALBYTEIN
  842. (
  843. pIReq->QueryCchQueryString()
  844. + strlen( pIReq->ECB()->lpszPathTranslated )
  845. + pIReq->QueryCbTotalBytes()
  846. );
  847. #endif
  848. HandleHit(pIReq);
  849. #ifdef SCRIPT_STATS
  850. InterlockedDecrement(&g_cHttpExtensionsExecuting);
  851. #endif // SCRIPT_STATS
  852. pIReq->Release();
  853. // Always return HSE_STATUS_PENDING and let CIsapiReqInfo Destructor do the DONE_WITH_SESSION
  854. return HSE_STATUS_PENDING;
  855. }
  856. /*===================================================================
  857. TerminateExtension
  858. IIS is supposed to call this entry point to unload ISAPI DLLs.
  859. Returns:
  860. NONE
  861. Side effects:
  862. Uninitializes the Denali ISAPI DLL if asked to.
  863. ===================================================================*/
  864. BOOL WINAPI TerminateExtension( DWORD dwFlag )
  865. {
  866. if ( dwFlag == HSE_TERM_ADVISORY_UNLOAD )
  867. return TRUE;
  868. if ( dwFlag == HSE_TERM_MUST_UNLOAD )
  869. {
  870. // If already shutdown don't uninit twice.
  871. if (g_fShutDownInProgress)
  872. return TRUE;
  873. // make sure this is a CoInitialize()'d thread
  874. HRESULT hr = CoInitialize(NULL);
  875. if (hr == RPC_E_CHANGED_MODE)
  876. {
  877. // already coinitialized MUTLITREADED - OK
  878. DllUnInit();
  879. }
  880. else if (SUCCEEDED(hr))
  881. {
  882. DllUnInit();
  883. // need to CoUninit() because CoInit() Succeeded
  884. CoUninitialize();
  885. }
  886. else //Should never reach here.
  887. {
  888. g_fTerminateExtension = TRUE;
  889. Assert (FALSE);
  890. }
  891. return TRUE;
  892. }
  893. return FALSE;
  894. }
  895. /*===================================================================
  896. HRESULT ShutDown
  897. ASP Processing ShutDown logic. (Moved from ThreadManager::UnInit())
  898. Returns:
  899. HRESULT - S_OK on success
  900. Side effects:
  901. May be slow. Kills all requests/sessions/applications
  902. ===================================================================*/
  903. HRESULT ShutDown()
  904. {
  905. long iT;
  906. const DWORD dwtLongWait = 1000; // 1 sec
  907. const DWORD dwtShortWait = 100; // 1/10 sec
  908. DBGPRINTF((DBG_CONTEXT, "ASP Shutdown: %d apps (%d restarting), %d sessions\n",
  909. g_nApplications, g_nApplicationsRestarting, g_nSessions ));
  910. //////////////////////////////////////////////////////////
  911. // Stop change notification on files in template cache
  912. g_TemplateCache.ShutdownCacheChangeNotification();
  913. //////////////////////////////////////////////////////////
  914. // Shut down debugging, which will have the effect of
  915. // resuming scripts stopped at a breakpoint.
  916. //
  917. // (otherwise stopping running scripts will hang later)
  918. if (g_pPDM)
  919. {
  920. g_TemplateCache.RemoveApplicationFromDebuggerUI(NULL); // remove all document nodes
  921. UnInitDebugging(); // kill PDM
  922. DBGPRINTF((DBG_CONTEXT, "ASP Shutdown: PDM Closed\n" ));
  923. }
  924. //////////////////////////////////////////////////////////
  925. // Drain down all pending browser requests
  926. if (g_nBrowserRequests > 0)
  927. {
  928. // Give them a little time each
  929. for (iT = 2*g_nBrowserRequests; g_nBrowserRequests > 0 && iT > 0; iT--)
  930. Sleep(dwtShortWait);
  931. if (g_nBrowserRequests > 0)
  932. {
  933. // Still there - kill scripts and wait again
  934. g_ScriptManager.EmptyRunningScriptList();
  935. for (iT = 2*g_nBrowserRequests; g_nBrowserRequests > 0 && iT > 0; iT--)
  936. Sleep(dwtShortWait);
  937. }
  938. }
  939. DBGPRINTF((DBG_CONTEXT, "ASP Shutdown: Requests drained: %d remaining\n",
  940. g_nBrowserRequests));
  941. //////////////////////////////////////////////////////////
  942. // Kill any remaining engines running scripts
  943. g_ScriptManager.EmptyRunningScriptList();
  944. DBGPRINTF((DBG_CONTEXT, "ASP Shutdown: Scripts killed\n"));
  945. //////////////////////////////////////////////////////////
  946. // Wait till there are no appications restarting
  947. g_ApplnMgr.Lock();
  948. while (g_nApplicationsRestarting > 0)
  949. {
  950. g_ApplnMgr.UnLock();
  951. Sleep(dwtShortWait);
  952. g_ApplnMgr.Lock();
  953. }
  954. g_ApplnMgr.UnLock();
  955. DBGPRINTF((DBG_CONTEXT, "ASP Shutdown: 0 applications restarting\n"));
  956. //////////////////////////////////////////////////////////
  957. // Make this thread's priority higher than that of worker threads
  958. SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
  959. //////////////////////////////////////////////////////////
  960. // For each application queue up all its sessions for deletion
  961. CApplnIterator ApplnIterator;
  962. ApplnIterator.Start();
  963. CAppln *pAppln;
  964. while (pAppln = ApplnIterator.Next())
  965. {
  966. // remove link to ATQ scheduler (even if killing of sessions fails)
  967. pAppln->PSessionMgr()->UnScheduleSessionKiller();
  968. for (iT = pAppln->GetNumSessions(); iT > 0; iT--)
  969. {
  970. pAppln->PSessionMgr()->DeleteAllSessions(TRUE);
  971. if (pAppln->GetNumSessions() == 0) // all gone?
  972. break;
  973. Sleep(dwtShortWait);
  974. }
  975. }
  976. ApplnIterator.Stop();
  977. DBGPRINTF((DBG_CONTEXT, "ASP Shutdown: All sessions queued up for deletion. nSessions=%d\n",
  978. g_nSessions));
  979. //////////////////////////////////////////////////////////
  980. // Wait till all sessions are gone (UnInited)
  981. while (g_nSessions > 0)
  982. {
  983. // Wait for a maximum of 0.1 sec x # of sessions
  984. for (iT = g_nSessions; g_nSessions > 0 && iT > 0; iT--)
  985. Sleep(dwtShortWait);
  986. if (g_nSessions > 0)
  987. g_ScriptManager.EmptyRunningScriptList(); // Kill runaway Session_OnEnd scripts
  988. }
  989. DBGPRINTF((DBG_CONTEXT, "ASP Shutdown: Finished waiting for sessions to go away. nSessions=%d\n",
  990. g_nSessions));
  991. //////////////////////////////////////////////////////////
  992. // Queue up all application objects for deletion
  993. g_ApplnMgr.DeleteAllApplications();
  994. DBGPRINTF((DBG_CONTEXT, "ASP Shutdown: All applications queued up for deletion. nApplications=%d\n",
  995. g_nApplications));
  996. //////////////////////////////////////////////////////////
  997. // Wait till all applications are gone (UnInited)
  998. while (g_nApplications > 0)
  999. {
  1000. // Wait for a maximum of 1 sec x # of applications
  1001. for (iT = g_nApplications; g_nApplications > 0 && iT > 0; iT--)
  1002. Sleep(dwtLongWait);
  1003. if (g_nApplications > 0)
  1004. g_ScriptManager.EmptyRunningScriptList(); // Kill runaway Applications_OnEnd scripts
  1005. }
  1006. DBGPRINTF((DBG_CONTEXT, "ASP Shutdown: Finished waiting for applications to go away. nApplications=%d\n",
  1007. g_nApplications));
  1008. /////////////////////////////////////////////////////////
  1009. // Wait on the CViperAsyncRequest objects. COM holds the
  1010. // final reference to these so we need to let the activity
  1011. // threads release any outstanding references before we
  1012. // exit.
  1013. while( g_nViperRequests > 0 )
  1014. {
  1015. Sleep( dwtShortWait );
  1016. }
  1017. //////////////////////////////////////////////////////////
  1018. // Free up libraries to force call of DllCanUnloadNow()
  1019. // Component writers should put cleanup code in the DllCanUnloadNow() entry point.
  1020. CoFreeUnusedLibraries();
  1021. //////////////////////////////////////////////////////////
  1022. // Kill Debug Activity if any
  1023. if (g_pDebugActivity)
  1024. delete g_pDebugActivity;
  1025. DBGPRINTF((DBG_CONTEXT, "ASP Shutdown: Debug Activity destroyed\n"));
  1026. //////////////////////////////////////////////////////////
  1027. return S_OK;
  1028. }
  1029. /*===================================================================
  1030. HRESULT GlobInit
  1031. Get all interesting global values (mostly from registry)
  1032. Returns:
  1033. HRESULT - S_OK on success
  1034. Side effects:
  1035. fills in glob. May be slow
  1036. ===================================================================*/
  1037. HRESULT GlobInit()
  1038. {
  1039. //
  1040. // BUGBUG - This really needs to be provided either through
  1041. // a server support function or via the wamexec
  1042. //
  1043. char szModule[MAX_PATH+1];
  1044. if (GetModuleFileNameA(NULL, szModule, MAX_PATH) > 0)
  1045. {
  1046. int cch = strlen(szModule);
  1047. if (cch > 12 && stricmp(szModule+cch-12, "inetinfo.exe") == 0)
  1048. {
  1049. g_fOOP = FALSE;
  1050. }
  1051. else if ( cch > 8 && stricmp( szModule+cch-8, "w3wp.exe" ) == 0 )
  1052. {
  1053. g_fOOP = FALSE;
  1054. }
  1055. else
  1056. {
  1057. g_fOOP = TRUE;
  1058. }
  1059. }
  1060. // Init gGlob
  1061. return gGlob.GlobInit();
  1062. }
  1063. /*===================================================================
  1064. GlobUnInit
  1065. It is a macro now. see glob.h
  1066. Returns:
  1067. HRESULT - S_OK on success
  1068. Side effects:
  1069. memory freed.
  1070. ===================================================================*/
  1071. HRESULT GlobUnInit()
  1072. {
  1073. return gGlob.GlobUnInit();
  1074. }
  1075. /*===================================================================
  1076. InitCachedBSTRs
  1077. Pre-create frequently used BSTRs
  1078. ===================================================================*/
  1079. HRESULT InitCachedBSTRs()
  1080. {
  1081. g_bstrApplication = SysAllocString(WSZ_OBJ_APPLICATION);
  1082. g_bstrRequest = SysAllocString(WSZ_OBJ_REQUEST);
  1083. g_bstrResponse = SysAllocString(WSZ_OBJ_RESPONSE);
  1084. g_bstrServer = SysAllocString(WSZ_OBJ_SERVER);
  1085. g_bstrCertificate = SysAllocString(WSZ_OBJ_CERTIFICATE);
  1086. g_bstrSession = SysAllocString(WSZ_OBJ_SESSION);
  1087. g_bstrScriptingNamespace = SysAllocString(WSZ_OBJ_SCRIPTINGNAMESPACE);
  1088. g_bstrObjectContext = SysAllocString(WSZ_OBJ_OBJECTCONTEXT);
  1089. return
  1090. (
  1091. g_bstrApplication &&
  1092. g_bstrRequest &&
  1093. g_bstrResponse &&
  1094. g_bstrServer &&
  1095. g_bstrCertificate &&
  1096. g_bstrSession &&
  1097. g_bstrScriptingNamespace &&
  1098. g_bstrObjectContext
  1099. )
  1100. ? S_OK : E_OUTOFMEMORY;
  1101. }
  1102. /*===================================================================
  1103. UnInitCachedBSTRs
  1104. Delete frequently used BSTRs
  1105. ===================================================================*/
  1106. HRESULT UnInitCachedBSTRs()
  1107. {
  1108. if (g_bstrApplication)
  1109. {
  1110. SysFreeString(g_bstrApplication);
  1111. g_bstrApplication = NULL;
  1112. }
  1113. if (g_bstrRequest)
  1114. {
  1115. SysFreeString(g_bstrRequest);
  1116. g_bstrRequest = NULL;
  1117. }
  1118. if (g_bstrResponse)
  1119. {
  1120. SysFreeString(g_bstrResponse);
  1121. g_bstrResponse = NULL;
  1122. }
  1123. if (g_bstrServer)
  1124. {
  1125. SysFreeString(g_bstrServer);
  1126. g_bstrServer = NULL;
  1127. }
  1128. if (g_bstrCertificate)
  1129. {
  1130. SysFreeString(g_bstrCertificate);
  1131. g_bstrCertificate = NULL;
  1132. }
  1133. if (g_bstrSession)
  1134. {
  1135. SysFreeString(g_bstrSession);
  1136. g_bstrSession = NULL;
  1137. }
  1138. if (g_bstrScriptingNamespace)
  1139. {
  1140. SysFreeString(g_bstrScriptingNamespace);
  1141. g_bstrScriptingNamespace = NULL;
  1142. }
  1143. if (g_bstrObjectContext)
  1144. {
  1145. SysFreeString(g_bstrObjectContext);
  1146. g_bstrObjectContext = NULL;
  1147. }
  1148. return S_OK;
  1149. }
  1150. // Cached typeinfo's
  1151. ITypeInfo *g_ptinfoIDispatch = NULL; // Cache IDispatch typeinfo
  1152. ITypeInfo *g_ptinfoIUnknown = NULL; // Cache IUnknown typeinfo
  1153. ITypeInfo *g_ptinfoIStringList = NULL; // Cache IStringList typeinfo
  1154. ITypeInfo *g_ptinfoIRequestDictionary = NULL; // Cache IRequestDictionary typeinfo
  1155. ITypeInfo *g_ptinfoIReadCookie = NULL; // Cache IReadCookie typeinfo
  1156. ITypeInfo *g_ptinfoIWriteCookie = NULL; // Cache IWriteCookie typeinfo
  1157. /*===================================================================
  1158. CacheStdTypeInfos
  1159. This is kindofa funny OA-threading bug workaround and perf improvement.
  1160. Because we know that they typinfo's for IUnknown and IDispatch are
  1161. going to be used like mad, we will load them on startup and keep
  1162. them addref'ed. Without this, OA would be loading and unloading
  1163. their typeinfos on almost every Invoke.
  1164. Also, cache denali's typelib so everyone can get at it, and
  1165. cache tye typeinfo's of all our non-top-level intrinsics.
  1166. Returns:
  1167. HRESULT - S_OK on success
  1168. Side effects:
  1169. ===================================================================*/
  1170. HRESULT CacheStdTypeInfos()
  1171. {
  1172. HRESULT hr = S_OK;
  1173. ITypeLib *pITypeLib = NULL;
  1174. CMBCSToWChar convStr;
  1175. /*
  1176. * Load the typeinfos for IUnk and IDisp
  1177. */
  1178. hr = LoadRegTypeLib(IID_StdOle,
  1179. STDOLE2_MAJORVERNUM,
  1180. STDOLE2_MINORVERNUM,
  1181. STDOLE2_LCID,
  1182. &pITypeLib);
  1183. if (hr != S_OK)
  1184. {
  1185. hr = LoadTypeLibEx(OLESTR("stdole2.tlb"), REGKIND_DEFAULT, &pITypeLib);
  1186. if (FAILED(hr))
  1187. goto LFail;
  1188. }
  1189. hr = pITypeLib->GetTypeInfoOfGuid(IID_IDispatch, &g_ptinfoIDispatch);
  1190. if (SUCCEEDED(hr))
  1191. {
  1192. hr = pITypeLib->GetTypeInfoOfGuid(IID_IUnknown, &g_ptinfoIUnknown);
  1193. }
  1194. pITypeLib->Release();
  1195. pITypeLib = NULL;
  1196. if (FAILED(hr))
  1197. goto LFail;
  1198. /*
  1199. * Load denali's typelibs. Save them in Glob.
  1200. */
  1201. /*
  1202. * The type libraries are registered under 0 (neutral),
  1203. * and 9 (English) with no specific sub-language, which
  1204. * would make them 407 or 409 and such.
  1205. * If we become sensitive to sub-languages, then use the
  1206. * full LCID instead of just the LANGID as done here.
  1207. */
  1208. char szPath[MAX_PATH + 4];
  1209. // Get the path for denali so we can look for the TLB there.
  1210. if (!GetModuleFileNameA(g_hinstDLL, szPath, MAX_PATH))
  1211. return E_FAIL;
  1212. if (FAILED(hr = convStr.Init(szPath)))
  1213. goto LFail;
  1214. hr = LoadTypeLibEx(convStr.GetString(), REGKIND_DEFAULT, &pITypeLib);
  1215. // Since it's presumably in our DLL, make sure that we loaded it.
  1216. Assert (SUCCEEDED(hr));
  1217. if (FAILED(hr))
  1218. goto LFail;
  1219. // Save it in Glob
  1220. gGlob.m_pITypeLibDenali = pITypeLib;
  1221. // now load the txn type lib
  1222. strcat(szPath, "\\2");
  1223. if (FAILED(hr = convStr.Init(szPath)))
  1224. goto LFail;
  1225. hr = LoadTypeLibEx(convStr.GetString(), REGKIND_DEFAULT, &pITypeLib);
  1226. // Since it's presumably in our DLL, make sure that we loaded it.
  1227. Assert (SUCCEEDED(hr));
  1228. if (FAILED(hr))
  1229. goto LFail;
  1230. // Save it in Glob
  1231. gGlob.m_pITypeLibTxn = pITypeLib;
  1232. /*
  1233. * Now cache the typeinfo's of all non-top-level intrinsics
  1234. * This is for the OA workaround and for performance.
  1235. */
  1236. hr = gGlob.m_pITypeLibDenali->GetTypeInfoOfGuid(IID_IStringList, &g_ptinfoIStringList);
  1237. if (FAILED(hr))
  1238. goto LFail;
  1239. hr = gGlob.m_pITypeLibDenali->GetTypeInfoOfGuid(IID_IRequestDictionary, &g_ptinfoIRequestDictionary);
  1240. if (FAILED(hr))
  1241. goto LFail;
  1242. hr = gGlob.m_pITypeLibDenali->GetTypeInfoOfGuid(IID_IReadCookie, &g_ptinfoIReadCookie);
  1243. if (FAILED(hr))
  1244. goto LFail;
  1245. hr = gGlob.m_pITypeLibDenali->GetTypeInfoOfGuid(IID_IWriteCookie, &g_ptinfoIWriteCookie);
  1246. if (FAILED(hr))
  1247. goto LFail;
  1248. LFail:
  1249. return(hr);
  1250. }
  1251. /*===================================================================
  1252. UnCacheStdTypeInfos
  1253. Release the typeinfo's we have cached for IUnknown and IDispatch
  1254. and the denali typelib and the other cached stuff.
  1255. Returns:
  1256. HRESULT - S_OK on success
  1257. Side effects:
  1258. ===================================================================*/
  1259. HRESULT UnCacheStdTypeInfos()
  1260. {
  1261. ITypeInfo **ppTypeInfo;
  1262. // Release the typeinfos for IUnk and IDisp
  1263. if (g_ptinfoIDispatch)
  1264. {
  1265. g_ptinfoIDispatch->Release();
  1266. g_ptinfoIDispatch = NULL;
  1267. }
  1268. if (g_ptinfoIUnknown)
  1269. {
  1270. g_ptinfoIUnknown->Release();
  1271. g_ptinfoIDispatch = NULL;
  1272. }
  1273. // Let go of the cached Denali typelibs
  1274. Glob(pITypeLibDenali)->Release();
  1275. Glob(pITypeLibTxn)->Release();
  1276. // Let go of other cached typeinfos
  1277. g_ptinfoIStringList->Release();
  1278. g_ptinfoIRequestDictionary->Release();
  1279. g_ptinfoIReadCookie->Release();
  1280. g_ptinfoIWriteCookie->Release();
  1281. return(S_OK);
  1282. }
  1283. /*===================================================================
  1284. SendHtmlSubstitute
  1285. Send the html file named XXX_ASP.HTM instead of rejecting the
  1286. request.
  1287. Parameters:
  1288. pIReq CIsapiReqInfo
  1289. Returns:
  1290. HRESULT (S_FALSE = no html substitute found)
  1291. ===================================================================*/
  1292. HRESULT SendHtmlSubstitute(CIsapiReqInfo *pIReq)
  1293. {
  1294. TCHAR *szAspPath = pIReq->QueryPszPathTranslated();
  1295. DWORD cchAspPath = pIReq->QueryCchPathTranslated();
  1296. // verify file name
  1297. if (cchAspPath < 4 || cchAspPath > MAX_PATH ||
  1298. _tcsicmp(szAspPath + cchAspPath - 4, _T(".asp")) != 0)
  1299. {
  1300. return S_FALSE;
  1301. }
  1302. // construct path of the html file
  1303. TCHAR szHtmPath[MAX_PATH+5];
  1304. DWORD cchHtmPath = cchAspPath + 4;
  1305. _tcscpy(szHtmPath, szAspPath);
  1306. szHtmPath[cchAspPath - 4] = _T('_');
  1307. _tcscpy(szHtmPath + cchAspPath, _T(".htm"));
  1308. // check if the html file exists
  1309. if (FAILED(AspGetFileAttributes(szHtmPath)))
  1310. return S_FALSE;
  1311. return CResponse::SyncWriteFile(pIReq, szHtmPath);
  1312. }
  1313. /*===================================================================
  1314. DoHangDetection
  1315. Checks a variety of global counters to see if this ASP process
  1316. is underwater. If the conditions are met, an ISAPI SSF function
  1317. is called to report this state.
  1318. Parameters:
  1319. pIReq CIsapiReqInfo
  1320. Returns:
  1321. void
  1322. ===================================================================*/
  1323. void DoHangDetection(CIsapiReqInfo *pIReq, DWORD totalReqs)
  1324. {
  1325. // we can bail quickly if there aren't any requests hung
  1326. if (g_HangDetectConfig.dwHangDetectionEnabled && g_nRequestsHung) {
  1327. // temp work around for a div by zero bug. If g_nRequestsHung
  1328. // is non-zero and g_nThreadsExecuting is zero, then this is
  1329. // an inconsistency in the counter management. A bug that will
  1330. // be hard to track down. To get us through beta3, I'm going to
  1331. // reset the requestshung counter.
  1332. if (g_nThreadsExecuting == 0) {
  1333. g_nRequestsHung = 0;
  1334. memset (g_nRequestSamples, 0 , sizeof(g_nRequestSamples));
  1335. return;
  1336. }
  1337. if (((totalReqs % g_HangDetectConfig.dwRequestThreshold) == 0)) {
  1338. DWORD dwPercentHung = (g_nRequestsHung*100)/g_nThreadsExecuting;
  1339. DWORD dwPercentQueueFull = 0;
  1340. DBGPRINTF((DBG_CONTEXT, "DoHangDetection: Request Thread Hit. Percent Hung Threads is %d (%d of %d)\n",dwPercentHung, g_nRequestsHung, g_nThreadsExecuting));
  1341. // need at least 50% hung before a recycle is requested
  1342. if (dwPercentHung >= g_HangDetectConfig.dwThreadsHungThreshold) {
  1343. // now, check the queue
  1344. dwPercentQueueFull = (Glob(dwRequestQueueMax) != 0)
  1345. ? (g_nBrowserRequests*100)/Glob(dwRequestQueueMax)
  1346. : 0;
  1347. DBGPRINTF((DBG_CONTEXT, "DoHangDetection: Percent Hung exceed threshold. Percent Queue Full is %d\n", dwPercentQueueFull));
  1348. if ((dwPercentQueueFull + dwPercentHung) >= 100) {
  1349. g_nConsecutiveIllStates++;
  1350. // Fill the Requests Queued Samples Array ..Instead of doing a memcopy(setup) this will be equally fast on a pipelined processor.
  1351. g_nRequestSamples[0] = g_nRequestSamples[1];
  1352. g_nRequestSamples[1] = g_nRequestSamples[2];
  1353. g_nRequestSamples[2] = g_nViperRequests;
  1354. DBGPRINTF((DBG_CONTEXT, "DoHangDetection: Exceeded combined threshold. Incrementing ConsecIllStates (%d)\n",g_nConsecutiveIllStates));
  1355. } // if ((dwPercentQueueFull + dwPercentHung) >= 100)
  1356. else {
  1357. g_nConsecutiveIllStates = 0;
  1358. memset (g_nRequestSamples, 0 , sizeof(g_nRequestSamples));
  1359. }
  1360. } // if (dwPercentHung >= g_HangDetectConfig.dwThreadsHungThreshold)
  1361. else {
  1362. g_nConsecutiveIllStates = 0;
  1363. memset (g_nRequestSamples, 0 , sizeof(g_nRequestSamples));
  1364. }
  1365. if (FReportUnhealthy()) {
  1366. char szResourceStr[MAX_MSG_LENGTH];
  1367. char szComposedStr[MAX_MSG_LENGTH];
  1368. DBGPRINTF((DBG_CONTEXT, "DoHangDetection: ConsecIllStatesThreshold exceeded. Reporting ill state to ISAPI\n"));
  1369. if (CchLoadStringOfId(IDS_UNHEALTHY_STATE_STR, szResourceStr, MAX_MSG_LENGTH) == 0)
  1370. strcpy(szResourceStr,"ASP unhealthy because %d%% of executing requests are hung and %d%% of the request queue is full.");
  1371. _snprintf(szComposedStr, MAX_MSG_LENGTH, szResourceStr, dwPercentHung, dwPercentQueueFull);
  1372. szComposedStr[sizeof(szComposedStr)-1] = '\0';
  1373. pIReq->ServerSupportFunction(HSE_REQ_REPORT_UNHEALTHY,
  1374. szComposedStr,
  1375. NULL,
  1376. NULL);
  1377. g_nIllStatesReported++;
  1378. DBGPRINTF((DBG_CONTEXT, "############################### Ill'ing ##############################\n"));
  1379. }
  1380. }
  1381. } // if (g_nRequestsHung)
  1382. else {
  1383. g_nConsecutiveIllStates = 0;
  1384. }
  1385. return;
  1386. }
  1387. /*===================================================================
  1388. FReportUnhealthy
  1389. returns TRUE of all conditions are met to report Unhealthy
  1390. Parameters:
  1391. none
  1392. Returns:
  1393. TRUE - Report Unhealthy
  1394. FALSE - Dont Report Unhealthy
  1395. ===================================================================*/
  1396. BOOL FReportUnhealthy()
  1397. {
  1398. return
  1399. ( // Is it over the threshold yet.
  1400. (g_nConsecutiveIllStates >= g_HangDetectConfig.dwConsecIllStatesThreshold)
  1401. // Should have at least 1 request queued other than the ones hung
  1402. && (g_nViperRequests > g_nRequestsHung)
  1403. // The queue size has not been decreasing
  1404. && ((g_nRequestSamples[0]<= g_nRequestSamples[1]) && (g_nRequestSamples[1]<= g_nRequestSamples[2]))
  1405. // This is the chosen thread to report unhealthy
  1406. && (InterlockedExchange(&g_fUnhealthyReported, 1) == 0)
  1407. );
  1408. }
  1409. /*===================================================================
  1410. DoOOMDetection
  1411. Checks to see if any Out of Memory errors have occurred recently.
  1412. If so, calls the UNHEALTHY SSF.
  1413. Parameters:
  1414. pIReq CIsapiReqInfo
  1415. Returns:
  1416. void
  1417. ===================================================================*/
  1418. void DoOOMDetection(CIsapiReqInfo *pIReq, DWORD totalReqs)
  1419. {
  1420. // see if there are OOM errors, but only report unhealthy once!
  1421. if (!g_fOOMRecycleDisabled
  1422. && g_nOOMErrors
  1423. && (InterlockedExchange(&g_fUnhealthyReported, 1) == 0)) {
  1424. char szResourceStr[MAX_MSG_LENGTH];
  1425. DBGPRINTF((DBG_CONTEXT, "DoOOMDetection: Reporting ill state to ISAPI\n"));
  1426. if (CchLoadStringOfId(IDS_UNHEALTHY_OOM_STATE_STR, szResourceStr, MAX_MSG_LENGTH) == 0)
  1427. strcpy(szResourceStr,"ASP unhealthy due to an out of memory condition.");
  1428. pIReq->ServerSupportFunction(HSE_REQ_REPORT_UNHEALTHY,
  1429. szResourceStr,
  1430. NULL,
  1431. NULL);
  1432. g_nIllStatesReported++;
  1433. DBGPRINTF((DBG_CONTEXT, "############################### Ill'ing ##############################\n"));
  1434. }
  1435. }
  1436. #ifdef LOG_FCNOTIFICATIONS
  1437. // UNDONE get this from registry
  1438. LPSTR g_szNotifyLogFile = "C:\\Temp\\AspNotify.Log";
  1439. HANDLE g_hfileNotifyLog;
  1440. HANDLE g_hmapNotifyLog;
  1441. char* g_pchNotifyLogStart;
  1442. char* g_pchNotifyLogCurrent;
  1443. LPSTR g_szNotifyPrefix = "File change notification: ";
  1444. LPSTR g_szCreateHandlePrefix = "Create handle: ";
  1445. void LfcnCreateLogFile()
  1446. {
  1447. DWORD dwErrCode;
  1448. if(INVALID_HANDLE_VALUE != (g_hfileNotifyLog =
  1449. CreateFile(
  1450. g_szNotifyLogFile, // file name
  1451. GENERIC_READ | GENERIC_WRITE, // access (read-write) mode
  1452. FILE_SHARE_READ, // share mode
  1453. NULL, // pointer to security descriptor
  1454. CREATE_ALWAYS, // how to create
  1455. FILE_ATTRIBUTE_NORMAL, // file attributes
  1456. NULL // handle to file with attributes to copy
  1457. )))
  1458. {
  1459. BYTE rgb[0x10000];
  1460. DWORD cb = sizeof( rgb );
  1461. DWORD cbWritten = 0;
  1462. // FillMemory( rgb, cb, 0xAB );
  1463. WriteFile(
  1464. g_hfileNotifyLog, // handle to file to write to
  1465. rgb, // pointer to data to write to file
  1466. cb, // number of bytes to write
  1467. &cbWritten, // pointer to number of bytes written
  1468. NULL // pointer to structure needed for overlapped I/O
  1469. );
  1470. if(NULL != (g_hmapNotifyLog =
  1471. CreateFileMapping(
  1472. g_hfileNotifyLog, // handle to file to map
  1473. NULL, // optional security attributes
  1474. PAGE_READWRITE, // protection for mapping object
  1475. 0, // high-order 32 bits of object size
  1476. 100, // low-order 32 bits of object size
  1477. NULL // name of file-mapping object
  1478. )))
  1479. {
  1480. if(NULL != (g_pchNotifyLogStart =
  1481. (char*) MapViewOfFile(
  1482. g_hmapNotifyLog, // file-mapping object to map into address space
  1483. FILE_MAP_WRITE, // access mode
  1484. 0, // high-order 32 bits of file offset
  1485. 0, // low-order 32 bits of file offset
  1486. 0 // number of bytes to map
  1487. )))
  1488. {
  1489. *g_pchNotifyLogStart = '\0';
  1490. g_pchNotifyLogCurrent = g_pchNotifyLogStart;
  1491. LfcnAppendLog( "ASP change-notifications log file \r\n" );
  1492. LfcnAppendLog( "================================= \r\n" );
  1493. DBGPRINTF((DBG_CONTEXT, "Notifications log file created and mapped.\r\n" ));
  1494. return;
  1495. }
  1496. }
  1497. }
  1498. dwErrCode = GetLastError();
  1499. DBGERROR((DBG_CONTEXT, "Failed to create notifications log file; last error was %d\r\n", szErrCode));
  1500. }
  1501. void LfcnCopyAdvance(char** ppchDest, const char* sz)
  1502. {
  1503. // UNDONE make this robust (WriteFile to extend file?)
  1504. strcpy( *ppchDest, sz );
  1505. *ppchDest += strlen( sz );
  1506. }
  1507. void LfcnAppendLog(const char* sz)
  1508. {
  1509. LfcnCopyAdvance( &g_pchNotifyLogCurrent, sz );
  1510. DBGPRINTF((DBG_CONTEXT, "%s", sz));
  1511. }
  1512. void LfcnLogNotification(char* szFile)
  1513. {
  1514. LfcnAppendLog( g_szNotifyPrefix );
  1515. LfcnAppendLog( szFile );
  1516. LfcnAppendLog( "\r\n" );
  1517. }
  1518. void LfcnLogHandleCreation(int i, char* szApp)
  1519. {
  1520. char szIndex[5];
  1521. _itoa( i, szIndex, 10);
  1522. LfcnAppendLog( g_szCreateHandlePrefix );
  1523. LfcnAppendLog( szIndex );
  1524. LfcnAppendLog( "\t" );
  1525. LfcnAppendLog( szApp );
  1526. LfcnAppendLog( "\r\n" );
  1527. }
  1528. void LfcnUnmapLogFile()
  1529. {
  1530. if(g_pchNotifyLogStart != NULL)
  1531. UnmapViewOfFile(g_pchNotifyLogStart);
  1532. if(g_hmapNotifyLog!= NULL)
  1533. CloseHandle(g_hmapNotifyLog);
  1534. if(g_hfileNotifyLog != NULL && g_hfileNotifyLog != INVALID_HANDLE_VALUE)
  1535. CloseHandle( g_hfileNotifyLog );
  1536. g_pchNotifyLogStart = NULL;
  1537. g_hmapNotifyLog = NULL;
  1538. g_hfileNotifyLog = NULL;
  1539. }
  1540. #endif //LOG_FCNOTIFICATIONS
  1541. HRESULT AdjustProcessSecurityToAllowPowerUsersToWait()
  1542. {
  1543. HRESULT hr = S_OK;
  1544. DWORD dwErr = ERROR_SUCCESS;
  1545. EXPLICIT_ACCESS ea[5];
  1546. SID_IDENTIFIER_AUTHORITY SIDAuthNT = SECURITY_NT_AUTHORITY;
  1547. PSID psidPowerUser = NULL;
  1548. PSID psidSystemOperator = NULL;
  1549. PSID psidAdministrators = NULL;
  1550. PSID psidPerfMonUser = NULL;
  1551. PSID psidPerfLogUser = NULL;
  1552. PACL pNewDACL = NULL;
  1553. PACL pOldDACL = NULL;
  1554. PSECURITY_DESCRIPTOR pSD = NULL;
  1555. HANDLE hProcess = GetCurrentProcess();
  1556. //
  1557. // Get a sid that represents the Administrators group.
  1558. //
  1559. dwErr = AllocateAndCreateWellKnownSid( WinBuiltinAdministratorsSid,
  1560. &psidAdministrators );
  1561. if ( dwErr != ERROR_SUCCESS )
  1562. {
  1563. hr = HRESULT_FROM_WIN32( dwErr );
  1564. DPERROR((
  1565. DBG_CONTEXT,
  1566. hr,
  1567. "Creating Power User SID failed\n"
  1568. ));
  1569. goto exit;
  1570. }
  1571. //
  1572. // Get a sid that represents the POWER_USERS group.
  1573. //
  1574. dwErr = AllocateAndCreateWellKnownSid( WinBuiltinPowerUsersSid,
  1575. &psidPowerUser );
  1576. if ( dwErr != ERROR_SUCCESS )
  1577. {
  1578. hr = HRESULT_FROM_WIN32( dwErr );
  1579. DPERROR((
  1580. DBG_CONTEXT,
  1581. hr,
  1582. "Creating Power User SID failed\n"
  1583. ));
  1584. goto exit;
  1585. }
  1586. //
  1587. // Get a sid that represents the SYSTEM_OPERATORS group.
  1588. //
  1589. dwErr = AllocateAndCreateWellKnownSid( WinBuiltinSystemOperatorsSid,
  1590. &psidSystemOperator );
  1591. if ( dwErr != ERROR_SUCCESS )
  1592. {
  1593. hr = HRESULT_FROM_WIN32( dwErr );
  1594. DPERROR((
  1595. DBG_CONTEXT,
  1596. hr,
  1597. "Creating System Operators SID failed\n"
  1598. ));
  1599. goto exit;
  1600. }
  1601. //
  1602. // Get a sid that represents the PERF LOG USER group.
  1603. //
  1604. dwErr = AllocateAndCreateWellKnownSid( WinBuiltinPerfLoggingUsersSid,
  1605. &psidPerfLogUser );
  1606. if ( dwErr != ERROR_SUCCESS )
  1607. {
  1608. hr = HRESULT_FROM_WIN32( dwErr );
  1609. DPERROR((
  1610. DBG_CONTEXT,
  1611. hr,
  1612. "Creating perf log user SID failed\n"
  1613. ));
  1614. goto exit;
  1615. }
  1616. //
  1617. // Get a sid that represents the PERF MON USER group.
  1618. //
  1619. dwErr = AllocateAndCreateWellKnownSid( WinBuiltinPerfMonitoringUsersSid,
  1620. &psidPerfMonUser );
  1621. if ( dwErr != ERROR_SUCCESS )
  1622. {
  1623. hr = HRESULT_FROM_WIN32( dwErr );
  1624. DPERROR((
  1625. DBG_CONTEXT,
  1626. hr,
  1627. "Creating perf mon user SID failed\n"
  1628. ));
  1629. goto exit;
  1630. }
  1631. //
  1632. // Now Get the SD for the Process.
  1633. //
  1634. //
  1635. // The pOldDACL is just a pointer into memory owned
  1636. // by the pSD, so only free the pSD.
  1637. //
  1638. dwErr = GetSecurityInfo( hProcess,
  1639. SE_KERNEL_OBJECT,
  1640. DACL_SECURITY_INFORMATION,
  1641. NULL, // owner SID
  1642. NULL, // primary group SID
  1643. &pOldDACL, // PACL*
  1644. NULL, // PACL*
  1645. &pSD ); // Security Descriptor
  1646. if ( dwErr != ERROR_SUCCESS )
  1647. {
  1648. hr = HRESULT_FROM_WIN32(dwErr);
  1649. DPERROR((
  1650. DBG_CONTEXT,
  1651. hr,
  1652. "Could not get security info for the current process \n"
  1653. ));
  1654. goto exit;
  1655. }
  1656. // Initialize an EXPLICIT_ACCESS structure for the new ACE.
  1657. ZeroMemory(&ea[0], sizeof(ea));
  1658. SetExplicitAccessSettings( &(ea[0]),
  1659. SYNCHRONIZE,
  1660. GRANT_ACCESS,
  1661. psidPowerUser );
  1662. SetExplicitAccessSettings( &(ea[1]),
  1663. SYNCHRONIZE,
  1664. GRANT_ACCESS,
  1665. psidSystemOperator );
  1666. SetExplicitAccessSettings( &(ea[2]),
  1667. SYNCHRONIZE,
  1668. GRANT_ACCESS,
  1669. psidAdministrators );
  1670. SetExplicitAccessSettings( &(ea[3]),
  1671. SYNCHRONIZE,
  1672. GRANT_ACCESS,
  1673. psidPerfMonUser );
  1674. SetExplicitAccessSettings( &(ea[4]),
  1675. SYNCHRONIZE,
  1676. GRANT_ACCESS,
  1677. psidPerfLogUser );
  1678. //
  1679. // Add the power user acl to the list.
  1680. //
  1681. dwErr = SetEntriesInAcl(sizeof(ea)/sizeof(EXPLICIT_ACCESS),
  1682. ea,
  1683. pOldDACL,
  1684. &pNewDACL);
  1685. if ( dwErr != ERROR_SUCCESS )
  1686. {
  1687. hr = HRESULT_FROM_WIN32(dwErr);
  1688. DPERROR((
  1689. DBG_CONTEXT,
  1690. hr,
  1691. "Could not set Acls into security descriptor \n"
  1692. ));
  1693. goto exit;
  1694. }
  1695. //
  1696. // Attach the new ACL as the object's DACL.
  1697. //
  1698. dwErr = SetSecurityInfo(hProcess,
  1699. SE_KERNEL_OBJECT,
  1700. DACL_SECURITY_INFORMATION,
  1701. NULL,
  1702. NULL,
  1703. pNewDACL,
  1704. NULL);
  1705. if ( dwErr != ERROR_SUCCESS )
  1706. {
  1707. hr = HRESULT_FROM_WIN32(dwErr);
  1708. DPERROR((
  1709. DBG_CONTEXT,
  1710. hr,
  1711. "Could not set process security info \n"
  1712. ));
  1713. goto exit;
  1714. }
  1715. exit:
  1716. FreeWellKnownSid(&psidPowerUser);
  1717. FreeWellKnownSid(&psidSystemOperator);
  1718. FreeWellKnownSid(&psidAdministrators);
  1719. FreeWellKnownSid(&psidPerfLogUser);
  1720. FreeWellKnownSid(&psidPerfMonUser);
  1721. if( pSD != NULL )
  1722. {
  1723. LocalFree((HLOCAL) pSD);
  1724. pSD = NULL;
  1725. }
  1726. if( pNewDACL != NULL )
  1727. {
  1728. LocalFree((HLOCAL) pNewDACL);
  1729. pNewDACL = NULL;
  1730. }
  1731. return hr;
  1732. }
  1733. HRESULT
  1734. InitializeResourceDll()
  1735. {
  1736. HRESULT hr = S_OK;
  1737. // check if already initialized
  1738. if (g_hResourceDLL)
  1739. return S_OK;
  1740. // Allocate MAX_PATH + some greater than reasonable amout for system32\inetsrv\iisres.dll
  1741. STACK_STRU(struResourceDll, MAX_PATH + 100);
  1742. UINT i = GetWindowsDirectory(struResourceDll.QueryStr(), MAX_PATH);
  1743. if ( 0 == i || MAX_PATH < i )
  1744. return HRESULT_FROM_WIN32(GetLastError());
  1745. struResourceDll.SyncWithBuffer();
  1746. hr = struResourceDll.Append(L"\\system32\\inetsrv\\");
  1747. if (FAILED(hr))
  1748. return hr;
  1749. hr = struResourceDll.Append(IIS_RESOURCE_DLL_NAME);
  1750. if (FAILED(hr))
  1751. return hr;
  1752. g_hResourceDLL = LoadLibrary(struResourceDll.QueryStr());
  1753. if (!g_hResourceDLL)
  1754. {
  1755. return HRESULT_FROM_WIN32(GetLastError());
  1756. }
  1757. return S_OK;
  1758. }
  1759. VOID
  1760. UninitializeResourceDll()
  1761. {
  1762. if (g_hResourceDLL)
  1763. {
  1764. FreeLibrary(g_hResourceDLL);
  1765. g_hResourceDLL = (HMODULE)0;
  1766. }
  1767. return;
  1768. }