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.

366 lines
8.1 KiB

  1. // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. //
  3. // APPMAIN.CPP
  4. //
  5. // DAV ISAPI DLL entrypoints, main routine, global instance management
  6. //
  7. //
  8. // Copyright 1986-1997 Microsoft Corporation, All Rights Reserved
  9. //
  10. #include <_davprs.h>
  11. #include <xatom.h> // XML atom cache
  12. #include "instdata.h"
  13. #include <langid.h>
  14. #include "custerr.h"
  15. #include "content.h"
  16. // THE one, global instance
  17. //
  18. CInst g_inst;
  19. // ------------------------------------------------------------------------
  20. //
  21. // CInst::PerProcessInit()
  22. //
  23. // Zero it out.
  24. //
  25. void
  26. CInst::PerProcessInit( HINSTANCE hinst )
  27. {
  28. m_hinst = hinst;
  29. #ifdef MINIMAL_ISAPI
  30. m_hfDummy = CreateFileW( L"c:\\temp\\test2.txt", // filename
  31. GENERIC_READ, // dwAccess
  32. FILE_SHARE_READ | FILE_SHARE_WRITE,
  33. NULL, // lpSecurityAttributes
  34. OPEN_EXISTING, // creation flags
  35. FILE_ATTRIBUTE_NORMAL |
  36. FILE_FLAG_SEQUENTIAL_SCAN |
  37. FILE_FLAG_OVERLAPPED, // attributes
  38. NULL ); // tenplate
  39. #endif // MINIMAL_ISAPI
  40. }
  41. // ------------------------------------------------------------------------
  42. //
  43. // CInst::GetInstData()
  44. //
  45. // Get the instance data for this ECB.
  46. // Handoff this call to our InstDataCache.
  47. //
  48. CInstData&
  49. CInst::GetInstData( const IEcb& ecb )
  50. {
  51. return CInstDataCache::GetInstData( ecb );
  52. }
  53. // ------------------------------------------------------------------------
  54. //
  55. // CDAVExt::FInitializeDll()
  56. //
  57. // Your standard DLL entrypoint.
  58. //
  59. BOOL
  60. CDAVExt::FInitializeDll( HINSTANCE hinst,
  61. DWORD dwReason )
  62. {
  63. BOOL fInitialized = TRUE;
  64. switch ( dwReason )
  65. {
  66. case DLL_THREAD_ATTACH:
  67. case DLL_THREAD_DETACH:
  68. Assert(FALSE);
  69. break;
  70. case DLL_PROCESS_ATTACH:
  71. {
  72. //
  73. // Do per process initialization (and implicit initialization of
  74. // the first thread). The try/catch block just allows us to
  75. // clean up neatly if anything at all goes wrong.
  76. //
  77. try
  78. {
  79. g_inst.PerProcessInit( hinst );
  80. }
  81. catch ( CDAVException& )
  82. {
  83. DebugTrace( "CDAVExt::FInitializeDll() - Caught exception in per-process initialization\n" );
  84. fInitialized = FALSE;
  85. }
  86. break;
  87. }
  88. case DLL_PROCESS_DETACH:
  89. {
  90. break;
  91. }
  92. default:
  93. {
  94. TrapSz( "FInitializeDll called for unknown reason\n" );
  95. fInitialized = FALSE;
  96. break;
  97. }
  98. }
  99. return fInitialized;
  100. }
  101. // ------------------------------------------------------------------------
  102. //
  103. // CDAVExt::FVersion()
  104. //
  105. BOOL
  106. CDAVExt::FVersion ( HSE_VERSION_INFO * pver )
  107. {
  108. BOOL fSuccess = FALSE;
  109. //
  110. // Init .INI file tagged debug traces
  111. //
  112. InitDavprsTraces();
  113. // Init ECB logging -- DBG only
  114. //
  115. #ifdef DBG
  116. if ( DEBUG_TRACE_TEST(ECBLogging) )
  117. InitECBLogging();
  118. #endif
  119. // Instatiate the virtual root cache
  120. // We must do that before we initialise the metabase as this cache will listen
  121. // to the metabase notifications that are registered when metabase is created.
  122. // So if CChildVRCache is not there we may notify the object that does not
  123. // exist and crash while doing that.
  124. //
  125. CChildVRCache::CreateInstance();
  126. // Init the metabase
  127. //
  128. if ( !FMDInitialize() )
  129. goto ret;
  130. // Instatiate the instance cache
  131. //
  132. CInstDataCache::CreateInstance();
  133. // Create the language ID cache
  134. //
  135. CLangIDCache::CreateInstance();
  136. if ( !CLangIDCache::FInitialize() )
  137. goto ret;
  138. // Instantiate the global registry-based mime map
  139. //
  140. if ( !FInitRegMimeMap() )
  141. goto ret;
  142. fSuccess = TRUE;
  143. ret:
  144. return fSuccess;
  145. }
  146. #ifndef MINIMAL_ISAPI
  147. #else // defined(MINIMAL_ISAPI)
  148. static VOID WINAPI
  149. IOCompleteNoOp( EXTENSION_CONTROL_BLOCK * pecb,
  150. PVOID pvContext,
  151. DWORD cbIO,
  152. DWORD dwLastError )
  153. {
  154. //
  155. // Done with the session. This must be done from inside
  156. // of the async callback because INETINFO crashes in
  157. // INFOCOMM.DLL if you try to put it immediately after
  158. // the SSF::HSE_REQ_TRANSMIT_FILE and the client sends
  159. // a huge pile of requests before waiting for a response.
  160. //
  161. pecb->ServerSupportFunction (pecb->ConnID,
  162. HSE_REQ_DONE_WITH_SESSION |
  163. (pvContext ? HSE_STATUS_SUCCESS_AND_KEEP_CONN : 0),
  164. NULL,
  165. NULL,
  166. NULL);
  167. }
  168. void
  169. CheckKeepAlive( LPEXTENSION_CONTROL_BLOCK pecb, DWORD * pdwKeepAlive )
  170. {
  171. pecb->ServerSupportFunction (pecb->ConnID,
  172. HSE_REQ_IS_KEEP_CONN,
  173. pdwKeepAlive,
  174. NULL,
  175. NULL);
  176. }
  177. void
  178. SendHeaders( LPEXTENSION_CONTROL_BLOCK pecb )
  179. {
  180. HSE_SEND_HEADER_EX_INFO hseSendHeaderExInfo;
  181. static CHAR rgchStatus[] = "200 OK";
  182. hseSendHeaderExInfo.pszStatus = rgchStatus;
  183. hseSendHeaderExInfo.cchStatus = sizeof(rgchStatus) - 1;
  184. hseSendHeaderExInfo.pszHeader = NULL;
  185. hseSendHeaderExInfo.cchHeader = 0;
  186. hseSendHeaderExInfo.fKeepConn = TRUE;
  187. pecb->ServerSupportFunction (pecb->ConnID,
  188. HSE_REQ_SEND_RESPONSE_HEADER_EX,
  189. &hseSendHeaderExInfo,
  190. NULL,
  191. NULL);
  192. }
  193. void
  194. SendResponse( LPEXTENSION_CONTROL_BLOCK pecb, DWORD dwKeepAlive )
  195. {
  196. HSE_TF_INFO hseTFInfo;
  197. ZeroMemory(&hseTFInfo, sizeof(HSE_TF_INFO));
  198. //
  199. // If we're going to close the connection anyway, might
  200. // as well send the headers along with everything else now.
  201. //
  202. if ( !dwKeepAlive )
  203. {
  204. static CHAR rgchHeaders[] =
  205. "HTTP/1.1 200 OK\r\n"
  206. "Content-Type: text/plain\r\n"
  207. "Connection: close\r\n"
  208. "\r\n";
  209. hseTFInfo.pHead = rgchHeaders;
  210. hseTFInfo.HeadLength = sizeof(rgchHeaders) - 1;
  211. }
  212. hseTFInfo.pfnHseIO = IOCompleteNoOp;
  213. hseTFInfo.pContext = (PVOID)(dwKeepAlive);
  214. hseTFInfo.dwFlags = HSE_IO_ASYNC |
  215. (dwKeepAlive ? 0 : HSE_IO_DISCONNECT_AFTER_SEND);
  216. hseTFInfo.BytesToWrite = 0;
  217. hseTFInfo.hFile = g_inst.m_hfDummy;
  218. pecb->ServerSupportFunction (pecb->ConnID,
  219. HSE_REQ_TRANSMIT_FILE,
  220. &hseTFInfo,
  221. NULL,
  222. NULL);
  223. }
  224. DWORD
  225. CDAVExt::DwMain( LPEXTENSION_CONTROL_BLOCK pecb,
  226. BOOL fUseRawUrlMappings /* = FALSE */ )
  227. {
  228. DWORD dwKeepAlive;
  229. //
  230. // Determine whether to keep the connection open
  231. //
  232. CheckKeepAlive( pecb, &dwKeepAlive );
  233. //
  234. // If keep alive is set, we *MUST* send the headers using
  235. // HSE_REQ_SEND_RESPONSE_HEADERS_EX (which is always synchronous)
  236. // because it's the only way that allows us to tell IIS to
  237. // keep the connection open.
  238. //
  239. if ( dwKeepAlive )
  240. SendHeaders( pecb );
  241. //
  242. // Transmit the dummy file
  243. //
  244. SendResponse( pecb, dwKeepAlive );
  245. return HSE_STATUS_PENDING;
  246. }
  247. #endif // defined(MINIMAL_ISAPI)
  248. // ------------------------------------------------------------------------
  249. //
  250. // CDAVExt::FTerminate()
  251. //
  252. // Terminates (deinitializes) the common portions of this DAV ISAPI
  253. //
  254. // Returns:
  255. // TRUE if the DAV ISAPI application can be unloaded now
  256. // FALSE otherwise
  257. //
  258. BOOL
  259. CDAVExt::FTerminate()
  260. {
  261. // Tear down the global registry-based mimemap
  262. //
  263. DeinitRegMimeMap();
  264. // Tear down the XML Atom cache
  265. //
  266. CXAtomCache::DeinitIfUsed();
  267. // Delete the language ID cache
  268. //
  269. CLangIDCache::DestroyInstance();
  270. // Tear down the instance data cache
  271. //
  272. CInstDataCache::DestroyInstance();
  273. //
  274. // Deinit the metabase
  275. //
  276. MDDeinitialize();
  277. // Tear down the child vroot cache
  278. // We must do that after metabase is uninitialized and metabase notifications
  279. // are shut down, as this cache listens to the metabase notifications.
  280. // So if CChildVRCache is not there we may notify the object that does not
  281. // exist and crash while doing that.
  282. //
  283. CChildVRCache::DestroyInstance();
  284. // Deinit ECB logging
  285. //
  286. #ifdef DBG
  287. if ( DEBUG_TRACE_TEST(ECBLogging) )
  288. DeinitECBLogging();
  289. #endif
  290. // Due to the fact that COM threads may still be siting in the pur code
  291. // even they are done modifying our data, and there is no way we can
  292. // push them out (synchronization would need to happen outside of our
  293. // dll-s) - we will sleep for 5 seconds, hoping tha they will leave us alone.
  294. //
  295. Sleep(5000);
  296. //
  297. // We can always shut down (for now...)
  298. //
  299. return TRUE;
  300. }