dllmain.cpp 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. // dllmain.cpp : Defines the entry point for the DLL application.
  2. #include <IPHlpApi.h>
  3. #include <VersionHelpers.h>
  4. #include "exceptions.h"
  5. DECLARE_DEBUG_PRINT_OBJECT("aspnetcorev2_outofprocess.dll");
  6. BOOL g_fWebSocketStaticInitialize = FALSE;
  7. BOOL g_fEnableReferenceCountTracing = FALSE;
  8. BOOL g_fGlobalInitialize = FALSE;
  9. BOOL g_fOutOfProcessInitialize = FALSE;
  10. BOOL g_fOutOfProcessInitializeError = FALSE;
  11. BOOL g_fWinHttpNonBlockingCallbackAvailable = FALSE;
  12. BOOL g_fProcessDetach = FALSE;
  13. DWORD g_OptionalWinHttpFlags = 0;
  14. DWORD g_dwTlsIndex = TLS_OUT_OF_INDEXES;
  15. SRWLOCK g_srwLockRH;
  16. HINTERNET g_hWinhttpSession = nullptr;
  17. IHttpServer * g_pHttpServer = nullptr;
  18. HINSTANCE g_hWinHttpModule;
  19. HINSTANCE g_hOutOfProcessRHModule;
  20. HINSTANCE g_hAspNetCoreModule;
  21. HANDLE g_hEventLog = nullptr;
  22. VOID
  23. InitializeGlobalConfiguration(
  24. IHttpServer * pServer
  25. )
  26. {
  27. HKEY hKey;
  28. BOOL fLocked = FALSE;
  29. if (!g_fGlobalInitialize)
  30. {
  31. AcquireSRWLockExclusive(&g_srwLockRH);
  32. fLocked = TRUE;
  33. if (g_fGlobalInitialize)
  34. {
  35. // Done by another thread
  36. goto Finished;
  37. }
  38. g_pHttpServer = pServer;
  39. if (pServer->IsCommandLineLaunch())
  40. {
  41. g_hEventLog = RegisterEventSource(nullptr, ASPNETCORE_IISEXPRESS_EVENT_PROVIDER);
  42. }
  43. else
  44. {
  45. g_hEventLog = RegisterEventSource(nullptr, ASPNETCORE_EVENT_PROVIDER);
  46. }
  47. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  48. L"SOFTWARE\\Microsoft\\IIS Extensions\\IIS AspNetCore Module V2\\Parameters",
  49. 0,
  50. KEY_READ,
  51. &hKey) == NO_ERROR)
  52. {
  53. DWORD dwType;
  54. DWORD dwData;
  55. DWORD cbData;
  56. cbData = sizeof(dwData);
  57. if ((RegQueryValueEx(hKey,
  58. L"OptionalWinHttpFlags",
  59. nullptr,
  60. &dwType,
  61. (LPBYTE)&dwData,
  62. &cbData) == NO_ERROR) &&
  63. (dwType == REG_DWORD))
  64. {
  65. g_OptionalWinHttpFlags = dwData;
  66. }
  67. cbData = sizeof(dwData);
  68. if ((RegQueryValueEx(hKey,
  69. L"EnableReferenceCountTracing",
  70. nullptr,
  71. &dwType,
  72. (LPBYTE)&dwData,
  73. &cbData) == NO_ERROR) &&
  74. (dwType == REG_DWORD) && (dwData == 1 || dwData == 0))
  75. {
  76. g_fEnableReferenceCountTracing = !!dwData;
  77. }
  78. }
  79. g_fWebSocketStaticInitialize = IsWindows8OrGreater();
  80. g_fGlobalInitialize = TRUE;
  81. }
  82. Finished:
  83. if (fLocked)
  84. {
  85. ReleaseSRWLockExclusive(&g_srwLockRH);
  86. }
  87. }
  88. //
  89. // Global initialization routine for OutOfProcess
  90. //
  91. HRESULT
  92. EnsureOutOfProcessInitializtion(IHttpApplication *pHttpApplication)
  93. {
  94. DBG_ASSERT(g_pHttpServer);
  95. HRESULT hr = S_OK;
  96. if (g_fOutOfProcessInitializeError)
  97. {
  98. FINISHED(E_NOT_VALID_STATE);
  99. }
  100. if (g_fOutOfProcessInitialize)
  101. {
  102. FINISHED(S_OK);
  103. }
  104. {
  105. auto lock = SRWExclusiveLock(g_srwLockRH);
  106. if (g_fOutOfProcessInitializeError)
  107. {
  108. FINISHED(E_NOT_VALID_STATE);
  109. }
  110. if (g_fOutOfProcessInitialize)
  111. {
  112. // Done by another thread
  113. FINISHED(S_OK);
  114. }
  115. g_fOutOfProcessInitialize = TRUE;
  116. g_hWinHttpModule = GetModuleHandle(TEXT("winhttp.dll"));
  117. g_hAspNetCoreModule = GetModuleHandle(TEXT("aspnetcorev2.dll"));
  118. hr = WINHTTP_HELPER::StaticInitialize();
  119. if (FAILED_LOG(hr))
  120. {
  121. if (hr == HRESULT_FROM_WIN32(ERROR_PROC_NOT_FOUND))
  122. {
  123. g_fWebSocketStaticInitialize = FALSE;
  124. }
  125. else
  126. {
  127. FINISHED(hr);
  128. }
  129. }
  130. #pragma warning(push)
  131. #pragma warning(disable: 26477) // NULL usage via Windows header
  132. g_hWinhttpSession = WinHttpOpen(L"",
  133. WINHTTP_ACCESS_TYPE_NO_PROXY,
  134. WINHTTP_NO_PROXY_NAME,
  135. WINHTTP_NO_PROXY_BYPASS,
  136. WINHTTP_FLAG_ASYNC);
  137. #pragma warning(pop)
  138. FINISHED_LAST_ERROR_IF(g_hWinhttpSession == nullptr);
  139. //
  140. // Don't set non-blocking callbacks WINHTTP_OPTION_ASSURED_NON_BLOCKING_CALLBACKS,
  141. // as we will call WinHttpQueryDataAvailable to get response on the same thread
  142. // that we received callback from Winhttp on completing sending/forwarding the request
  143. //
  144. //
  145. // Setup the callback function
  146. //
  147. FINISHED_LAST_ERROR_IF(WinHttpSetStatusCallback(g_hWinhttpSession,
  148. FORWARDING_HANDLER::OnWinHttpCompletion,
  149. (WINHTTP_CALLBACK_FLAG_ALL_COMPLETIONS |
  150. WINHTTP_CALLBACK_STATUS_SENDING_REQUEST),
  151. 0) == WINHTTP_INVALID_STATUS_CALLBACK);
  152. //
  153. // Make sure we see the redirects (rather than winhttp doing it
  154. // automatically)
  155. //
  156. DWORD dwRedirectOption = WINHTTP_OPTION_REDIRECT_POLICY_NEVER;
  157. FINISHED_LAST_ERROR_IF(!WinHttpSetOption(g_hWinhttpSession,
  158. WINHTTP_OPTION_REDIRECT_POLICY,
  159. &dwRedirectOption,
  160. sizeof(dwRedirectOption)));
  161. g_dwTlsIndex = TlsAlloc();
  162. FINISHED_LAST_ERROR_IF(g_dwTlsIndex == TLS_OUT_OF_INDEXES);
  163. FINISHED_IF_FAILED(ALLOC_CACHE_HANDLER::StaticInitialize());
  164. FINISHED_IF_FAILED(FORWARDING_HANDLER::StaticInitialize(g_fEnableReferenceCountTracing));
  165. FINISHED_IF_FAILED(WEBSOCKET_HANDLER::StaticInitialize(g_fEnableReferenceCountTracing));
  166. DebugInitializeFromConfig(*g_pHttpServer, *pHttpApplication);
  167. }
  168. Finished:
  169. if (FAILED(hr))
  170. {
  171. g_fOutOfProcessInitializeError = TRUE;
  172. }
  173. return hr;
  174. }
  175. BOOL APIENTRY DllMain(HMODULE hModule,
  176. DWORD ul_reason_for_call,
  177. LPVOID lpReserved
  178. )
  179. {
  180. UNREFERENCED_PARAMETER(lpReserved);
  181. switch (ul_reason_for_call)
  182. {
  183. case DLL_PROCESS_ATTACH:
  184. g_hOutOfProcessRHModule = hModule;
  185. DisableThreadLibraryCalls(hModule);
  186. InitializeSRWLock(&g_srwLockRH);
  187. DebugInitialize(hModule);
  188. break;
  189. case DLL_PROCESS_DETACH:
  190. g_fProcessDetach = TRUE;
  191. FORWARDING_HANDLER::StaticTerminate();
  192. ALLOC_CACHE_HANDLER::StaticTerminate();
  193. DebugStop();
  194. break;
  195. default:
  196. break;
  197. }
  198. return TRUE;
  199. }
  200. HRESULT
  201. __stdcall
  202. CreateApplication(
  203. _In_ IHttpServer *pServer,
  204. _In_ IHttpApplication *pHttpApplication,
  205. _In_ APPLICATION_PARAMETER *pParameters,
  206. _In_ DWORD nParameters,
  207. _Out_ IAPPLICATION **ppApplication
  208. )
  209. {
  210. TraceContextScope traceScope(FindParameter<IHttpTraceContext*>("TraceContext", pParameters, nParameters));
  211. auto pSite = FindParameter<IHttpSite*>("Site", pParameters, nParameters);
  212. InitializeGlobalConfiguration(pServer);
  213. REQUESTHANDLER_CONFIG *pConfig = nullptr;
  214. RETURN_IF_FAILED(REQUESTHANDLER_CONFIG::CreateRequestHandlerConfig(pServer, pSite, pHttpApplication, &pConfig));
  215. std::unique_ptr<REQUESTHANDLER_CONFIG> pRequestHandlerConfig(pConfig);
  216. RETURN_IF_FAILED(EnsureOutOfProcessInitializtion(pHttpApplication));
  217. std::unique_ptr<OUT_OF_PROCESS_APPLICATION> pApplication = std::make_unique<OUT_OF_PROCESS_APPLICATION>(*pHttpApplication, std::move(pRequestHandlerConfig));
  218. RETURN_IF_FAILED(pApplication->Initialize());
  219. RETURN_IF_FAILED(pApplication->StartMonitoringAppOffline());
  220. *ppApplication = pApplication.release();
  221. return S_OK;
  222. }