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.

505 lines
12 KiB

  1. /*
  2. * E N T R Y . C P P
  3. *
  4. * Entrypoints for Caligula DLLs
  5. *
  6. * Copyright 1986-1997 Microsoft Corporation, All Rights Reserved
  7. */
  8. #include "_davfs.h"
  9. #include "_shlkmgr.h"
  10. #include <langtocpid.h>
  11. #include <ex\idlethrd.h>
  12. #include <ntverp.h>
  13. #include <iisver.h>
  14. // Global items --------------------------------------------------------------
  15. //
  16. EXTERN_C const CHAR gc_szSignature[] = "HTTPEXT";
  17. EXTERN_C const WCHAR gc_wszSignature[] = L"HTTPEXT";
  18. HINSTANCE g_hinst = NULL;
  19. WCHAR gc_wszDllPath[MAX_PATH+1];
  20. CHAR gc_szVersion[] = VER_PRODUCTVERSION_STR;
  21. // Per process instance data -------------------------------------------------
  22. //
  23. class CImplInst : private RefCountedGlobal<CImplInst, HSE_VERSION_INFO *>
  24. {
  25. //
  26. // Friend declarations required by RefCountedGlobal template
  27. //
  28. friend class Singleton<CImplInst>;
  29. friend class RefCountedGlobal<CImplInst, HSE_VERSION_INFO *>;
  30. //
  31. // Flags to track initialization progress so we know
  32. // how much to uninitialize if initialization fails overall
  33. //
  34. BOOL m_fInitializedHeap;
  35. // CREATORS
  36. //
  37. // Declared private to ensure that arbitrary instances
  38. // of this class cannot be created. The Singleton
  39. // template (declared as a friend above) controls
  40. // the sole instance of this class.
  41. //
  42. CImplInst() :
  43. m_fInitializedHeap(FALSE)
  44. {
  45. }
  46. BOOL FInit( HSE_VERSION_INFO * pver );
  47. ~CImplInst();
  48. //
  49. // Array of strings used in service state change
  50. // event log messages.
  51. //
  52. static LPCSTR mc_rgszLogServiceStateChange[];
  53. // NOT IMPLEMENTED
  54. //
  55. CImplInst( const CImplInst& );
  56. CImplInst& operator=( const CImplInst& );
  57. public:
  58. using RefCountedGlobal<CImplInst, HSE_VERSION_INFO *>::DwInitRef;
  59. using RefCountedGlobal<CImplInst, HSE_VERSION_INFO *>::DeinitRef;
  60. };
  61. LPCSTR CImplInst::mc_rgszLogServiceStateChange[] = { gc_szSignature, gc_szVersion };
  62. STGOPENSTORAGEONHANDLE g_pfnStgOpenStorageOnHandle = NULL;
  63. #ifdef DBG
  64. BOOL g_fDavTrace = FALSE;
  65. DEC_CONST CHAR gc_szDbgIni[] = "HTTPEXT.INI";
  66. DEC_CONST INT gc_cchDbgIni = CchConstString(gc_szDbgIni);
  67. #endif
  68. // ------------------------------------------------------------------------
  69. //
  70. // CImplInst::FInit()
  71. //
  72. // Second-phase (failable) CImplInst constructor. Code that instantiates
  73. // the CImplInst should call this function after instantiation. If the
  74. // call returns FALSE, calling code should immediately destroy the
  75. // CImplInst.
  76. //
  77. BOOL
  78. CImplInst::FInit( HSE_VERSION_INFO * pver )
  79. {
  80. BOOL fSuccess = FALSE;
  81. //
  82. // Handle exceptions locally. If anything below throws
  83. // an exception then fail the initialization.
  84. //
  85. try
  86. {
  87. HINSTANCE hLib;
  88. // First and foremost, check to ensure that
  89. // our resources are well attached and accessible
  90. // if this fails, then we want to fail our loading.
  91. //
  92. if (!LoadStringA (g_hinst,
  93. IDS_ExtensionName,
  94. pver->lpszExtensionDesc,
  95. sizeof(pver->lpszExtensionDesc)))
  96. goto Exit;
  97. // Setup the HSE version numbering
  98. //
  99. pver->dwExtensionVersion = MAKELONG (HSE_VERSION_MINOR, HSE_VERSION_MAJOR);
  100. #ifdef DBG
  101. // Do the DBG tracing initialization
  102. //
  103. g_fDavTrace = GetPrivateProfileIntA (gc_szDbgTraces,
  104. gc_szSignature,
  105. FALSE,
  106. gc_szDbgIni);
  107. #endif // DBG
  108. // Init the heap allocators
  109. //
  110. if ( !g_heap.FInit() )
  111. goto Exit;
  112. m_fInitializedHeap = TRUE;
  113. // Initialize the resource string cache
  114. //
  115. if ( !FInitResourceStringCache() )
  116. goto Exit;
  117. // Init the volume type cache
  118. //
  119. if ( !FInitVolumeTypeCache() )
  120. goto Exit;
  121. // Init the parser
  122. //
  123. if ( !CDAVExt::FVersion (pver) )
  124. goto Exit;
  125. // Create shared lock mgr
  126. //
  127. if (FAILED(CSharedLockMgr::CreateInstance().HrInitialize()))
  128. goto Exit;
  129. // Create the thread pool
  130. //
  131. if (!CPoolManager::FInit())
  132. goto Exit;
  133. // Start the idle thread
  134. //
  135. if ( !FInitIdleThread() )
  136. goto Exit;
  137. // Init the cache mapping accept language string to cpid
  138. // cache used to decode non-UTF8 characters in URLs
  139. //
  140. if (!CLangToCpidCache::FCreateInstance())
  141. goto Exit;
  142. // If this API is not available on ole32.dll. we'll not be able
  143. // to operate properties, but we should still work to some extent
  144. // so we'll take care of the NULL function pointer in our code.
  145. // don't fail now
  146. //
  147. // Don't use relative paths for dlls, It is easy to put suspect dlls
  148. // somewhere in an application's path. Always use absolute paths.
  149. //
  150. CHAR szOle32Path[MAX_PATH+1];
  151. UINT cSystemDir;
  152. // Get the system directory
  153. //
  154. cSystemDir = GetSystemDirectory (szOle32Path, CElems(szOle32Path));
  155. // GetSystemDirectory will return
  156. // 1. the number of characters copied if it succeeds (excluding the
  157. // terminating NULL)
  158. // 2. 0 if it fails
  159. // 3. the number of characters required if the supplied buffer is
  160. // too smallto hold the path.
  161. // Since we gave enough space for the system
  162. // directory, we will treat "buffer not enough" errors as failures.
  163. //
  164. if ((0 < cSystemDir) && (CElems(szOle32Path) > cSystemDir))
  165. {
  166. // GetSystemDirectory path does not end with a backslash
  167. //
  168. if (CElems("\\ole32.dll") + cSystemDir <= CElems(szOle32Path))
  169. {
  170. strcat(szOle32Path, "\\ole32.dll");
  171. hLib = LoadLibraryA (szOle32Path);
  172. if (hLib)
  173. {
  174. g_pfnStgOpenStorageOnHandle = (STGOPENSTORAGEONHANDLE)
  175. GetProcAddress (hLib, "StgOpenStorageOnHandle");
  176. }
  177. }
  178. }
  179. // Start up event log message takes two parameters
  180. // the signature and the version
  181. //
  182. #undef LOG_STARTUP_EVENT
  183. #ifdef LOG_STARTUP_EVENT
  184. LogEvent (DAVPRS_SERVICE_STARTUP,
  185. EVENTLOG_INFORMATION_TYPE,
  186. sizeof(mc_rgszLogServiceStateChange) / sizeof(LPCSTR),
  187. mc_rgszLogServiceStateChange,
  188. 0,
  189. NULL);
  190. #endif // LOG_STARTUP_EVENT
  191. }
  192. catch ( CDAVException& )
  193. {
  194. goto Exit;
  195. }
  196. fSuccess = TRUE;
  197. Exit:
  198. return fSuccess;
  199. }
  200. // ------------------------------------------------------------------------
  201. //
  202. // CImplInst::~CImplInst()
  203. //
  204. CImplInst::~CImplInst()
  205. {
  206. //
  207. // DO NOT allow exceptions to propagate out of this call.
  208. // This is intended as a safety valve only. In order to
  209. // avoid leaking instance data, individual instance data
  210. // components should handle any exceptions themselves.
  211. //
  212. try
  213. {
  214. //
  215. // If we logged a startup message, then log a shutdown message
  216. //
  217. #undef LOG_STARTUP_EVENT
  218. #ifdef LOG_STARTUP_EVENT
  219. LogEvent (DAVPRS_SERVICE_SHUTDOWN,
  220. EVENTLOG_INFORMATION_TYPE,
  221. sizeof(mc_rgszLogServiceStateChange) / sizeof(LPCSTR),
  222. mc_rgszLogServiceStateChange,
  223. 0,
  224. NULL);
  225. #endif // LOG_STARTUP_EVENT
  226. //
  227. // Deinit the idle thread. Do this before taking down the
  228. // thread pool there may be delayed thread pool work items
  229. // pending on the idle thread.
  230. //
  231. DeleteIdleThread();
  232. //
  233. // Deinit the thread pool
  234. //
  235. CPoolManager::Deinit();
  236. // Deinit the language string to cpid cache
  237. //
  238. CLangToCpidCache::DestroyInstance();
  239. //
  240. // remove the IDBCreateCommand if exist
  241. //
  242. ReleaseDBCreateCommandObject();
  243. // Destroy shared lock mgr
  244. //
  245. CSharedLockMgr::DestroyInstance();
  246. // Shutdown the parser
  247. //
  248. (void) CDAVExt::FTerminate ();
  249. // Deinit the volume type cache
  250. //
  251. DeinitVolumeTypeCache();
  252. // Clean out the security-thread-token cache.
  253. //
  254. CleanupSecurityToken();
  255. // Deinit the resource string cache
  256. //
  257. DeinitResourceStringCache();
  258. // Destroy allocators
  259. //
  260. if ( m_fInitializedHeap )
  261. g_heap.Deinit();
  262. }
  263. catch ( CDAVException& )
  264. {
  265. }
  266. }
  267. // ------------------------------------------------------------------------
  268. //
  269. // Instance refcounting callouts from _davprs
  270. //
  271. VOID AddRefImplInst()
  272. {
  273. HSE_VERSION_INFO lVer;
  274. DWORD cRef;
  275. cRef = CImplInst::DwInitRef(&lVer);
  276. //
  277. // We should already have at least one ref on the instance
  278. // before we called DwInitRef(), so we should more than one
  279. // ref after the call.
  280. //
  281. Assert( cRef > 1 );
  282. }
  283. VOID ReleaseImplInst()
  284. {
  285. CImplInst::DeinitRef();
  286. }
  287. // IIS Entrypoints -----------------------------------------------------------
  288. //
  289. EXTERN_C BOOL WINAPI
  290. FGetExtensionVersion (HSE_VERSION_INFO * pver)
  291. {
  292. CWin32ExceptionHandler win32ExceptionHandler;
  293. //
  294. // Initialize one instance reference and return whether it succeeded.
  295. //
  296. return !!CImplInst::DwInitRef( pver );
  297. }
  298. EXTERN_C BOOL WINAPI
  299. FTerminateDavFS (DWORD)
  300. {
  301. CWin32ExceptionHandler win32ExceptionHandler;
  302. //
  303. // Deinitialize one instance reference
  304. //
  305. CImplInst::DeinitRef();
  306. //
  307. // After the instance data has been released, we are ready to terminate.
  308. //
  309. return TRUE;
  310. }
  311. EXTERN_C DWORD WINAPI
  312. DwDavFSExtensionProc (LPEXTENSION_CONTROL_BLOCK pecb)
  313. {
  314. HSE_VERSION_INFO lVer;
  315. DWORD dwHSEStatusRet = HSE_STATUS_ERROR;
  316. if ( CImplInst::DwInitRef(&lVer) )
  317. {
  318. dwHSEStatusRet = CDAVExt::DwMain(pecb);
  319. CImplInst::DeinitRef();
  320. }
  321. return dwHSEStatusRet;
  322. }
  323. // Win32 DLL Entrypoints -----------------------------------------------------
  324. //
  325. EXTERN_C BOOL WINAPI
  326. DllMain (HINSTANCE hinst, DWORD dwReason, LPVOID lpvReserved)
  327. {
  328. switch (dwReason)
  329. {
  330. default:
  331. {
  332. DebugTrace ("FInitHttpExtDll(), unknown reason\n");
  333. return FALSE;
  334. }
  335. case DLL_THREAD_ATTACH:
  336. case DLL_THREAD_DETACH:
  337. {
  338. //
  339. // We disable thread library calls (see below),
  340. // so we should never see DLL_THREAD_ATTACH or
  341. // DLL_THREAD_DETACH.
  342. //
  343. Assert (FALSE);
  344. //
  345. // But if we do, it doesn't harm anything.
  346. //
  347. return TRUE;
  348. }
  349. case DLL_PROCESS_ATTACH:
  350. {
  351. //
  352. // Init .INI file tagged debug traces
  353. //
  354. InitTraces();
  355. // Cache the inst
  356. //
  357. g_hinst = hinst;
  358. // And the full path to the DLL
  359. //
  360. if ( !GetModuleFileNameW( hinst, gc_wszDllPath, sizeof(gc_wszDllPath)/sizeof(WCHAR) ) )
  361. {
  362. DebugTrace( "FInitHttpExtDll() - GetModuleFileName() failed in DLL_PROCESS_ATTACH\n" );
  363. return FALSE;
  364. }
  365. // Call the parser's initialization for every call into our
  366. // DLL initialization proc. The order of operations here is
  367. // fairly important. The parser should be called after we do
  368. // our processing in the non-DETACH case.
  369. //
  370. if ( !CDAVExt::FInitializeDll (hinst, dwReason) )
  371. return FALSE;
  372. // We are going to disable thread library calls. If the parser
  373. // really ever needs these then the this needs to change.
  374. //
  375. DisableThreadLibraryCalls (hinst);
  376. return TRUE;
  377. }
  378. case DLL_PROCESS_DETACH:
  379. {
  380. // And in the detach case, the impl. gets the last word.
  381. // Ignore any failures -- the DLL is being unloaded and
  382. // the process is going away whether we like it or not.
  383. //
  384. (void) CDAVExt::FInitializeDll (hinst, dwReason);
  385. return TRUE;
  386. }
  387. }
  388. }
  389. // OLE Entrypoints -----------------------------------------------------------
  390. //
  391. STDAPI
  392. HrDllCanUnloadNowDavFS (VOID)
  393. {
  394. return S_OK;
  395. }
  396. STDAPI
  397. HrDllGetClassObjectDavFS (REFCLSID rclsid, REFIID riid, LPVOID * ppv)
  398. {
  399. return E_NOINTERFACE;
  400. }
  401. STDAPI
  402. HrDllRegisterServerDavFS (VOID)
  403. {
  404. HRESULT hr;
  405. // This is a "first line" entrypoint into our dll. Need to init some stuff.
  406. // Right now, the heap is the only important piece.
  407. //
  408. g_heap.FInit();
  409. // Everybody gets to register regardless of failures
  410. //
  411. hr = EventLogDllRegisterServer( gc_wszDllPath );
  412. return hr;
  413. }
  414. STDAPI
  415. HrDllUnregisterServerDavFS (VOID)
  416. {
  417. HRESULT hr;
  418. // This is a "first line" entrypoint into our dll. Need to init some stuff.
  419. // Right now, the heap is the only important piece.
  420. //
  421. g_heap.FInit();
  422. // Everybody gets to unregister regardless of failures
  423. //
  424. hr = EventLogDllUnregisterServer();
  425. return hr;
  426. }