// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. #include "precomp.hxx" #include #ifdef DEBUG DECLARE_DEBUG_PRINTS_OBJECT(); DECLARE_DEBUG_VARIABLE(); DECLARE_PLATFORM_TYPE(); #endif // DEBUG HTTP_MODULE_ID g_pModuleId = NULL; IHttpServer * g_pHttpServer = NULL; BOOL g_fAsyncDisconnectAvailable = FALSE; BOOL g_fWinHttpNonBlockingCallbackAvailable = FALSE; BOOL g_fRecycleProcessCalled = FALSE; PCWSTR g_pszModuleName = NULL; HINSTANCE g_hModule; HINSTANCE g_hWinHttpModule; BOOL g_fWebSocketSupported = FALSE; DWORD g_dwTlsIndex = TLS_OUT_OF_INDEXES; BOOL g_fEnableReferenceCountTracing = FALSE; DWORD g_dwAspNetCoreDebugFlags = 0; BOOL g_fNsiApiNotSupported = FALSE; DWORD g_dwActiveServerProcesses = 0; DWORD g_OptionalWinHttpFlags = 0; //specify additional WinHTTP options when using WinHttpOpenRequest API. DWORD g_dwDebugFlags = 0; PCSTR g_szDebugLabel = "ASPNET_CORE_MODULE"; BOOL WINAPI DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: g_hModule = hModule; DisableThreadLibraryCalls(hModule); break; default: break; } return TRUE; } VOID LoadGlobalConfiguration( VOID ) { HKEY hKey; if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\IIS Extensions\\IIS AspNetCore Module\\Parameters", 0, KEY_READ, &hKey) == NO_ERROR) { DWORD dwType; DWORD dwData; DWORD cbData; cbData = sizeof(dwData); if ((RegQueryValueEx(hKey, L"OptionalWinHttpFlags", NULL, &dwType, (LPBYTE)&dwData, &cbData) == NO_ERROR) && (dwType == REG_DWORD)) { g_OptionalWinHttpFlags = dwData; } cbData = sizeof(dwData); if ((RegQueryValueEx(hKey, L"EnableReferenceCountTracing", NULL, &dwType, (LPBYTE)&dwData, &cbData) == NO_ERROR) && (dwType == REG_DWORD) && (dwData == 1 || dwData == 0)) { g_fEnableReferenceCountTracing = !!dwData; } cbData = sizeof(dwData); if ((RegQueryValueEx(hKey, L"DebugFlags", NULL, &dwType, (LPBYTE)&dwData, &cbData) == NO_ERROR) && (dwType == REG_DWORD)) { g_dwAspNetCoreDebugFlags = dwData; } RegCloseKey(hKey); } DWORD dwSize = 0; DWORD dwResult = GetExtendedTcpTable(NULL, &dwSize, FALSE, AF_INET, TCP_TABLE_OWNER_PID_LISTENER, 0); if (dwResult != NO_ERROR && dwResult != ERROR_INSUFFICIENT_BUFFER) { g_fNsiApiNotSupported = TRUE; } } HRESULT __stdcall RegisterModule( DWORD dwServerVersion, IHttpModuleRegistrationInfo * pModuleInfo, IHttpServer * pHttpServer ) /*++ Routine description: Function called by IIS immediately after loading the module, used to let IIS know what notifications the module is interested in Arguments: dwServerVersion - IIS version the module is being loaded on pModuleInfo - info regarding this module pHttpServer - callback functions which can be used by the module at any point Return value: HRESULT --*/ { HRESULT hr = S_OK; CProxyModuleFactory * pFactory = NULL; #ifdef DEBUG CREATE_DEBUG_PRINT_OBJECT("Asp.Net Core Module"); g_dwDebugFlags = DEBUG_FLAGS_ANY; #endif // DEBUG CREATE_DEBUG_PRINT_OBJECT; LoadGlobalConfiguration(); // // 7.0 is 0,7 // if (dwServerVersion > MAKELONG(0, 7)) { g_fAsyncDisconnectAvailable = TRUE; } // // 8.0 is 0,8 // if (dwServerVersion >= MAKELONG(0, 8)) { // IISOOB:36641 Enable back WINHTTP_OPTION_ASSURED_NON_BLOCKING_CALLBACKS for Win8. // g_fWinHttpNonBlockingCallbackAvailable = TRUE; g_fWebSocketSupported = TRUE; } hr = WINHTTP_HELPER::StaticInitialize(); if (FAILED(hr)) { if (hr == HRESULT_FROM_WIN32(ERROR_PROC_NOT_FOUND)) { g_fWebSocketSupported = FALSE; } else { goto Finished; } } g_pModuleId = pModuleInfo->GetId(); g_pszModuleName = pModuleInfo->GetName(); g_pHttpServer = pHttpServer; g_hWinHttpModule = GetModuleHandle(TEXT("winhttp.dll")); // // WinHTTP does not create enough threads, ask it to create more. // Starting in Windows 7, this setting is ignored because WinHTTP // uses a thread pool. // SYSTEM_INFO si; GetSystemInfo(&si); DWORD dwThreadCount = (si.dwNumberOfProcessors * 3 + 1) / 2; WinHttpSetOption(NULL, WINHTTP_OPTION_WORKER_THREAD_COUNT, &dwThreadCount, sizeof(dwThreadCount)); // // Create the factory before any static initialization. // The CProxyModuleFactory::Terminate method will clean any // static object initialized. // pFactory = new CProxyModuleFactory; if (pFactory == NULL) { hr = E_OUTOFMEMORY; goto Finished; } hr = pModuleInfo->SetRequestNotifications( pFactory, RQ_EXECUTE_REQUEST_HANDLER, 0); if (FAILED(hr)) { goto Finished; } pFactory = NULL; g_pResponseHeaderHash = new RESPONSE_HEADER_HASH; if (g_pResponseHeaderHash == NULL) { hr = E_OUTOFMEMORY; goto Finished; } hr = g_pResponseHeaderHash->Initialize(); if (FAILED(hr)) { goto Finished; } hr = ALLOC_CACHE_HANDLER::StaticInitialize(); if (FAILED(hr)) { goto Finished; } hr = FORWARDING_HANDLER::StaticInitialize(g_fEnableReferenceCountTracing); if (FAILED(hr)) { goto Finished; } hr = WEBSOCKET_HANDLER::StaticInitialize(g_fEnableReferenceCountTracing); if (FAILED(hr)) { goto Finished; } Finished: if (pFactory != NULL) { pFactory->Terminate(); pFactory = NULL; } return hr; }